Skip to content

Commit b0b9839

Browse files
committed
[Gtk4] Fix Show/Hide events of Menu in menu bar
Hook into "map" of the GtkPopoverMenu to make it register for show/hide signals.
1 parent 1450629 commit b0b9839

File tree

4 files changed

+78
-1
lines changed

4 files changed

+78
-1
lines changed

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@
2626
#pragma warning (disable: 4100)
2727
#endif
2828

29+
#ifndef NO_GTK_1IS_1POPOVER_1MENU
30+
JNIEXPORT jboolean JNICALL GTK4_NATIVE(GTK_1IS_1POPOVER_1MENU)
31+
(JNIEnv *env, jclass that, jlong arg0)
32+
{
33+
jboolean rc = 0;
34+
GTK4_NATIVE_ENTER(env, that, GTK_1IS_1POPOVER_1MENU_FUNC);
35+
rc = (jboolean)GTK_IS_POPOVER_MENU(arg0);
36+
GTK4_NATIVE_EXIT(env, that, GTK_1IS_1POPOVER_1MENU_FUNC);
37+
return rc;
38+
}
39+
#endif
40+
2941
#ifndef NO_gdk_1clipboard_1get_1content
3042
JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1clipboard_1get_1content)
3143
(JNIEnv *env, jclass that, jlong arg0)

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#endif
2121

2222
typedef enum {
23+
GTK_1IS_1POPOVER_1MENU_FUNC,
2324
gdk_1clipboard_1get_1content_FUNC,
2425
gdk_1clipboard_1get_1formats_FUNC,
2526
gdk_1clipboard_1is_1local_FUNC,

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public class GTK4 {
3030
public static final int GTK_PICK_INSENSITIVE = 1;
3131
public static final int GTK_PICK_NON_TARGETABLE = 2;
3232

33+
public static final native boolean GTK_IS_POPOVER_MENU(long obj);
34+
3335
/**
3436
* @param context cast=(GtkIMContext *)
3537
* @param event cast=(GdkEvent *)

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

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public class Menu extends Widget {
5555
long menuHandle;
5656

5757
/** GTK4 only fields */
58-
long modelHandle, actionGroup, shortcutController;
58+
long modelHandle, popoverHandle, actionGroup, shortcutController;
5959

6060
class Section {
6161
LinkedList<MenuItem> sectionItems;
@@ -822,6 +822,50 @@ public boolean getVisible () {
822822
return GTK.gtk_widget_get_mapped (handle);
823823
}
824824

825+
@Override
826+
long gtk_map (long widget) {
827+
if (GTK.GTK4 && (style & SWT.BAR) != 0) {
828+
/*
829+
* The GtkPopoverMenuBar has been mapped, which means its internal
830+
* GtkPopoverMenuBarItem children now exist. Find the GtkPopoverMenu child for each,
831+
* and connect SHOW/HIDE signals so that SWT MenuListeners on DROP_DOWN are notified.
832+
*/
833+
connectDropDownMenuSignals();
834+
}
835+
return super.gtk_map(widget);
836+
}
837+
838+
private void connectDropDownMenuSignals() {
839+
if (items == null) return;
840+
long barItem = GTK4.gtk_widget_get_first_child(handle);
841+
842+
for (MenuItem menuItem : items) {
843+
if (barItem == 0) break;
844+
if ((menuItem.style & SWT.SEPARATOR) != 0) continue;
845+
if (menuItem.menu != null && menuItem.menu.popoverHandle == 0) {
846+
long popover = findGtkPopoverMenuChild(barItem);
847+
if (popover != 0) {
848+
menuItem.menu.popoverHandle = popover;
849+
display.addWidget(popover, menuItem.menu);
850+
OS.g_signal_connect_closure_by_id(popover, display.signalIds[SHOW], 0, display.getClosure(SHOW), false);
851+
OS.g_signal_connect_closure_by_id(popover, display.signalIds[HIDE], 0, display.getClosure(HIDE), false);
852+
}
853+
}
854+
barItem = GTK4.gtk_widget_get_next_sibling(barItem);
855+
}
856+
}
857+
858+
private long findGtkPopoverMenuChild(long barItem) {
859+
long child = GTK4.gtk_widget_get_first_child(barItem);
860+
while (child != 0) {
861+
if (GTK4.GTK_IS_POPOVER_MENU(child)) {
862+
return child;
863+
}
864+
child = GTK4.gtk_widget_get_next_sibling(child);
865+
}
866+
return 0;
867+
}
868+
825869
@Override
826870
long gtk_hide (long widget) {
827871
if ((style & SWT.POP_UP) != 0) {
@@ -911,6 +955,15 @@ void hookEvents() {
911955
if ((style & SWT.DROP_DOWN) == 0) {
912956
OS.g_signal_connect_closure_by_id(handle, display.signalIds[SHOW], 0, display.getClosure(SHOW), false);
913957
OS.g_signal_connect_closure_by_id(handle, display.signalIds[HIDE], 0, display.getClosure(HIDE), false);
958+
if ((style & SWT.BAR) != 0) {
959+
/*
960+
* Connect MAP signal on the GtkPopoverMenuBar so that once it is
961+
* realized and its internal GtkPopoverMenuBarItem children exist,
962+
* we can find the GtkPopoverMenu for each DROP_DOWN submenu and
963+
* route SHOW/HIDE signals back to the SWT DROP_DOWN Menu.
964+
*/
965+
OS.g_signal_connect_closure_by_id(handle, display.signalIds[MAP], 0, display.getClosure(MAP), false);
966+
}
914967
}
915968

916969
} else {
@@ -1044,6 +1097,15 @@ void destroyWidget () {
10441097
}
10451098
}
10461099

1100+
@Override
1101+
void deregister() {
1102+
super.deregister();
1103+
if (GTK.GTK4 && (style & SWT.DROP_DOWN) != 0 && popoverHandle != 0) {
1104+
display.removeWidget(popoverHandle);
1105+
popoverHandle = 0;
1106+
}
1107+
}
1108+
10471109
/**
10481110
* Removes the listener from the collection of listeners who will
10491111
* be notified when the menu events are generated for the control.

0 commit comments

Comments
 (0)