[gtk+] Manually update toplevel_under_pointer when a grab changes to owner_events



commit ccb09d1c6fc1beeb2d371d4e427af71cfc7d6de6
Author: Alexander Larsson <alexl redhat com>
Date:   Fri Jul 10 17:30:42 2009 +0200

    Manually update toplevel_under_pointer when a grab changes to owner_events
    
    When we ungrab the pointer we don't get enter events for the window the
    pointer is in at the time of the ungrab, so we manually query for the
    window the pointer is in. The same thing actually happens on re-grab if
    the previous grab was !owner_events (meaning we don't get crossing events
    for windows other than the grab) but the new grab is owner_events (and
    thus non-grab windows need to get crossing events).
    
    This factors out some common code and enables it also for the re-grab
    to owner_events case.

 gdk/gdkdisplay.c |  131 ++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 83 insertions(+), 48 deletions(-)
---
diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c
index 399d193..ff11f08 100644
--- a/gdk/gdkdisplay.c
+++ b/gdk/gdkdisplay.c
@@ -903,6 +903,42 @@ synthesize_crossing_events (GdkDisplay *display,
     }
 }
 
+static GdkWindow *
+get_current_toplevel (GdkDisplay *display,
+		      int *x_out, int *y_out,
+		      GdkModifierType *state_out)
+{
+  GdkWindow *pointer_window;
+  GdkWindowObject *w;
+  int x, y;
+  GdkModifierType state;
+
+  pointer_window = _gdk_windowing_window_at_pointer (display,  &x, &y, &state);
+  if (pointer_window != NULL &&
+      (GDK_WINDOW_DESTROYED (pointer_window) ||
+       GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
+       GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
+    pointer_window = NULL;
+
+  w = (GdkWindowObject *)pointer_window;
+  if (w)
+    {
+      /* Convert to toplevel */
+      while (w->parent != NULL &&
+	     w->parent->window_type != GDK_WINDOW_ROOT)
+	{
+	  x += w->x;
+	  y += w->y;
+	  w = w->parent;
+	}
+    }
+
+  *x_out = x;
+  *y_out = y;
+  *state_out = state;
+  return (GdkWindow *)w;
+}
+
 static void
 switch_to_pointer_grab (GdkDisplay *display,
 			GdkPointerGrabInfo *grab,
@@ -910,8 +946,7 @@ switch_to_pointer_grab (GdkDisplay *display,
 			guint32 time,
 			gulong serial)
 {
-  GdkWindow *src_window, *pointer_window;
-  GdkWindowObject *w;
+  GdkWindow *src_window, *pointer_window, *new_toplevel;
   GList *old_grabs;
   GdkModifierType state;
   int x, y;
@@ -944,66 +979,66 @@ switch_to_pointer_grab (GdkDisplay *display,
 					  src_window, grab->window,
 					  GDK_CROSSING_GRAB, time, serial);
 	    }
-	  
+
 	  /* !owner_event Grabbing a window that we're not inside, current status is
 	     now NULL (i.e. outside grabbed window) */
 	  if (!grab->owner_events && display->pointer_info.window_under_pointer != grab->window)
 	    _gdk_display_set_window_under_pointer (display, NULL);
 	}
-  
+
       grab->activated = TRUE;
     }
-  else if (last_grab)
+
+  if (last_grab)
     {
-      pointer_window = _gdk_windowing_window_at_pointer (display,  &x, &y, &state);
-      if (pointer_window != NULL &&
-	  (GDK_WINDOW_DESTROYED (pointer_window) ||
-	   GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
-	   GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
-	pointer_window = NULL;
-      
-      /* We force checked what window we're in, so we need to
-       * update the toplevel_under_pointer info, as that won't get told of
-       * this change.
-       */
-      if (display->pointer_info.toplevel_under_pointer)
-	g_object_unref (display->pointer_info.toplevel_under_pointer);
-      display->pointer_info.toplevel_under_pointer = NULL;
-      
-      if (pointer_window)
+      new_toplevel = NULL;
+
+      if (grab == NULL /* ungrab */ ||
+	  (!last_grab->owner_events && grab->owner_events) /* switched to owner_events */ )
+	{
+	  /* We force check what window we're in, and update the toplevel_under_pointer info,
+	   * as that won't get told of this change with toplevel enter events.
+	   */
+	  if (display->pointer_info.toplevel_under_pointer)
+	    g_object_unref (display->pointer_info.toplevel_under_pointer);
+	  display->pointer_info.toplevel_under_pointer = NULL;
+
+	  new_toplevel = get_current_toplevel (display, &x, &y, &state);
+	  if (new_toplevel)
+	    {
+	      /* w is now toplevel and x,y in toplevel coords */
+	      display->pointer_info.toplevel_under_pointer = g_object_ref (new_toplevel);
+	      display->pointer_info.toplevel_x = x;
+	      display->pointer_info.toplevel_y = y;
+	      display->pointer_info.state = state;
+	    }
+	}
+
+      if (grab == NULL) /* Ungrabbed, send events */
 	{
-	  /* Convert to toplevel */
-	  w = (GdkWindowObject *)pointer_window;
-	  while (/*w->parent != NULL && */
-		 w->parent->window_type != GDK_WINDOW_ROOT)
+	  pointer_window = NULL;
+	  if (new_toplevel)
 	    {
-	      x += w->x;
-	      y += w->y;
-	      w = w->parent;
+	      /* Find (possibly virtual) child window */
+	      pointer_window =
+		_gdk_window_find_descendant_at (new_toplevel,
+						x, y,
+						NULL, NULL);
 	    }
 	  
-	  /* w is now toplevel and x,y in toplevel coords */
-	  display->pointer_info.toplevel_under_pointer = g_object_ref (w);
+	  if (pointer_window != last_grab->window)
+	    synthesize_crossing_events (display,
+					last_grab->window, pointer_window,
+					GDK_CROSSING_UNGRAB, time, serial);
 	  
-	  /* Find (possibly virtual) child window */
-	  pointer_window =
-	    _gdk_window_find_descendant_at ((GdkWindow *)w,
-					    x, y,
-					    NULL, NULL);
-	}
+	  /* We're now ungrabbed, update the window_under_pointer */
+	  _gdk_display_set_window_under_pointer (display, pointer_window);
 
-      if (pointer_window != last_grab->window)
-	synthesize_crossing_events (display,
-				    last_grab->window, pointer_window,
-				    GDK_CROSSING_UNGRAB, time, serial);
-      
-      /* We're now ungrabbed, update the window_under_pointer */
-      _gdk_display_set_window_under_pointer (display, pointer_window);
-      
-      if (last_grab->implicit_ungrab)
-	generate_grab_broken_event (last_grab->window,
-				    FALSE, TRUE, 
-				    NULL);
+	  if (last_grab->implicit_ungrab)
+	    generate_grab_broken_event (last_grab->window,
+					FALSE, TRUE,
+					NULL);
+	}
     }
   
   display->pointer_grabs = old_grabs;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]