Skip to content

Fix MenuListener not fired for menubar DROP_DOWN menus on GTK4#102

Draft
Copilot wants to merge 2 commits intomasterfrom
copilot/fix-menu-listener-gtk4
Draft

Fix MenuListener not fired for menubar DROP_DOWN menus on GTK4#102
Copilot wants to merge 2 commits intomasterfrom
copilot/fix-menu-listener-gtk4

Conversation

Copy link

Copilot AI commented Mar 16, 2026

On GTK4, MenuListener.menuShown/menuHidden are never fired for SWT.DROP_DOWN menus attached to a menubar — only popup menus (SWT.POP_UP) work.

Root Cause

In GTK4, SWT.DROP_DOWN menus use a GMenuModel as their handle (not a real GTK widget), so SHOW/HIDE signals cannot be connected to them directly. The visible popover widgets are created internally by GtkPopoverMenuBar as private GtkPopoverMenuBarItem children, each owning a GtkPopoverMenu. SWT had no visibility into these internal widgets.

Changes

  • Menu.java
    • Add popoverHandle field on DROP_DOWN menus to track the GTK-internal GtkPopoverMenu
    • Connect the MAP signal to BAR menus in hookEvents() — the bar's GtkPopoverMenuBarItem children exist by the time the bar maps
    • Override gtk_map(): when the bar maps, call connectDropDownMenuSignals() to wire up signal routing for all submenus
    • connectDropDownMenuSignals(): iterates GtkPopoverMenuBarItem children in lockstep with items, finds each item's GtkPopoverMenu by type name, registers it in SWT's widget table (keyed to the DROP_DOWN Menu), and connects SHOW/HIDE signals — these route through the existing gtk_show()/gtk_hide() handlers which fire SWT.Show/SWT.Hide
    • findGtkPopoverMenuChild(): walks a GtkPopoverMenuBarItem's direct children looking for type name "GtkPopoverMenu"
    • Override deregister() on DROP_DOWN menus to remove the popover from the widget table on dispose, preventing stale signal dispatch
Menu fileMenu = new Menu(shell, SWT.DROP_DOWN);
fileItem.setMenu(fileMenu);

fileMenu.addMenuListener(new MenuListener() {
    @Override public void menuShown(MenuEvent e)  { /* now fires on GTK4 */ }
    @Override public void menuHidden(MenuEvent e) { /* now fires on GTK4 */ }
});

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • repo.eclipse.org
    • Triggering command: /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/21.0.10-7/x64/bin/java /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/21.0.10-7/x64/bin/java --enable-native-access=ALL-UNNAMED -classpath /opt/hostedtoolcache/maven/3.9.12/x64/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/opt/hostedtoolcache/maven/3.9.12/x64/bin/m2.conf -Dmaven.home=/opt/hostedtoolcache/maven/3.9.12/x64 -Dlibrary.jansi.path=/opt/hostedtoolcache/maven/3.9.12/x64/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/eclipse.platform.swt/eclipse.platform.swt org.codehaus.plexus.classworlds.launcher.Launcher compile -pl bundles/org.eclipse.swt -Dnative=gtk.linux.x86_64 -q -l as -lcairo rin-Hotspot_jdk/--norc rin-Hotspot_jdk/--noprofile b-2.0 (dns block)
    • Triggering command: /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/21.0.10-7/x64/bin/java /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/21.0.10-7/x64/bin/java --enable-native-access=ALL-UNNAMED -classpath /opt/hostedtoolcache/maven/3.9.12/x64/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/opt/hostedtoolcache/maven/3.9.12/x64/bin/m2.conf -Dmaven.home=/opt/hostedtoolcache/maven/3.9.12/x64 -Dlibrary.jansi.path=/opt/hostedtoolcache/maven/3.9.12/x64/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/eclipse.platform.swt/eclipse.platform.swt org.codehaus.plexus.classworlds.launcher.Launcher compile -pl bundles/org.eclipse.swt -Dnative=gtk.linux.x86_64 ableScrollsPastContent.java adioButtonNotRendered.java nu_setVisible.java sesHeader.java fbuzz (dns block)
    • Triggering command: /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/21.0.10-7/x64/bin/java /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/21.0.10-7/x64/bin/java --enable-native-access=ALL-UNNAMED -classpath /opt/hostedtoolcache/maven/3.9.12/x64/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/opt/hostedtoolcache/maven/3.9.12/x64/bin/m2.conf -Dmaven.home=/opt/hostedtoolcache/maven/3.9.12/x64 -Dlibrary.jansi.path=/opt/hostedtoolcache/maven/3.9.12/x64/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/eclipse.platform.swt/eclipse.platform.swt org.codehaus.plexus.classworlds.launcher.Launcher test -pl tests/org.eclipse.swt.tests -Dtest=Test_org_eclipse_swt_widgets_Menu -q origin n-Hotspot_jdk/21.0.10-7/x64/include/linux (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>MenuListener on GTK4 not called</issue_title>
<issue_description>If a menu listener is added to menu in menubar , menu listener is not called. It works for a popup menu though.
Snippet to test is:

import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.widgets.*;

public class MenuListenerTest {
    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setText("MenuListener Test");

        Menu menuBar = new Menu(shell, SWT.BAR);
        shell.setMenuBar(menuBar);

        MenuItem fileItem = new MenuItem(menuBar, SWT.CASCADE);
        fileItem.setText("File");

        Menu fileMenu = new Menu(shell, SWT.DROP_DOWN);
        fileItem.setMenu(fileMenu);

        fileMenu.addMenuListener(new MenuListener() {
            @Override
            public void menuShown(MenuEvent e) {
                System.out.println("Menu shown");
            }

            @Override
            public void menuHidden(MenuEvent e) {
                System.out.println("Menu hidden");
            }
        });

        new MenuItem(fileMenu, SWT.PUSH).setText("Item 1");

        shell.setSize(200, 150);
        shell.open();

        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) display.sleep();
        }
        display.dispose();
    }
}

```</issue_description>

## Comments on the Issue (you are @copilot in this section)

<comments>
</comments>

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

In GTK4, DROP_DOWN menus use a GMenuModel as their handle (not a GTK
widget), so SHOW/HIDE signals cannot be connected to them directly.

The fix: when the GtkPopoverMenuBar (BAR menu) maps, traverse its
GtkPopoverMenuBarItem children in order, find each child's internal
GtkPopoverMenu widget by type name, register it in the SWT widget
table associated with the corresponding SWT DROP_DOWN menu, and
connect SHOW/HIDE GTK signals to it. These route via the existing
gtk_show()/gtk_hide() handlers to fire SWT.Show/SWT.Hide events.

Cleanup: deregister() is overridden to remove the popover from the
widget table when the DROP_DOWN menu is disposed.

Co-authored-by: akurtakov <574788+akurtakov@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix MenuListener on GTK4 not being called Fix MenuListener not fired for menubar DROP_DOWN menus on GTK4 Mar 16, 2026
Copilot AI requested a review from akurtakov March 16, 2026 07:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MenuListener on GTK4 not called

2 participants