Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXi Yan2018-07-26 12:49:25 -0400
committerAlexander Kurtakov2018-08-04 06:47:06 -0400
commit35c14d6152ad0f9431f998d2f1b3849f4eb258bb (patch)
treeb22b5b44fc0562e64f3f20780352df1cca1880e0
parent9d77cdae8ede54cd29d86993fdb4c85b4d7229aa (diff)
downloadeclipse.platform.swt-35c14d6152ad0f9431f998d2f1b3849f4eb258bb.tar.gz
eclipse.platform.swt-35c14d6152ad0f9431f998d2f1b3849f4eb258bb.tar.xz
eclipse.platform.swt-35c14d6152ad0f9431f998d2f1b3849f4eb258bb.zip
Bug 530577 - [Wayland] Popup menus sometimes emit GDK warnings
1) On Wayland, clicking Show In button in Open Resource dialog causes menu.setVisible to be called twice, once due to MouseDown and once due to ButtonClicked. This causes two duplicate menus (with different handles) to popup at the same time. The second one does not have a top-most parent which emits a GDK warning, and the menu cannot be closed. The same issue also happens on both X11 and Wayland with toggle buttons. See bug 528998. The fix is to avoid adding two identical popup menus in the queue. 2) Implemented Menu#setLocation() on Wayland by passing the window of the relative parent shell of menu to gtk_menu_popup_at_rect to position the menu. Used hasLocation flag for Wayland (see Bug 530204). Tested on Wayland and X11 with GTK3.22. Clicking "Show In" button in Open Resource Dialog, and the "Run As..." triangle now opens popup menu under the button rather than by the mouse. Right click on perspective button and clicking anywhere now able to close the context menu, whereas before requires two clicks. Change-Id: I89110e5d095ca896fa0b0d775e617889ea75912d Signed-off-by: Xi Yan <xixiyan@redhat.com>
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java6
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Menu.java58
2 files changed, 35 insertions, 29 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java
index 66cddf2c72..68b5de99d6 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java
@@ -770,6 +770,12 @@ void addPopup (Menu menu) {
int length = popups.length;
for (int i=0; i<length; i++) {
if (popups [i] == menu) return;
+ /* Bug 530577, 528998: Clicking on button that triggers popup menus causes
+ * menu.setVisible to be called twice, once due to MouseDown, and once due to ButtonClicked.
+ * This causes two duplicate menus (with different handles) to popup at the same time.
+ * The fix is to avoid having two identical popup menus in the queue.
+ */
+ if (popups[i] != null && popups[i].getNameText().equals(menu.getNameText())) return;
}
int index = 0;
while (index < length) {
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 5105b51ada..46f3894b46 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
@@ -40,10 +40,6 @@ import org.eclipse.swt.internal.gtk.*;
*/
public class Menu extends Widget {
int x, y;
- /**
- * Only set to true on X11, as Wayland has no global
- * coordinates. See bug 530204.
- */
boolean hasLocation;
MenuItem cascade, selectedItem;
Decorations parent;
@@ -234,8 +230,7 @@ void _setVisible (boolean visible) {
* event processed is used.
*/
GTK.gtk_menu_popup (handle, 0, 0, address, data, 0, display.getLastEventTime ());
- }
- else {
+ } else {
long /*int*/ eventPtr = 0;
if (hasLocation) {
// Create the GdkEvent manually as we need to control
@@ -243,27 +238,35 @@ void _setVisible (boolean visible) {
eventPtr = GDK.gdk_event_new(GDK.GDK_BUTTON_PRESS);
GdkEventButton event = new GdkEventButton ();
event.type = GDK.GDK_BUTTON_PRESS;
- event.device = GDK.gdk_get_pointer(GDK.gdk_display_get_default ());
- // Get and (add reference to) the global GdkWindow
- event.window = GDK.gdk_display_get_default_group(GDK.gdk_display_get_default());
- OS.g_object_ref(event.window);
- /*
- * Get the origin of the global GdkWindow to calculate the size of any offsets
- * such as client side decorations, or the system tray.
- */
- int [] globalWindowOriginY = new int [1];
- int [] globalWindowOriginX = new int [1];
- GDK.gdk_window_get_origin (event.window, globalWindowOriginX, globalWindowOriginY);
- // Set the time and save the event in memory
- event.time = display.getLastEventTime ();
- OS.memmove (eventPtr, event, GdkEventButton.sizeof);
+ event.device = GDK.gdk_get_pointer(GDK.gdk_display_get_default());
+ event.time = display.getLastEventTime();
// Create the rectangle relative to the parent (in this case, global) GdkWindow
GdkRectangle rect = new GdkRectangle();
- rect.x = this.x - globalWindowOriginX[0];
- rect.y = this.y - globalWindowOriginY[0];
-
- // Popup the menu and pin it at the top left corner of the GdkRectangle relative to the global GdkWindow
+ if (OS.isX11()) {
+ // Get and (add reference to) the global GdkWindow
+ event.window = GDK.gdk_display_get_default_group(GDK.gdk_display_get_default());
+ OS.g_object_ref(event.window);
+ OS.memmove (eventPtr, event, GdkEventButton.sizeof);
+ /*
+ * Get the origin of the global GdkWindow to calculate the size of any offsets
+ * such as client side decorations, or the system tray.
+ */
+ int [] globalWindowOriginY = new int [1];
+ int [] globalWindowOriginX = new int [1];
+ GDK.gdk_window_get_origin (event.window, globalWindowOriginX, globalWindowOriginY);
+ rect.x = this.x - globalWindowOriginX[0];
+ rect.y = this.y - globalWindowOriginY[0];
+ } else {
+ // On Wayland, get the relative GdkWindow from the parent shell.
+ event.window = OS.g_object_ref(GTK.gtk_widget_get_window (getShell().topHandle()));
+ OS.memmove (eventPtr, event, GdkEventButton.sizeof);
+ // Bug in GTK?: testing with SWT_MENU_LOCATION_DEBUGGING=1 shows final_rect.x and
+ // final_rect.y popup menu position is off by 1 compared to this.x and this.y
+ rect.x = this.x + 1;
+ rect.y = this.y + 1;
+ }
+ // Popup the menu and pin it at the top left corner of the GdkRectangle relative to the GdkWindow
GTK.gtk_menu_popup_at_rect(handle, event.window, rect, GDK.GDK_GRAVITY_NORTH_WEST,
GDK.GDK_GRAVITY_NORTH_WEST, eventPtr);
GDK.gdk_event_free (eventPtr);
@@ -288,7 +291,7 @@ void _setVisible (boolean visible) {
}
adjustParentWindowWayland(eventPtr);
verifyMenuPosition(getItemCount());
- GTK.gtk_menu_popup_at_pointer (handle, eventPtr);
+ GTK.gtk_menu_popup_at_pointer(handle, eventPtr);
GDK.gdk_event_free (eventPtr);
}
}
@@ -1090,10 +1093,7 @@ void setLocationInPixels (int x, int y) {
if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return;
this.x = x;
this.y = y;
- // Only set the hasLocation flag on X11.
- if (OS.isX11()) {
- hasLocation = true;
- }
+ hasLocation = true;
}
/**

Back to the top