Skip to content

Commit 99d94c0

Browse files
committed
[GTK4] Fix custom drawing in GTK4
This involves changing the mechanism with which we do custom drawing. Previously we tried to hook into GtkWidget's snapshot, but this required messing around with the vtable of the widget to call our handler instead. This commit changes to using GtkOverlays + GtkDrawingAreas to allow custom drawing on top of the GtkWidgets. Fixes #2819
1 parent a0d6ffc commit 99d94c0

File tree

8 files changed

+308
-59
lines changed

8 files changed

+308
-59
lines changed

bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4.c

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,6 +1066,72 @@ JNIEXPORT void JNICALL GTK4_NATIVE(gtk_1drag_1source_1set_1icon)
10661066
}
10671067
#endif
10681068

1069+
#ifndef NO_gtk_1drawing_1area_1get_1content_1height
1070+
JNIEXPORT jint JNICALL GTK4_NATIVE(gtk_1drawing_1area_1get_1content_1height)
1071+
(JNIEnv *env, jclass that, jlong arg0)
1072+
{
1073+
jint rc = 0;
1074+
GTK4_NATIVE_ENTER(env, that, gtk_1drawing_1area_1get_1content_1height_FUNC);
1075+
rc = (jint)gtk_drawing_area_get_content_height((GtkDrawingArea *)arg0);
1076+
GTK4_NATIVE_EXIT(env, that, gtk_1drawing_1area_1get_1content_1height_FUNC);
1077+
return rc;
1078+
}
1079+
#endif
1080+
1081+
#ifndef NO_gtk_1drawing_1area_1get_1content_1width
1082+
JNIEXPORT jint JNICALL GTK4_NATIVE(gtk_1drawing_1area_1get_1content_1width)
1083+
(JNIEnv *env, jclass that, jlong arg0)
1084+
{
1085+
jint rc = 0;
1086+
GTK4_NATIVE_ENTER(env, that, gtk_1drawing_1area_1get_1content_1width_FUNC);
1087+
rc = (jint)gtk_drawing_area_get_content_width((GtkDrawingArea *)arg0);
1088+
GTK4_NATIVE_EXIT(env, that, gtk_1drawing_1area_1get_1content_1width_FUNC);
1089+
return rc;
1090+
}
1091+
#endif
1092+
1093+
#ifndef NO_gtk_1drawing_1area_1new
1094+
JNIEXPORT jlong JNICALL GTK4_NATIVE(gtk_1drawing_1area_1new)
1095+
(JNIEnv *env, jclass that)
1096+
{
1097+
jlong rc = 0;
1098+
GTK4_NATIVE_ENTER(env, that, gtk_1drawing_1area_1new_FUNC);
1099+
rc = (jlong)gtk_drawing_area_new();
1100+
GTK4_NATIVE_EXIT(env, that, gtk_1drawing_1area_1new_FUNC);
1101+
return rc;
1102+
}
1103+
#endif
1104+
1105+
#ifndef NO_gtk_1drawing_1area_1set_1content_1height
1106+
JNIEXPORT void JNICALL GTK4_NATIVE(gtk_1drawing_1area_1set_1content_1height)
1107+
(JNIEnv *env, jclass that, jlong arg0, jint arg1)
1108+
{
1109+
GTK4_NATIVE_ENTER(env, that, gtk_1drawing_1area_1set_1content_1height_FUNC);
1110+
gtk_drawing_area_set_content_height((GtkDrawingArea *)arg0, (int)arg1);
1111+
GTK4_NATIVE_EXIT(env, that, gtk_1drawing_1area_1set_1content_1height_FUNC);
1112+
}
1113+
#endif
1114+
1115+
#ifndef NO_gtk_1drawing_1area_1set_1content_1width
1116+
JNIEXPORT void JNICALL GTK4_NATIVE(gtk_1drawing_1area_1set_1content_1width)
1117+
(JNIEnv *env, jclass that, jlong arg0, jint arg1)
1118+
{
1119+
GTK4_NATIVE_ENTER(env, that, gtk_1drawing_1area_1set_1content_1width_FUNC);
1120+
gtk_drawing_area_set_content_width((GtkDrawingArea *)arg0, (int)arg1);
1121+
GTK4_NATIVE_EXIT(env, that, gtk_1drawing_1area_1set_1content_1width_FUNC);
1122+
}
1123+
#endif
1124+
1125+
#ifndef NO_gtk_1drawing_1area_1set_1draw_1func
1126+
JNIEXPORT void JNICALL GTK4_NATIVE(gtk_1drawing_1area_1set_1draw_1func)
1127+
(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jlong arg3)
1128+
{
1129+
GTK4_NATIVE_ENTER(env, that, gtk_1drawing_1area_1set_1draw_1func_FUNC);
1130+
gtk_drawing_area_set_draw_func((GtkDrawingArea *)arg0, (GtkDrawingAreaDrawFunc)arg1, (gpointer)arg2, (GDestroyNotify)arg3);
1131+
GTK4_NATIVE_EXIT(env, that, gtk_1drawing_1area_1set_1draw_1func_FUNC);
1132+
}
1133+
#endif
1134+
10691135
#ifndef NO_gtk_1drop_1target_1async_1new
10701136
JNIEXPORT jlong JNICALL GTK4_NATIVE(gtk_1drop_1target_1async_1new)
10711137
(JNIEnv *env, jclass that, jlong arg0, jint arg1)
@@ -2072,6 +2138,116 @@ JNIEXPORT jlong JNICALL GTK4_NATIVE(gtk_1native_1get_1surface)
20722138
}
20732139
#endif
20742140

