# HG changeset patch # User Jonas Ã…dahl # Date 1466685442 -28800 # Thu Jun 23 20:37:22 2016 +0800 # Branch pointer-lock-v4 # Node ID a6ea023741629a0c6a4c68f36715a27735c21d87 # Parent 392c7c4d478e1d6f3115da6e60fc5c10e92a5679 wayland: Add support for relative mouse mode Generate the C protocol files from the protocol XML files installed by wayland-protocols, and use them to implement support for relative pointer motions and pointer locking. Note that at the time, the protocol is unstable and may change in the future. Any future breaking changes will, however, fail gracefully and result in no regressions compared to before this patch. diff -r 392c7c4d478e -r a6ea02374162 configure --- a/configure Thu Jun 23 18:39:05 2016 +0800 +++ b/configure Thu Jun 23 20:37:22 2016 +0800 @@ -18807,11 +18807,12 @@ if test x$PKG_CONFIG != xno && \ test x$video_opengl_egl = xyes && \ test x$video_opengles_v2 = xyes; then - if $PKG_CONFIG --exists wayland-client wayland-scanner wayland-egl wayland-cursor egl xkbcommon ; then + if $PKG_CONFIG --exists wayland-client wayland-scanner wayland-protocols wayland-egl wayland-cursor egl xkbcommon ; then WAYLAND_CFLAGS=`$PKG_CONFIG --cflags wayland-client wayland-egl wayland-cursor xkbcommon` WAYLAND_LIBS=`$PKG_CONFIG --libs wayland-client wayland-egl wayland-cursor xkbcommon` WAYLAND_SCANNER=`$PKG_CONFIG --variable=wayland_scanner wayland-scanner` WAYLAND_CORE_PROTOCOL_DIR=`$PKG_CONFIG --variable=pkgdatadir wayland-client` + WAYLAND_PROTOCOLS_DIR=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols` video_wayland=yes fi fi @@ -18827,6 +18828,9 @@ $as_echo "#define SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH 1" >>confdefs.h fi + + WAYLAND_PROTOCOLS_UNSTABLE="relative-pointer-unstable-v1 pointer-constraints-unstable-v1" + SOURCES="$SOURCES $srcdir/src/video/wayland/*.c" EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS -I\$(gen)" # Check whether --enable-wayland-shared was given. @@ -23736,8 +23740,12 @@ if test x$video_wayland = xyes; then WAYLAND_CORE_PROTOCOL_SOURCE='$(gen)/wayland-protocol.c' WAYLAND_CORE_PROTOCOL_HEADER='$(gen)/wayland-client-protocol.h' - GEN_SOURCES="$GEN_SOURCES $WAYLAND_CORE_PROTOCOL_SOURCE" - GEN_HEADERS="$GEN_HEADERS $WAYLAND_CORE_PROTOCOL_HEADER" + WAYLAND_PROTOCOLS_UNSTABLE_SOURCES=`echo $WAYLAND_PROTOCOLS_UNSTABLE |\ + sed 's,[^ ]\+,\\$(gen)/&-protocol.c,g'` + WAYLAND_PROTOCOLS_UNSTABLE_HEADERS=`echo $WAYLAND_PROTOCOLS_UNSTABLE |\ + sed 's,[^ ]\+,\\$(gen)/&-client-protocol.h,g'` + GEN_SOURCES="$GEN_SOURCES $WAYLAND_CORE_PROTOCOL_SOURCE $WAYLAND_PROTOCOLS_UNSTABLE_SOURCES" + GEN_HEADERS="$GEN_HEADERS $WAYLAND_CORE_PROTOCOL_HEADER $WAYLAND_PROTOCOLS_UNSTABLE_HEADERS" WAYLAND_CORE_PROTOCOL_SOURCE_DEPENDS=" $WAYLAND_CORE_PROTOCOL_SOURCE: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml @@ -23753,10 +23761,30 @@ \$(objects)/`echo $WAYLAND_CORE_PROTOCOL_SOURCE | sed 's/\$(gen)\/\(.*\).c$/\1.lo/'`: $WAYLAND_CORE_PROTOCOL_SOURCE \$(RUN_CMD_CC)\$(LIBTOOL) --tag=CC --mode=compile \$(CC) \$(CFLAGS) \$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \$< -o \$@" + WAYLAND_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\ + do echo ; echo \$p | sed\ + "s,^\\([a-z\\-]\\+\\)-unstable-\\(v[0-9]\+\\)\$,\\$(gen)/&-client-protocol.h: $WAYLAND_PROTOCOLS_DIR/unstable/\1/&.xml\\\\ + \\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\ + \\$(RUN_CMD_GEN)\\$(WAYLAND_SCANNER) client-header \\$< \\$@," ; done` + + WAYLAND_PROTOCOLS_CODE_UNSTABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\ + do echo ; echo \$p | sed\ + "s,^\\([a-z\\-]\\+\\)-unstable-\\(v[0-9]\+\\)\$,\\$(gen)/&-protocol.c: $WAYLAND_PROTOCOLS_DIR/unstable/\1/&.xml\\\\ + \\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\ + \\$(RUN_CMD_GEN)\\$(WAYLAND_SCANNER) code \\$< \\$@," ; done` + + WAYLAND_PROTOCOLS_OBJECTS_UNSTABLE=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\ + do echo ; echo \$p | sed\ + "s,^\\([a-z\\-]\\+\\)-unstable-\\(v[0-9]\+\\)\$,\\\$(objects)/&-protocol.lo: \\$(gen)/&-protocol.c \\$(gen)/&-client-protocol.h\\\\ + \\$(RUN_CMD_CC)\\$(LIBTOOL) --tag=CC --mode=compile \\$(CC) \\$(CFLAGS) \\$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \\$< -o \\$@," ; done` + WAYLAND_PROTOCOLS_DEPENDS=" $WAYLAND_CORE_PROTOCOL_SOURCE_DEPENDS $WAYLAND_CORE_PROTOCOL_HEADER_DEPENDS $WAYLAND_CORE_PROTOCOL_OBJECT +$WAYLAND_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS +$WAYLAND_PROTOCOLS_CODE_UNSTABLE_DEPENDS +$WAYLAND_PROTOCOLS_OBJECTS_UNSTABLE " fi diff -r 392c7c4d478e -r a6ea02374162 configure.in --- a/configure.in Thu Jun 23 18:39:05 2016 +0800 +++ b/configure.in Thu Jun 23 20:37:22 2016 +0800 @@ -1201,11 +1201,12 @@ if test x$PKG_CONFIG != xno && \ test x$video_opengl_egl = xyes && \ test x$video_opengles_v2 = xyes; then - if $PKG_CONFIG --exists wayland-client wayland-scanner wayland-egl wayland-cursor egl xkbcommon ; then + if $PKG_CONFIG --exists wayland-client wayland-scanner wayland-protocols wayland-egl wayland-cursor egl xkbcommon ; then WAYLAND_CFLAGS=`$PKG_CONFIG --cflags wayland-client wayland-egl wayland-cursor xkbcommon` WAYLAND_LIBS=`$PKG_CONFIG --libs wayland-client wayland-egl wayland-cursor xkbcommon` WAYLAND_SCANNER=`$PKG_CONFIG --variable=wayland_scanner wayland-scanner` WAYLAND_CORE_PROTOCOL_DIR=`$PKG_CONFIG --variable=pkgdatadir wayland-client` + WAYLAND_PROTOCOLS_DIR=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols` video_wayland=yes fi fi @@ -1216,6 +1217,9 @@ if test x$enable_video_wayland_qt_touch = xyes; then AC_DEFINE(SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH, 1, [ ]) fi + + WAYLAND_PROTOCOLS_UNSTABLE="relative-pointer-unstable-v1 pointer-constraints-unstable-v1" + SOURCES="$SOURCES $srcdir/src/video/wayland/*.c" EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS -I\$(gen)" AC_ARG_ENABLE(wayland-shared, @@ -3486,8 +3490,12 @@ if test x$video_wayland = xyes; then WAYLAND_CORE_PROTOCOL_SOURCE='$(gen)/wayland-protocol.c' WAYLAND_CORE_PROTOCOL_HEADER='$(gen)/wayland-client-protocol.h' - GEN_SOURCES="$GEN_SOURCES $WAYLAND_CORE_PROTOCOL_SOURCE" - GEN_HEADERS="$GEN_HEADERS $WAYLAND_CORE_PROTOCOL_HEADER" + WAYLAND_PROTOCOLS_UNSTABLE_SOURCES=`echo $WAYLAND_PROTOCOLS_UNSTABLE |\ + sed 's,[[^ ]]\+,\\$(gen)/&-protocol.c,g'` + WAYLAND_PROTOCOLS_UNSTABLE_HEADERS=`echo $WAYLAND_PROTOCOLS_UNSTABLE |\ + sed 's,[[^ ]]\+,\\$(gen)/&-client-protocol.h,g'` + GEN_SOURCES="$GEN_SOURCES $WAYLAND_CORE_PROTOCOL_SOURCE $WAYLAND_PROTOCOLS_UNSTABLE_SOURCES" + GEN_HEADERS="$GEN_HEADERS $WAYLAND_CORE_PROTOCOL_HEADER $WAYLAND_PROTOCOLS_UNSTABLE_HEADERS" WAYLAND_CORE_PROTOCOL_SOURCE_DEPENDS=" $WAYLAND_CORE_PROTOCOL_SOURCE: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml @@ -3503,10 +3511,30 @@ \$(objects)/`echo $WAYLAND_CORE_PROTOCOL_SOURCE | sed 's/\$(gen)\/\(.*\).c$/\1.lo/'`: $WAYLAND_CORE_PROTOCOL_SOURCE \$(RUN_CMD_CC)\$(LIBTOOL) --tag=CC --mode=compile \$(CC) \$(CFLAGS) \$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \$< -o \$@" + WAYLAND_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\ + do echo ; echo \$p | sed\ + "s,^\\([[a-z\\-]]\\+\\)-unstable-\\(v[[0-9]]\+\\)\$,\\$(gen)/&-client-protocol.h: $WAYLAND_PROTOCOLS_DIR/unstable/\1/&.xml\\\\ + \\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\ + \\$(RUN_CMD_GEN)\\$(WAYLAND_SCANNER) client-header \\$< \\$@," ; done` + + WAYLAND_PROTOCOLS_CODE_UNSTABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\ + do echo ; echo \$p | sed\ + "s,^\\([[a-z\\-]]\\+\\)-unstable-\\(v[[0-9]]\+\\)\$,\\$(gen)/&-protocol.c: $WAYLAND_PROTOCOLS_DIR/unstable/\1/&.xml\\\\ + \\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\ + \\$(RUN_CMD_GEN)\\$(WAYLAND_SCANNER) code \\$< \\$@," ; done` + + WAYLAND_PROTOCOLS_OBJECTS_UNSTABLE=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\ + do echo ; echo \$p | sed\ + "s,^\\([[a-z\\-]]\\+\\)-unstable-\\(v[[0-9]]\+\\)\$,\\\$(objects)/&-protocol.lo: \\$(gen)/&-protocol.c \\$(gen)/&-client-protocol.h\\\\ + \\$(RUN_CMD_CC)\\$(LIBTOOL) --tag=CC --mode=compile \\$(CC) \\$(CFLAGS) \\$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \\$< -o \\$@," ; done` + WAYLAND_PROTOCOLS_DEPENDS=" $WAYLAND_CORE_PROTOCOL_SOURCE_DEPENDS $WAYLAND_CORE_PROTOCOL_HEADER_DEPENDS $WAYLAND_CORE_PROTOCOL_OBJECT +$WAYLAND_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS +$WAYLAND_PROTOCOLS_CODE_UNSTABLE_DEPENDS +$WAYLAND_PROTOCOLS_OBJECTS_UNSTABLE " fi diff -r 392c7c4d478e -r a6ea02374162 src/video/wayland/SDL_waylandevents.c --- a/src/video/wayland/SDL_waylandevents.c Thu Jun 23 18:39:05 2016 +0800 +++ b/src/video/wayland/SDL_waylandevents.c Thu Jun 23 20:37:22 2016 +0800 @@ -25,6 +25,7 @@ #include "SDL_stdinc.h" #include "SDL_assert.h" +#include "SDL_log.h" #include "../../events/SDL_sysevents.h" #include "../../events/SDL_events_c.h" @@ -36,6 +37,9 @@ #include "SDL_waylanddyn.h" +#include "pointer-constraints-unstable-v1-client-protocol.h" +#include "relative-pointer-unstable-v1-client-protocol.h" + #include #include #include @@ -48,13 +52,17 @@ struct wl_seat *seat; struct wl_pointer *pointer; struct wl_keyboard *keyboard; + struct zwp_relative_pointer_v1 *relative_pointer; SDL_WindowData *pointer_focus; SDL_WindowData *keyboard_focus; /* Last motion location */ wl_fixed_t sx_w; wl_fixed_t sy_w; - + + double dx_frac; + double dy_frac; + struct { struct xkb_keymap *keymap; struct xkb_state *state; @@ -170,10 +178,9 @@ } static void -pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial, - uint32_t time, uint32_t button, uint32_t state_w) +pointer_handle_button_common(struct SDL_WaylandInput *input, uint32_t serial, + uint32_t time, uint32_t button, uint32_t state_w) { - struct SDL_WaylandInput *input = data; SDL_WindowData *window = input->pointer_focus; enum wl_pointer_button_state state = state_w; uint32_t sdl_button; @@ -182,7 +189,7 @@ switch (button) { case BTN_LEFT: sdl_button = SDL_BUTTON_LEFT; - if (ProcessHitTest(data, serial)) { + if (ProcessHitTest(input, serial)) { return; /* don't pass this event on to app. */ } break; @@ -208,10 +215,18 @@ } static void -pointer_handle_axis(void *data, struct wl_pointer *pointer, - uint32_t time, uint32_t axis, wl_fixed_t value) +pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial, + uint32_t time, uint32_t button, uint32_t state_w) { struct SDL_WaylandInput *input = data; + + pointer_handle_button_common(input, serial, time, button, state_w); +} + +static void +pointer_handle_axis_common(struct SDL_WaylandInput *input, + uint32_t time, uint32_t axis, wl_fixed_t value) +{ SDL_WindowData *window = input->pointer_focus; enum wl_pointer_axis a = axis; int x, y; @@ -234,6 +249,15 @@ } } +static void +pointer_handle_axis(void *data, struct wl_pointer *pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) +{ + struct SDL_WaylandInput *input = data; + + pointer_handle_axis_common(input, time, axis, value); +} + static const struct wl_pointer_listener pointer_listener = { pointer_handle_enter, pointer_handle_leave, @@ -453,6 +477,164 @@ d->input = NULL; } +void Wayland_display_add_relative_pointer_manager(SDL_VideoData *d, uint32_t id) +{ + d->relative_pointer_manager = + wl_registry_bind(d->registry, id, + &zwp_relative_pointer_manager_v1_interface, 1); +} + +void Wayland_display_destroy_relative_pointer_manager(SDL_VideoData *d) +{ + if (d->relative_pointer_manager) + zwp_relative_pointer_manager_v1_destroy(d->relative_pointer_manager); +} + +void Wayland_display_add_pointer_constraints(SDL_VideoData *d, uint32_t id) +{ + d->pointer_constraints = + wl_registry_bind(d->registry, id, + &zwp_pointer_constraints_v1_interface, 1); +} + +void Wayland_display_destroy_pointer_constraints(SDL_VideoData *d) +{ + if (d->pointer_constraints) + zwp_pointer_constraints_v1_destroy(d->pointer_constraints); +} + +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) +{ + struct SDL_WaylandInput *input = data; + SDL_VideoData *d = input->display; + SDL_WindowData *window = input->pointer_focus; + double dx_unaccel; + double dy_unaccel; + double dx; + double dy; + + dx_unaccel = wl_fixed_to_double(dx_unaccel_w); + dy_unaccel = wl_fixed_to_double(dy_unaccel_w); + + /* Add left over fraction from last event. */ + dx_unaccel += input->dx_frac; + dy_unaccel += input->dy_frac; + + input->dx_frac = modf(dx_unaccel, &dx); + input->dy_frac = modf(dy_unaccel, &dy); + + if (input->pointer_focus && d->relative_mouse_mode) { + SDL_SendMouseMotion(window->sdlwindow, 0, 1, (int)dx, (int)dy); + } +} + +static const struct zwp_relative_pointer_v1_listener relative_pointer_listener = { + relative_pointer_handle_relative_motion, +}; + +static void +locked_pointer_locked(void *data, + struct zwp_locked_pointer_v1 *locked_pointer) +{ +} + +static void +locked_pointer_unlocked(void *data, + struct zwp_locked_pointer_v1 *locked_pointer) +{ +} + +static const struct zwp_locked_pointer_v1_listener locked_pointer_listener = { + locked_pointer_locked, + locked_pointer_unlocked, +}; + +static void +lock_pointer_to_window(SDL_Window *window, + struct SDL_WaylandInput *input) +{ + SDL_WindowData *w = window->driverdata; + SDL_VideoData *d = input->display; + struct zwp_locked_pointer_v1 *locked_pointer; + + if (w->locked_pointer) + return; + + locked_pointer = + zwp_pointer_constraints_v1_lock_pointer(d->pointer_constraints, + w->surface, + input->pointer, + NULL, + ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); + zwp_locked_pointer_v1_add_listener(locked_pointer, + &locked_pointer_listener, + window); + + w->locked_pointer = locked_pointer; +} + +int Wayland_input_lock_pointer(struct SDL_WaylandInput *input) +{ + SDL_VideoDevice *vd = SDL_GetVideoDevice(); + SDL_VideoData *d = input->display; + SDL_Window *window; + struct zwp_relative_pointer_v1 *relative_pointer; + + if (!d->relative_pointer_manager) + return -1; + + if (!d->pointer_constraints) + return -1; + + if (!input->relative_pointer) { + relative_pointer = + zwp_relative_pointer_manager_v1_get_relative_pointer( + d->relative_pointer_manager, + input->pointer); + zwp_relative_pointer_v1_add_listener(relative_pointer, + &relative_pointer_listener, + input); + input->relative_pointer = relative_pointer; + } + + for (window = vd->windows; window; window = window->next) + lock_pointer_to_window(window, input); + + d->relative_mouse_mode = 1; + + return 0; +} + +int Wayland_input_unlock_pointer(struct SDL_WaylandInput *input) +{ + SDL_VideoDevice *vd = SDL_GetVideoDevice(); + SDL_VideoData *d = input->display; + SDL_Window *window; + SDL_WindowData *w; + + for (window = vd->windows; window; window = window->next) { + w = window->driverdata; + if (w->locked_pointer) + zwp_locked_pointer_v1_destroy(w->locked_pointer); + w->locked_pointer = NULL; + } + + zwp_relative_pointer_v1_destroy(input->relative_pointer); + input->relative_pointer = NULL; + + d->relative_mouse_mode = 0; + + return 0; +} + #endif /* SDL_VIDEO_DRIVER_WAYLAND */ /* vi: set ts=4 sw=4 expandtab: */ diff -r 392c7c4d478e -r a6ea02374162 src/video/wayland/SDL_waylandevents_c.h --- a/src/video/wayland/SDL_waylandevents_c.h Thu Jun 23 18:39:05 2016 +0800 +++ b/src/video/wayland/SDL_waylandevents_c.h Thu Jun 23 20:37:22 2016 +0800 @@ -32,6 +32,15 @@ extern void Wayland_display_add_input(SDL_VideoData *d, uint32_t id); extern void Wayland_display_destroy_input(SDL_VideoData *d); +extern void Wayland_display_add_pointer_constraints(SDL_VideoData *d, uint32_t id); +extern void Wayland_display_destroy_pointer_constraints(SDL_VideoData *d); + +extern int Wayland_input_lock_pointer(struct SDL_WaylandInput *input); +extern int Wayland_input_unlock_pointer(struct SDL_WaylandInput *input); + +extern void Wayland_display_add_relative_pointer_manager(SDL_VideoData *d, uint32_t id); +extern void Wayland_display_destroy_relative_pointer_manager(SDL_VideoData *d); + #endif /* _SDL_waylandevents_h */ /* vi: set ts=4 sw=4 expandtab: */ diff -r 392c7c4d478e -r a6ea02374162 src/video/wayland/SDL_waylandmouse.c --- a/src/video/wayland/SDL_waylandmouse.c Thu Jun 23 18:39:05 2016 +0800 +++ b/src/video/wayland/SDL_waylandmouse.c Thu Jun 23 20:37:22 2016 +0800 @@ -365,7 +365,13 @@ static int Wayland_SetRelativeMouseMode(SDL_bool enabled) { - return SDL_Unsupported(); + SDL_VideoDevice *vd = SDL_GetVideoDevice(); + SDL_VideoData *data = (SDL_VideoData *) vd->driverdata; + + if (enabled) + return Wayland_input_lock_pointer(data->input); + else + return Wayland_input_unlock_pointer(data->input); } void diff -r 392c7c4d478e -r a6ea02374162 src/video/wayland/SDL_waylandvideo.c --- a/src/video/wayland/SDL_waylandvideo.c Thu Jun 23 18:39:05 2016 +0800 +++ b/src/video/wayland/SDL_waylandvideo.c Thu Jun 23 20:37:22 2016 +0800 @@ -253,7 +253,10 @@ } else if (strcmp(interface, "wl_shm") == 0) { d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); d->cursor_theme = WAYLAND_wl_cursor_theme_load(NULL, 32, d->shm); - + } else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0) { + Wayland_display_add_relative_pointer_manager(d, id); + } else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0) { + Wayland_display_add_pointer_constraints(d, id); #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH } else if (strcmp(interface, "qt_touch_extension") == 0) { Wayland_touch_create(d, id); @@ -340,6 +343,8 @@ } Wayland_display_destroy_input(data); + Wayland_display_destroy_pointer_constraints(data); + Wayland_display_destroy_relative_pointer_manager(data); if (data->xkb_context) { WAYLAND_xkb_context_unref(data->xkb_context); diff -r 392c7c4d478e -r a6ea02374162 src/video/wayland/SDL_waylandvideo.h --- a/src/video/wayland/SDL_waylandvideo.h Thu Jun 23 18:39:05 2016 +0800 +++ b/src/video/wayland/SDL_waylandvideo.h Thu Jun 23 20:37:22 2016 +0800 @@ -44,6 +44,8 @@ struct wl_cursor_theme *cursor_theme; struct wl_pointer *pointer; struct wl_shell *shell; + struct zwp_relative_pointer_manager_v1 *relative_pointer_manager; + struct zwp_pointer_constraints_v1 *pointer_constraints; EGLDisplay edpy; EGLContext context; @@ -57,6 +59,8 @@ struct qt_surface_extension *surface_extension; struct qt_windowmanager *windowmanager; #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */ + + int relative_mouse_mode; } SDL_VideoData; #endif /* _SDL_waylandvideo_h */ diff -r 392c7c4d478e -r a6ea02374162 src/video/wayland/SDL_waylandwindow.c --- a/src/video/wayland/SDL_waylandwindow.c Thu Jun 23 18:39:05 2016 +0800 +++ b/src/video/wayland/SDL_waylandwindow.c Thu Jun 23 20:37:22 2016 +0800 @@ -26,6 +26,7 @@ #include "../SDL_sysvideo.h" #include "../../events/SDL_windowevents_c.h" #include "../SDL_egl_c.h" +#include "SDL_waylandevents_c.h" #include "SDL_waylandwindow.h" #include "SDL_waylandvideo.h" #include "SDL_waylandtouch.h" @@ -214,6 +215,10 @@ wl_surface_set_opaque_region(data->surface, region); wl_region_destroy(region); + if (c->relative_mouse_mode) { + Wayland_input_lock_pointer(c->input); + } + WAYLAND_wl_display_flush(c->display); return 0; diff -r 392c7c4d478e -r a6ea02374162 src/video/wayland/SDL_waylandwindow.h --- a/src/video/wayland/SDL_waylandwindow.h Thu Jun 23 18:39:05 2016 +0800 +++ b/src/video/wayland/SDL_waylandwindow.h Thu Jun 23 20:37:22 2016 +0800 @@ -39,6 +39,7 @@ struct wl_egl_window *egl_window; struct SDL_WaylandInput *keyboard_device; EGLSurface egl_surface; + struct zwp_locked_pointer_v1 *locked_pointer; #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH struct qt_extended_surface *extended_surface;