diff options
author | Xi Yan | 2018-11-15 19:48:38 +0000 |
---|---|---|
committer | Xi Yan | 2018-11-26 14:38:52 +0000 |
commit | 4f1dc4d293b947f57c46577c047c26655532a383 (patch) | |
tree | ef278b2a1ae70419b53bab1ec02de40cfc6c341e | |
parent | 6a1ac083ec74438453fbf8f14fcbaee4db59be2f (diff) | |
download | eclipse.platform.swt-4f1dc4d293b947f57c46577c047c26655532a383.tar.gz eclipse.platform.swt-4f1dc4d293b947f57c46577c047c26655532a383.tar.xz eclipse.platform.swt-4f1dc4d293b947f57c46577c047c26655532a383.zip |
Bug 541185 - [Wayland] Help popup close after a click
1) Wayland sends an extra focus out event when clicking into the popup
after grabbing keyboard focus, which causes popup to be closed.
Workaround is to ignore this extra focus out event to fix the issue with
javadoc close after a click.
2) Current workaround that hides shell before grabbing focus is not
necessary for normal popups without a child. Deal with the case a popup
has a popup child separately in bringToTop().
This patch fixes the issue with clicking into Javadoc links, and
highlighting text in Javadoc popups. However, there is still some
remaining issues (perhaps unrelated) with auto-completion: use Tab to
switch focus to the completion details page, clicking works but
highlighting the text closes the popup. (but this issue doesn't happen
if we use mouse to switch focus to completion details page)
Change-Id: Ic095b64c2eaafdeeca65b6e61937c7d31256c97f
Signed-off-by: Xi Yan <xixiyan@redhat.com>
-rw-r--r-- | bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java | 2 | ||||
-rw-r--r-- | bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java | 35 |
2 files changed, 26 insertions, 11 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java index 8b2f346c76..a71af47b72 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java @@ -89,6 +89,8 @@ public class Composite extends Scrollable { static final String NO_INPUT_METHOD = "org.eclipse.swt.internal.gtk.noInputMethod"; //$NON-NLS-1$ + boolean hasPopupChild; // Wayland only, see Shell#bringToTop() + Composite () { /* Do nothing */ } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java index b239ee4c6a..7b82b91916 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java @@ -129,6 +129,7 @@ public class Shell extends Decorations { Control lastActive; ToolTip [] toolTips; boolean ignoreFocusOut, ignoreFocusIn; + boolean ignoreFocusOutAfterGrab; Region originalRegion; static final int MAXIMUM_TRIM = 128; @@ -594,19 +595,30 @@ void bringToTop (boolean force) { } else { if (GTK.GTK_VERSION >= OS.VERSION(3, 20, 0)) { GTK.gtk_grab_add(shellHandle); + long /*int*/ seat = GDK.gdk_display_get_default_seat(GDK.gdk_window_get_display(window)); /* - * On Wayland, calling gdk_seat_grab on visible window causes caret to get stuck in Eclipse - * after closing Javadoc/completion popup. Workaround is to hide the immediate popup mapped - * to a top level window before grabbing, and show it using gdkSeatGrabPrepareFunc callback. + * NOTE: Using gdk_seat_grab to get the keyboard focus needs to be handled differently + * for cases with a single popup, and for cases with multiple popup + * 1) For normal popups without a child popup (i.e. F2 Javadoc), showing GdkWindow and + * grabbing focus does the job + * 2) For popups with a child popup attached to it (i.e. auto-completion), using (1) + * makes pressing Tab close the popup instead of changing focus. + * Current best workaround is to hide the immediate popup mapped to a top level window + * before grabbing, and show it using gdkSeatGrabPrepareFunc callback. */ - if (gdkSeatGrabCallback == null) { - gdkSeatGrabCallback = new Callback(Shell.class, "GdkSeatGrabPrepareFunc", 3); //$NON-NLS-1$ + if (!hasPopupChild) { + GDK.gdk_window_show(window); + GDK.gdk_seat_grab(seat, window, GDK.GDK_SEAT_CAPABILITY_KEYBOARD, true, 0, 0, 0, 0); + } else { + if (gdkSeatGrabCallback == null) { + gdkSeatGrabCallback = new Callback(Shell.class, "GdkSeatGrabPrepareFunc", 3); //$NON-NLS-1$ + } + long /*int*/ gdkSeatGrabPrepareFunc = gdkSeatGrabCallback.getAddress(); + if (gdkSeatGrabPrepareFunc == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS); + if (GTK.gtk_widget_get_visible(shellHandle) && !isMappedToPopup()) GTK.gtk_widget_hide(shellHandle); + GDK.gdk_seat_grab(seat, window, GDK.GDK_SEAT_CAPABILITY_KEYBOARD, true, 0, 0, gdkSeatGrabPrepareFunc, shellHandle); } - long /*int*/ gdkSeatGrabPrepareFunc = gdkSeatGrabCallback.getAddress(); - if (gdkSeatGrabPrepareFunc == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS); - long /*int*/ seat = GDK.gdk_display_get_default_seat(GDK.gdk_window_get_display(window)); - if (GTK.gtk_widget_get_visible(shellHandle) && !isMappedToPopup()) GTK.gtk_widget_hide(shellHandle); - GDK.gdk_seat_grab(seat, window, GDK.GDK_SEAT_CAPABILITY_KEYBOARD, true, 0, 0, gdkSeatGrabPrepareFunc, shellHandle); + ignoreFocusOutAfterGrab = true; } } } else { @@ -740,6 +752,7 @@ void createHandle (int index) { } long /*int*/ parentDestroyedFunc = parentDestroyedCallback.getAddress(); OS.g_signal_connect(parent.topHandle(), OS.destroy, parentDestroyedFunc, shellHandle); + parent.hasPopupChild = true; } } else { GTK.gtk_window_set_transient_for (shellHandle, parent.topHandle ()); @@ -1476,7 +1489,7 @@ long /*int*/ gtk_focus_out_event (long /*int*/ widget, long /*int*/ event) { return super.gtk_focus_out_event (widget, event); } Display display = this.display; - if (!ignoreFocusOut) { + if (!ignoreFocusOut && !ignoreFocusOutAfterGrab) { sendEvent (SWT.Deactivate); setActiveControl (null); } |