Clients can lock the pointer surface wide, and receive relative pointer
events while the pointer is locked.

Signed-off-by: Jonas Ådahl <[email protected]>
---
 Makefile.am      |   4 +-
 clients/window.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 clients/window.h |  42 +++++++++++++
 3 files changed, 222 insertions(+), 1 deletion(-)

diff --git a/Makefile.am b/Makefile.am
index ed74983..cf4bf60 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -448,7 +448,9 @@ nodist_libtoytoolkit_la_SOURCES =                   \
        protocol/workspaces-protocol.c                  \
        protocol/workspaces-client-protocol.h           \
        protocol/xdg-shell-protocol.c                   \
-       protocol/xdg-shell-client-protocol.h
+       protocol/xdg-shell-client-protocol.h            \
+       protocol/pointer-lock-protocol.c                \
+       protocol/pointer-lock-client-protocol.h
 
 BUILT_SOURCES += $(nodist_libtoytoolkit_la_SOURCES)
 
diff --git a/clients/window.c b/clients/window.c
index e44d65c..d67039b 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -68,6 +68,7 @@ typedef void *EGLContext;
 #include "xdg-shell-client-protocol.h"
 #include "text-cursor-position-client-protocol.h"
 #include "workspaces-client-protocol.h"
+#include "pointer-lock-client-protocol.h"
 #include "../shared/os-compatibility.h"
 
 #include "window.h"
