[gtk+/client-side-windows] Base pointer grab on get-offscreen-parent



commit 904f0ccb7c9f5bb368ece32693b694318ac5c3fa
Author: Alexander Larsson <alexl redhat com>
Date:   Fri Jun 5 14:50:58 2009 +0200

    Base pointer grab on get-offscreen-parent
---
 gdk/gdk.symbols       |    2 +-
 gdk/gdkinternals.h    |    7 +++
 gdk/gdkwindow.c       |  106 +++++++++++++++++++++++++++++++++++++++++++++++++
 gdk/x11/gdkmain-x11.c |   98 ++++++++-------------------------------------
 4 files changed, 131 insertions(+), 82 deletions(-)

diff --git a/gdk/gdk.symbols b/gdk/gdk.symbols
index 44cee62..d7ec27c 100644
--- a/gdk/gdk.symbols
+++ b/gdk/gdk.symbols
@@ -69,7 +69,6 @@ gdk_get_use_xshm
 gdk_set_use_xshm
 #endif
 gdk_keyboard_grab
-gdk_pointer_grab
 #endif
 #endif
 
@@ -715,6 +714,7 @@ gdk_window_set_user_data
 gdk_window_thaw_toplevel_updates_libgtk_only
 gdk_window_thaw_updates
 gdk_window_set_composited
+gdk_pointer_grab
 #endif
 #endif
 
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
index 288f518..b6da9bb 100644
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@ -453,6 +453,13 @@ GdkWindow* _gdk_windowing_window_at_pointer  (GdkDisplay       *display,
 					      gint             *win_x,
 					      gint             *win_y,
 					      GdkModifierType  *mask);
