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
