135946 - Virtual Tree eats shell activations
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 ecca358..fd88aa1 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
@@ -1364,11 +1364,8 @@
break;
}
}
- return 0;
- }
- Widget widget = getWidget (data);
- if (widget == null) return 0;
- return widget.filterProc (xEvent, gdkEvent, data);
+ }
+ return 0;
}
/**
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 4c159ab..5762183 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
@@ -432,7 +432,21 @@
if (focusHandle != 0 && !OS.GTK_WIDGET_HAS_FOCUS (focusHandle)) return;
}
}
+ /*
+ * Bug in GTK. When a shell that is not managed by the window
+ * manage is given focus, GTK gets stuck in "focus follows pointer"
+ * mode when the pointer is within the shell and its parent when
+ * the shell is hidden or disposed. The fix is to use XSetInputFocus()
+ * to assign focus when ever the active shell has not managed by
+ * the window manager.
+ *
+ * NOTE: This bug is fixed in GTK+ 2.6.8 and above.
+ */
+ boolean xFocus = false;
if (activeShell != null) {
+ if (OS.GTK_VERSION < OS.VERSION (2, 6, 8)) {
+ xFocus = (activeShell.style & SWT.ON_TOP) != 0;
+ }
display.activeShell = null;
display.activePending = true;
}
@@ -443,7 +457,7 @@
* the focus.
*/
int /*long*/ window = OS.GTK_WIDGET_WINDOW (shellHandle);
- if ((style & SWT.ON_TOP) != 0 && OS.GDK_WINDOWING_X11 ()) {
+ if ((xFocus || (style & SWT.ON_TOP) != 0) && OS.GDK_WINDOWING_X11 ()) {
int /*long*/ xDisplay = OS.gdk_x11_drawable_get_xdisplay (window);
int /*long*/ xWindow = OS.gdk_x11_drawable_get_xid (window);
OS.gdk_error_trap_push ();
@@ -630,35 +644,21 @@
return shellHandle;
}
-int /*long*/ filterProc (int /*long*/ xEvent, int /*long*/ gdkEvent, int /*long*/ data) {
- /*
- * Bug in GTK. When a shell that has no window manager trimmings
- * is given focus, GTK gets stuck in "focus follows pointer" mode when
- * the pointer is within the shell and its parent when the shell is disposed.
- * The fix is to modify the X events that cause this to happen.
- */
- XFocusChangeEvent focusEvent = new XFocusChangeEvent ();
- OS.memmove (focusEvent, xEvent, 4);
- switch (focusEvent.type) {
- case OS.FocusIn: {
- OS.memmove (focusEvent, xEvent, XFocusChangeEvent.sizeof);
- if (focusEvent.detail == OS.NotifyPointer) {
- focusEvent.detail = OS.NotifyNonlinear;
- OS.memmove (xEvent, focusEvent, XFocusChangeEvent.sizeof);
+void fixActiveShell () {
+ if (display.activeShell == this) {
+ Shell shell = null;
+ if (parent != null && parent.isVisible ()) shell = parent.getShell ();
+ if (shell == null && (style & SWT.ON_TOP) != 0) {
+ Shell [] shells = display.getShells ();
+ for (int i = 0; i < shells.length; i++) {
+ if (shells [i] != null && shells [i].isVisible ()) {
+ shell = shells [i];
+ break;
+ }
}
- break;
}
- case OS.EnterNotify: {
- XCrossingEvent crossingEvent = new XCrossingEvent ();
- OS.memmove (crossingEvent, xEvent, XCrossingEvent.sizeof);
- if (crossingEvent.focus) {
- crossingEvent.focus = false;
- OS.memmove (xEvent, crossingEvent, XCrossingEvent.sizeof);
- }
- break;
- }
+ if (shell != null) shell.bringToTop (false);
}
- return 0;
}
void fixShell (Shell newShell, Control control) {
@@ -933,17 +933,6 @@
if ((style & SWT.ON_TOP) != 0) {
OS.gdk_window_set_override_redirect (window, true);
}
- /*
- * Bug in GTK. When a shell that has no window manager trimmings
- * is given focus, GTK gets stuck in "focus follows pointer" mode when
- * the pointer is within the shell and its parent when the shell is disposed.
- * The fix is to modify the X events that cause this to happen.
- *
- * NOTE: This bug is fixed in GTK+ 2.6.8 and above.
- */
- if (OS.GTK_VERSION < OS.VERSION (2, 6, 8)) {
- OS.gdk_window_add_filter (window, display.filterProc, shellHandle);
- }
return result;
}
@@ -1470,7 +1459,8 @@
updateLayout (false);
}
}
- } else {
+ } else {
+ fixActiveShell ();
OS.gtk_widget_hide (shellHandle);
sendEvent (SWT.Hide);
}
@@ -1557,21 +1547,8 @@
* more than once. If this happens, fail silently.
*/
if (isDisposed()) return;
-
- /*
- * Feature in GTK. When the active shell is disposed,
- * GTK assigns focus temporarily to the root window
- * unless it has previously been told to do otherwise.
- * The fix is to make the parent be the active top level
- * shell when the child shell is disposed.
- */
+ fixActiveShell ();
OS.gtk_widget_hide (shellHandle);
- if (parent != null) {
- if (display.activeShell == this) {
- Shell shell = parent.getShell ();
- shell.bringToTop (false);
- }
- }
super.dispose ();
}
@@ -1632,10 +1609,6 @@
if (display.activeShell == this) display.activeShell = null;
if (tooltipsHandle != 0) OS.g_object_unref (tooltipsHandle);
tooltipsHandle = 0;
- if (OS.GTK_VERSION < OS.VERSION (2, 6, 8) ) {
- int /*long*/ window = OS.GTK_WIDGET_WINDOW (shellHandle);
- OS.gdk_window_remove_filter (window, display.filterProc, shellHandle);
- }
region = null;
lastActive = null;
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Widget.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Widget.java
index a6db1b4..dd4382c 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Widget.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Widget.java
@@ -792,10 +792,6 @@
return display.filters (eventType);
}
-int /*long*/ filterProc (int /*long*/ xEvent, int /*long*/ gdkEvent, int /*long*/ data) {
- return 0;
-}
-
int /*long*/ fixedMapProc (int /*long*/ widget) {
return 0;
}