182 lines
6.7 KiB
Diff
182 lines
6.7 KiB
Diff
From 16cdb3a8cdd60da9eef12d1d10a01d4eed21a5a7 Mon Sep 17 00:00:00 2001
|
|
From: Francesco Giudici <fgiudici@redhat.com>
|
|
Date: Mon, 20 Apr 2020 10:25:03 +0200
|
|
Subject: [PATCH 8/9] wayland: fix mouse lock in server mode
|
|
|
|
We can now properly manage mouse pointer lock by using the wayland protocols.
|
|
Includes fix from Frediano Ziglio to manage switching from mouse in
|
|
server mode to client mode without releasing the pointer
|
|
(see https://gitlab.freedesktop.org/fziglio/spice-gtk/-/commit/c14b047e45)
|
|
|
|
Signed-off-by: Francesco Giudici <fgiudici@redhat.com>
|
|
Acked-by: Frediano Ziglio <fziglio@redhat.com>
|
|
(cherry picked from commit dd7015d57ca936cc81060b1e2a09d3afc1478d4a)
|
|
---
|
|
src/spice-widget.c | 85 +++++++++++++++++++++++++++++++++++-----------
|
|
1 file changed, 66 insertions(+), 19 deletions(-)
|
|
|
|
diff --git a/src/spice-widget.c b/src/spice-widget.c
|
|
index 7700f47..6cfc72f 100644
|
|
--- a/src/spice-widget.c
|
|
+++ b/src/spice-widget.c
|
|
@@ -34,7 +34,13 @@
|
|
#endif
|
|
#ifdef GDK_WINDOWING_WAYLAND
|
|
#include <gdk/gdkwayland.h>
|
|
+#ifdef HAVE_WAYLAND_PROTOCOLS
|
|
+#include "pointer-constraints-unstable-v1-client-protocol.h"
|
|
+#include "relative-pointer-unstable-v1-client-protocol.h"
|
|
+#include "wayland-extensions.h"
|
|
#endif
|
|
+#endif
|
|
+
|
|
#ifdef G_OS_WIN32
|
|
#include <windows.h>
|
|
#include <dinput.h>
|
|
@@ -698,6 +704,11 @@ static void spice_display_init(SpiceDisplay *display)
|
|
|
|
d->grabseq = spice_grab_sequence_new_from_string("Control_L+Alt_L");
|
|
d->activeseq = g_new0(gboolean, d->grabseq->nkeysyms);
|
|
+
|
|
+#ifdef HAVE_WAYLAND_PROTOCOLS
|
|
+ if GDK_IS_WAYLAND_DISPLAY(gtk_widget_get_display(widget))
|
|
+ spice_wayland_extensions_init(widget);
|
|
+#endif
|
|
}
|
|
|
|
static void
|
|
@@ -900,7 +911,7 @@ static void ungrab_keyboard(SpiceDisplay *display)
|
|
* We simply issue a gdk_seat_ungrab() followed immediately by another
|
|
* gdk_seat_grab() on the pointer if the pointer grab is to be kept.
|
|
*/
|
|
- if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default())) {
|
|
+ if (GDK_IS_WAYLAND_DISPLAY(gtk_widget_get_display(GTK_WIDGET(display)))) {
|
|
SpiceDisplayPrivate *d = display->priv;
|
|
|
|
gdk_seat_ungrab(seat);
|
|
@@ -1055,15 +1066,49 @@ error:
|
|
}
|
|
#endif
|
|
|
|
+#ifdef HAVE_WAYLAND_PROTOCOLS
|
|
+static void
|
|
+relative_pointer_handle_relative_motion(void *data,
|
|
+ struct zwp_relative_pointer_v1 *pointer,
|
|
+ uint32_t time_hi,
|
|
+ uint32_t time_lo,
|
|
+ wl_fixed_t dx_w,
|
|
+ wl_fixed_t dy_w,
|
|
+ wl_fixed_t dx_unaccel_w,
|
|
+ wl_fixed_t dy_unaccel_w)
|
|
+{
|
|
+ SpiceDisplay *display = SPICE_DISPLAY(data);
|
|
+ GtkWidget *widget = GTK_WIDGET(display);
|
|
+ SpiceDisplayPrivate *d = display->priv;
|
|
+
|
|
+ if (!d->inputs)
|
|
+ return;
|
|
+ if (d->disable_inputs)
|
|
+ return;
|
|
+ /* mode changed to client in the meantime */
|
|
+ if (d->mouse_mode != SPICE_MOUSE_MODE_SERVER) {
|
|
+ spice_wayland_extensions_disable_relative_pointer(widget);
|
|
+ spice_wayland_extensions_unlock_pointer(widget);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ spice_inputs_channel_motion(d->inputs,
|
|
+ wl_fixed_to_int(dx_unaccel_w),
|
|
+ wl_fixed_to_int(dy_unaccel_w),
|
|
+ d->mouse_button_mask);
|
|
+}
|
|
+#endif
|
|
+
|
|
static gboolean do_pointer_grab(SpiceDisplay *display)
|
|
{
|
|
+ GtkWidget *widget = GTK_WIDGET(display);
|
|
SpiceDisplayPrivate *d = display->priv;
|
|
- GdkWindow *window = GDK_WINDOW(gtk_widget_get_window(GTK_WIDGET(display)));
|
|
+ GdkWindow *window = GDK_WINDOW(gtk_widget_get_window(widget));
|
|
GdkGrabStatus status;
|
|
GdkCursor *blank = spice_display_get_blank_cursor(display);
|
|
gboolean grab_successful = FALSE;
|
|
|
|
- if (!gtk_widget_get_realized(GTK_WIDGET(display)))
|
|
+ if (!gtk_widget_get_realized(widget))
|
|
goto end;
|
|
|
|
#ifdef G_OS_WIN32
|
|
@@ -1080,6 +1125,14 @@ static gboolean do_pointer_grab(SpiceDisplay *display)
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
+
|
|
+#ifdef HAVE_WAYLAND_PROTOCOLS
|
|
+ if (GDK_IS_WAYLAND_DISPLAY(gtk_widget_get_display(widget))) {
|
|
+ spice_wayland_extensions_enable_relative_pointer(widget, relative_pointer_handle_relative_motion);
|
|
+ spice_wayland_extensions_lock_pointer(widget, NULL, NULL);
|
|
+ }
|
|
+#endif
|
|
+
|
|
grab_successful = (status == GDK_GRAB_SUCCESS);
|
|
if (!grab_successful) {
|
|
d->mouse_grab_active = false;
|
|
@@ -1204,7 +1257,8 @@ static void ungrab_pointer(SpiceDisplay *display)
|
|
* immediately by another gdk_seat_grab() on the keyboard if the
|
|
* keyboard grab is to be kept.
|
|
*/
|
|
- if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default())) {
|
|
+ if (GDK_IS_WAYLAND_DISPLAY(gtk_widget_get_display(GTK_WIDGET(display)))) {
|
|
+ GtkWidget *widget = GTK_WIDGET(display);
|
|
SpiceDisplayPrivate *d = display->priv;
|
|
|
|
gdk_seat_ungrab(seat);
|
|
@@ -1213,7 +1267,7 @@ static void ungrab_pointer(SpiceDisplay *display)
|
|
GdkGrabStatus status;
|
|
|
|
status = gdk_seat_grab(seat,
|
|
- gtk_widget_get_window(GTK_WIDGET(display)),
|
|
+ gtk_widget_get_window(widget),
|
|
GDK_SEAT_CAPABILITY_KEYBOARD,
|
|
FALSE,
|
|
NULL,
|
|
@@ -1224,6 +1278,12 @@ static void ungrab_pointer(SpiceDisplay *display)
|
|
g_warning("keyboard grab failed %u", status);
|
|
d->keyboard_grab_active = false;
|
|
}
|
|
+#ifdef HAVE_WAYLAND_PROTOCOLS
|
|
+ if (d->mouse_mode == SPICE_MOUSE_MODE_SERVER) {
|
|
+ spice_wayland_extensions_disable_relative_pointer(widget);
|
|
+ spice_wayland_extensions_unlock_pointer(widget);
|
|
+ }
|
|
+#endif
|
|
}
|
|
|
|
return;
|
|
@@ -1860,21 +1920,8 @@ static gboolean leave_event(GtkWidget *widget, GdkEventCrossing *crossing G_GNUC
|
|
|
|
DISPLAY_DEBUG(display, "%s", __FUNCTION__);
|
|
|
|
- if (d->mouse_grab_active) {
|
|
-#ifdef GDK_WINDOWING_WAYLAND
|
|
- /* On Wayland, there is no active pointer grab, so once the pointer
|
|
- * has left the window, the events are routed to the window with
|
|
- * pointer focus instead of ours, in which case we should just
|
|
- * ungrab to avoid nasty side effects. */
|
|
- if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default())) {
|
|
- GdkWindow *window = gtk_widget_get_window(widget);
|
|
-
|
|
- if (window == crossing->window)
|
|
- try_mouse_ungrab(display);
|
|
- }
|
|
-#endif
|
|
+ if (d->mouse_grab_active)
|
|
return true;
|
|
- }
|
|
|
|
d->mouse_have_pointer = false;
|
|
spice_gtk_session_set_mouse_has_pointer(d->gtk_session, false);
|
|
--
|
|
2.26.2
|
|
|