1
0
mirror of https://github.com/Relintai/sdl2_frt.git synced 2024-12-20 22:16:49 +01:00

wayland: Add support for relative mouse mode, by Jonas ?dahl <jadahl@gmail.com>

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.
This commit is contained in:
Sam Lantinga 2016-09-01 01:26:56 -07:00
parent 19d3500ae1
commit f11a440999
9 changed files with 283 additions and 15 deletions

34
configure vendored
View File

@ -18807,11 +18807,12 @@ $as_echo_n "checking for Wayland support... " >&6; }
if test x$PKG_CONFIG != xno && \ if test x$PKG_CONFIG != xno && \
test x$video_opengl_egl = xyes && \ test x$video_opengl_egl = xyes && \
test x$video_opengles_v2 = xyes; then 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_CFLAGS=`$PKG_CONFIG --cflags wayland-client wayland-egl wayland-cursor xkbcommon`
WAYLAND_LIBS=`$PKG_CONFIG --libs 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_SCANNER=`$PKG_CONFIG --variable=wayland_scanner wayland-scanner`
WAYLAND_CORE_PROTOCOL_DIR=`$PKG_CONFIG --variable=pkgdatadir wayland-client` WAYLAND_CORE_PROTOCOL_DIR=`$PKG_CONFIG --variable=pkgdatadir wayland-client`
WAYLAND_PROTOCOLS_DIR=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols`
video_wayland=yes video_wayland=yes
fi fi
fi fi
@ -18827,6 +18828,9 @@ $as_echo "#define SDL_VIDEO_DRIVER_WAYLAND 1" >>confdefs.h
$as_echo "#define SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH 1" >>confdefs.h $as_echo "#define SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH 1" >>confdefs.h
fi fi
WAYLAND_PROTOCOLS_UNSTABLE="relative-pointer-unstable-v1 pointer-constraints-unstable-v1"
SOURCES="$SOURCES $srcdir/src/video/wayland/*.c" SOURCES="$SOURCES $srcdir/src/video/wayland/*.c"
EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS -I\$(gen)" EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS -I\$(gen)"
# Check whether --enable-wayland-shared was given. # Check whether --enable-wayland-shared was given.
@ -23736,8 +23740,12 @@ SDLTEST_SOURCES="$srcdir/src/test/*.c"
if test x$video_wayland = xyes; then if test x$video_wayland = xyes; then
WAYLAND_CORE_PROTOCOL_SOURCE='$(gen)/wayland-protocol.c' WAYLAND_CORE_PROTOCOL_SOURCE='$(gen)/wayland-protocol.c'
WAYLAND_CORE_PROTOCOL_HEADER='$(gen)/wayland-client-protocol.h' WAYLAND_CORE_PROTOCOL_HEADER='$(gen)/wayland-client-protocol.h'
GEN_SOURCES="$GEN_SOURCES $WAYLAND_CORE_PROTOCOL_SOURCE" WAYLAND_PROTOCOLS_UNSTABLE_SOURCES=`echo $WAYLAND_PROTOCOLS_UNSTABLE |\
GEN_HEADERS="$GEN_HEADERS $WAYLAND_CORE_PROTOCOL_HEADER" 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_DEPENDS="
$WAYLAND_CORE_PROTOCOL_SOURCE: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml $WAYLAND_CORE_PROTOCOL_SOURCE: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml
@ -23753,10 +23761,30 @@ $WAYLAND_CORE_PROTOCOL_HEADER: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml
\$(objects)/`echo $WAYLAND_CORE_PROTOCOL_SOURCE | sed 's/\$(gen)\/\(.*\).c$/\1.lo/'`: $WAYLAND_CORE_PROTOCOL_SOURCE \$(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 \$@" \$(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_PROTOCOLS_DEPENDS="
$WAYLAND_CORE_PROTOCOL_SOURCE_DEPENDS $WAYLAND_CORE_PROTOCOL_SOURCE_DEPENDS
$WAYLAND_CORE_PROTOCOL_HEADER_DEPENDS $WAYLAND_CORE_PROTOCOL_HEADER_DEPENDS
$WAYLAND_CORE_PROTOCOL_OBJECT $WAYLAND_CORE_PROTOCOL_OBJECT
$WAYLAND_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS
$WAYLAND_PROTOCOLS_CODE_UNSTABLE_DEPENDS
$WAYLAND_PROTOCOLS_OBJECTS_UNSTABLE
" "
fi fi

View File

@ -1201,11 +1201,12 @@ AC_HELP_STRING([--enable-video-wayland-qt-touch], [QtWayland server support for
if test x$PKG_CONFIG != xno && \ if test x$PKG_CONFIG != xno && \
test x$video_opengl_egl = xyes && \ test x$video_opengl_egl = xyes && \
test x$video_opengles_v2 = xyes; then 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_CFLAGS=`$PKG_CONFIG --cflags wayland-client wayland-egl wayland-cursor xkbcommon`
WAYLAND_LIBS=`$PKG_CONFIG --libs 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_SCANNER=`$PKG_CONFIG --variable=wayland_scanner wayland-scanner`
WAYLAND_CORE_PROTOCOL_DIR=`$PKG_CONFIG --variable=pkgdatadir wayland-client` WAYLAND_CORE_PROTOCOL_DIR=`$PKG_CONFIG --variable=pkgdatadir wayland-client`
WAYLAND_PROTOCOLS_DIR=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols`
video_wayland=yes video_wayland=yes
fi fi
fi fi
@ -1216,6 +1217,9 @@ AC_HELP_STRING([--enable-video-wayland-qt-touch], [QtWayland server support for
if test x$enable_video_wayland_qt_touch = xyes; then if test x$enable_video_wayland_qt_touch = xyes; then
AC_DEFINE(SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH, 1, [ ]) AC_DEFINE(SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH, 1, [ ])
fi fi
WAYLAND_PROTOCOLS_UNSTABLE="relative-pointer-unstable-v1 pointer-constraints-unstable-v1"
SOURCES="$SOURCES $srcdir/src/video/wayland/*.c" SOURCES="$SOURCES $srcdir/src/video/wayland/*.c"
EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS -I\$(gen)" EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS -I\$(gen)"
AC_ARG_ENABLE(wayland-shared, AC_ARG_ENABLE(wayland-shared,
@ -3486,8 +3490,12 @@ SDLTEST_SOURCES="$srcdir/src/test/*.c"
if test x$video_wayland = xyes; then if test x$video_wayland = xyes; then
WAYLAND_CORE_PROTOCOL_SOURCE='$(gen)/wayland-protocol.c' WAYLAND_CORE_PROTOCOL_SOURCE='$(gen)/wayland-protocol.c'
WAYLAND_CORE_PROTOCOL_HEADER='$(gen)/wayland-client-protocol.h' WAYLAND_CORE_PROTOCOL_HEADER='$(gen)/wayland-client-protocol.h'
GEN_SOURCES="$GEN_SOURCES $WAYLAND_CORE_PROTOCOL_SOURCE" WAYLAND_PROTOCOLS_UNSTABLE_SOURCES=`echo $WAYLAND_PROTOCOLS_UNSTABLE |\
GEN_HEADERS="$GEN_HEADERS $WAYLAND_CORE_PROTOCOL_HEADER" 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_DEPENDS="
$WAYLAND_CORE_PROTOCOL_SOURCE: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml $WAYLAND_CORE_PROTOCOL_SOURCE: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml
@ -3503,10 +3511,30 @@ $WAYLAND_CORE_PROTOCOL_HEADER: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml
\$(objects)/`echo $WAYLAND_CORE_PROTOCOL_SOURCE | sed 's/\$(gen)\/\(.*\).c$/\1.lo/'`: $WAYLAND_CORE_PROTOCOL_SOURCE \$(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 \$@" \$(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_PROTOCOLS_DEPENDS="
$WAYLAND_CORE_PROTOCOL_SOURCE_DEPENDS $WAYLAND_CORE_PROTOCOL_SOURCE_DEPENDS
$WAYLAND_CORE_PROTOCOL_HEADER_DEPENDS $WAYLAND_CORE_PROTOCOL_HEADER_DEPENDS
$WAYLAND_CORE_PROTOCOL_OBJECT $WAYLAND_CORE_PROTOCOL_OBJECT
$WAYLAND_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS
$WAYLAND_PROTOCOLS_CODE_UNSTABLE_DEPENDS
$WAYLAND_PROTOCOLS_OBJECTS_UNSTABLE
" "
fi fi

View File

@ -25,6 +25,7 @@
#include "SDL_stdinc.h" #include "SDL_stdinc.h"
#include "SDL_assert.h" #include "SDL_assert.h"
#include "SDL_log.h"
#include "../../events/SDL_sysevents.h" #include "../../events/SDL_sysevents.h"
#include "../../events/SDL_events_c.h" #include "../../events/SDL_events_c.h"
@ -36,6 +37,9 @@
#include "SDL_waylanddyn.h" #include "SDL_waylanddyn.h"
#include "pointer-constraints-unstable-v1-client-protocol.h"
#include "relative-pointer-unstable-v1-client-protocol.h"
#include <linux/input.h> #include <linux/input.h>
#include <sys/select.h> #include <sys/select.h>
#include <sys/mman.h> #include <sys/mman.h>
@ -48,6 +52,7 @@ struct SDL_WaylandInput {
struct wl_seat *seat; struct wl_seat *seat;
struct wl_pointer *pointer; struct wl_pointer *pointer;
struct wl_keyboard *keyboard; struct wl_keyboard *keyboard;
struct zwp_relative_pointer_v1 *relative_pointer;
SDL_WindowData *pointer_focus; SDL_WindowData *pointer_focus;
SDL_WindowData *keyboard_focus; SDL_WindowData *keyboard_focus;
@ -55,6 +60,9 @@ struct SDL_WaylandInput {
wl_fixed_t sx_w; wl_fixed_t sx_w;
wl_fixed_t sy_w; wl_fixed_t sy_w;
double dx_frac;
double dy_frac;
struct { struct {
struct xkb_keymap *keymap; struct xkb_keymap *keymap;
struct xkb_state *state; struct xkb_state *state;
@ -170,10 +178,9 @@ ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
} }
static void static void
pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial, pointer_handle_button_common(struct SDL_WaylandInput *input, uint32_t serial,
uint32_t time, uint32_t button, uint32_t state_w) uint32_t time, uint32_t button, uint32_t state_w)
{ {
struct SDL_WaylandInput *input = data;
SDL_WindowData *window = input->pointer_focus; SDL_WindowData *window = input->pointer_focus;
enum wl_pointer_button_state state = state_w; enum wl_pointer_button_state state = state_w;
uint32_t sdl_button; uint32_t sdl_button;
@ -182,7 +189,7 @@ pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
switch (button) { switch (button) {
case BTN_LEFT: case BTN_LEFT:
sdl_button = SDL_BUTTON_LEFT; sdl_button = SDL_BUTTON_LEFT;
if (ProcessHitTest(data, serial)) { if (ProcessHitTest(input, serial)) {
return; /* don't pass this event on to app. */ return; /* don't pass this event on to app. */
} }
break; break;
@ -208,10 +215,18 @@ pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
} }
static void static void
pointer_handle_axis(void *data, struct wl_pointer *pointer, pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
uint32_t time, uint32_t axis, wl_fixed_t value) uint32_t time, uint32_t button, uint32_t state_w)
{ {
struct SDL_WaylandInput *input = data; 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; SDL_WindowData *window = input->pointer_focus;
enum wl_pointer_axis a = axis; enum wl_pointer_axis a = axis;
int x, y; int x, y;
@ -234,6 +249,15 @@ pointer_handle_axis(void *data, struct wl_pointer *pointer,
} }
} }
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 = { static const struct wl_pointer_listener pointer_listener = {
pointer_handle_enter, pointer_handle_enter,
pointer_handle_leave, pointer_handle_leave,
@ -453,6 +477,164 @@ void Wayland_display_destroy_input(SDL_VideoData *d)
d->input = NULL; 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 */ #endif /* SDL_VIDEO_DRIVER_WAYLAND */
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */

View File

@ -32,6 +32,15 @@ extern void Wayland_PumpEvents(_THIS);
extern void Wayland_display_add_input(SDL_VideoData *d, uint32_t id); 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_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 */ #endif /* _SDL_waylandevents_h */
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */

View File

@ -365,7 +365,13 @@ Wayland_WarpMouseGlobal(int x, int y)
static int static int
Wayland_SetRelativeMouseMode(SDL_bool enabled) 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 void

View File

@ -305,7 +305,10 @@ display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
} else if (strcmp(interface, "wl_shm") == 0) { } else if (strcmp(interface, "wl_shm") == 0) {
d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
d->cursor_theme = WAYLAND_wl_cursor_theme_load(NULL, 32, d->shm); 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 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
} else if (strcmp(interface, "qt_touch_extension") == 0) { } else if (strcmp(interface, "qt_touch_extension") == 0) {
Wayland_touch_create(d, id); Wayland_touch_create(d, id);
@ -395,6 +398,8 @@ Wayland_VideoQuit(_THIS)
} }
Wayland_display_destroy_input(data); Wayland_display_destroy_input(data);
Wayland_display_destroy_pointer_constraints(data);
Wayland_display_destroy_relative_pointer_manager(data);
if (data->xkb_context) { if (data->xkb_context) {
WAYLAND_xkb_context_unref(data->xkb_context); WAYLAND_xkb_context_unref(data->xkb_context);

View File

@ -44,6 +44,8 @@ typedef struct {
struct wl_cursor_theme *cursor_theme; struct wl_cursor_theme *cursor_theme;
struct wl_pointer *pointer; struct wl_pointer *pointer;
struct wl_shell *shell; struct wl_shell *shell;
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
struct zwp_pointer_constraints_v1 *pointer_constraints;
EGLDisplay edpy; EGLDisplay edpy;
EGLContext context; EGLContext context;
@ -59,6 +61,8 @@ typedef struct {
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */ #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
char *classname; char *classname;
int relative_mouse_mode;
} SDL_VideoData; } SDL_VideoData;
#endif /* _SDL_waylandvideo_h */ #endif /* _SDL_waylandvideo_h */

View File

@ -26,6 +26,7 @@
#include "../SDL_sysvideo.h" #include "../SDL_sysvideo.h"
#include "../../events/SDL_windowevents_c.h" #include "../../events/SDL_windowevents_c.h"
#include "../SDL_egl_c.h" #include "../SDL_egl_c.h"
#include "SDL_waylandevents_c.h"
#include "SDL_waylandwindow.h" #include "SDL_waylandwindow.h"
#include "SDL_waylandvideo.h" #include "SDL_waylandvideo.h"
#include "SDL_waylandtouch.h" #include "SDL_waylandtouch.h"
@ -215,6 +216,10 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
wl_surface_set_opaque_region(data->surface, region); wl_surface_set_opaque_region(data->surface, region);
wl_region_destroy(region); wl_region_destroy(region);
if (c->relative_mouse_mode) {
Wayland_input_lock_pointer(c->input);
}
WAYLAND_wl_display_flush(c->display); WAYLAND_wl_display_flush(c->display);
return 0; return 0;

View File

@ -39,6 +39,7 @@ typedef struct {
struct wl_egl_window *egl_window; struct wl_egl_window *egl_window;
struct SDL_WaylandInput *keyboard_device; struct SDL_WaylandInput *keyboard_device;
EGLSurface egl_surface; EGLSurface egl_surface;
struct zwp_locked_pointer_v1 *locked_pointer;
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
struct qt_extended_surface *extended_surface; struct qt_extended_surface *extended_surface;