Blame SOURCES/0006-wayland-add-wayland-extensions-functions.patch

be82ae
From 19e0922572cee7bda989a82407208eac8a41b47f Mon Sep 17 00:00:00 2001
be82ae
From: Francesco Giudici <fgiudici@redhat.com>
be82ae
Date: Tue, 28 Mar 2017 15:07:16 +0200
be82ae
Subject: [PATCH 6/9] wayland: add wayland-extensions functions
be82ae
be82ae
add utilities to lock the pointer to a window and to get relative mouse
be82ae
movement in Wayland. This is made possible thanks to the wayland
be82ae
protocols introduced in the previous commit.
be82ae
be82ae
Code freely taken and adapted from Christophe Fergeau branch:
be82ae
https://gitlab.freedesktop.org/teuf/spice-gtk/-/tree/wayland
be82ae
be82ae
Signed-off-by: Francesco Giudici <fgiudici@redhat.com>
be82ae
Acked-by: Frediano Ziglio <fziglio@redhat.com>
be82ae
(cherry picked from commit 59d5c92c74da0f452b9104191bb752c33d26ec77)
be82ae
---
be82ae
 src/meson.build          |   5 +
be82ae
 src/wayland-extensions.c | 235 +++++++++++++++++++++++++++++++++++++++
be82ae
 src/wayland-extensions.h |  32 ++++++
be82ae
 3 files changed, 272 insertions(+)
be82ae
 create mode 100644 src/wayland-extensions.c
be82ae
 create mode 100644 src/wayland-extensions.h
be82ae
be82ae
diff --git a/src/meson.build b/src/meson.build
be82ae
index bdd2239..16810a7 100644
be82ae
--- a/src/meson.build
be82ae
+++ b/src/meson.build
be82ae
@@ -374,6 +374,11 @@ if spice_gtk_has_gtk
be82ae
         message('@0@ @1@: @2@ -> @3@'.format(prog_scanner, output_type, xml_path, output_file))
be82ae
       endforeach
be82ae
     endforeach
be82ae
+
be82ae
+    spice_client_gtk_sources += [
be82ae
+      'wayland-extensions.c',
be82ae
+      'wayland-extensions.h',
be82ae
+    ]
be82ae
   endif
be82ae
 
be82ae
   #
