From 8f1f5bec9a694d02da876bf3d915c05d91ff7fb9 Mon Sep 17 00:00:00 2001 From: Patrick Ziegler Date: Thu, 30 Jan 2025 18:56:21 +0100 Subject: [PATCH] [GTK4] Implement correct moveAbove()/moveBelow() control behavior Regardless of which control are given as input parameters, the controls are currently always added as last child to their parents. Underlying issue seems to be that the swt_fixed_restack() method does not handle the GTK4 widgets correctly. As a solution, perform the movement using the proper API. To understand the combination in which GTK methods need to be called, consider the expected behavior based on the GTK and SWT documentation: [GTK4 Documentation] - gtk_widget_insert_after(widget, parent, previous_sibling) It will be placed after previous_sibling, or at the beginning if previous_sibling is NULL. - gtk_widget_insert_before(widget, parent, next_sibling) It will be placed before next_sibling, or at the end if next_sibling is NULL. [SWT Documentation] - moveAbove(control) Moves the receiver above the specified control in the drawing order. If the argument is null, then the receiver is moved to the top of the drawing order This means that if the specified control is NULL, gtk_widget_insert_after(...) needs to be called, otherwise gtk_widget_insert_before(...). - moveBelow(control) Moves the receiver below the specified control in the drawing order. If the argument is null, then the receiver is moved to the bottom of the drawing order. Here the inverse applies. If the specified control is NULL, gtk_widget_insert_before(...) needs to be called, otherwise gtk_widget_insert_after(...). --- .../Eclipse SWT PI/gtk/library/gtk4.c | 20 +++++++++++++++++++ .../Eclipse SWT PI/gtk/library/gtk4_stats.h | 2 ++ .../org/eclipse/swt/internal/gtk4/GTK4.java | 12 +++++++++++ .../org/eclipse/swt/widgets/Composite.java | 20 +++++++++++++++++-- 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4.c index 4ee62a17eff..73fd53a0254 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4.c +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4.c @@ -2083,6 +2083,26 @@ JNIEXPORT jlong JNICALL GTK4_NATIVE(gtk_1widget_1get_1root) } #endif +#ifndef NO_gtk_1widget_1insert_1after +JNIEXPORT void JNICALL GTK4_NATIVE(gtk_1widget_1insert_1after) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2) +{ + GTK4_NATIVE_ENTER(env, that, gtk_1widget_1insert_1after_FUNC); + gtk_widget_insert_after((GtkWidget *)arg0, (GtkWidget *)arg1, (GtkWidget *)arg2); + GTK4_NATIVE_EXIT(env, that, gtk_1widget_1insert_1after_FUNC); +} +#endif + +#ifndef NO_gtk_1widget_1insert_1before +JNIEXPORT void JNICALL GTK4_NATIVE(gtk_1widget_1insert_1before) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2) +{ + GTK4_NATIVE_ENTER(env, that, gtk_1widget_1insert_1before_FUNC); + gtk_widget_insert_before((GtkWidget *)arg0, (GtkWidget *)arg1, (GtkWidget *)arg2); + GTK4_NATIVE_EXIT(env, that, gtk_1widget_1insert_1before_FUNC); +} +#endif + #ifndef NO_gtk_1widget_1measure JNIEXPORT void JNICALL GTK4_NATIVE(gtk_1widget_1measure) (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jintArray arg3, jintArray arg4, jintArray arg5, jintArray arg6) diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4_stats.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4_stats.h index 328ec74e362..b3a97eb2827 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4_stats.h +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4_stats.h @@ -173,6 +173,8 @@ typedef enum { gtk_1widget_1get_1prev_1sibling_FUNC, gtk_1widget_1get_1receives_1default_FUNC, gtk_1widget_1get_1root_FUNC, + gtk_1widget_1insert_1after_FUNC, + gtk_1widget_1insert_1before_FUNC, gtk_1widget_1measure_FUNC, gtk_1widget_1set_1cursor_FUNC, gtk_1widget_1set_1focusable_FUNC, diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk4/GTK4.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk4/GTK4.java index 1a7f3083a24..13168e7ebe9 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk4/GTK4.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk4/GTK4.java @@ -649,6 +649,18 @@ public class GTK4 { * @param allocation cast=(GtkAllocation *),flags=no_out */ public static final native void gtk_widget_size_allocate(long widget, GtkAllocation allocation, int baseline); + /** + * @param widget cast=(GtkWidget *) + * @param parent cast=(GtkWidget *) + * @param previous_sibling cast=(GtkWidget *) + */ + public static final native void gtk_widget_insert_after(long widget, long parent, long previous_sibling); + /** + * @param widget cast=(GtkWidget *) + * @param parent cast=(GtkWidget *) + * @param next_sibling cast=(GtkWidget *) + */ + public static final native void gtk_widget_insert_before(long widget, long parent, long next_sibling); /* GtkComboBox */ /** @param combo_box cast=(GtkComboBox *) */ diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java index adae7906a9f..4beb8488ff0 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java @@ -1353,7 +1353,15 @@ void markLayout (boolean changed, boolean all) { void moveAbove (long child, long sibling) { if (child == sibling) return; long parentHandle = parentingHandle (); - OS.swt_fixed_restack (parentHandle, child, sibling, true); + if (GTK.GTK4) { + if (sibling == 0) { + GTK4.gtk_widget_insert_after(child, parentHandle, 0L); + } else { + GTK4.gtk_widget_insert_before(child, parentHandle, sibling); + } + } else { + OS.swt_fixed_restack (parentHandle, child, sibling, true); + } return; } @@ -1364,7 +1372,15 @@ void moveBelow (long child, long sibling) { moveAbove (child, scrolledHandle != 0 ? scrolledHandle : handle); return; } - OS.swt_fixed_restack (parentHandle, child, sibling, false); + if (GTK.GTK4) { + if (sibling == 0) { + GTK4.gtk_widget_insert_before(child, parentHandle, 0L); + } else { + GTK4.gtk_widget_insert_after(child, parentHandle, sibling); + } + } else { + OS.swt_fixed_restack (parentHandle, child, sibling, false); + } return; }