Community
Participate
Working Groups
Mouse UP event for the right mouse button is not fired if there is a MenuDetect listener with a menu added and menu is shown on right click. This works on Windows and does not work on Linux GTK3/GTK2. I've tried back to 3.8.2, same result. Seem to be always the case on GTK. In the snippet above, just do the right click to show the menu and check the printed events: import org.eclipse.swt.SWT; import org.eclipse.swt.events.MenuDetectEvent; import org.eclipse.swt.events.MenuDetectListener; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.Shell; public class NoMouseUpEvent { public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display); shell.setLayout(new FillLayout(SWT.VERTICAL)); shell.setSize(400, 200); Composite c = new Composite(shell, 0); c.setBackground(display.getSystemColor(SWT.COLOR_WHITE)); Label lbl = new Label(c, 0); lbl.setText("Right click to see the menu"); lbl.setSize(400, 200); lbl.addMouseListener(new MouseListener() { public void mouseUp(MouseEvent e) { System.out.println("Mouse Up: " + e); } public void mouseDown(MouseEvent e) { System.out.println("Mouse Down: " + e); } public void mouseDoubleClick(MouseEvent e) { System.out.println("Double click: " + e); } }); final Menu menu = new Menu(shell, SWT.POP_UP); MenuItem item = new MenuItem(menu, SWT.PUSH); item.setText("Menu Item"); lbl.addMenuDetectListener(new MenuDetectListener() { public void menuDetected(MenuDetectEvent e) { System.out.println("Menu detected: " + e); } }); lbl.addMenuDetectListener(new MenuDetectListener() { public void menuDetected(MenuDetectEvent e) { System.out.println("Menu visible: " + e); // The line below prevents mouseUp events :-( menu.setVisible(true); } }); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } display.dispose(); } }
Eric, any ideas?
Sorry, I missed this ticket somehow. I can reproduce the issue on my machine. It likely has something to do with how menus are shown in SWT. Menu.setVisible() doesn't actually show the menu right away, it adds the Menu to the Display.popups array, which gets processed at some later point (look at Display.runPopups()). My guess is that the menu processing somehow manages to eat events on the queue, and thus they are never fired. There's definitely a bug here somewhere.
Windows 10: java.lang.Exception: Mouse Down: MouseEvent{Label {Right click to see the menu} time=-1794077187 data=null button=3 stateMask=0x0 x=172 y=71 count=1} at swt.problems.Bug541850_NoMouseUpEvent$1.mouseDown(Bug541850_NoMouseUpEvent.java:35) at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:196) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89) at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4131) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1055) at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3944) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3547) at swt.problems.Bug541850_NoMouseUpEvent.main(Bug541850_NoMouseUpEvent.java:63) Menu detected: MenuDetectEvent{Label {Right click to see the menu} time=-1794077093 data=null x=270 y=217 doit=true detail=0} Menu visible: MenuDetectEvent{Label {Right click to see the menu} time=-1794077093 data=null x=270 y=217 doit=true detail=0} java.lang.Exception: Mouse Up: MouseEvent{Label {Right click to see the menu} time=-1794077093 data=null button=3 stateMask=0x200000 x=158 y=82 count=1} at swt.problems.Bug541850_NoMouseUpEvent$1.mouseUp(Bug541850_NoMouseUpEvent.java:31) at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:224) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89) at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4131) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1055) at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3944) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3547) at swt.problems.Bug541850_NoMouseUpEvent.main(Bug541850_NoMouseUpEvent.java:63) RHEL 7.4 (GTK 3.22.10): (SWT:32616): Gtk-WARNING **: Allocating size to SwtFixed 0x7ffff057e410 without calling gtk_widget_get_preferred_width/height(). How does the code know the size to allocate? Menu detected: MenuDetectEvent{Label {Right click to see the menu} time=688795212 data=null x=272 y=118 doit=true detail=0} Menu visible: MenuDetectEvent{Label {Right click to see the menu} time=688795212 data=null x=272 y=118 doit=true detail=0} java.lang.Exception: Mouse Down: MouseEvent{Label {Right click to see the menu} time=688795212 data=null button=3 stateMask=0x0 x=272 y=94 count=1} at swt.problems.Bug541850_NoMouseUpEvent$1.mouseDown(Bug541850_NoMouseUpEvent.java:35) at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:196) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89) at org.eclipse.swt.widgets.Display.sendEvent(Display.java:5769) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1401) at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:5037) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:4567) at swt.problems.Bug541850_NoMouseUpEvent.main(Bug541850_NoMouseUpEvent.java:63) Looks like a missing GTK+ event, I'll write a GTK+ snippet with a label and see what events are sent on mouse right-click.
Very basic GTK+ snippet: #include <iostream> #include <gtk/gtk.h> // g++ -g label_mouse_events.cpp `pkg-config --cflags --libs gtk+-3.0` -o LabelMouseEvents && ./LabelMouseEvents static gboolean mouse_press(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { printf("press!\n"); if (event->type == GDK_BUTTON_PRESS && event->button == 3) {//3 is right mouse btn printf("right mouse press!\n"); } if (event->type == GDK_BUTTON_PRESS && event->button == 1) {//1 is left mouse btn printf("left mouse press!\n"); } return true; } static gboolean mouse_release(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { printf("release!\n"); if (event->type == GDK_BUTTON_RELEASE && event->button == 3) {//3 is right mouse btn printf("right mouse release!\n"); } if (event->type == GDK_BUTTON_RELEASE && event->button == 1) {//1 is left mouse btn printf("left mouse release!\n"); } return true; } int main (int argc, char **argv) { GtkWidget *window, *scrolled_window, *label, *event_box; GtkTextBuffer *buffer; GtkTextIter iter; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect(window, "delete_event", gtk_main_quit, NULL); /* dirty */ gtk_window_set_default_size(GTK_WINDOW(window), 200, 200); scrolled_window = gtk_scrolled_window_new (NULL, NULL); gtk_container_add(GTK_CONTAINER(window), scrolled_window); event_box = gtk_event_box_new (); gtk_container_add (GTK_CONTAINER(scrolled_window), event_box); label = gtk_label_new ("some label"); gtk_container_add (GTK_CONTAINER (event_box), label); gtk_widget_show (label); /* And bind an action to it */ gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK); g_signal_connect(GTK_WIDGET(event_box), "button-press-event", G_CALLBACK(mouse_press), NULL); g_signal_connect(GTK_WIDGET(event_box), "button-release-event", G_CALLBACK(mouse_release), NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_widget_show_all(window); gtk_main(); return 0; } I've added some outputs to Control code: Right-click: java.lang.Exception: BUTTON PRESS EVENT at org.eclipse.swt.widgets.Control.gtk_button_press_event(Control.java:3371) at org.eclipse.swt.widgets.Control.gtk_button_press_event(Control.java:3367) at org.eclipse.swt.widgets.Widget.windowProc(Widget.java:2154) at org.eclipse.swt.widgets.Control.windowProc(Control.java:6615) at org.eclipse.swt.widgets.Label.windowProc(Label.java:729) at org.eclipse.swt.widgets.Display.windowProc(Display.java:6014) at org.eclipse.swt.internal.gtk.GTK._gtk_main_do_event(Native Method) at org.eclipse.swt.internal.gtk.GTK.gtk_main_do_event(GTK.java:4084) at org.eclipse.swt.widgets.Display.eventProc(Display.java:1402) at org.eclipse.swt.internal.gtk.OS._g_main_context_iteration(Native Method) at org.eclipse.swt.internal.gtk.OS.g_main_context_iteration(OS.java:1582) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:4565) at swt.problems.Bug541850_NoMouseUpEvent.main(Bug541850_NoMouseUpEvent.java:63) Menu detected: MenuDetectEvent{Label {Right click to see the menu} time=691776427 data=null x=1394 y=61 doit=true detail=0} Menu visible: MenuDetectEvent{Label {Right click to see the menu} time=691776427 data=null x=1394 y=61 doit=true detail=0} Mouse Down: MouseEvent{Label {Right click to see the menu} time=691776427 data=null button=3 stateMask=0x0 x=114 y=37 count=1} Left-click: java.lang.Exception: BUTTON PRESS EVENT at org.eclipse.swt.widgets.Control.gtk_button_press_event(Control.java:3371) at org.eclipse.swt.widgets.Control.gtk_button_press_event(Control.java:3367) at org.eclipse.swt.widgets.Widget.windowProc(Widget.java:2154) at org.eclipse.swt.widgets.Control.windowProc(Control.java:6615) at org.eclipse.swt.widgets.Label.windowProc(Label.java:729) at org.eclipse.swt.widgets.Display.windowProc(Display.java:6014) at org.eclipse.swt.internal.gtk.GTK._gtk_main_do_event(Native Method) at org.eclipse.swt.internal.gtk.GTK.gtk_main_do_event(GTK.java:4084) at org.eclipse.swt.widgets.Display.eventProc(Display.java:1402) at org.eclipse.swt.internal.gtk.OS._g_main_context_iteration(Native Method) at org.eclipse.swt.internal.gtk.OS.g_main_context_iteration(OS.java:1582) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:4565) at swt.problems.Bug541850_NoMouseUpEvent.main(Bug541850_NoMouseUpEvent.java:63) Mouse Down: MouseEvent{Label {Right click to see the menu} time=691778179 data=null button=1 stateMask=0x0 x=71 y=44 count=1} java.lang.Exception: BUTTON RELEASE EVENT at org.eclipse.swt.widgets.Control.gtk_button_release_event(Control.java:3470) at org.eclipse.swt.widgets.Widget.windowProc(Widget.java:2155) at org.eclipse.swt.widgets.Control.windowProc(Control.java:6615) at org.eclipse.swt.widgets.Label.windowProc(Label.java:729) at org.eclipse.swt.widgets.Display.windowProc(Display.java:6014) at org.eclipse.swt.internal.gtk.GTK._gtk_main_do_event(Native Method) at org.eclipse.swt.internal.gtk.GTK.gtk_main_do_event(GTK.java:4084) at org.eclipse.swt.widgets.Display.eventProc(Display.java:1402) at org.eclipse.swt.internal.gtk.OS._g_main_context_iteration(Native Method) at org.eclipse.swt.internal.gtk.OS.g_main_context_iteration(OS.java:1582) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:4565) at swt.problems.Bug541850_NoMouseUpEvent.main(Bug541850_NoMouseUpEvent.java:63) Mouse Up: MouseEvent{Label {Right click to see the menu} time=691778251 data=null button=1 stateMask=0x80000 x=71 y=44 count=1} Commenting all the call which shows the context menu (org.eclipse.swt.widgets.Control.showMenu(int, int)) in org.eclipse.swt.widgets.Control.gtk_event_after(long, long) results in seen release event. I'll see if I can add similar context menu handling to the GTK+ snippet... Call stack to bring up the menu: java.lang.Exception: menu becoming visible at org.eclipse.swt.widgets.Menu.setVisible(Menu.java:1303) at swt.problems.Bug541850_NoMouseUpEvent$3.menuDetected(Bug541850_NoMouseUpEvent.java:57) at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:188) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89) at org.eclipse.swt.widgets.Display.sendEvent(Display.java:5769) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1401) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1427) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1410) at org.eclipse.swt.widgets.Control.showMenu(Control.java:6085) at org.eclipse.swt.widgets.Control.showMenu(Control.java:6077) at org.eclipse.swt.widgets.Control.gtk_event_after(Control.java:3587) at org.eclipse.swt.widgets.Widget.windowProc(Widget.java:2161) at org.eclipse.swt.widgets.Control.windowProc(Control.java:6615) at org.eclipse.swt.widgets.Label.windowProc(Label.java:729) at org.eclipse.swt.widgets.Display.windowProc(Display.java:6014) at org.eclipse.swt.internal.gtk.GTK._gtk_main_do_event(Native Method) at org.eclipse.swt.internal.gtk.GTK.gtk_main_do_event(GTK.java:4084) at org.eclipse.swt.widgets.Display.eventProc(Display.java:1402) at org.eclipse.swt.internal.gtk.OS._g_main_context_iteration(Native Method) at org.eclipse.swt.internal.gtk.OS.g_main_context_iteration(OS.java:1582) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:4565) at swt.problems.Bug541850_NoMouseUpEvent.main(Bug541850_NoMouseUpEvent.java:63)
BTW, I notice the following code in org.eclipse.swt.widgets.Menu._setVisible(boolean): diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Menu.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Menu.java index 9eb7d92f94..5b2a44e0cc 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Menu.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Menu.java @@ -308,6 +308,7 @@ void _setVisible (boolean visible) { * immediately and not as a post event in display, requiring the current event. */ eventPtr = GTK.gtk_get_current_event(); + boolean wasCreated = false; if (eventPtr == 0) { eventPtr = GDK.gdk_event_new(GDK.GDK_BUTTON_PRESS); GdkEventButton event = new GdkEventButton (); @@ -319,11 +320,14 @@ void _setVisible (boolean visible) { event.device = GDK.gdk_get_pointer(GDK.gdk_display_get_default ()); event.time = display.getLastEventTime (); OS.memmove (eventPtr, event, GdkEventButton.sizeof); + wasCreated = true; } adjustParentWindowWayland(eventPtr); verifyMenuPosition(getItemCount()); GTK.gtk_menu_popup_at_pointer(handle, eventPtr); - GDK.gdk_event_free (eventPtr); + if (wasCreated) { + GDK.gdk_event_free (eventPtr); + } } } poppedUpCount = getItemCount(); Freeing the current event without any condition (see the added one in the diff above) is maybe bad? Its not the cause for the problem here though.
(In reply to Simeon Andreev from comment #5) > Freeing the current event without any condition (see the added one in the > diff above) is maybe bad? Its not the cause for the problem here though. I don't think so, gtk_get_current_event() just returns a copy so it shouldn't be an issue. All calls to gtk_get_current_event() have to free the result otherwise there will be leaks. https://developer.gnome.org/gtk3/stable/gtk3-General.html#gtk-get-current-event As for this bug, it will probably be really hard to reproduce it natively. SWT's menu system is pretty strange, see Display.runPopups().
If I make _setVisible() public (just to test) and call this directly in the mouse-down listener in the snippet from Andrey, I still see the problem (I've removed the menu detection listener, so there should be no Display pop-up logic). However if I create a menu in my GTK+ snippet and pop it up during mouse down (button pressed), there still is a mouse up (button released) event. This is somewhat confusing?
In particular the current GTK event is null in that scenario, while in my snippet it is not. Definitely clear why it could be null with the display pop-ups, but if called directly on mouse event handling? Eric would it make sense for me to try using gtk_menu_popup_for_device() instead of gtk_menu_popup_at_pointer() in the _setVisible() method? It doesn't mess with creating GDK button press events. Or it wouldn't make any difference?
(In reply to Simeon Andreev from comment #7) > If I make _setVisible() public (just to test) and call this directly in the > mouse-down listener in the snippet from Andrey, I still see the problem > (I've removed the menu detection listener, so there should be no Display > pop-up logic). > > However if I create a menu in my GTK+ snippet and pop it up during mouse > down (button pressed), there still is a mouse up (button released) event. > This is somewhat confusing? Weird. BTW you can use GtkInspector to check for events being sent, this is useful if trying to determine whether GTK is missing events or if SWT is eating them somewhere. Open GtkInspector -> Target the widget -> Select "Signals" from the dropdown menu -> then click the black dot next to the menu. It will trace signal emissions and show a count in the table -- very useful. (In reply to Simeon Andreev from comment #8) > In particular the current GTK event is null in that scenario, while in my > snippet it is not. Definitely clear why it could be null with the display > pop-ups, but if called directly on mouse event handling? > > Eric would it make sense for me to try using gtk_menu_popup_for_device() > instead of gtk_menu_popup_at_pointer() in the _setVisible() method? It > doesn't mess with creating GDK button press events. Or it wouldn't make any > difference? You can try it, but I think it will end up with the same result. Try looking with GtkInspector to see if the event is being emitted in the first place (with your SWT snippet).
When I try clicking on the dot next to the menu (its red and its hover says "trace signal emissions on this object"), the snippet from Andrey crashes with this message on standard error: Gtk:ERROR:inspector/signals-list.c:250:start_tracing_cb: assertion failed: (hook_id == 0) If I select the label specifically before starting to trace, there are a bunch of outputs on standard error warning me about non-hooked signals. I see no output when right-clicking. Am I using the tracing wrong?
(In reply to Simeon Andreev from comment #10) > When I try clicking on the dot next to the menu (its red and its hover says > "trace signal emissions on this object"), the snippet from Andrey crashes > with this message on standard error: > > Gtk:ERROR:inspector/signals-list.c:250:start_tracing_cb: assertion failed: > (hook_id == 0) > > If I select the label specifically before starting to trace, there are a > bunch of outputs on standard error warning me about non-hooked signals. I > see no output when right-clicking. > > Am I using the tracing wrong? Not sure, this is how I do it. 1) Run the SWT snippet from Andrey. 2) Press Ctrl + Shift + i to get GtkInspector open. 3) Click the target icon and select the "GtkEventBox" widget (this is handle for Labels) 4) Go to the signals menu, click the black dot. 5) Click the Label. On my machine I *do not* see button-release-events being sent for the GtkEventBox at all. If I left click I do, but not for right clicks.