# HG changeset patch # User Jonas Ã…dahl # Date 1456212811 -28800 # Tue Feb 23 15:33:31 2016 +0800 # Branch pointer-lock-v3 # Node ID 41215d2653899ca4971b49d9524d3ecd8bd9866c # Parent 6ab58dc0c9f8dfc8c150c2861c3fa95a885b21fd wayland: Add support for relative mouse mode This adds two new build time dependency: wayland-protocols and wayland-scanner. wayland-scanner is used to generate one C source file and one C header file which provides the necessary C API for making the protocol requests and receiving the protocol events related to pointer locking and relative pointer events. 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. So far it is only enabled when building non-shared version of the Wayland video driver. diff -r 6ab58dc0c9f8 -r 41215d265389 .hgignore --- a/.hgignore Wed Feb 17 15:14:20 2016 +0800 +++ b/.hgignore Tue Feb 23 15:33:31 2016 +0800 @@ -8,6 +8,7 @@ sdl-config SDL2.spec build +gen Build # for Xcode diff -r 6ab58dc0c9f8 -r 41215d265389 Makefile.in --- a/Makefile.in Wed Feb 17 15:14:20 2016 +0800 +++ b/Makefile.in Tue Feb 23 15:33:31 2016 +0800 @@ -3,6 +3,7 @@ top_builddir = . srcdir = @srcdir@ objects = build +gen = gen prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ @@ -31,6 +32,8 @@ TARGET = libSDL2.la OBJECTS = @OBJECTS@ +GEN_HEADERS = @GEN_HEADERS@ +GEN_OBJECTS = @GEN_OBJECTS@ VERSION_OBJECTS = @VERSION_OBJECTS@ SDLMAIN_TARGET = libSDL2main.a @@ -39,6 +42,8 @@ SDLTEST_TARGET = libSDL2_test.a SDLTEST_OBJECTS = @SDLTEST_OBJECTS@ +WAYLAND_SCANNER = @WAYLAND_SCANNER@ + SRC_DIST = *.txt acinclude Android.mk autogen.sh android-project build-scripts cmake cmake_uninstall.cmake.in configure configure.in debian docs include Makefile.* sdl2-config.cmake.in sdl2-config.in sdl2.m4 sdl2.pc.in SDL2.spec.in src test VisualC.html VisualC VisualC-WinRT Xcode Xcode-iOS GEN_DIST = SDL2.spec @@ -48,6 +53,7 @@ RUN_CMD_CXX = @echo " CXX " $@; RUN_CMD_LTLINK = @echo " LTLINK" $@; RUN_CMD_RANLIB = @echo " RANLIB" $@; +RUN_CMD_GEN = @echo " GEN " $@; LIBTOOL += --quiet endif @@ -137,8 +143,8 @@ .PHONY: all update-revision install install-bin install-hdrs install-lib install-data uninstall uninstall-bin uninstall-hdrs uninstall-lib uninstall-data clean distclean dist $(OBJECTS:.lo=.d) -$(objects)/$(TARGET): $(OBJECTS) $(VERSION_OBJECTS) - $(RUN_CMD_LTLINK)$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(OBJECTS) $(VERSION_OBJECTS) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LT_LDFLAGS) +$(objects)/$(TARGET): $(GEN_HEADERS) $(GEN_OBJECTS) $(OBJECTS) $(VERSION_OBJECTS) + $(RUN_CMD_LTLINK)$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(OBJECTS) $(GEN_OBJECTS) $(VERSION_OBJECTS) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LT_LDFLAGS) $(objects)/$(SDLMAIN_TARGET): $(SDLMAIN_OBJECTS) $(RUN_CMD_AR)$(AR) cru $@ $(SDLMAIN_OBJECTS) @@ -200,6 +206,7 @@ clean: rm -rf $(objects) + rm -rf $(gen) if test -f test/Makefile; then (cd test; $(MAKE) $@); fi distclean: clean diff -r 6ab58dc0c9f8 -r 41215d265389 configure --- a/configure Wed Feb 17 15:14:20 2016 +0800 +++ b/configure Tue Feb 23 15:33:31 2016 +0800 @@ -630,6 +630,7 @@ #endif" ac_subst_vars='LTLIBOBJS +WAYLAND_SCANNER EXTRA_LDFLAGS BUILD_LDFLAGS EXTRA_CFLAGS @@ -637,6 +638,8 @@ SDLTEST_OBJECTS SDLMAIN_OBJECTS VERSION_OBJECTS +GEN_OBJECTS +GEN_HEADERS OBJECTS INCLUDE ac_aux_dir @@ -18804,9 +18807,11 @@ 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-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_PROTOCOLS_DIR=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols` video_wayland=yes fi fi @@ -18822,8 +18827,10 @@ $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" # Check whether --enable-wayland-shared was given. if test "${enable_wayland_shared+set}" = set; then : enableval=$enable_wayland_shared; @@ -18889,7 +18896,14 @@ EXTRA_LDFLAGS="$EXTRA_LDFLAGS $WAYLAND_LIBS" SUMMARY_video="${SUMMARY_video} wayland" fi + + if test x$enable_wayland_shared=no; then + WAYLAND_CFLAGS="$WAYLAND_CFLAGS -DENABLE_WAYLAND_EXTENSIONS -I\$(gen)" + fi + have_video=yes + + EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS" fi fi } @@ -23728,6 +23742,38 @@ fi SDLTEST_SOURCES="$srcdir/src/test/*.c" +if test x$video_wayland = xyes && + test x$enable_wayland_shared = xno; then + 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_PROTOCOLS_UNSTABLE_SOURCES" + GEN_HEADERS="$GEN_HEADERS $WAYLAND_PROTOCOLS_UNSTABLE_HEADERS" + + WAYLAND_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\ + do 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 \$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 \$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_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS +$WAYLAND_PROTOCOLS_CODE_UNSTABLE_DEPENDS +$WAYLAND_PROTOCOLS_OBJECTS_UNSTABLE" +fi + OBJECTS=`echo $SOURCES` DEPENDS=`echo $SOURCES | tr ' ' '\n'` for EXT in asm cc m c S; do @@ -23737,6 +23783,8 @@ \\$(RUN_CMD_CC)\\$(LIBTOOL) --tag=CC --mode=compile \\$(CC) \\$(CFLAGS) \\$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \\$< -o \\$@,g"` done +GEN_OBJECTS=`echo "$GEN_SOURCES" | sed 's,[^ ]*/\([^ ]*\)\.c,$(objects)/\1.lo,g'` + VERSION_OBJECTS=`echo $VERSION_SOURCES` VERSION_DEPENDS=`echo $VERSION_SOURCES` VERSION_OBJECTS=`echo "$VERSION_OBJECTS" | sed 's,[^ ]*/\([^ ]*\)\.rc,$(objects)/\1.o,g'` @@ -23838,6 +23886,10 @@ + + + + cat >Makefile.rules <<__EOF__ # Build rules for objects @@ -23849,6 +23901,7 @@ $VERSION_DEPENDS $SDLMAIN_DEPENDS $SDLTEST_DEPENDS +$WAYLAND_PROTOCOLS_DEPENDS __EOF__ ac_config_files="$ac_config_files Makefile:Makefile.in:Makefile.rules sdl2-config sdl2-config.cmake SDL2.spec sdl2.pc" diff -r 6ab58dc0c9f8 -r 41215d265389 configure.in --- a/configure.in Wed Feb 17 15:14:20 2016 +0800 +++ b/configure.in Tue Feb 23 15:33:31 2016 +0800 @@ -1201,9 +1201,11 @@ 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-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_PROTOCOLS_DIR=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols` video_wayland=yes fi fi @@ -1214,8 +1216,10 @@ 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" AC_ARG_ENABLE(wayland-shared, AC_HELP_STRING([--enable-wayland-shared], [dynamically load Wayland support [[default=maybe]]]), , enable_wayland_shared=maybe) @@ -1262,7 +1266,14 @@ EXTRA_LDFLAGS="$EXTRA_LDFLAGS $WAYLAND_LIBS" SUMMARY_video="${SUMMARY_video} wayland" fi + + if test x$enable_wayland_shared=no; then + WAYLAND_CFLAGS="$WAYLAND_CFLAGS -DENABLE_WAYLAND_EXTENSIONS -I\$(gen)" + fi + have_video=yes + + EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS" fi fi } @@ -3481,6 +3492,38 @@ fi SDLTEST_SOURCES="$srcdir/src/test/*.c" +if test x$video_wayland = xyes && + test x$enable_wayland_shared = xno; then + 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_PROTOCOLS_UNSTABLE_SOURCES" + GEN_HEADERS="$GEN_HEADERS $WAYLAND_PROTOCOLS_UNSTABLE_HEADERS" + + WAYLAND_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\ + do 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 \$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 \$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_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS +$WAYLAND_PROTOCOLS_CODE_UNSTABLE_DEPENDS +$WAYLAND_PROTOCOLS_OBJECTS_UNSTABLE" +fi + OBJECTS=`echo $SOURCES` DEPENDS=`echo $SOURCES | tr ' ' '\n'` for EXT in asm cc m c S; do @@ -3490,6 +3533,8 @@ \\$(RUN_CMD_CC)\\$(LIBTOOL) --tag=CC --mode=compile \\$(CC) \\$(CFLAGS) \\$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \\$< -o \\$@,g"` done +GEN_OBJECTS=`echo "$GEN_SOURCES" | sed 's,[[^ ]]*/\([[^ ]]*\)\.c,$(objects)/\1.lo,g'` + VERSION_OBJECTS=`echo $VERSION_SOURCES` VERSION_DEPENDS=`echo $VERSION_SOURCES` VERSION_OBJECTS=`echo "$VERSION_OBJECTS" | sed 's,[[^ ]]*/\([[^ ]]*\)\.rc,$(objects)/\1.o,g'` @@ -3567,6 +3612,8 @@ AC_SUBST(ac_aux_dir) AC_SUBST(INCLUDE) AC_SUBST(OBJECTS) +AC_SUBST(GEN_HEADERS) +AC_SUBST(GEN_OBJECTS) AC_SUBST(VERSION_OBJECTS) AC_SUBST(SDLMAIN_OBJECTS) AC_SUBST(SDLTEST_OBJECTS) @@ -3575,6 +3622,7 @@ AC_SUBST(BUILD_LDFLAGS) AC_SUBST(EXTRA_LDFLAGS) AC_SUBST(WINDRES) +AC_SUBST(WAYLAND_SCANNER) cat >Makefile.rules <<__EOF__ @@ -3587,6 +3635,7 @@ $VERSION_DEPENDS $SDLMAIN_DEPENDS $SDLTEST_DEPENDS +$WAYLAND_PROTOCOLS_DEPENDS __EOF__ AC_CONFIG_FILES([ diff -r 6ab58dc0c9f8 -r 41215d265389 src/video/wayland/SDL_waylandevents.c --- a/src/video/wayland/SDL_waylandevents.c Wed Feb 17 15:14:20 2016 +0800 +++ b/src/video/wayland/SDL_waylandevents.c Tue Feb 23 15:33:31 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,11 @@ #include "SDL_waylanddyn.h" +#ifdef ENABLE_WAYLAND_EXTENSIONS +#include "pointer-constraints-unstable-v1-client-protocol.h" +#include "relative-pointer-unstable-v1-client-protocol.h" +#endif + #include #include #include @@ -49,13 +55,19 @@ struct wl_seat *seat; struct wl_pointer *pointer; struct wl_keyboard *keyboard; +#ifdef ENABLE_WAYLAND_EXTENSIONS + struct zwp_relative_pointer_v1 *relative_pointer; +#endif 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; @@ -171,10 +183,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; @@ -183,7 +194,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; @@ -209,10 +220,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; @@ -235,6 +254,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, @@ -420,6 +448,7 @@ input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, 1); input->sx_w = wl_fixed_from_int(0); input->sy_w = wl_fixed_from_int(0); + d->input = input; wl_seat_add_listener(input->seat, &seat_listener, input); @@ -454,6 +483,209 @@ d->input = NULL; } +#ifdef ENABLE_WAYLAND_EXTENSIONS +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 inline double +double_fixed_to_double(int32_t i, int32_t f) +{ + union { + double d; + int64_t i; + } u; + + u.i = ((1023LL + (52LL - 31LL)) << 52) + (1LL << 51) + f; + + return i + (u.d - (3LL << (52 - 32))); +} + +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; +} + +#else + +int Wayland_input_lock_pointer(struct SDL_WaylandInput *input) +{ + SDL_LogError(SDL_LOG_CATEGORY_INPUT, "Relative pointer mode not supported\n"); + return -1; +} + +int Wayland_input_unlock_pointer(struct SDL_WaylandInput *input) +{ + return 0; +} + +void Wayland_display_add_relative_pointer_manager(SDL_VideoData *d, uint32_t id) +{ +} + +void Wayland_display_destroy_relative_pointer_manager(SDL_VideoData *d) +{ +} + +void Wayland_display_add_pointer_constraints(SDL_VideoData *d, uint32_t id) +{ +} + +void Wayland_display_destroy_pointer_constraints(SDL_VideoData *d) +{ +} + +#endif /* ENABLE_WAYLAND_EXTENSIONS */ + #endif /* SDL_VIDEO_DRIVER_WAYLAND */ /* vi: set ts=4 sw=4 expandtab: */ diff -r 6ab58dc0c9f8 -r 41215d265389 src/video/wayland/SDL_waylandevents_c.h --- a/src/video/wayland/SDL_waylandevents_c.h Wed Feb 17 15:14:20 2016 +0800 +++ b/src/video/wayland/SDL_waylandevents_c.h Tue Feb 23 15:33:31 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 6ab58dc0c9f8 -r 41215d265389 src/video/wayland/SDL_waylandmouse.c --- a/src/video/wayland/SDL_waylandmouse.c Wed Feb 17 15:14:20 2016 +0800 +++ b/src/video/wayland/SDL_waylandmouse.c Tue Feb 23 15:33:31 2016 +0800 @@ -356,7 +356,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 6ab58dc0c9f8 -r 41215d265389 src/video/wayland/SDL_waylandvideo.c --- a/src/video/wayland/SDL_waylandvideo.c Wed Feb 17 15:14:20 2016 +0800 +++ b/src/video/wayland/SDL_waylandvideo.c Tue Feb 23 15:33:31 2016 +0800 @@ -254,7 +254,10 @@ d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); d->cursor_theme = WAYLAND_wl_cursor_theme_load(NULL, 32, d->shm); d->default_cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "left_ptr"); - + } 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); @@ -341,6 +344,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 6ab58dc0c9f8 -r 41215d265389 src/video/wayland/SDL_waylandvideo.h --- a/src/video/wayland/SDL_waylandvideo.h Wed Feb 17 15:14:20 2016 +0800 +++ b/src/video/wayland/SDL_waylandvideo.h Tue Feb 23 15:33:31 2016 +0800 @@ -45,6 +45,10 @@ struct wl_cursor *default_cursor; struct wl_pointer *pointer; struct wl_shell *shell; +#ifdef ENABLE_WAYLAND_EXTENSIONS + struct zwp_relative_pointer_manager_v1 *relative_pointer_manager; + struct zwp_pointer_constraints_v1 *pointer_constraints; +#endif EGLDisplay edpy; EGLContext context; @@ -58,6 +62,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 6ab58dc0c9f8 -r 41215d265389 src/video/wayland/SDL_waylandwindow.c --- a/src/video/wayland/SDL_waylandwindow.c Wed Feb 17 15:14:20 2016 +0800 +++ b/src/video/wayland/SDL_waylandwindow.c Tue Feb 23 15:33:31 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 6ab58dc0c9f8 -r 41215d265389 src/video/wayland/SDL_waylandwindow.h --- a/src/video/wayland/SDL_waylandwindow.h Wed Feb 17 15:14:20 2016 +0800 +++ b/src/video/wayland/SDL_waylandwindow.h Tue Feb 23 15:33:31 2016 +0800 @@ -39,6 +39,9 @@ struct wl_egl_window *egl_window; struct SDL_WaylandInput *keyboard_device; EGLSurface egl_surface; +#ifdef ENABLE_WAYLAND_EXTENSIONS + struct zwp_locked_pointer_v1 *locked_pointer; +#endif /* ENABLE_WAYLAND_EXTENSIONS */ #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH struct qt_extended_surface *extended_surface;