2141+
#ifndef NO_gtk_1overlay_1add_1overlay
2142+
JNIEXPORT void JNICALL GTK4_NATIVE(gtk_1overlay_1add_1overlay)
2143+
(JNIEnv *env, jclass that, jlong arg0, jlong arg1)
2144+
{
2145+
GTK4_NATIVE_ENTER(env, that, gtk_1overlay_1add_1overlay_FUNC);
2146+
gtk_overlay_add_overlay((GtkOverlay *)arg0, (GtkWidget *)arg1);
2147+
GTK4_NATIVE_EXIT(env, that, gtk_1overlay_1add_1overlay_FUNC);
2148+
}
2149+
#endif
2150+
2151+
#ifndef NO_gtk_1overlay_1get_1child
2152+
JNIEXPORT jlong JNICALL GTK4_NATIVE(gtk_1overlay_1get_1child)
2153+
(JNIEnv *env, jclass that, jlong arg0)
2154+
{
2155+
jlong rc = 0;
2156+
GTK4_NATIVE_ENTER(env, that, gtk_1overlay_1get_1child_FUNC);
2157+
rc = (jlong)gtk_overlay_get_child((GtkOverlay *)arg0);
2158+
GTK4_NATIVE_EXIT(env, that, gtk_1overlay_1get_1child_FUNC);
2159+
return rc;
2160+
}
2161+
#endif
2162+
2163+
#ifndef NO_gtk_1overlay_1get_1clip_1overlay
2164+
JNIEXPORT jboolean JNICALL GTK4_NATIVE(gtk_1overlay_1get_1clip_1overlay)
2165+
(JNIEnv *env, jclass that, jlong arg0, jlong arg1)
2166+
{
2167+
jboolean rc = 0;
2168+
GTK4_NATIVE_ENTER(env, that, gtk_1overlay_1get_1clip_1overlay_FUNC);
2169+
rc = (jboolean)gtk_overlay_get_clip_overlay((GtkOverlay *)arg0, (GtkWidget *)arg1);
2170+
GTK4_NATIVE_EXIT(env, that, gtk_1overlay_1get_1clip_1overlay_FUNC);
2171+
return rc;
2172+
}
2173+
#endif
2174+
2175+
#ifndef NO_gtk_1overlay_1get_1measure_1overlay
2176+
JNIEXPORT jboolean JNICALL GTK4_NATIVE(gtk_1overlay_1get_1measure_1overlay)
2177+
(JNIEnv *env, jclass that, jlong arg0, jlong arg1)
2178+
{
2179+
jboolean rc = 0;
2180+
GTK4_NATIVE_ENTER(env, that, gtk_1overlay_1get_1measure_1overlay_FUNC);
2181+
rc = (jboolean)gtk_overlay_get_measure_overlay((GtkOverlay *)arg0, (GtkWidget *)arg1);
2182+
GTK4_NATIVE_EXIT(env, that, gtk_1overlay_1get_1measure_1overlay_FUNC);
2183+
return rc;
2184+
}
2185+
#endif
2186+
2187+
#ifndef NO_gtk_1overlay_1get_1type
2188+
JNIEXPORT jlong JNICALL GTK4_NATIVE(gtk_1overlay_1get_1type)
2189+
(JNIEnv *env, jclass that)
2190+
{
2191+
jlong rc = 0;
2192+
GTK4_NATIVE_ENTER(env, that, gtk_1overlay_1get_1type_FUNC);
2193+
rc = (jlong)gtk_overlay_get_type();
2194+
GTK4_NATIVE_EXIT(env, that, gtk_1overlay_1get_1type_FUNC);
2195+
return rc;
2196+
}
2197+
#endif
2198+
2199+
#ifndef NO_gtk_1overlay_1new
2200+
JNIEXPORT jlong JNICALL GTK4_NATIVE(gtk_1overlay_1new)
2201+
(JNIEnv *env, jclass that)
2202+
{
2203+
jlong rc = 0;
2204+
GTK4_NATIVE_ENTER(env, that, gtk_1overlay_1new_FUNC);
2205+
rc = (jlong)gtk_overlay_new();
2206+
GTK4_NATIVE_EXIT(env, that, gtk_1overlay_1new_FUNC);
2207+
return rc;
2208+
}
2209+
#endif
2210+
2211+
#ifndef NO_gtk_1overlay_1remove_1overlay
2212+
JNIEXPORT void JNICALL GTK4_NATIVE(gtk_1overlay_1remove_1overlay)
2213+
(JNIEnv *env, jclass that, jlong arg0, jlong arg1)
2214+
{
2215+
GTK4_NATIVE_ENTER(env, that, gtk_1overlay_1remove_1overlay_FUNC);
2216+
gtk_overlay_remove_overlay((GtkOverlay *)arg0, (GtkWidget *)arg1);
2217+
GTK4_NATIVE_EXIT(env, that, gtk_1overlay_1remove_1overlay_FUNC);
2218+
}
2219+
#endif
2220+
2221+
#ifndef NO_gtk_1overlay_1set_1child
2222+
JNIEXPORT void JNICALL GTK4_NATIVE(gtk_1overlay_1set_1child)
2223+
(JNIEnv *env, jclass that, jlong arg0, jlong arg1)
2224+
{
2225+
GTK4_NATIVE_ENTER(env, that, gtk_1overlay_1set_1child_FUNC);
2226+
gtk_overlay_set_child((GtkOverlay *)arg0, (GtkWidget *)arg1);
2227+
GTK4_NATIVE_EXIT(env, that, gtk_1overlay_1set_1child_FUNC);
2228+
}
2229+
#endif
2230+
2231+
#ifndef NO_gtk_1overlay_1set_1clip_1overlay
2232+
JNIEXPORT void JNICALL GTK4_NATIVE(gtk_1overlay_1set_1clip_1overlay)
2233+
(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jboolean arg2)
2234+
{
2235+
GTK4_NATIVE_ENTER(env, that, gtk_1overlay_1set_1clip_1overlay_FUNC);
2236+
gtk_overlay_set_clip_overlay((GtkOverlay *)arg0, (GtkWidget *)arg1, (gboolean)arg2);
2237+
GTK4_NATIVE_EXIT(env, that, gtk_1overlay_1set_1clip_1overlay_FUNC);
2238+
}
2239+
#endif
2240+
2241+
#ifndef NO_gtk_1overlay_1set_1measure_1overlay
2242+
JNIEXPORT void JNICALL GTK4_NATIVE(gtk_1overlay_1set_1measure_1overlay)
2243+
(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jboolean arg2)
2244+
{
2245+
GTK4_NATIVE_ENTER(env, that, gtk_1overlay_1set_1measure_1overlay_FUNC);
2246+
gtk_overlay_set_measure_overlay((GtkOverlay *)arg0, (GtkWidget *)arg1, (gboolean)arg2);
2247+
GTK4_NATIVE_EXIT(env, that, gtk_1overlay_1set_1measure_1overlay_FUNC);
2248+
}
2249+
#endif
2250+
20752251
#ifndef NO_gtk_1picture_1new
20762252
JNIEXPORT jlong JNICALL GTK4_NATIVE(gtk_1picture_1new)
20772253
(JNIEnv *env, jclass that)

bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4_stats.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,12 @@ typedef enum {
101101
gtk_1drag_1source_1new_FUNC,
102102
gtk_1drag_1source_1set_1actions_FUNC,
103103
gtk_1drag_1source_1set_1icon_FUNC,
104+
gtk_1drawing_1area_1get_1content_1height_FUNC,
105+
gtk_1drawing_1area_1get_1content_1width_FUNC,
106+
gtk_1drawing_1area_1new_FUNC,
107+
gtk_1drawing_1area_1set_1content_1height_FUNC,
108+
gtk_1drawing_1area_1set_1content_1width_FUNC,
109+
gtk_1drawing_1area_1set_1draw_1func_FUNC,
104110
gtk_1drop_1target_1async_1new_FUNC,
105111
gtk_1drop_1target_1async_1set_1formats_FUNC,
106112
gtk_1editable_1get_1delegate_FUNC,
@@ -169,6 +175,16 @@ typedef enum {
169175
gtk_1named_1action_1new_FUNC,
170176
gtk_1native_1get_1for_1surface_FUNC,
171177
gtk_1native_1get_1surface_FUNC,
178+
gtk_1overlay_1add_1overlay_FUNC,
179+
gtk_1overlay_1get_1child_FUNC,
180+
gtk_1overlay_1get_1clip_1overlay_FUNC,
181+
gtk_1overlay_1get_1measure_1overlay_FUNC,
182+
gtk_1overlay_1get_1type_FUNC,
183+
gtk_1overlay_1new_FUNC,
184+
gtk_1overlay_1remove_1overlay_FUNC,
185+
gtk_1overlay_1set_1child_FUNC,
186+
gtk_1overlay_1set_1clip_1overlay_FUNC,
187+
gtk_1overlay_1set_1measure_1overlay_FUNC,
172188
gtk_1picture_1new_FUNC,
173189
gtk_1picture_1set_1can_1shrink_FUNC,
174190
gtk_1picture_1set_1paintable_FUNC,

bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk4/GTK4.java

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,4 +1064,78 @@ public class GTK4 {
10641064
*/
10651065
public static final native long gtk_gesture_get_last_updated_sequence(long gesture);
10661066

1067+
/**
1068+
*/
1069+
public static final native long gtk_drawing_area_new();
1070+
/**
1071+
*
1072+
* @param self cast=(GtkDrawingArea *)
1073+
* @param draw_func cast=(GtkDrawingAreaDrawFunc)
1074+
* @param user_data cast=(gpointer)
1075+
* @param destroy cast=(GDestroyNotify)
1076+
*/
1077+
public static final native void gtk_drawing_area_set_draw_func(long self, long draw_func, long user_data, long destroy);
1078+
/**
1079+
* @param self cast=(GtkDrawingArea *)
1080+
*/
1081+
public static final native int gtk_drawing_area_get_content_height (long self);
1082+
/**
1083+
* @param self cast=(GtkDrawingArea *)
1084+
*/
1085+
public static final native int gtk_drawing_area_get_content_width (long self);
1086+
/**
1087+
* @param self cast=(GtkDrawingArea *)
1088+
* @param height cast=(int)
1089+
*/
1090+
public static final native void gtk_drawing_area_set_content_height (long self, int height);
1091+
/**
1092+
* @param self cast=(GtkDrawingArea *)
1093+
* @param width cast=(int)
1094+
*/
1095+
public static final native void gtk_drawing_area_set_content_width (long self, int width);
1096+
1097+
public static final native long gtk_overlay_get_type();
1098+
public static final native long gtk_overlay_new();
1099+
1100+
/**
1101+
* @param overlay cast=(GtkOverlay *)
1102+
* @param widget cast=(GtkWidget *)
1103+
*/
1104+
public static final native void gtk_overlay_add_overlay (long overlay, long widget);
1105+
/**
1106+
* @param overlay cast=(GtkOverlay *)
1107+
* @param widget cast=(GtkWidget *)
1108+
*/
1109+
public static final native void gtk_overlay_remove_overlay (long overlay, long widget);
1110+
/**
1111+
* @param overlay cast=(GtkOverlay *)
1112+
* @param widget cast=(GtkWidget *)
1113+
*/
1114+
public static final native void gtk_overlay_set_child (long overlay, long widget);
1115+
/**
1116+
* @param overlay cast=(GtkOverlay *)
1117+
*/
1118+
public static final native long gtk_overlay_get_child (long overlay);
1119+
/**
1120+
* @param overlay cast=(GtkOverlay *)
1121+
* @param widget cast=(GtkWidget *)
1122+
*/
1123+
public static final native boolean gtk_overlay_get_measure_overlay (long overlay, long widget);
1124+
/**
1125+
* @param overlay cast=(GtkOverlay *)
1126+
* @param widget cast=(GtkWidget *)
1127+
* @param measure cast=(gboolean)
1128+
*/
1129+
public static final native void gtk_overlay_set_measure_overlay (long overlay, long widget, boolean measure);
1130+
/**
1131+
* @param overlay cast=(GtkOverlay *)
1132+
* @param widget cast=(GtkWidget *)
1133+
*/
1134+
public static final native boolean gtk_overlay_get_clip_overlay (long overlay, long widget);
1135+
/**
1136+
* @param overlay cast=(GtkOverlay *)
1137+
* @param widget cast=(GtkWidget *)
1138+
* @param clip_overlay cast=(gboolean)
1139+
*/
1140+
public static final native void gtk_overlay_set_clip_overlay (long overlay, long widget, boolean clip_overlay);
10671141
}

bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Button.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@
5050
* @noextend This class is not intended to be subclassed by clients.
5151
*/
5252
public class Button extends Control {
53-
long boxHandle, labelHandle, imageHandle, arrowHandle, groupHandle;
53+
private long drawingAreaHandle;
54+
private long overlayaHandle;
55+
private long boxHandle, labelHandle, imageHandle, arrowHandle, groupHandle;
5456
boolean selected, grayed;
5557
/** True iff this toggle button requires special theme handling. See bug 546552.*/
5658
boolean toggleButtonTheming;
@@ -389,7 +391,16 @@ void createHandle (int index) {
389391
if (imageHandle == 0) error(SWT.ERROR_NO_HANDLES);
390392

391393
if (GTK.GTK4) {
392-
GTK.gtk_widget_set_parent(boxHandle, handle);
394+
drawingAreaHandle = GTK4.gtk_drawing_area_new();
395+
GTK.gtk_widget_set_hexpand(drawingAreaHandle, true);
396+
GTK.gtk_widget_set_vexpand(drawingAreaHandle, true);
397+
GTK4.gtk_drawing_area_set_draw_func(drawingAreaHandle, display.gtk4DrawProc, handle, 0);
398+
399+
overlayaHandle = GTK4.gtk_overlay_new();
400+
GTK4.gtk_overlay_add_overlay(overlayaHandle, drawingAreaHandle);
401+
402+
GTK.gtk_widget_set_parent(overlayaHandle, handle);
403+
GTK4.gtk_overlay_set_child(overlayaHandle, boxHandle);
393404
GTK4.gtk_box_append(boxHandle, imageHandle);
394405
GTK4.gtk_box_append(boxHandle, labelHandle);
395406
} else {
@@ -454,6 +465,8 @@ void checkBackground() {
454465
@Override
455466
void deregister () {
456467
super.deregister ();
468+
if (drawingAreaHandle != 0) display.removeWidget (drawingAreaHandle);
469+
if (overlayaHandle != 0) display.removeWidget (overlayaHandle);
457470
if (boxHandle != 0) display.removeWidget (boxHandle);
458471
if (labelHandle != 0) display.removeWidget (labelHandle);
459472
if (imageHandle != 0) display.removeWidget (imageHandle);
@@ -720,6 +733,8 @@ boolean mnemonicMatch (char key) {
720733
@Override
721734
void register () {
722735
super.register ();
736+
if (drawingAreaHandle != 0) display.addWidget (drawingAreaHandle, this);
737+
if (overlayaHandle != 0) display.addWidget (overlayaHandle, this);
723738
if (boxHandle != 0) display.addWidget (boxHandle, this);
724739
if (labelHandle != 0) display.addWidget (labelHandle, this);
725740
if (imageHandle != 0) display.addWidget (imageHandle, this);
@@ -729,6 +744,7 @@ void register () {
729744
@Override
730745
void releaseHandle () {
731746
super.releaseHandle ();
747+
overlayaHandle = drawingAreaHandle = 0;
732748
boxHandle = imageHandle = labelHandle = arrowHandle = 0;
733749
}
734750

@@ -737,7 +753,9 @@ void releaseWidget() {
737753
super.releaseWidget();
738754

739755
if (GTK.GTK4) {
740-
if (boxHandle != 0) GTK.gtk_widget_unparent(boxHandle);
756+
// TODO review this with the new overlay work
757+
if (overlayaHandle != 0) GTK.gtk_widget_unparent(overlayaHandle);
758+
// if (boxHandle != 0) GTK.gtk_widget_unparent(boxHandle);
741759
}
742760

743761
// Release reference to hidden GtkCheckButton that allows for SWT.RADIO behavior
@@ -1290,6 +1308,7 @@ public void setText (String string) {
12901308
}
12911309

12921310
private void updateWidgetsVisibility() {
1311+
// TODO what do I need to do on show widget for overlay/drawing area
12931312
if (text.length() == 0 && image == null) {
12941313
gtk_widget_hide (boxHandle);
12951314
gtk_widget_hide (labelHandle);
@@ -1310,6 +1329,7 @@ private void updateWidgetsVisibility() {
13101329
@Override
13111330
void showWidget () {
13121331
super.showWidget ();
1332+
// TODO what do I need to do on show widget for overlay/drawing area
13131333
if (boxHandle != 0 && ((text != null && text.length() != 0) || image != null)) gtk_widget_show (boxHandle);
13141334
if (labelHandle != 0 && text != null && text.length() != 0) gtk_widget_show (labelHandle);
13151335
if (arrowHandle != 0) gtk_widget_show (arrowHandle);

bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Canvas.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,11 @@ long gtk_draw (long widget, long cairo) {
176176
}
177177

178178
@Override
179-
void gtk4_draw (long widget, long cairo, Rectangle bounds) {
180-
if ((state & OBSCURED) != 0) return;
181-
super.gtk4_draw (widget, cairo, bounds);
182-
drawCaretInFocus(widget, cairo);
179+
void gtk4_draw (long cairo, int width, int height) {
180+
// TODO
181+
// if ((state & OBSCURED) != 0) return;
182+
// super.gtk4_draw (widget, cairo, bounds);
183+
// drawCaretInFocus(widget, cairo);
183184
}
184185

185186
void drawCaretInFocus(long widget, long cairo) {

0 commit comments

Comments
 (0)