+GdkGrabStatus _gdk_windowing_pointer_grab    (GdkWindow        *window,
+					      GdkWindow        *native,
+					      gboolean          owner_events,
+					      GdkEventMask      event_mask,
+					      GdkWindow        *confine_to,
+					      GdkCursor        *cursor,
+					      guint32           time);
 void _gdk_windowing_got_event                (GdkDisplay       *display,
 					      GList            *event_link,
 					      GdkEvent         *event,
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 178a4ec..76a9f82 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -8434,6 +8434,112 @@ _gdk_display_set_window_under_pointer (GdkDisplay *display,
   _gdk_display_enable_motion_hints (display);
 }
 
+static GdkWindow *
+gdk_window_get_offscreen_parent (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindow *res;
+
+  res = NULL;
+  g_signal_emit_by_name (private->impl_window,
+			 "get-offscreen-parent",
+			 &res);
+
+  return res;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_pointer_grab
+ *
+ *   Grabs the pointer to a specific window
+ *
+ * Arguments:
+ *   "window" is the window which will receive the grab
+ *   "owner_events" specifies whether events will be reported as is,
+ *     or relative to "window"
+ *   "event_mask" masks only interesting events
+ *   "confine_to" limits the cursor movement to the specified window
+ *   "cursor" changes the cursor for the duration of the grab
+ *   "time" specifies the time
+ *
+ * Results:
+ *
+ * Side effects:
+ *   requires a corresponding call to gdk_pointer_ungrab
+ *
+ *--------------------------------------------------------------
+ */
+GdkGrabStatus
+gdk_pointer_grab (GdkWindow *	  window,
+		  gboolean	  owner_events,
+		  GdkEventMask	  event_mask,
+		  GdkWindow *	  confine_to,
+		  GdkCursor *	  cursor,
+		  guint32	  time)
+{
+  GdkWindow *native;
+  GdkDisplay *display;
+  GdkGrabStatus res;
+  gulong serial;
+
+  g_return_val_if_fail (window != NULL, 0);
+  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
+  g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
+
+  /* We need a native window for confine to to work, ensure we have one */
+  if (confine_to)
+    {
+      if (!gdk_window_ensure_native (confine_to))
+	{
+	  g_warning ("Can't confine to grabbed window, not native");
+	  confine_to = NULL;
+	}
+    }
+
+  /* Non-viewable client side window => fail */
+  if (!_gdk_window_has_impl (window) &&
+      !gdk_window_is_viewable (window))
+    return GDK_GRAB_NOT_VIEWABLE;
+
+  native = gdk_window_get_toplevel (window);
+  while (gdk_window_is_offscreen ((GdkWindowObject *)native))
+    {
+      native = gdk_window_get_offscreen_parent (native);
+
+      if (native == NULL ||
+	  (!_gdk_window_has_impl (native) &&
+	   !gdk_window_is_viewable (native)))
+	return GDK_GRAB_NOT_VIEWABLE;
+
+      native = gdk_window_get_toplevel (native);
+    }
+
+  display = gdk_drawable_get_display (window);
+
+  serial = _gdk_windowing_window_get_next_serial (display);
+
+  res = _gdk_windowing_pointer_grab (window,
+				     native,
+				     owner_events,
+				     event_mask,
+				     confine_to,
+				     cursor,
+				     time);
+
+  if (res == GDK_GRAB_SUCCESS)
+    _gdk_display_add_pointer_grab (display,
+				   window,
+				   native,
+				   owner_events,
+				   event_mask,
+				   serial,
+				   time,
+				   FALSE);
+
+  return res;
+}
+
 void
 gdk_window_set_has_offscreen_children (GdkWindow *window,
 				       gboolean has_offscreen_children)
diff --git a/gdk/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c
index 471a8f2..f12c709 100644
--- a/gdk/x11/gdkmain-x11.c
+++ b/gdk/x11/gdkmain-x11.c
@@ -138,16 +138,6 @@ gdk_x11_convert_grab_status (gint status)
   return 0;
 }
 
-struct XPointerGrabInfo {
-  GdkDisplay *display;
-  GdkWindow *window;
-  GdkWindow *native_window;
-  gboolean owner_events;
-  gulong serial;
-  guint event_mask;
-  guint32 time;
-};
-
 static void
 has_pointer_grab_callback (GdkDisplay *display,
 			   gpointer data,
@@ -156,81 +146,38 @@ has_pointer_grab_callback (GdkDisplay *display,
   _gdk_display_pointer_grab_update (display, serial);
 }
 
-/*
- *--------------------------------------------------------------
- * gdk_pointer_grab
- *
- *   Grabs the pointer to a specific window
- *
- * Arguments:
- *   "window" is the window which will receive the grab
- *   "owner_events" specifies whether events will be reported as is,
- *     or relative to "window"
- *   "event_mask" masks only interesting events
- *   "confine_to" limits the cursor movement to the specified window
- *   "cursor" changes the cursor for the duration of the grab
- *   "time" specifies the time
- *
- * Results:
- *
- * Side effects:
- *   requires a corresponding call to gdk_pointer_ungrab
- *
- *--------------------------------------------------------------
- */
-
 GdkGrabStatus
-gdk_pointer_grab (GdkWindow *	  window,
-		  gboolean	  owner_events,
-		  GdkEventMask	  event_mask,
-		  GdkWindow *	  confine_to,
-		  GdkCursor *	  cursor,
-		  guint32	  time)
+_gdk_windowing_pointer_grab (GdkWindow *window,
+			     GdkWindow *native,
+			     gboolean owner_events,
+			     GdkEventMask event_mask,
+			     GdkWindow *confine_to,
+			     GdkCursor *cursor,
+			     guint32 time)
 {
   gint return_val;
   GdkCursorPrivate *cursor_private;
-  GdkWindow *native;
   GdkDisplayX11 *display_x11;
   guint xevent_mask;
   Window xwindow;
   Window xconfine_to;
   Cursor xcursor;
-  unsigned long serial;
   int i;
-  
-  g_return_val_if_fail (window != NULL, 0);
-  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
-  g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
-
-  native = gdk_window_get_toplevel (window);
-
-  /* We need a native window for confine to to work, ensure we have one */
-  if (confine_to)
-    gdk_window_ensure_native (confine_to);
-  
-  /* TODO: What do we do for offscreens and  their children? We need to proxy the grab somehow */
-  if (!GDK_IS_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (native)->impl))
-    return GDK_GRAB_SUCCESS;
 
-  if (!_gdk_window_has_impl (window) &&
-      !gdk_window_is_viewable (window))
-    return GDK_GRAB_NOT_VIEWABLE;
-  
   if (confine_to)
     confine_to = _gdk_window_get_impl_window (confine_to);
 
   display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (native));
 
   cursor_private = (GdkCursorPrivate*) cursor;
-  
+
   xwindow = GDK_WINDOW_XID (native);
-  serial = NextRequest (GDK_WINDOW_XDISPLAY (native));
-  
+
   if (!confine_to || GDK_WINDOW_DESTROYED (confine_to))
     xconfine_to = None;
   else
     xconfine_to = GDK_WINDOW_XID (confine_to);
-  
+
   if (!cursor)
     xcursor = None;
   else
@@ -238,7 +185,7 @@ gdk_pointer_grab (GdkWindow *	  window,
       _gdk_x11_cursor_update_theme (cursor);
       xcursor = cursor_private->xcursor;
     }
-  
+
   xevent_mask = 0;
   for (i = 0; i < _gdk_nenvent_masks; i++)
     {
@@ -250,7 +197,7 @@ gdk_pointer_grab (GdkWindow *	  window,
    * hints. If we set a native one we just wouldn't get any events.
    */
   xevent_mask &= ~PointerMotionHintMask;
-  
+
   return_val = _gdk_input_grab_pointer (window,
 					native,
 					owner_events,
@@ -258,7 +205,7 @@ gdk_pointer_grab (GdkWindow *	  window,
 					confine_to,
 					time);
 
-  if (return_val == GrabSuccess || 
+  if (return_val == GrabSuccess ||
       G_UNLIKELY (!display_x11->trusted_client && return_val == AlreadyGrabbed))
     {
       if (!GDK_WINDOW_DESTROYED (native))
@@ -280,22 +227,11 @@ gdk_pointer_grab (GdkWindow *	  window,
       else
 	return_val = AlreadyGrabbed;
     }
-  
+
   if (return_val == GrabSuccess)
-    {
-      _gdk_display_add_pointer_grab (GDK_DISPLAY_OBJECT (display_x11),
-				     window,
-				     native,
-				     owner_events,
-				     event_mask,
-				     serial,
-				     time,
-				     FALSE);
-
-      _gdk_x11_roundtrip_async (GDK_DISPLAY_OBJECT (display_x11), 
-				has_pointer_grab_callback,
-				NULL);
-    }
+    _gdk_x11_roundtrip_async (GDK_DISPLAY_OBJECT (display_x11),
+			      has_pointer_grab_callback,
+			      NULL);
 
   return gdk_x11_convert_grab_status (return_val);
 }



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