]> Pileus Git - ~andy/gtk/commitdiff
GdkDisplayX11: Don't use substructure events in internal accounting
authorOwen W. Taylor <otaylor@fishsoup.net>
Wed, 19 Sep 2012 02:13:06 +0000 (22:13 -0400)
committerOwen W. Taylor <otaylor@fishsoup.net>
Thu, 14 Feb 2013 22:19:47 +0000 (17:19 -0500)
We may receive events because SubstructureNotifyMask has been selected
for the root window. (Most likely, this would occur because GTK+
is being used inside a window manager like Metacity or Mutter.)
This can confuse various types of internal accounting, so detect
such events and comprehensively ignore them for GDK's internal
purposes. We still need to generate GDK events for these cases
because you can select for substructure events with
GDK_SUBSTRUCTURE_MASK.

https://bugzilla.gnome.org/show_bug.cgi?id=685460

gdk/x11/gdkdisplay-x11.c

index 194df810ca825875331528804caff4096fbf90e6..20bde58a80c19f2aa0290582bf6898d79d351ea0 100644 (file)
@@ -382,15 +382,11 @@ gdk_check_wm_state_changed (GdkWindow *window)
     do_net_wm_state_changes (window);
 }
 
-static GdkWindow *
-get_event_window (GdkEventTranslator *translator,
-                  XEvent             *xevent)
+static Window
+get_event_xwindow (XEvent             *xevent)
 {
-  GdkDisplay *display;
   Window xwindow;
 
-  display = (GdkDisplay *) translator;
-
   switch (xevent->type)
     {
     case DestroyNotify:
@@ -405,11 +401,20 @@ get_event_window (GdkEventTranslator *translator,
     case ConfigureNotify:
       xwindow = xevent->xconfigure.window;
       break;
+    case ReparentNotify:
+      xwindow = xevent->xreparent.window;
+      break;
+    case GravityNotify:
+      xwindow = xevent->xgravity.window;
+      break;
+    case CirculateNotify:
+      xwindow = xevent->xcirculate.window;
+      break;
     default:
       xwindow = xevent->xany.window;
     }
 
-  return gdk_x11_window_lookup_for_display (display, xwindow);
+  return xwindow;
 }
 
 static gboolean
@@ -418,7 +423,9 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
                                  GdkEvent           *event,
                                  XEvent             *xevent)
 {
+  Window xwindow;
   GdkWindow *window;
+  gboolean is_substructure;
   GdkWindowImplX11 *window_impl = NULL;
   GdkScreen *screen = NULL;
   GdkX11Screen *x11_screen = NULL;
@@ -426,12 +433,20 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
   GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
   gboolean return_val;
 
-  /* Find the GdkWindow that this event relates to.
-   * Basically this means substructure events
-   * are reported same as structure events
+  /* Find the GdkWindow that this event relates to. If that's
+   * not the same as the window that the event was sent to,
+   * we are getting an event from SubstructureNotifyMask.
+   * We ignore such events for internal operation, but we
+   * need to report them to the application because of
+   * GDK_SUBSTRUCTURE_MASK (which should be removed at next
+   * opportunity.) The most likely reason for getting these
+   * events is when we are used in the Metacity or Mutter
+   * window managers.
    */
-  window = get_event_window (translator, xevent);
+  xwindow = get_event_xwindow (xevent);
+  is_substructure = xwindow != xevent->xany.window;
 
+  window = gdk_x11_window_lookup_for_display (display, xwindow);
   if (window)
     {
       /* We may receive events such as NoExpose/GraphicsExpose
@@ -460,7 +475,7 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
        }
     }
 
-  if (xevent->type == DestroyNotify)
+  if (xevent->type == DestroyNotify && !is_substructure)
     {
       int i, n;
 
@@ -622,8 +637,7 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
                g_message ("destroy notify:\twindow: %ld",
                           xevent->xdestroywindow.window));
 
-      /* Ignore DestroyNotify from SubstructureNotifyMask */
-      if (xevent->xdestroywindow.window == xevent->xdestroywindow.event)
+      if (!is_substructure)
        {
          event->any.type = GDK_DESTROY;
          event->any.window = window;
@@ -646,27 +660,29 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
       event->any.type = GDK_UNMAP;
       event->any.window = window;
 
-      /* If the WM supports the _NET_WM_STATE_HIDDEN hint, we do not want to
-       * interpret UnmapNotify events as implying iconic state.
-       * http://bugzilla.gnome.org/show_bug.cgi?id=590726.
-       */
-      if (screen &&
-          !gdk_x11_screen_supports_net_wm_hint (screen,
-                                                gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN")))
-        {
-          /* If we are shown (not withdrawn) and get an unmap, it means we were
-           * iconified in the X sense. If we are withdrawn, and get an unmap, it
-           * means we hid the window ourselves, so we will have already flipped
-           * the iconified bit off.
+      if (window && !is_substructure)
+       {
+          /* If the WM supports the _NET_WM_STATE_HIDDEN hint, we do not want to
+           * interpret UnmapNotify events as implying iconic state.
+           * http://bugzilla.gnome.org/show_bug.cgi?id=590726.
            */
-          if (window && GDK_WINDOW_IS_MAPPED (window))
-            gdk_synthesize_window_state (window,
-                                         0,
-                                         GDK_WINDOW_STATE_ICONIFIED);
-        }
+          if (screen &&
+              !gdk_x11_screen_supports_net_wm_hint (screen,
+                                                    gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN")))
+            {
+              /* If we are shown (not withdrawn) and get an unmap, it means we were
+               * iconified in the X sense. If we are withdrawn, and get an unmap, it
+               * means we hid the window ourselves, so we will have already flipped
+               * the iconified bit off.
+               */
+              if (GDK_WINDOW_IS_MAPPED (window))
+                gdk_synthesize_window_state (window,
+                                             0,
+                                             GDK_WINDOW_STATE_ICONIFIED);
+            }
 
-      if (window)
-        _gdk_x11_window_grab_check_unmap (window, xevent->xany.serial);
+          _gdk_x11_window_grab_check_unmap (window, xevent->xany.serial);
+        }
 
       break;
 
@@ -678,11 +694,14 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
       event->any.type = GDK_MAP;
       event->any.window = window;
 
-      /* Unset iconified if it was set */
-      if (window && (window->state & GDK_WINDOW_STATE_ICONIFIED))
-        gdk_synthesize_window_state (window,
-                                     GDK_WINDOW_STATE_ICONIFIED,
-                                     0);
+      if (window && !is_substructure)
+       {
+         /* Unset iconified if it was set */
+         if (window->state & GDK_WINDOW_STATE_ICONIFIED)
+           gdk_synthesize_window_state (window,
+                                        GDK_WINDOW_STATE_ICONIFIED,
+                                        0);
+       }
 
       break;
 
@@ -728,7 +747,7 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
         }
 
 #ifdef HAVE_XSYNC
-      if (toplevel && display_x11->use_sync && !XSyncValueIsZero (toplevel->pending_counter_value))
+      if (!is_substructure && toplevel && display_x11->use_sync && !XSyncValueIsZero (toplevel->pending_counter_value))
        {
          toplevel->current_counter_value = toplevel->pending_counter_value;
          XSyncIntToValue (&toplevel->pending_counter_value, 0);
@@ -773,21 +792,24 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
              event->configure.x = xevent->xconfigure.x;
              event->configure.y = xevent->xconfigure.y;
            }
-         window->x = event->configure.x;
-         window->y = event->configure.y;
-         window->width = xevent->xconfigure.width;
-         window->height = xevent->xconfigure.height;
+         if (!is_substructure)
+           {
+             window->x = event->configure.x;
+             window->y = event->configure.y;
+             window->width = xevent->xconfigure.width;
+             window->height = xevent->xconfigure.height;
 
-         _gdk_window_update_size (window);
-         _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
+             _gdk_window_update_size (window);
+             _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
 
-          if (window->resize_count >= 1)
-            {
-              window->resize_count -= 1;
+             if (window->resize_count >= 1)
+               {
+                 window->resize_count -= 1;
 
-              if (window->resize_count == 0)
-                _gdk_x11_moveresize_configure_done (display, window);
-            }
+                 if (window->resize_count == 0)
+                   _gdk_x11_moveresize_configure_done (display, window);
+               }
+           }
         }
       break;