[client] wayland: support LG_DS_WARP_SURFACE

This commit implements support for LG_DS_WARP_SURFACE, as well as a warp
routine based on cursor confines.

This may not necessarily work for all compositors. As such, the old cursor
routines are still kept, and used when wm.warpSupport is set to false.
This commit is contained in:
Quantum 2021-02-15 19:02:29 -05:00 committed by Geoffrey McRae
parent 270631f1b9
commit 9b688909b0

View File

@ -79,6 +79,8 @@ struct WaylandDSState
bool fullscreen; bool fullscreen;
uint32_t resizeSerial; uint32_t resizeSerial;
bool configured; bool configured;
bool warpSupport;
double cursorX, cursorY;
#ifdef ENABLE_EGL #ifdef ENABLE_EGL
struct wl_egl_window * eglWindow; struct wl_egl_window * eglWindow;
@ -267,10 +269,11 @@ static const struct wl_registry_listener registryListener = {
static void pointerMotionHandler(void * data, struct wl_pointer * pointer, static void pointerMotionHandler(void * data, struct wl_pointer * pointer,
uint32_t serial, wl_fixed_t sxW, wl_fixed_t syW) uint32_t serial, wl_fixed_t sxW, wl_fixed_t syW)
{ {
int sx = wl_fixed_to_int(sxW); wm.cursorX = wl_fixed_to_double(sxW);
int sy = wl_fixed_to_int(syW); wm.cursorY = wl_fixed_to_double(syW);
app_updateCursorPos(sx, sy); app_updateCursorPos(wm.cursorX, wm.cursorY);
if (!wm.relativePointer)
if (!wm.warpSupport && !wm.relativePointer)
app_handleMouseBasic(); app_handleMouseBasic();
} }
@ -283,14 +286,20 @@ static void pointerEnterHandler(void * data, struct wl_pointer * pointer,
wl_pointer_set_cursor(pointer, serial, wm.showPointer ? wm.cursor : NULL, 0, 0); wl_pointer_set_cursor(pointer, serial, wm.showPointer ? wm.cursor : NULL, 0, 0);
wm.pointerEnterSerial = serial; wm.pointerEnterSerial = serial;
wm.cursorX = wl_fixed_to_double(sxW);
wm.cursorY = wl_fixed_to_double(syW);
app_updateCursorPos(wm.cursorX, wm.cursorY);
if (wm.warpSupport)
{
app_handleMouseRelative(0.0, 0.0, 0.0, 0.0);
return;
}
if (wm.relativePointer) if (wm.relativePointer)
return; return;
int sx = wl_fixed_to_int(sxW);
int sy = wl_fixed_to_int(syW);
app_resyncMouseBasic(); app_resyncMouseBasic();
app_updateCursorPos(sx, sy);
if (!wm.relativePointer)
app_handleMouseBasic(); app_handleMouseBasic();
} }
@ -348,6 +357,26 @@ static const struct wl_pointer_listener pointerListener = {
.axis = pointerAxisHandler, .axis = pointerAxisHandler,
}; };
static void relativePointerMotionHandler(void * data,
struct zwp_relative_pointer_v1 *pointer, uint32_t timeHi, uint32_t timeLo,
wl_fixed_t dxW, wl_fixed_t dyW, wl_fixed_t dxUnaccelW,
wl_fixed_t dyUnaccelW)
{
wm.cursorX += wl_fixed_to_double(dxW);
wm.cursorY += wl_fixed_to_double(dyW);
app_updateCursorPos(wm.cursorX, wm.cursorY);
app_handleMouseRelative(
wl_fixed_to_double(dxW),
wl_fixed_to_double(dyW),
wl_fixed_to_double(dxUnaccelW),
wl_fixed_to_double(dyUnaccelW));
}
static const struct zwp_relative_pointer_v1_listener relativePointerListener = {
.relative_motion = relativePointerMotionHandler,
};
static void waylandInhibitIdle(void) static void waylandInhibitIdle(void)
{ {
if (wm.idleInhibitManager && !wm.idleInhibitor) if (wm.idleInhibitManager && !wm.idleInhibitor)
@ -644,6 +673,13 @@ static bool waylandInit(const LG_DSInitParams params)
DEBUG_WARN("zwp_idle_inhibit_manager_v1 not exported by compositor, will " DEBUG_WARN("zwp_idle_inhibit_manager_v1 not exported by compositor, will "
"not be able to suppress idle states"); "not be able to suppress idle states");
if (wm.warpSupport && (!wm.relativePointerManager || !wm.pointerConstraints))
{
DEBUG_WARN("Cursor warp is requested, but cannot be honoured due to lack "
"of zwp_relative_pointer_manager_v1 or zwp_pointer_constraints_v1");
wm.warpSupport = false;
}
wl_seat_add_listener(wm.seat, &seatListener, NULL); wl_seat_add_listener(wm.seat, &seatListener, NULL);
xdg_wm_base_add_listener(wm.xdgWmBase, &xdgWmBaseListener, NULL); xdg_wm_base_add_listener(wm.xdgWmBase, &xdgWmBaseListener, NULL);
wl_display_roundtrip(wm.display); wl_display_roundtrip(wm.display);
@ -651,6 +687,15 @@ static bool waylandInit(const LG_DSInitParams params)
wm.dataDevice = wl_data_device_manager_get_data_device( wm.dataDevice = wl_data_device_manager_get_data_device(
wm.dataDeviceManager, wm.seat); wm.dataDeviceManager, wm.seat);
if (wm.warpSupport)
{
wm.relativePointer =
zwp_relative_pointer_manager_v1_get_relative_pointer(
wm.relativePointerManager, wm.pointer);
zwp_relative_pointer_v1_add_listener(wm.relativePointer,
&relativePointerListener, NULL);
}
wm.surface = wl_compositor_create_surface(wm.compositor); wm.surface = wl_compositor_create_surface(wm.compositor);
wm.eglWindow = wl_egl_window_create(wm.surface, params.w, params.h); wm.eglWindow = wl_egl_window_create(wm.surface, params.w, params.h);
wm.xdgSurface = xdg_wm_base_get_xdg_surface(wm.xdgWmBase, wm.surface); wm.xdgSurface = xdg_wm_base_get_xdg_surface(wm.xdgWmBase, wm.surface);
@ -905,28 +950,12 @@ static bool waylandGetFullscreen(void)
return wm.fullscreen; return wm.fullscreen;
} }
static void relativePointerMotionHandler(void * data,
struct zwp_relative_pointer_v1 *pointer, uint32_t timeHi, uint32_t timeLo,
wl_fixed_t dxW, wl_fixed_t dyW, wl_fixed_t dxUnaccelW,
wl_fixed_t dyUnaccelW)
{
app_handleMouseRelative(
wl_fixed_to_double(dxW),
wl_fixed_to_double(dyW),
wl_fixed_to_double(dxUnaccelW),
wl_fixed_to_double(dyUnaccelW));
}
static const struct zwp_relative_pointer_v1_listener relativePointerListener = {
.relative_motion = relativePointerMotionHandler,
};
static void waylandGrabPointer(void) static void waylandGrabPointer(void)
{ {
if (!wm.relativePointerManager || !wm.pointerConstraints) if (!wm.relativePointerManager || !wm.pointerConstraints)
return; return;
if (!wm.relativePointer) if (!wm.warpSupport && !wm.relativePointer)
{ {
wm.relativePointer = wm.relativePointer =
zwp_relative_pointer_manager_v1_get_relative_pointer( zwp_relative_pointer_manager_v1_get_relative_pointer(
@ -945,21 +974,27 @@ static void waylandGrabPointer(void)
static void waylandUngrabPointer(void) static void waylandUngrabPointer(void)
{ {
if (wm.relativePointer)
{
zwp_relative_pointer_v1_destroy(wm.relativePointer);
wm.relativePointer = NULL;
}
if (wm.confinedPointer) if (wm.confinedPointer)
{ {
zwp_confined_pointer_v1_destroy(wm.confinedPointer); zwp_confined_pointer_v1_destroy(wm.confinedPointer);
wm.confinedPointer = NULL; wm.confinedPointer = NULL;
} }
if (!wm.warpSupport)
{
if (!wm.relativePointer)
{
wm.relativePointer =
zwp_relative_pointer_manager_v1_get_relative_pointer(
wm.relativePointerManager, wm.pointer);
zwp_relative_pointer_v1_add_listener(wm.relativePointer,
&relativePointerListener, NULL);
}
app_resyncMouseBasic(); app_resyncMouseBasic();
app_handleMouseBasic(); app_handleMouseBasic();
} }
}
static void waylandGrabKeyboard(void) static void waylandGrabKeyboard(void)
{ {
@ -981,11 +1016,37 @@ static void waylandUngrabKeyboard(void)
static void waylandWarpPointer(int x, int y, bool exiting) static void waylandWarpPointer(int x, int y, bool exiting)
{ {
// This is an unsupported operation on Wayland. if (x < 0) x = 0;
else if (x >= wm.width) x = wm.width - 1;
if (y < 0) y = 0;
else if (y >= wm.height) y = wm.height - 1;
struct wl_region * region = wl_compositor_create_region(wm.compositor);
wl_region_add(region, x, y, 1, 1);
if (wm.confinedPointer)
{
zwp_confined_pointer_v1_set_region(wm.confinedPointer, region);
wl_surface_commit(wm.surface);
zwp_confined_pointer_v1_set_region(wm.confinedPointer, NULL);
}
else
{
struct zwp_confined_pointer_v1 * confine;
confine = zwp_pointer_constraints_v1_confine_pointer(
wm.pointerConstraints, wm.surface, wm.pointer, region,
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
wl_surface_commit(wm.surface);
zwp_confined_pointer_v1_destroy(confine);
}
wl_surface_commit(wm.surface);
wl_region_destroy(region);
} }
static void waylandRealignPointer(void) static void waylandRealignPointer(void)
{ {
if (!wm.warpSupport)
app_resyncMouseBasic(); app_resyncMouseBasic();
} }
@ -1015,7 +1076,7 @@ static bool waylandGetProp(LG_DSProperty prop, void * ret)
{ {
if (prop == LG_DS_WARP_SUPPORT) if (prop == LG_DS_WARP_SUPPORT)
{ {
*(enum LG_DSWarpSupport*)ret = LG_DS_WARP_NONE; *(enum LG_DSWarpSupport*)ret = wm.warpSupport ? LG_DS_WARP_SURFACE : LG_DS_WARP_NONE;
return true; return true;
} }