[Xfce4-commits] [apps/xfce4-screensaver] 294/425: [GTK+3.20] Switch to GdkSeat

noreply at xfce.org noreply at xfce.org
Mon Oct 15 01:52:21 CEST 2018


This is an automated email from the git hooks/post-receive script.

b   l   u   e   s   a   b   r   e       p   u   s   h   e   d       a       c   o   m   m   i   t       t   o       b   r   a   n   c   h       m   a   s   t   e   r   
   in repository apps/xfce4-screensaver.

commit a7b8a687fa461b752b944bcdfda5a73a61088d12
Author: Alexei Sorokin <sor.alexei at meowr.ru>
Date:   Tue Mar 28 16:18:00 2017 +0300

    [GTK+3.20] Switch to GdkSeat
    
    This changes the code quite a lot as both grabbing the pointer and the keyboard
    have to be done simultaneously now.
---
 src/gs-grab-x11.c | 453 +++++++++++++++++++++---------------------------------
 src/gs-grab.h     |  11 +-
 src/gs-manager.c  |  56 ++++---
 src/gs-monitor.c  |   4 +-
 src/test-window.c |   7 +-
 5 files changed, 227 insertions(+), 304 deletions(-)

diff --git a/src/gs-grab-x11.c b/src/gs-grab-x11.c
index c2fba38..d174716 100644
--- a/src/gs-grab-x11.c
+++ b/src/gs-grab-x11.c
@@ -39,7 +39,7 @@
 
 static void     gs_grab_class_init (GSGrabClass *klass);
 static void     gs_grab_init       (GSGrab      *grab);
-static void     gs_grab_finalize   (GObject        *object);
+static void     gs_grab_finalize   (GObject     *object);
 
 #define GS_GRAB_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GS_TYPE_GRAB, GSGrabPrivate))
 
@@ -49,11 +49,10 @@ static gpointer grab_object = NULL;
 
 struct GSGrabPrivate
 {
-	guint       mouse_hide_cursor : 1;
-	GdkWindow  *mouse_grab_window;
-	GdkWindow  *keyboard_grab_window;
-	GdkDisplay *mouse_grab_display;
-	GdkDisplay *keyboard_grab_display;
+	GdkWindow  *grab_window;
+	GdkDisplay *grab_display;
+	guint       no_pointer_grab : 1;
+	guint       hide_cursor : 1;
 
 	GtkWidget *invisible;
 };
@@ -153,74 +152,105 @@ xorg_lock_smasher_set_active (GSGrab  *grab,
 }
 #endif /* HAVE_XF86MISCSETGRABKEYSSTATE */
 
+#if GTK_CHECK_VERSION (3, 20, 0)
+static void
+prepare_window_grab_cb (GdkSeat   *seat,
+                        GdkWindow *window,
+                        gpointer   user_data)
+{
+	gdk_window_show_unraised (window);
+}
+#endif
+
 static int
