From 4b13e80e22c817e26f162b9d6513d78ea64c585d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=8A?= =?UTF-8?q?=D1=80=20=D0=9A=D1=83=D1=80=D1=82=D0=B0=D0=BA=D0=BE=D0=B2?= Date: Wed, 7 Oct 2026 17:42:01 +0300 Subject: [PATCH] [GTK4] Expand and collapse Tree rows with Left and Right The Left and Right bindings added to the GtkTreeView class came after GtkTreeView's own move-cursor bindings, which handle the keys first, so they never ran. Handle the keys in the key press handler instead, as on GTK3: expand or collapse the cursor row when it has children, otherwise let GtkTreeView move the cursor. Assisted-by: Anthropic Claude Code (claude-opus-5-5[1m]) --- .../gtk/org/eclipse/swt/widgets/Tree.java | 65 ++++++++++--------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java index 82c1019f0f0..75647ac9f65 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java @@ -881,7 +881,6 @@ void createHandle (int index) { } if (GTK.GTK4) { - bindArrowKeyBindings(); /* * GTK renders the drop highlight requested through * gtk_tree_view_set_drag_dest_row() from the private TreeViewDragInfo struct, @@ -899,34 +898,6 @@ void createHandle (int index) { } } -/** - * Binds the left and right arrow keys to - * allow for expanding and collapsing of the - * tree nodes. - * - * Note: This function is to only be called in GTK4. - * Binding of the arrow keys are also done in GTK3, - * however it is done through GtkBindingSets in CSS. - * See Device.init() for more information, specifically, - * swt_functional_gtk_3_20.css - */ -void bindArrowKeyBindings() { - if (!GTK.GTK4) return; - - int[] keyval = new int[1]; - GTK.gtk_accelerator_parse(Converter.javaStringToCString("Left"), keyval, null); - GTK4.gtk_widget_class_add_binding_signal(GTK.GTK_WIDGET_GET_CLASS(handle), keyval[0], 0, - Converter.javaStringToCString("expand-collapse-cursor-row"), - Converter.javaStringToCString("(bbb)"), - false, false, false); - - GTK.gtk_accelerator_parse(Converter.javaStringToCString("Right"), keyval, null); - GTK4.gtk_widget_class_add_binding_signal(GTK.GTK_WIDGET_GET_CLASS(handle), keyval[0], 0, - Converter.javaStringToCString("expand-collapse-cursor-row"), - Converter.javaStringToCString("(bbb)"), - false, true, false); -} - @Override int applyThemeBackground () { return -1; /* No Change */ @@ -2347,7 +2318,41 @@ boolean gtk4_key_press_event (long controller, int keyval, int keycode, int stat } break; } - return super.gtk4_key_press_event(controller, keyval, keycode, state, event); + boolean handled = super.gtk4_key_press_event(controller, keyval, keycode, state, event); + if (handled || isDisposed ()) return handled; + switch (keyval) { + case GDK.GDK_Left: + case GDK.GDK_Right: + /* + * GtkTreeView moves between cells for Left and Right. Expand and collapse the + * cursor row instead when it has children, as on GTK3. Leave the keys of the + * search entry alone. + */ + if ((state & (GDK.GDK_SHIFT_MASK | GDK.GDK_CONTROL_MASK | GDK.GDK_MOD1_MASK | GDK.GDK_SUPER_MASK | GDK.GDK_META_MASK | GDK.GDK_HYPER_MASK)) == 0 && GTK.gtk_widget_has_focus (handle)) { + boolean expand = (keyval == GDK.GDK_Right) != ((style & SWT.RIGHT_TO_LEFT) != 0); + return expandCollapseCursorRow (expand); + } + break; + } + return false; +} + +boolean expandCollapseCursorRow (boolean expand) { + long [] path = new long [1]; + GTK.gtk_tree_view_get_cursor (handle, path, null); + if (path [0] == 0) return false; + long iter = OS.g_malloc (GTK.GtkTreeIter_sizeof ()); + boolean parent = GTK.gtk_tree_model_get_iter (modelHandle, iter, path [0]) && GTK.gtk_tree_model_iter_n_children (modelHandle, iter) > 0; + OS.g_free (iter); + if (parent) { + if (expand) { + GTK.gtk_tree_view_expand_row (handle, path [0], false); + } else { + GTK.gtk_tree_view_collapse_row (handle, path [0]); + } + } + GTK.gtk_tree_path_free (path [0]); + return parent; } @Override