@@ -91,6 +92,7 @@ struct display {
        struct text_cursor_position *text_cursor_position;
        struct workspace_manager *workspace_manager;
        struct xdg_shell *xdg_shell;
+       struct _wl_pointer_lock *pointer_lock;
        EGLDisplay dpy;
        EGLConfig argb_config;
        EGLContext argb_ctx;
@@ -242,6 +244,12 @@ struct window {
        window_output_handler_t output_handler;
        window_state_changed_handler_t state_changed_handler;
 
+       pointer_lock_enter_handler_t pointer_lock_enter_handler;
+       pointer_lock_leave_handler_t pointer_lock_leave_handler;
+       pointer_lock_motion_handler_t pointer_lock_motion_handler;
+       pointer_lock_button_handler_t pointer_lock_button_handler;
+       pointer_lock_axis_handler_t pointer_lock_axis_handler;
+
        struct surface *main_surface;
        struct xdg_surface *xdg_surface;
        struct xdg_popup *xdg_popup;
@@ -254,6 +262,8 @@ struct window {
        /* struct surface::link, contains also main_surface */
        struct wl_list subsurface_list;
 
+       struct wl_pointer *locked_pointer;
+
        void *user_data;
        struct wl_list link;
 };
@@ -4384,6 +4394,169 @@ window_damage(struct window *window, int32_t x, int32_t 
y,
        wl_surface_damage(window->main_surface->surface, x, y, width, height);
 }
 
+void
+window_set_pointer_lock_enter_handler(struct window *window,
+                                     pointer_lock_enter_handler_t handler)
+{
+       window->pointer_lock_enter_handler = handler;
+}
+
+void
+window_set_pointer_lock_leave_handler(struct window *window,
+                                     pointer_lock_leave_handler_t handler)
+{
+       window->pointer_lock_leave_handler = handler;
+}
+
+void
+window_set_pointer_lock_motion_handler(struct window *window,
+                                      pointer_lock_motion_handler_t handler)
+{
+       window->pointer_lock_motion_handler = handler;
+}
+
+void
+window_set_pointer_lock_button_handler(struct window *window,
+                                      pointer_lock_button_handler_t handler)
+{
+       window->pointer_lock_button_handler = handler;
+}
+
+void
+window_set_pointer_lock_axis_handler(struct window *window,
+                                    pointer_lock_axis_handler_t handler)
+{
+       window->pointer_lock_axis_handler = handler;
+}
+
+static void
+locked_pointer_handle_enter(void *data, struct wl_pointer *pointer,
+                           uint32_t serial, struct wl_surface *surface,
+                           wl_fixed_t dx, wl_fixed_t dy)
+{
+       struct input *input = data;
+       struct window *window;
+
+       window = wl_surface_get_user_data(surface);
+       if (window->pointer_lock_enter_handler) {
+               window->pointer_lock_enter_handler(window, input,
+                                                  wl_fixed_to_double(dx),
+                                                  wl_fixed_to_double(dy),
+                                                  window->user_data);
+       }
+
+       input->display->serial = serial;
+       input->pointer_enter_serial = serial;
+       input->pointer_focus = window;
+}
+
+static void
+locked_pointer_handle_leave(void *data, struct wl_pointer *pointer,
+                           uint32_t serial, struct wl_surface *surface)
+{
+       struct input *input = data;
+       struct window *window;
+
+       window = wl_surface_get_user_data(surface);
+       if (window->pointer_lock_leave_handler) {
+               window->pointer_lock_leave_handler(window, input,
+                                                  window->user_data);
+       }
+
+       input->display->serial = serial;
+       input_remove_pointer_focus(input);
+}
+
+static void
+locked_pointer_handle_motion(void *data, struct wl_pointer *pointer,
+                            uint32_t time, wl_fixed_t dx, wl_fixed_t dy)
+{
+       struct input *input = data;
+       struct window *window;
+
+       window = input->pointer_focus;
+       if (window->pointer_lock_motion_handler) {
+               window->pointer_lock_motion_handler(window, input, time,
+                                                   wl_fixed_to_double(dx),
+                                                   wl_fixed_to_double(dy),
+                                                   window->user_data);
+       }
+}
+
+static void
+locked_pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t 
serial,
+                            uint32_t time, uint32_t button, uint32_t state_w)
+{
+       struct input *input = data;
+       struct window *window = input->pointer_focus;
+
+       if (window->pointer_lock_button_handler) {
+               window->pointer_lock_button_handler(window, input, time,
+                                                   button, state_w,
+                                                   window->user_data);
+       }
+}
+
+static void
+locked_pointer_handle_axis(void *data, struct wl_pointer *pointer,
+                          uint32_t time, uint32_t axis, wl_fixed_t value)
+{
+       struct input *input = data;
+       struct window *window = input->pointer_focus;
+
+       if (window->pointer_lock_axis_handler) {
+               window->pointer_lock_axis_handler(window, input, time,
+                                                 axis, value,
+                                                 window->user_data);
+       }
+}
+
+static const struct wl_pointer_listener pointer_lock_pointer_listener = {
+       locked_pointer_handle_enter,
+       locked_pointer_handle_leave,
+       locked_pointer_handle_motion,
+       locked_pointer_handle_button,
+       locked_pointer_handle_axis,
+};
+
+int
+window_lock_pointer(struct window *window, struct input *input)
+{
+       struct wl_pointer *locked_pointer;
+
+       if (!window->display->pointer_lock)
+               return -1;
+
+       if (!input->pointer)
+               return -1;
+
+       input_ungrab(input);
+
+       locked_pointer =
+               _wl_pointer_lock_lock_pointer(window->display->pointer_lock,
+                                             window->main_surface->surface,
+                                             input->pointer);
+       wl_pointer_set_user_data(locked_pointer, input);
+       wl_pointer_add_listener(locked_pointer,
+                               &pointer_lock_pointer_listener,
+                               input);
+
+       window->locked_pointer = locked_pointer;
+
+       return 0;
+}
+
+void
+window_unlock_pointer(struct window *window)
+{
+       if (!window->locked_pointer)
+               return;
+
+       wl_pointer_release(window->locked_pointer);
+}
+
 static void
 surface_enter(void *data,
              struct wl_surface *wl_surface, struct wl_output *wl_output)
@@ -5208,6 +5381,10 @@ registry_handle_global(void *data, struct wl_registry 
*registry, uint32_t id,
        } else if (strcmp(interface, "wl_seat") == 0) {
                d->seat_version = version;
                display_add_input(d, id);
+       } else if (strcmp(interface, "_wl_pointer_lock") == 0) {
+               d->pointer_lock = wl_registry_bind(registry, id,
+                                                  &_wl_pointer_lock_interface,
+                                                  1);
        } else if (strcmp(interface, "wl_shm") == 0) {
                d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
                wl_shm_add_listener(d->shm, &shm_listener, d);
diff --git a/clients/window.h b/clients/window.h
index 5247f19..b141c5d 100644
--- a/clients/window.h
+++ b/clients/window.h
@@ -222,6 +222,26 @@ typedef void (*window_output_handler_t)(struct window 
*window, struct output *ou
 typedef void (*window_state_changed_handler_t)(struct window *window,
                                               void *data);
 
+
+typedef void (*pointer_lock_enter_handler_t)(struct window *window,
+                                            struct input *input,
+                                            float x, float y, void *data);
+typedef void (*pointer_lock_leave_handler_t)(struct window *window,
+                                            struct input *input, void *data);
+typedef void (*pointer_lock_motion_handler_t)(struct window *window,
+                                             struct input *input, uint32_t 
time,
+                                             float x, float y, void *data);
+typedef void (*pointer_lock_button_handler_t)(struct window *window,
+                                             struct input *input, uint32_t 
time,
+                                             uint32_t button,
+                                             enum wl_pointer_button_state 
state,
+                                             void *data);
+typedef void (*pointer_lock_axis_handler_t)(struct window *window,
+                                           struct input *input, uint32_t time,
+                                           uint32_t axis,
+                                           wl_fixed_t value,
+                                           void *data);
+
 typedef void (*widget_resize_handler_t)(struct widget *widget,
                                        int32_t width, int32_t height,
                                        void *data);
@@ -351,6 +371,12 @@ void
 window_damage(struct window *window, int32_t x, int32_t y,
              int32_t width, int32_t height);
 
+int
+window_lock_pointer(struct window *window, struct input *input);
+
+void
+window_unlock_pointer(struct window *window);
+
 cairo_surface_t *
 window_get_surface(struct window *window);
 
@@ -446,6 +472,22 @@ void
 window_set_preferred_format(struct window *window,
                            enum preferred_format format);
 
+void
+window_set_pointer_lock_enter_handler(struct window *window,
+                                     pointer_lock_enter_handler_t handler);
+void
+window_set_pointer_lock_leave_handler(struct window *window,
+                                     pointer_lock_leave_handler_t handler);
+void
+window_set_pointer_lock_motion_handler(struct window *window,
+                                      pointer_lock_motion_handler_t handler);
+void
+window_set_pointer_lock_button_handler(struct window *window,
+                                      pointer_lock_button_handler_t handler);
+void
+window_set_pointer_lock_axis_handler(struct window *window,
+                                    pointer_lock_axis_handler_t handler);
+
 int
 widget_set_tooltip(struct widget *parent, char *entry, float x, float y);
 
-- 
1.8.5.1

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to