-gs_grab_get_keyboard (GSGrab     *grab,
-                      GdkWindow  *window,
-                      GdkDisplay *display)
+gs_grab_get (GSGrab     *grab,
+             GdkWindow  *window,
+             GdkDisplay *display,
+             gboolean    no_pointer_grab,
+             gboolean    hide_cursor)
 {
 	GdkGrabStatus status;
+#if GTK_CHECK_VERSION (3, 20, 0)
+	GdkSeat      *seat;
+	GdkSeatCapabilities caps;
+#endif
+	GdkCursor    *cursor;
 
 	g_return_val_if_fail (window != NULL, FALSE);
 	g_return_val_if_fail (display != NULL, FALSE);
 
-	gs_debug ("Grabbing keyboard widget=%X", (guint32) GDK_WINDOW_XID (window));
+	cursor = gdk_cursor_new_for_display (display, GDK_BLANK_CURSOR);
+
+	gs_debug ("Grabbing devices for window=%X", (guint32) GDK_WINDOW_XID (window));
+
+#if GTK_CHECK_VERSION (3, 20, 0)
+	seat = gdk_display_get_default_seat (display);
+	if (!no_pointer_grab)
+		caps = GDK_SEAT_CAPABILITY_ALL;
+	else
+		caps = GDK_SEAT_CAPABILITY_KEYBOARD;
+
+	status = gdk_seat_grab (seat, window,
+	                        caps, TRUE,
+	                        (hide_cursor ? cursor : NULL),
+	                        NULL,
+	                        prepare_window_grab_cb,
+	                        NULL);
+
+	/* make it release grabbed pointer if requested and if any;
+	   time between grabbing and ungrabbing is minimal as grab was already
+	   completed once */
+	if (status == GDK_GRAB_SUCCESS && no_pointer_grab &&
+	    gdk_display_device_is_grabbed (display, gdk_seat_get_pointer (seat)))
+	{
+		gs_grab_release (grab, FALSE);
+		gs_debug ("Regrabbing keyboard");
+		status = gdk_seat_grab (seat, window,
+		                        caps, TRUE,
+		                        (hide_cursor ? cursor : NULL),
+		                        NULL, NULL, NULL);
+	}
+#else
 	status = gdk_keyboard_grab (window, FALSE, GDK_CURRENT_TIME);
 
-	if (status == GDK_GRAB_SUCCESS)
+	if (status == GDK_GRAB_SUCCESS && !no_pointer_grab)
 	{
-		if (grab->priv->keyboard_grab_window != NULL)
-		{
-			g_object_remove_weak_pointer (G_OBJECT (grab->priv->keyboard_grab_window),
-			                              (gpointer *) &grab->priv->keyboard_grab_window);
-		}
-		grab->priv->keyboard_grab_window = window;
+		GdkGrabStatus pstatus;
 
-		g_object_add_weak_pointer (G_OBJECT (grab->priv->keyboard_grab_window),
-		                           (gpointer *) &grab->priv->keyboard_grab_window);
+		pstatus = gdk_pointer_grab (window, TRUE, 0, NULL,
+	                                    (hide_cursor ? cursor : NULL),
+	                                    GDK_CURRENT_TIME);
 
-		grab->priv->keyboard_grab_display = display;
+		if (pstatus != GDK_GRAB_SUCCESS)
+		{
+			gdk_keyboard_ungrab (GDK_CURRENT_TIME);
+			if (status == GDK_GRAB_SUCCESS)
+			{
+				status = pstatus;
+			}
+		}
 	}
 	else
 	{
-		gs_debug ("Couldn't grab keyboard!  (%s)", grab_string (status));
+		gdk_pointer_ungrab (GDK_CURRENT_TIME);
 	}
-
-	return status;
-}
-
-static int
-gs_grab_get_mouse (GSGrab     *grab,
-                   GdkWindow  *window,
-                   GdkDisplay *display,
-                   gboolean    hide_cursor)
-{
-	GdkGrabStatus status;
-	GdkCursor    *cursor;
-
-	g_return_val_if_fail (window != NULL, FALSE);
-	g_return_val_if_fail (display != NULL, FALSE);
-
-	cursor = gdk_cursor_new_for_display (display, GDK_BLANK_CURSOR);
-
-	gs_debug ("Grabbing mouse widget=%X", (guint32) GDK_WINDOW_XID (window));
-	status = gdk_pointer_grab (window, TRUE, 0, NULL,
-	                           (hide_cursor ? cursor : NULL),
-	                           GDK_CURRENT_TIME);
+#endif
 
 	if (status == GDK_GRAB_SUCCESS)
 	{
-		if (grab->priv->mouse_grab_window != NULL)
+		if (grab->priv->grab_window != NULL)
 		{
-			g_object_remove_weak_pointer (G_OBJECT (grab->priv->mouse_grab_window),
-			                              (gpointer *) &grab->priv->mouse_grab_window);
+			g_object_remove_weak_pointer (G_OBJECT (grab->priv->grab_window),
+			                              (gpointer *) &grab->priv->grab_window);
 		}
-		grab->priv->mouse_grab_window = window;
+		grab->priv->grab_window = window;
 
-		g_object_add_weak_pointer (G_OBJECT (grab->priv->mouse_grab_window),
-		                           (gpointer *) &grab->priv->mouse_grab_window);
+		g_object_add_weak_pointer (G_OBJECT (grab->priv->grab_window),
+		                           (gpointer *) &grab->priv->grab_window);
 
-		grab->priv->mouse_grab_display = display;
-		grab->priv->mouse_hide_cursor = hide_cursor;
+		grab->priv->grab_display = display;
+		grab->priv->no_pointer_grab = no_pointer_grab;
+		grab->priv->hide_cursor = hide_cursor;
 	}
 
 	g_object_unref (G_OBJECT (cursor));
@@ -229,192 +259,128 @@ gs_grab_get_mouse (GSGrab     *grab,
 }
 
 void
-gs_grab_keyboard_reset (GSGrab *grab)
+gs_grab_reset (GSGrab *grab)
 {
-	if (grab->priv->keyboard_grab_window != NULL)
+	if (grab->priv->grab_window != NULL)
 	{
-		g_object_remove_weak_pointer (G_OBJECT (grab->priv->keyboard_grab_window),
-		                              (gpointer *) &grab->priv->keyboard_grab_window);
+		g_object_remove_weak_pointer (G_OBJECT (grab->priv->grab_window),
+		                              (gpointer *) &grab->priv->grab_window);
 	}
-	grab->priv->keyboard_grab_window = NULL;
-	grab->priv->keyboard_grab_display = NULL;
-}
-
-static gboolean
-gs_grab_release_keyboard (GSGrab *grab)
-{
-	gs_debug ("Ungrabbing keyboard");
-	gdk_keyboard_ungrab (GDK_CURRENT_TIME);
-
-	gs_grab_keyboard_reset (grab);
-
-	return TRUE;
+	grab->priv->grab_window = NULL;
+	grab->priv->grab_display = NULL;
 }
 
 void
-gs_grab_mouse_reset (GSGrab *grab)
-{
-	if (grab->priv->mouse_grab_window != NULL)
-	{
-		g_object_remove_weak_pointer (G_OBJECT (grab->priv->mouse_grab_window),
-		                              (gpointer *) &grab->priv->mouse_grab_window);
-	}
-
-	grab->priv->mouse_grab_window = NULL;
-	grab->priv->mouse_grab_display = NULL;
-}
-
-gboolean
-gs_grab_release_mouse (GSGrab *grab)
+gs_grab_release (GSGrab *grab, gboolean flush)
 {
-	gs_debug ("Ungrabbing pointer");
-	gdk_pointer_ungrab (GDK_CURRENT_TIME);
-
-	gs_grab_mouse_reset (grab);
-
-	return TRUE;
-}
-
-static gboolean
-gs_grab_move_mouse (GSGrab     *grab,
-                    GdkWindow  *window,
-                    GdkDisplay *display,
-                    gboolean    hide_cursor)
-{
-	gboolean    result;
-	GdkWindow  *old_window;
-	GdkDisplay *old_display;
-	gboolean    old_hide_cursor;
-
+#if GTK_CHECK_VERSION (3, 20, 0)
+	GdkDisplay *display;
+	GdkSeat    *seat;
 
-	/* if the pointer is not grabbed and we have a
-	   mouse_grab_window defined then we lost the grab */
-	if (!gdk_pointer_is_grabbed ())
-	{
-		gs_grab_mouse_reset (grab);
-	}
+	display = gdk_display_get_default ();
+	seat = gdk_display_get_default_seat (display);
 
-	if (grab->priv->mouse_grab_window == window)
-	{
-		gs_debug ("Window %X is already grabbed, skipping",
-		          (guint32) GDK_WINDOW_XID (grab->priv->mouse_grab_window));
-		return TRUE;
-	}
+#endif
+	gs_debug ("Ungrabbing devices");
 
-#if 0
-	gs_debug ("Intentionally skipping move pointer grabs");
-	/* FIXME: GTK+ doesn't like having the pointer grabbed */
-	return TRUE;
+#if GTK_CHECK_VERSION (3, 20, 0)
+	gdk_seat_ungrab (seat);
 #else
-	if (grab->priv->mouse_grab_window)
+	if (gdk_pointer_is_grabbed ())
 	{
-		gs_debug ("Moving pointer grab from %X to %X",
-		          (guint32) GDK_WINDOW_XID (grab->priv->mouse_grab_window),
-		          (guint32) GDK_WINDOW_XID (window));
-	}
-	else
-	{
-		gs_debug ("Getting pointer grab on %X",
-		          (guint32) GDK_WINDOW_XID (window));
+		gdk_pointer_ungrab (GDK_CURRENT_TIME);
 	}
+	gdk_keyboard_ungrab (GDK_CURRENT_TIME);
 #endif
 
-	gs_debug ("*** doing X server grab");
-	gdk_x11_grab_server ();
-
-	old_window = grab->priv->mouse_grab_window;
-	old_display = grab->priv->mouse_grab_display;
-	old_hide_cursor = grab->priv->mouse_hide_cursor;
-
-	if (old_window)
-	{
-		gs_grab_release_mouse (grab);
-	}
-
-	result = gs_grab_get_mouse (grab, window, display, hide_cursor);
+	gs_grab_reset (grab);
 
-	if (result != GDK_GRAB_SUCCESS)
+	/* FIXME: decide when this is good and when not */
+	if (flush)
 	{
-		sleep (1);
-		result = gs_grab_get_mouse (grab, window, display, hide_cursor);
-	}
+		/* FIXME: is it right to enable this? */
+		xorg_lock_smasher_set_active (grab, TRUE);
 
-	if ((result != GDK_GRAB_SUCCESS) && old_window)
-	{
-		gs_debug ("Could not grab mouse for new window.  Resuming previous grab.");
-		gs_grab_get_mouse (grab, old_window, old_display, old_hide_cursor);
+		gdk_display_sync (gdk_display_get_default ());
+		gdk_flush ();
 	}
-
-	gs_debug ("*** releasing X server grab");
-	gdk_x11_ungrab_server ();
-	gdk_flush ();
-
-	return (result == GDK_GRAB_SUCCESS);
 }
 
 static gboolean
-gs_grab_move_keyboard (GSGrab     *grab,
-                       GdkWindow  *window,
-                       GdkDisplay *display)
+gs_grab_move (GSGrab     *grab,
+              GdkWindow  *window,
+              GdkDisplay *display,
+              gboolean    no_pointer_grab,
+              gboolean    hide_cursor)
 {
-	gboolean    result;
+	int         result;
 	GdkWindow  *old_window;
 	GdkDisplay *old_display;
+	gboolean    old_hide_cursor;
 
-	if (grab->priv->keyboard_grab_window == window)
+	if (grab->priv->grab_window == window &&
+	    grab->priv->no_pointer_grab == no_pointer_grab)
 	{
 		gs_debug ("Window %X is already grabbed, skipping",
-		          (guint32) GDK_WINDOW_XID (grab->priv->keyboard_grab_window));
+		          (guint32) GDK_WINDOW_XID (grab->priv->grab_window));
 		return TRUE;
 	}
 
-	if (grab->priv->keyboard_grab_window != NULL)
+	if (grab->priv->grab_window != NULL)
 	{
-		gs_debug ("Moving keyboard grab from %X to %X",
-		          (guint32) GDK_WINDOW_XID (grab->priv->keyboard_grab_window),
+		gs_debug ("Moving devices grab from %X to %X",
+		          (guint32) GDK_WINDOW_XID (grab->priv->grab_window),
 		          (guint32) GDK_WINDOW_XID (window));
 	}
 	else
 	{
-		gs_debug ("Getting keyboard grab on %X",
+		gs_debug ("Getting devices grab on %X",
 		          (guint32) GDK_WINDOW_XID (window));
 
 	}
 
 	gs_debug ("*** doing X server grab");
-	gdk_x11_grab_server ();
+	gdk_x11_display_grab (display);
 
-	old_window = grab->priv->keyboard_grab_window;
-	old_display = grab->priv->keyboard_grab_display;
+	old_window = grab->priv->grab_window;
+	old_display = grab->priv->grab_display;
+	old_hide_cursor = grab->priv->hide_cursor;
 
 	if (old_window)
 	{
-		gs_grab_release_keyboard (grab);
+		gs_grab_release (grab, FALSE);
 	}
 
-	result = gs_grab_get_keyboard (grab, window, display);
+	result = gs_grab_get (grab, window, display,
+	                      no_pointer_grab, hide_cursor);
 
 	if (result != GDK_GRAB_SUCCESS)
 	{
-		sleep (1);
-		result = gs_grab_get_keyboard (grab, window, display);
+		g_usleep (G_USEC_PER_SEC);
+		result = gs_grab_get (grab, window, display,
+		                      no_pointer_grab, hide_cursor);
 	}
 
 	if ((result != GDK_GRAB_SUCCESS) && old_window)
 	{
-		gs_debug ("Could not grab keyboard for new window. Resuming previous grab.");
-		gs_grab_get_keyboard (grab, old_window, old_display);
+		int old_result;
+
+		gs_debug ("Could not grab devices for new window. Resuming previous grab.");
+		old_result = gs_grab_get (grab, old_window, old_display,
+		                          no_pointer_grab, old_hide_cursor);
+		if (old_result != GDK_GRAB_SUCCESS)
+			gs_debug ("Could not grab devices for old window");
 	}
 
 	gs_debug ("*** releasing X server grab");
-	gdk_x11_ungrab_server ();
-	gdk_flush ();
+	gdk_x11_display_ungrab (display);
+	gdk_display_flush (display);
 
 	return (result == GDK_GRAB_SUCCESS);
 }
 
 static void
-gs_grab_nuke_focus (void)
+gs_grab_nuke_focus (GdkDisplay *display)
 {
 	Window focus = 0;
 	int    rev = 0;
@@ -423,121 +389,59 @@ gs_grab_nuke_focus (void)
 
 	gdk_error_trap_push ();
 
-	XGetInputFocus (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &focus, &rev);
-	XSetInputFocus (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), None, RevertToNone, CurrentTime);
+	XGetInputFocus (GDK_DISPLAY_XDISPLAY (display), &focus, &rev);
+	XSetInputFocus (GDK_DISPLAY_XDISPLAY (display), None,
+	                RevertToNone, CurrentTime);
 
 	gdk_error_trap_pop_ignored ();
 }
 
-void
-gs_grab_release (GSGrab *grab)
-{
-	gs_debug ("Releasing all grabs");
-
-	gs_grab_release_mouse (grab);
-	gs_grab_release_keyboard (grab);
-
-	/* FIXME: is it right to enable this ? */
-	xorg_lock_smasher_set_active (grab, TRUE);
-
-	gdk_display_sync (gdk_display_get_default ());
-	gdk_flush ();
-}
-
 gboolean
 gs_grab_grab_window (GSGrab     *grab,
                      GdkWindow  *window,
                      GdkDisplay *display,
+                     gboolean    no_pointer_grab,
                      gboolean    hide_cursor)
 {
-	gboolean    mstatus = FALSE;
-	gboolean    kstatus = FALSE;
+	gboolean    status = FALSE;
 	int         i;
-	int         retries = 4;
-	gboolean    focus_fuckus = FALSE;
-
-AGAIN:
+	int         retries = 12;
 
 	for (i = 0; i < retries; i++)
 	{
-		kstatus = gs_grab_get_keyboard (grab, window, display);
-		if (kstatus == GDK_GRAB_SUCCESS)
+		status = gs_grab_get (grab, window, display,
+		                      no_pointer_grab, hide_cursor);
+		if (status == GDK_GRAB_SUCCESS)
 		{
 			break;
 		}
-
-		/* else, wait a second and try to grab again. */
-		sleep (1);
-	}
-
-	if (kstatus != GDK_GRAB_SUCCESS)
-	{
-		if (!focus_fuckus)
+		else if (i == (int) (retries / 2))
 		{
-			focus_fuckus = TRUE;
-			gs_grab_nuke_focus ();
-			goto AGAIN;
-		}
-	}
-
-	for (i = 0; i < retries; i++)
-	{
-		mstatus = gs_grab_get_mouse (grab, window, display, hide_cursor);
-		if (mstatus == GDK_GRAB_SUCCESS)
-		{
-			break;
+			/* try nuking focus in the middle */
+			gs_grab_nuke_focus (display);
 		}
 
-		/* else, wait a second and try to grab again. */
-		sleep (1);
+		/* else, wait a second and try to grab again */
+		g_usleep (G_USEC_PER_SEC);
 	}
 
-	if (mstatus != GDK_GRAB_SUCCESS)
+	if (status != GDK_GRAB_SUCCESS)
 	{
-		gs_debug ("Couldn't grab pointer!  (%s)",
-		          grab_string (mstatus));
-	}
-
-#if 0
-	/* FIXME: release the pointer grab so GTK+ will work */
-	gs_grab_release_mouse (grab);
-#endif
-
-	/* When should we allow blanking to proceed?  The current theory
-	   is that both a keyboard grab and a mouse grab are mandatory
-
-	   - If we don't have a keyboard grab, then we won't be able to
-	   read a password to unlock, so the kbd grab is manditory.
-
-	   - If we don't have a mouse grab, then we might not see mouse
-	   clicks as a signal to unblank, on-screen widgets won't work ideally,
-	   and gs_grab_move_to_window() will spin forever when it gets called.
-	*/
-
-	if (kstatus != GDK_GRAB_SUCCESS || mstatus != GDK_GRAB_SUCCESS)
-	{
-		/* Do not blank without a keyboard and mouse grabs. */
-
-		/* Release keyboard or mouse which was grabbed. */
-		if (kstatus == GDK_GRAB_SUCCESS)
-		{
-			gs_grab_release_keyboard (grab);
-		}
-		if (mstatus == GDK_GRAB_SUCCESS)
-		{
-			gs_grab_release_mouse (grab);
-		}
+		gs_debug ("Couldn't grab devices!  (%s)",
+		          grab_string (status));
 
+		/* do not blank without a devices grab */
 		return FALSE;
 	}
 
-	/* Grab is good, go ahead and blank.  */
+	/* grab is good, go ahead and blank  */
 	return TRUE;
 }
 
-/* this is used to grab the keyboard and mouse to the root */
+/* this is used to grab devices to the root */
 gboolean
 gs_grab_grab_root (GSGrab  *grab,
+                   gboolean no_pointer_grab,
                    gboolean hide_cursor)
 {
 	GdkDisplay *display;
@@ -557,37 +461,40 @@ gs_grab_grab_root (GSGrab  *grab,
 	gdk_device_get_position (device, &screen, NULL, NULL);
 	root = gdk_screen_get_root_window (screen);
 
-	res = gs_grab_grab_window (grab, root, display, hide_cursor);
+	res = gs_grab_grab_window (grab, root, display,
+	                           no_pointer_grab, hide_cursor);
 
 	return res;
 }
 
-/* this is used to grab the keyboard and mouse to an offscreen window */
+/* this is used to grab devices to an offscreen window */
 gboolean
 gs_grab_grab_offscreen (GSGrab *grab,
+                        gboolean no_pointer_grab,
                         gboolean hide_cursor)
 {
+	GdkWindow *window;
 	GdkDisplay *display;
 	GdkScreen  *screen;
 	gboolean    res;
 
 	gs_debug ("Grabbing an offscreen window");
 
+	window = gtk_widget_get_window (GTK_WIDGET (grab->priv->invisible));
 	screen = gtk_invisible_get_screen (GTK_INVISIBLE (grab->priv->invisible));
 	display = gdk_screen_get_display (screen);
-	res = gs_grab_grab_window (grab,
-	                           gtk_widget_get_window (GTK_WIDGET (grab->priv->invisible)),
-	                           display,
-	                           hide_cursor);
+	res = gs_grab_grab_window (grab, window, display,
+	                           no_pointer_grab, hide_cursor);
 
 	return res;
 }
 
-/* This is similar to gs_grab_grab_window but doesn't fail */
+/* this is similar to gs_grab_grab_window but doesn't fail */
 void
 gs_grab_move_to_window (GSGrab     *grab,
                         GdkWindow  *window,
                         GdkDisplay *display,
+                        gboolean    no_pointer_grab,
                         gboolean    hide_cursor)
 {
 	gboolean result = FALSE;
@@ -596,19 +503,12 @@ gs_grab_move_to_window (GSGrab     *grab,
 
 	xorg_lock_smasher_set_active (grab, FALSE);
 
-	do
-	{
-		result = gs_grab_move_keyboard (grab, window, display);
-		gdk_flush ();
-	}
-	while (!result);
-
-	do
+	while (!result)
 	{
-		result = gs_grab_move_mouse (grab, window, display, hide_cursor);
+		result = gs_grab_move (grab, window, display,
+		                       no_pointer_grab, hide_cursor);
 		gdk_flush ();
 	}
-	while (!result);
 }
 
 static void
@@ -626,7 +526,8 @@ gs_grab_init (GSGrab *grab)
 {
 	grab->priv = GS_GRAB_GET_PRIVATE (grab);
 
-	grab->priv->mouse_hide_cursor = FALSE;
+	grab->priv->no_pointer_grab = FALSE;
+	grab->priv->hide_cursor = FALSE;
 	grab->priv->invisible = gtk_invisible_new ();
 	gtk_widget_show (grab->priv->invisible);
 }
diff --git a/src/gs-grab.h b/src/gs-grab.h
index dad9379..7c4086c 100644
--- a/src/gs-grab.h
+++ b/src/gs-grab.h
@@ -53,26 +53,29 @@ GType     gs_grab_get_type         (void);
 
 GSGrab  * gs_grab_new              (void);
 
-void      gs_grab_release          (GSGrab    *grab);
-gboolean  gs_grab_release_mouse    (GSGrab    *grab);
+void      gs_grab_release          (GSGrab    *grab,
+                                    gboolean   flush);
 
 gboolean  gs_grab_grab_window      (GSGrab     *grab,
                                     GdkWindow  *window,
                                     GdkDisplay *display,
+                                    gboolean    no_pointer_grab,
                                     gboolean    hide_cursor);
 
 gboolean  gs_grab_grab_root        (GSGrab    *grab,
+                                    gboolean   no_pointer_grab,
                                     gboolean   hide_cursor);
 gboolean  gs_grab_grab_offscreen   (GSGrab    *grab,
+                                    gboolean   no_pointer_grab,
                                     gboolean   hide_cursor);
 
 void      gs_grab_move_to_window   (GSGrab     *grab,
                                     GdkWindow  *window,
                                     GdkDisplay *display,
+                                    gboolean    no_pointer_grab,
                                     gboolean    hide_cursor);
 
-void      gs_grab_mouse_reset      (GSGrab    *grab);
-void      gs_grab_keyboard_reset   (GSGrab    *grab);
+void      gs_grab_reset            (GSGrab     *grab);
 
 G_END_DECLS
 
diff --git a/src/gs-manager.c b/src/gs-manager.c
index 10e268e..34e1f1f 100644
--- a/src/gs-manager.c
+++ b/src/gs-manager.c
@@ -1207,11 +1207,11 @@ manager_maybe_grab_window (GSManager *manager,
 	if (gs_window_get_display (window) == display &&
 	    gs_window_get_monitor (window) == monitor)
 	{
-		gs_debug ("Moving grab to %p", window);
+		gs_debug ("Initiate grab move to %p", window);
 		gs_grab_move_to_window (manager->priv->grab,
 		                        gs_window_get_gdk_window (window),
 		                        gs_window_get_display (window),
-		                        FALSE);
+		                        FALSE, FALSE);
 		grabbed = TRUE;
 	}
 
@@ -1223,14 +1223,35 @@ window_grab_broken_cb (GSWindow           *window,
                        GdkEventGrabBroken *event,
                        GSManager          *manager)
 {
-	gs_debug ("GRAB BROKEN!");
+#if GTK_CHECK_VERSION (3, 20, 0)
+	GdkDisplay *display;
+	GdkSeat    *seat;
+	GdkDevice  *device;
+
+	display = gdk_window_get_display (gs_window_get_gdk_window (window));
+	seat = gdk_display_get_default_seat (display);
+
+#endif
 	if (event->keyboard)
 	{
-		gs_grab_keyboard_reset (manager->priv->grab);
+		gs_debug ("KEYBOARD GRAB BROKEN!");
+#if GTK_CHECK_VERSION (3, 20, 0)
+		device = gdk_seat_get_pointer (seat);
+		if (!gdk_display_device_is_grabbed (display, device))
+			gs_grab_reset (manager->priv->grab);
+#else
+		if (!gdk_pointer_is_grabbed ())
+			gs_grab_reset (manager->priv->grab);
+#endif
 	}
 	else
 	{
-		gs_grab_mouse_reset (manager->priv->grab);
+		gs_debug ("POINTER GRAB BROKEN!");
+#if GTK_CHECK_VERSION (3, 20, 0)
+		device = gdk_seat_get_keyboard (seat);
+		if (!gdk_display_device_is_grabbed (display, device))
+			gs_grab_reset (manager->priv->grab);
+#endif
 	}
 }
 
@@ -1405,7 +1426,7 @@ handle_window_dialog_up (GSManager *manager,
 	g_signal_emit (manager, signals [AUTH_REQUEST_BEGIN], 0);
 
 	manager->priv->dialog_up = TRUE;
-	/* Make all other windows insensitive so we don't get events */
+	/* make all other windows insensitive to not get events */
 	for (l = manager->priv->windows; l; l = l->next)
 	{
 		if (l->data != window)
@@ -1414,15 +1435,14 @@ handle_window_dialog_up (GSManager *manager,
 		}
 	}
 
-	/* Move keyboard and mouse grabs so dialog can be used */
+	/* move devices grab so that dialog can be used;
+	   release the pointer grab while dialog is up so that
+	   the dialog can be used. We'll regrab it when the dialog goes down */
+	gs_debug ("Initiate pointer-less grab move to %p", window);
 	gs_grab_move_to_window (manager->priv->grab,
 	                        gs_window_get_gdk_window (window),
 	                        gs_window_get_display (window),
-	                        FALSE);
-
-	/* Release the pointer grab while dialog is up so that
-	   the dialog can be used.  We'll regrab it when the dialog goes down. */
-	gs_grab_release_mouse (manager->priv->grab);
+	                        TRUE, FALSE);
 
 	if (! manager->priv->throttled)
 	{
@@ -1443,13 +1463,13 @@ handle_window_dialog_down (GSManager *manager,
 
 	gs_debug ("Handling dialog down");
 
-	/* Regrab the mouse */
+	/* regrab pointer */
 	gs_grab_move_to_window (manager->priv->grab,
 	                        gs_window_get_gdk_window (window),
 	                        gs_window_get_display (window),
-	                        FALSE);
+	                        FALSE, FALSE);
 
-	/* Make all windows sensitive so we get events */
+	/* make all windows sensitive to get events */
 	for (l = manager->priv->windows; l; l = l->next)
 	{
 		gtk_widget_set_sensitive (GTK_WIDGET (l->data), TRUE);
@@ -1741,7 +1761,7 @@ gs_manager_finalize (GObject *object)
 	remove_unfade_idle (manager);
 	remove_timers (manager);
 
-	gs_grab_release (manager->priv->grab);
+	gs_grab_release (manager->priv->grab, TRUE);
 
 	manager_stop_jobs (manager);
 
@@ -1875,7 +1895,7 @@ gs_manager_activate (GSManager *manager)
 		return FALSE;
 	}
 
-	res = gs_grab_grab_root (manager->priv->grab, FALSE);
+	res = gs_grab_grab_root (manager->priv->grab, FALSE, FALSE);
 	if (! res)
 	{
 		return FALSE;
@@ -1933,7 +1953,7 @@ gs_manager_deactivate (GSManager *manager)
 	gs_fade_reset (manager->priv->fade);
 	remove_timers (manager);
 
-	gs_grab_release (manager->priv->grab);
+	gs_grab_release (manager->priv->grab, TRUE);
 
 	manager_stop_jobs (manager);
 
diff --git a/src/gs-monitor.c b/src/gs-monitor.c
index 42dead3..732a59b 100644
--- a/src/gs-monitor.c
+++ b/src/gs-monitor.c
@@ -102,7 +102,7 @@ static gboolean release_grab_timeout(GSMonitor* monitor)
 
 	if (! manager_active)
 	{
-		gs_grab_release(monitor->priv->grab);
+		gs_grab_release(monitor->priv->grab, TRUE);
 	}
 
 	monitor->priv->release_grab_id = 0;
@@ -128,7 +128,7 @@ static gboolean watcher_idle_notice_cb(GSWatcher* watcher, gboolean in_effect, G
 		if (activation_enabled && ! inhibited)
 		{
 			/* start slow fade */
-			if (gs_grab_grab_offscreen(monitor->priv->grab, FALSE))
+			if (gs_grab_grab_offscreen(monitor->priv->grab, FALSE, FALSE))
 			{
 				gs_fade_async(monitor->priv->fade, FADE_TIMEOUT, NULL, NULL);
 			}
diff --git a/src/test-window.c b/src/test-window.c
index f07c5c7..1a5fd42 100644
--- a/src/test-window.c
+++ b/src/test-window.c
@@ -57,12 +57,11 @@ static void
 window_show_cb (GSWindow  *window,
                 gpointer   data)
 {
-	/* Grab keyboard so dialog can be used */
+	/* move devices grab so that dialog can be used */
 	gs_grab_move_to_window (grab,
 	                        gs_window_get_gdk_window (window),
 	                        gs_window_get_display (window),
-	                        FALSE);
-
+	                        TRUE, FALSE);
 }
 
 static gboolean
@@ -92,7 +91,7 @@ window_destroyed_cb (GtkWindow *window,
                      gpointer   data)
 {
 	disconnect_window_signals (GS_WINDOW (window));
-	gs_grab_release (grab);
+	gs_grab_release (grab, TRUE);
 	gtk_main_quit ();
 }
 

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Xfce4-commits mailing list