be82ae
diff --git a/src/wayland-extensions.c b/src/wayland-extensions.c
be82ae
new file mode 100644
be82ae
index 0000000..64b5139
be82ae
--- /dev/null
be82ae
+++ b/src/wayland-extensions.c
be82ae
@@ -0,0 +1,235 @@
be82ae
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
be82ae
+/*
be82ae
+   Copyright (C) 2017 Red Hat, Inc.
be82ae
+
be82ae
+   This library is free software; you can redistribute it and/or
be82ae
+   modify it under the terms of the GNU Lesser General Public
be82ae
+   License as published by the Free Software Foundation; either
be82ae
+   version 2.1 of the License, or (at your option) any later version.
be82ae
+
be82ae
+   This library is distributed in the hope that it will be useful,
be82ae
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
be82ae
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
be82ae
+   Lesser General Public License for more details.
be82ae
+
be82ae
+   You should have received a copy of the GNU Lesser General Public
be82ae
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
be82ae
+*/
be82ae
+
be82ae
+#include <config.h>
be82ae
+
be82ae
+#include <stdint.h>
be82ae
+#include <string.h>
be82ae
+
be82ae
+#include <gtk/gtk.h>
be82ae
+
be82ae
+#include <gdk/gdkwayland.h>
be82ae
+#include "pointer-constraints-unstable-v1-client-protocol.h"
be82ae
+#include "relative-pointer-unstable-v1-client-protocol.h"
be82ae
+
be82ae
+#include "wayland-extensions.h"
be82ae
+
be82ae
+static void *
be82ae
+gtk_wl_registry_bind(GtkWidget *widget,
be82ae
+                     uint32_t name,
be82ae
+                     const struct wl_interface *interface,
be82ae
+                     uint32_t version)
be82ae
+{
be82ae
+    GdkDisplay *gdk_display = gtk_widget_get_display(widget);
be82ae
+    struct wl_display *display;
be82ae
+    struct wl_registry *registry;
be82ae
+
be82ae
+    if (!GDK_IS_WAYLAND_DISPLAY(gdk_display)) {
be82ae
+        return NULL;
be82ae
+    }
be82ae
+
be82ae
+    display = gdk_wayland_display_get_wl_display(gdk_display);
be82ae
+    registry = wl_display_get_registry(display);
be82ae
+
be82ae
+    return wl_registry_bind(registry, name, interface, version);
be82ae
+}
be82ae
+
be82ae
+static void
be82ae
+gtk_wl_registry_add_listener(GtkWidget *widget, const struct wl_registry_listener *listener)
be82ae
+{
be82ae
+    GdkDisplay *gdk_display = gtk_widget_get_display(widget);
be82ae
+    struct wl_display *display;
be82ae
+    struct wl_registry *registry;
be82ae
+
be82ae
+    if (!GDK_IS_WAYLAND_DISPLAY(gdk_display)) {
be82ae
+        return;
be82ae
+    }
be82ae
+
be82ae
+    display = gdk_wayland_display_get_wl_display(gdk_display);
be82ae
+    registry = wl_display_get_registry(display);
be82ae
+    wl_registry_add_listener(registry, listener, widget);
be82ae
+    wl_display_roundtrip(display);
be82ae
+}
be82ae
+
be82ae
+
be82ae
+static void
be82ae
+registry_handle_global(void *data,
be82ae
+                       struct wl_registry *registry,
be82ae
+                       uint32_t name,
be82ae
+                       const char *interface,
be82ae
+                       uint32_t version)
be82ae
+{
be82ae
+    GtkWidget *widget = GTK_WIDGET(data);
be82ae
+
be82ae
+    if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0) {
be82ae
+        struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
be82ae
+        relative_pointer_manager = gtk_wl_registry_bind(widget, name,
be82ae
+                                                        &zwp_relative_pointer_manager_v1_interface,
be82ae
+                                                        1);
be82ae
+        g_object_set_data_full(G_OBJECT(widget),
be82ae
+                               "zwp_relative_pointer_manager_v1",
be82ae
+                               relative_pointer_manager,
be82ae
+                               (GDestroyNotify)zwp_relative_pointer_manager_v1_destroy);
be82ae
+    } else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0) {
be82ae
+        struct zwp_pointer_constraints_v1 *pointer_constraints;
be82ae
+        pointer_constraints = gtk_wl_registry_bind(widget, name,
be82ae
+                                                   &zwp_pointer_constraints_v1_interface,
be82ae
+                                                   1);
be82ae
+        g_object_set_data_full(G_OBJECT(widget),
be82ae
+                               "zwp_pointer_constraints_v1",
be82ae
+                               pointer_constraints,
be82ae
+                               (GDestroyNotify)zwp_pointer_constraints_v1_destroy);
be82ae
+    }
be82ae
+}
be82ae
+
be82ae
+static void
be82ae
+registry_handle_global_remove(void *data,
be82ae
+                              struct wl_registry *registry,
be82ae
+                              uint32_t name)
be82ae
+{
be82ae
+}
be82ae
+
be82ae
+static const struct wl_registry_listener registry_listener = {
be82ae
+    registry_handle_global,
be82ae
+    registry_handle_global_remove
be82ae
+};
be82ae
+
be82ae
+void
be82ae
+spice_wayland_extensions_init(GtkWidget *widget)
be82ae
+{
be82ae
+    g_return_if_fail(GTK_IS_WIDGET(widget));
be82ae
+
be82ae
+    gtk_wl_registry_add_listener(widget, &registry_listener);
be82ae
+}
be82ae
+
be82ae
+
be82ae
+static GdkDevice *
be82ae
+spice_gdk_window_get_pointing_device(GdkWindow *window)
be82ae
+{
be82ae
+    GdkDisplay *gdk_display = gdk_window_get_display(window);
be82ae
+
be82ae
+    return gdk_seat_get_pointer(gdk_display_get_default_seat(gdk_display));
be82ae
+}
be82ae
+
be82ae
+static struct zwp_relative_pointer_v1_listener relative_pointer_listener;
be82ae
+
be82ae
+// NOTE this API works only on a single widget per application
be82ae
+int
be82ae
+spice_wayland_extensions_enable_relative_pointer(GtkWidget *widget,
be82ae
+                                                 void (*cb)(void *,
be82ae
+                                                            struct zwp_relative_pointer_v1 *,
be82ae
+                                                            uint32_t, uint32_t,
be82ae
+                                                            wl_fixed_t, wl_fixed_t, wl_fixed_t, wl_fixed_t))
be82ae
+{
be82ae
+    struct zwp_relative_pointer_v1 *relative_pointer;
be82ae
+
be82ae
+    g_return_val_if_fail(GTK_IS_WIDGET(widget), -1);
be82ae
+
be82ae
+    relative_pointer = g_object_get_data(G_OBJECT(widget), "zwp_relative_pointer_v1");
be82ae
+
be82ae
+    if (relative_pointer == NULL) {
be82ae
+        struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
be82ae
+        GdkWindow *window = gtk_widget_get_window(widget);
be82ae
+        struct wl_pointer *pointer;
be82ae
+
be82ae
+        relative_pointer_manager = g_object_get_data(G_OBJECT(widget), "zwp_relative_pointer_manager_v1");
be82ae
+        if (relative_pointer_manager == NULL)
be82ae
+            return -1;
be82ae
+
be82ae
+        pointer = gdk_wayland_device_get_wl_pointer(spice_gdk_window_get_pointing_device(window));
be82ae
+        relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(relative_pointer_manager,
be82ae
+                                                                                pointer);
be82ae
+
be82ae
+        relative_pointer_listener.relative_motion = cb;
be82ae
+        zwp_relative_pointer_v1_add_listener(relative_pointer,
be82ae
+                                             &relative_pointer_listener,
be82ae
+                                             widget);
be82ae
+
be82ae
+        g_object_set_data_full(G_OBJECT(widget),
be82ae
+                               "zwp_relative_pointer_v1",
be82ae
+                               relative_pointer,
be82ae
+                               (GDestroyNotify)zwp_relative_pointer_v1_destroy);
be82ae
+    }
be82ae
+
be82ae
+    return 0;
be82ae
+}
be82ae
+
be82ae
+int spice_wayland_extensions_disable_relative_pointer(GtkWidget *widget)
be82ae
+{
be82ae
+    g_return_val_if_fail(GTK_IS_WIDGET(widget), -1);
be82ae
+
be82ae
+    /* This will call zwp_relative_pointer_v1_destroy() and stop relative
be82ae
+     * movement */
be82ae
+    g_object_set_data(G_OBJECT(widget), "zwp_relative_pointer_v1", NULL);
be82ae
+
be82ae
+    return 0;
be82ae
+}
be82ae
+
be82ae
+static struct zwp_locked_pointer_v1_listener locked_pointer_listener;
be82ae
+
be82ae
+// NOTE this API works only on a single widget per application
be82ae
+int
be82ae
+spice_wayland_extensions_lock_pointer(GtkWidget *widget,
be82ae
+                                      void (*lock_cb)(void *, struct zwp_locked_pointer_v1 *),
be82ae
+                                      void (*unlock_cb)(void *, struct zwp_locked_pointer_v1 *))
be82ae
+{
be82ae
+    struct zwp_pointer_constraints_v1 *pointer_constraints;
be82ae
+    struct zwp_locked_pointer_v1 *locked_pointer;
be82ae
+    GdkWindow *window;
be82ae
+    struct wl_pointer *pointer;
be82ae
+
be82ae
+    g_return_val_if_fail(GTK_IS_WIDGET(widget), -1);
be82ae
+
be82ae
+    pointer_constraints = g_object_get_data(G_OBJECT(widget), "zwp_pointer_constraints_v1");
be82ae
+    locked_pointer = g_object_get_data(G_OBJECT(widget), "zwp_locked_pointer_v1");
be82ae
+    if (locked_pointer != NULL) {
be82ae
+        /* A previous lock already in place */
be82ae
+        return 0;
be82ae
+    }
be82ae
+
be82ae
+    window = gtk_widget_get_window(widget);
be82ae
+    pointer = gdk_wayland_device_get_wl_pointer(spice_gdk_window_get_pointing_device(window));
be82ae
+    locked_pointer = zwp_pointer_constraints_v1_lock_pointer(pointer_constraints,
be82ae
+                                                             gdk_wayland_window_get_wl_surface(window),
be82ae
+                                                             pointer,
be82ae
+                                                             NULL,
be82ae
+                                                             ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
be82ae
+    if (lock_cb || unlock_cb) {
be82ae
+        locked_pointer_listener.locked = lock_cb;
be82ae
+        locked_pointer_listener.unlocked = unlock_cb;
be82ae
+        zwp_locked_pointer_v1_add_listener(locked_pointer,
be82ae
+                                           &locked_pointer_listener,
be82ae
+                                           widget);
be82ae
+    }
be82ae
+    g_object_set_data_full(G_OBJECT(widget),
be82ae
+                           "zwp_locked_pointer_v1",
be82ae
+                           locked_pointer,
be82ae
+                           (GDestroyNotify)zwp_locked_pointer_v1_destroy);
be82ae
+
be82ae
+    return 0;
be82ae
+}
be82ae
+
be82ae
+int
be82ae
+spice_wayland_extensions_unlock_pointer(GtkWidget *widget)
be82ae
+{
be82ae
+    g_return_val_if_fail(GTK_IS_WIDGET(widget), -1);
be82ae
+
be82ae
+    g_object_set_data(G_OBJECT(widget), "zwp_locked_pointer_v1", NULL);
be82ae
+
be82ae
+    return 0;
be82ae
+}
be82ae
diff --git a/src/wayland-extensions.h b/src/wayland-extensions.h
be82ae
new file mode 100644
be82ae
index 0000000..bf34044
be82ae
--- /dev/null
be82ae
+++ b/src/wayland-extensions.h
be82ae
@@ -0,0 +1,32 @@
be82ae
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
be82ae
+/*
be82ae
+   Copyright (C) 2017 Red Hat, Inc.
be82ae
+
be82ae
+   This library is free software; you can redistribute it and/or
be82ae
+   modify it under the terms of the GNU Lesser General Public
be82ae
+   License as published by the Free Software Foundation; either
be82ae
+   version 2.1 of the License, or (at your option) any later version.
be82ae
+
be82ae
+   This library is distributed in the hope that it will be useful,
be82ae
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
be82ae
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
be82ae
+   Lesser General Public License for more details.
be82ae
+
be82ae
+   You should have received a copy of the GNU Lesser General Public
be82ae
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
be82ae
+*/
be82ae
+#pragma once
be82ae
+
be82ae
+#include <gtk/gtk.h>
be82ae
+
be82ae
+void spice_wayland_extensions_init(GtkWidget *widget);
be82ae
+int spice_wayland_extensions_enable_relative_pointer(GtkWidget *widget,
be82ae
+                                                     void (*cb)(void *,
be82ae
+                                                                struct zwp_relative_pointer_v1 *,
be82ae
+                                                                uint32_t, uint32_t,
be82ae
+                                                                wl_fixed_t, wl_fixed_t, wl_fixed_t, wl_fixed_t));
be82ae
+int spice_wayland_extensions_disable_relative_pointer(GtkWidget *widget);
be82ae
+int spice_wayland_extensions_lock_pointer(GtkWidget *widget,
be82ae
+                                          void (*lock_cb)(void *, struct zwp_locked_pointer_v1 *),
be82ae
+                                          void (*unlock_cb)(void *, struct zwp_locked_pointer_v1 *));
be82ae
+int spice_wayland_extensions_unlock_pointer(GtkWidget *widget);
be82ae
-- 
be82ae
2.26.2
be82ae