From b76f8de298fe5476b77fa562df07b57d5837bab6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ionu=C8=9B=20Leonte?= <[EMAIL REDACTED]>
Date: Mon, 20 Nov 2023 23:33:11 +0200
Subject: [PATCH] Hit testing tweaks for X11 and Wayland (#8582)
Hit testing on X11 and Wayland should now behave more like it
does on Windows - the current active zone is tracked on mouse
motion events and the cursor is changed accordingly when hovering
a "special" zone (such as the resize handles).
---
src/video/wayland/SDL_waylandevents.c | 40 +++++++++++++------
src/video/wayland/SDL_waylandmouse.c | 55 ++++++++++++++++++++-------
src/video/wayland/SDL_waylandmouse.h | 1 +
src/video/wayland/SDL_waylandwindow.c | 2 +
src/video/wayland/SDL_waylandwindow.h | 2 +
src/video/x11/SDL_x11events.c | 26 ++++++++++---
src/video/x11/SDL_x11events.h | 3 +-
src/video/x11/SDL_x11mouse.c | 28 ++++++++++++++
src/video/x11/SDL_x11mouse.h | 1 +
src/video/x11/SDL_x11window.c | 1 +
src/video/x11/SDL_x11window.h | 1 +
src/video/x11/SDL_x11xinput2.c | 10 ++---
12 files changed, 134 insertions(+), 36 deletions(-)
diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c
index 1a954c59ccd4..e8eb58be2dad 100644
--- a/src/video/wayland/SDL_waylandevents.c
+++ b/src/video/wayland/SDL_waylandevents.c
@@ -32,6 +32,7 @@
#include "SDL_waylandvideo.h"
#include "SDL_waylandevents_c.h"
#include "SDL_waylandwindow.h"
+#include "SDL_waylandmouse.h"
#include "pointer-constraints-unstable-v1-client-protocol.h"
#include "relative-pointer-unstable-v1-client-protocol.h"
@@ -490,13 +491,26 @@ static void pointer_handle_motion(void *data, struct wl_pointer *pointer,
uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w)
{
struct SDL_WaylandInput *input = data;
- SDL_WindowData *window = input->pointer_focus;
+ SDL_WindowData *window_data = input->pointer_focus;
+ SDL_Window *window = window_data ? window_data->sdlwindow : NULL;
+
input->sx_w = sx_w;
input->sy_w = sy_w;
if (input->pointer_focus) {
- float sx = (float)(wl_fixed_to_double(sx_w) * window->pointer_scale_x);
- float sy = (float)(wl_fixed_to_double(sy_w) * window->pointer_scale_y);
- SDL_SendMouseMotion(Wayland_GetPointerTimestamp(input, time), window->sdlwindow, 0, 0, sx, sy);
+ float sx = (float)(wl_fixed_to_double(sx_w) * window_data->pointer_scale_x);
+ float sy = (float)(wl_fixed_to_double(sy_w) * window_data->pointer_scale_y);
+ SDL_SendMouseMotion(Wayland_GetPointerTimestamp(input, time), window_data->sdlwindow, 0, 0, sx, sy);
+ }
+
+ if (window && window->hit_test) {
+ const SDL_Point point = { wl_fixed_to_int(sx_w), wl_fixed_to_int(sy_w) };
+ SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
+ if (rc == window_data->hit_test_result) {
+ return;
+ }
+
+ Wayland_SetHitTestCursor(rc);
+ window_data->hit_test_result = rc;
}
}
@@ -540,7 +554,7 @@ static void pointer_handle_enter(void *data, struct wl_pointer *pointer,
/* If the cursor was changed while our window didn't have pointer
* focus, we might need to trigger another call to
* wl_pointer_set_cursor() for the new cursor to be displayed. */
- SDL_SetCursor(NULL);
+ Wayland_SetHitTestCursor(window->hit_test_result);
}
}
@@ -580,9 +594,6 @@ static SDL_bool ProcessHitTest(SDL_WindowData *window_data,
SDL_Window *window = window_data->sdlwindow;
if (window->hit_test) {
- const SDL_Point point = { wl_fixed_to_int(sx_w), wl_fixed_to_int(sy_w) };
- const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
-
static const uint32_t directions[] = {
XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT, XDG_TOPLEVEL_RESIZE_EDGE_TOP,
XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT, XDG_TOPLEVEL_RESIZE_EDGE_RIGHT,
@@ -599,12 +610,14 @@ static SDL_bool ProcessHitTest(SDL_WindowData *window_data,
};
#endif
- switch (rc) {
+ switch (window_data->hit_test_result) {
case SDL_HITTEST_DRAGGABLE:
#ifdef HAVE_LIBDECOR_H
if (window_data->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
if (window_data->shell_surface.libdecor.frame) {
- libdecor_frame_move(window_data->shell_surface.libdecor.frame, seat, serial);
+ libdecor_frame_move(window_data->shell_surface.libdecor.frame,
+ seat,
+ serial);
}
} else
#endif
@@ -628,7 +641,10 @@ static SDL_bool ProcessHitTest(SDL_WindowData *window_data,
#ifdef HAVE_LIBDECOR_H
if (window_data->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
if (window_data->shell_surface.libdecor.frame) {
- libdecor_frame_resize(window_data->shell_surface.libdecor.frame, seat, serial, directions_libdecor[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
+ libdecor_frame_resize(window_data->shell_surface.libdecor.frame,
+ seat,
+ serial,
+ directions_libdecor[window_data->hit_test_result - SDL_HITTEST_RESIZE_TOPLEFT]);
}
} else
#endif
@@ -637,7 +653,7 @@ static SDL_bool ProcessHitTest(SDL_WindowData *window_data,
xdg_toplevel_resize(window_data->shell_surface.xdg.roleobj.toplevel,
seat,
serial,
- directions[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
+ directions[window_data->hit_test_result - SDL_HITTEST_RESIZE_TOPLEFT]);
}
}
return SDL_TRUE;
diff --git a/src/video/wayland/SDL_waylandmouse.c b/src/video/wayland/SDL_waylandmouse.c
index 8c1bae80fce5..037df7bce633 100644
--- a/src/video/wayland/SDL_waylandmouse.c
+++ b/src/video/wayland/SDL_waylandmouse.c
@@ -41,6 +41,8 @@
#include "../../SDL_hints_c.h"
+static SDL_Cursor *sys_cursors[SDL_HITTEST_RESIZE_LEFT + 1];
+
static int Wayland_SetRelativeMouseMode(SDL_bool enabled);
typedef struct
@@ -315,43 +317,44 @@ static SDL_bool wayland_get_system_cursor(SDL_VideoData *vdata, Wayland_CursorDa
vdata->cursor_themes[vdata->num_cursor_themes++].theme = theme;
}
- /* Next, find the cursor from the theme... */
+ /* Next, find the cursor from the theme. Names taken from: */
+ /* https://www.freedesktop.org/wiki/Specifications/cursor-spec/ */
switch (cdata->system_cursor) {
case SDL_SYSTEM_CURSOR_ARROW:
- cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "left_ptr");
+ cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "default");
break;
case SDL_SYSTEM_CURSOR_IBEAM:
- cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "xterm");
+ cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "text");
break;
case SDL_SYSTEM_CURSOR_WAIT:
- cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "watch");
+ cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "wait");
break;
case SDL_SYSTEM_CURSOR_CROSSHAIR:
- cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "tcross");
+ cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "crosshair");
break;
case SDL_SYSTEM_CURSOR_WAITARROW:
- cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "watch");
+ cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "progress");
break;
case SDL_SYSTEM_CURSOR_SIZENWSE:
- cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "top_left_corner");
+ cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "nw-resize");
break;
case SDL_SYSTEM_CURSOR_SIZENESW:
- cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "top_right_corner");
+ cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "ne-resize");
break;
case SDL_SYSTEM_CURSOR_SIZEWE:
- cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "sb_h_double_arrow");
+ cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "e-resize");
break;
case SDL_SYSTEM_CURSOR_SIZENS:
- cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "sb_v_double_arrow");
+ cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "n-resize");
break;
case SDL_SYSTEM_CURSOR_SIZEALL:
- cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "fleur");
+ cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "fleur"); // ?
break;
case SDL_SYSTEM_CURSOR_NO:
- cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "pirate");
+ cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "not-allowed");
break;
case SDL_SYSTEM_CURSOR_HAND:
- cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "hand2");
+ cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "pointer");
break;
default:
SDL_assert(0);
@@ -771,6 +774,23 @@ void Wayland_InitMouse(void)
input->relative_mode_override = SDL_FALSE;
input->cursor_visible = SDL_TRUE;
+ SDL_HitTestResult r = SDL_HITTEST_NORMAL;
+ while (r <= SDL_HITTEST_RESIZE_LEFT) {
+ switch (r) {
+ case SDL_HITTEST_NORMAL: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); break;
+ case SDL_HITTEST_DRAGGABLE: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); break;
+ case SDL_HITTEST_RESIZE_TOPLEFT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); break;
+ case SDL_HITTEST_RESIZE_TOP: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); break;
+ case SDL_HITTEST_RESIZE_TOPRIGHT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); break;
+ case SDL_HITTEST_RESIZE_RIGHT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); break;
+ case SDL_HITTEST_RESIZE_BOTTOMRIGHT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); break;
+ case SDL_HITTEST_RESIZE_BOTTOM: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); break;
+ case SDL_HITTEST_RESIZE_BOTTOMLEFT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); break;
+ case SDL_HITTEST_RESIZE_LEFT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); break;
+ }
+ r++;
+ }
+
#ifdef SDL_USE_LIBDBUS
Wayland_DBusInitCursorProperties(d);
#endif
@@ -795,4 +815,13 @@ void Wayland_FiniMouse(SDL_VideoData *data)
Wayland_EmulateMouseWarpChanged, input);
}
+void Wayland_SetHitTestCursor(SDL_HitTestResult rc)
+{
+ if (rc == SDL_HITTEST_NORMAL || rc == SDL_HITTEST_DRAGGABLE) {
+ SDL_SetCursor(NULL);
+ } else {
+ Wayland_ShowCursor(sys_cursors[rc]);
+ }
+}
+
#endif /* SDL_VIDEO_DRIVER_WAYLAND */
diff --git a/src/video/wayland/SDL_waylandmouse.h b/src/video/wayland/SDL_waylandmouse.h
index ac194af0c064..0f63d11e48e9 100644
--- a/src/video/wayland/SDL_waylandmouse.h
+++ b/src/video/wayland/SDL_waylandmouse.h
@@ -26,6 +26,7 @@
extern void Wayland_InitMouse(void);
extern void Wayland_FiniMouse(SDL_VideoData *data);
+extern void Wayland_SetHitTestCursor(SDL_HitTestResult rc);
#if 0 /* TODO RECONNECT: See waylandvideo.c for more information! */
extern void Wayland_RecreateCursors(void);
#endif /* 0 */
diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c
index 043571aaceb6..ad2ce5c41fed 100644
--- a/src/video/wayland/SDL_waylandwindow.c
+++ b/src/video/wayland/SDL_waylandwindow.c
@@ -2109,6 +2109,8 @@ int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert
SDL_SetProperty(props, "SDL.window.wayland.surface", data->surface);
SDL_SetProperty(props, "SDL.window.wayland.egl_window", data->egl_window);
+ data->hit_test_result = SDL_HITTEST_NORMAL;
+
return 0;
}
diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h
index e53fe3168066..0821cd616390 100644
--- a/src/video/wayland/SDL_waylandwindow.h
+++ b/src/video/wayland/SDL_waylandwindow.h
@@ -121,6 +121,8 @@ struct SDL_WindowData
SDL_bool is_fullscreen;
SDL_bool in_fullscreen_transition;
SDL_bool fullscreen_was_positioned;
+
+ SDL_HitTestResult hit_test_result;
};
extern void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window);
diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c
index 52ef9575ae8e..512b69a27225 100644
--- a/src/video/x11/SDL_x11events.c
+++ b/src/video/x11/SDL_x11events.c
@@ -559,13 +559,26 @@ static void InitiateWindowResize(SDL_VideoDevice *_this, const SDL_WindowData *d
X11_XSync(display, 0);
}
-SDL_bool X11_ProcessHitTest(SDL_VideoDevice *_this, const SDL_WindowData *data, const float x, const float y)
+SDL_bool X11_ProcessHitTest(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y, SDL_bool force_new_result)
+{
+ SDL_Window *window = data->window;
+ if (!window->hit_test) return SDL_FALSE;
+ const SDL_Point point = { x, y };
+ SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
+ if (!force_new_result && rc == data->hit_test_result) {
+ return SDL_TRUE;
+ }
+ X11_SetHitTestCursor(rc);
+ data->hit_test_result = rc;
+ return SDL_TRUE;
+}
+
+SDL_bool X11_TriggerHitTestAction(SDL_VideoDevice *_this, const SDL_WindowData *data, const float x, const float y)
{
SDL_Window *window = data->window;
if (window->hit_test) {
const SDL_Point point = { x, y };
- const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
static const int directions[] = {
_NET_WM_MOVERESIZE_SIZE_TOPLEFT, _NET_WM_MOVERESIZE_SIZE_TOP,
_NET_WM_MOVERESIZE_SIZE_TOPRIGHT, _NET_WM_MOVERESIZE_SIZE_RIGHT,
@@ -573,7 +586,7 @@ SDL_bool X11_ProcessHitTest(SDL_VideoDevice *_this, const SDL_WindowData *data,
_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT, _NET_WM_MOVERESIZE_SIZE_LEFT
};
- switch (rc) {
+ switch (data->hit_test_result) {
case SDL_HITTEST_DRAGGABLE:
InitiateWindowMove(_this, data, &point);
return SDL_TRUE;
@@ -586,7 +599,7 @@ SDL_bool X11_ProcessHitTest(SDL_VideoDevice *_this, const SDL_WindowData *data,
case SDL_HITTEST_RESIZE_BOTTOM:
case SDL_HITTEST_RESIZE_BOTTOMLEFT:
case SDL_HITTEST_RESIZE_LEFT:
- InitiateWindowResize(_this, data, &point, directions[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
+ InitiateWindowResize(_this, data, &point, directions[data->hit_test_result - SDL_HITTEST_RESIZE_TOPLEFT]);
return SDL_TRUE;
default:
@@ -819,7 +832,7 @@ void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, i
} else {
SDL_bool ignore_click = SDL_FALSE;
if (button == Button1) {
- if (X11_ProcessHitTest(_this, windowdata, x, y)) {
+ if (X11_TriggerHitTestAction(_this, windowdata, x, y)) {
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_HIT_TEST, 0, 0);
return; /* don't pass this event on to app. */
}
@@ -1078,6 +1091,8 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
/* We ungrab in LeaveNotify, so we may need to grab again here */
SDL_UpdateWindowGrab(data->window);
+
+ X11_ProcessHitTest(_this, data, mouse->last_x, mouse->last_y, SDL_TRUE);
} break;
/* Losing mouse coverage? */
case LeaveNotify:
@@ -1483,6 +1498,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
printf("window %p: X11 motion: %d,%d\n", data, xevent->xmotion.x, xevent->xmotion.y);
#endif
+ X11_ProcessHitTest(_this, data, (float)xevent->xmotion.x, (float)xevent->xmotion.y, SDL_FALSE);
SDL_SendMouseMotion(0, data->window, 0, 0, (float)xevent->xmotion.x, (float)xevent->xmotion.y);
}
} break;
diff --git a/src/video/x11/SDL_x11events.h b/src/video/x11/SDL_x11events.h
index 02c666540514..4aadd290bf8d 100644
--- a/src/video/x11/SDL_x11events.h
+++ b/src/video/x11/SDL_x11events.h
@@ -32,6 +32,7 @@ extern void X11_GetBorderValues(SDL_WindowData *data);
extern void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *wdata, int button, const float x, const float y, const unsigned long time);
extern void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *wdata, int button);
extern SDL_WindowData *X11_FindWindow(SDL_VideoDevice *_this, Window window);
-extern SDL_bool X11_ProcessHitTest(SDL_VideoDevice *_this, const SDL_WindowData *data, const float x, const float y);
+extern SDL_bool X11_ProcessHitTest(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y, SDL_bool force_new_result);
+extern SDL_bool X11_TriggerHitTestAction(SDL_VideoDevice *_this, const SDL_WindowData *data, const float x, const float y);
#endif /* SDL_x11events_h_ */
diff --git a/src/video/x11/SDL_x11mouse.c b/src/video/x11/SDL_x11mouse.c
index 3f2d3d3dd9f2..895bed923228 100644
--- a/src/video/x11/SDL_x11mouse.c
+++ b/src/video/x11/SDL_x11mouse.c
@@ -31,6 +31,8 @@
/* FIXME: Find a better place to put this... */
static Cursor x11_empty_cursor = None;
+static SDL_Cursor *sys_cursors[SDL_HITTEST_RESIZE_LEFT + 1];
+
static Display *GetDisplay(void)
{
return SDL_GetVideoDevice()->driverdata->display;
@@ -472,6 +474,23 @@ void X11_InitMouse(SDL_VideoDevice *_this)
mouse->CaptureMouse = X11_CaptureMouse;
mouse->GetGlobalMouseState = X11_GetGlobalMouseState;
+ SDL_HitTestResult r = SDL_HITTEST_NORMAL;
+ while (r <= SDL_HITTEST_RESIZE_LEFT) {
+ switch (r) {
+ case SDL_HITTEST_NORMAL: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); break;
+ case SDL_HITTEST_DRAGGABLE: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); break;
+ case SDL_HITTEST_RESIZE_TOPLEFT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); break;
+ case SDL_HITTEST_RESIZE_TOP: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); break;
+ case SDL_HITTEST_RESIZE_TOPRIGHT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); break;
+ case SDL_HITTEST_RESIZE_RIGHT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); break;
+ case SDL_HITTEST_RESIZE_BOTTOMRIGHT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); break;
+ case SDL_HITTEST_RESIZE_BOTTOM: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); break;
+ case SDL_HITTEST_RESIZE_BOTTOMLEFT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); break;
+ case SDL_HITTEST_RESIZE_LEFT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); break;
+ }
+ r++;
+ }
+
SDL_SetDefaultCursor(X11_CreateDefaultCursor());
}
@@ -490,4 +509,13 @@ void X11_QuitMouse(SDL_VideoDevice *_this)
X11_DestroyEmptyCursor();
}
+void X11_SetHitTestCursor(SDL_HitTestResult rc)
+{
+ if (rc == SDL_HITTEST_NORMAL || rc == SDL_HITTEST_DRAGGABLE) {
+ SDL_SetCursor(NULL);
+ } else {
+ X11_ShowCursor(sys_cursors[rc]);
+ }
+}
+
#endif /* SDL_VIDEO_DRIVER_X11 */
diff --git a/src/video/x11/SDL_x11mouse.h b/src/video/x11/SDL_x11mouse.h
index 96e0f93195d5..902f9b7791d9 100644
--- a/src/video/x11/SDL_x11mouse.h
+++ b/src/video/x11/SDL_x11mouse.h
@@ -35,5 +35,6 @@ typedef struct SDL_XInput2DeviceInfo
extern void X11_InitMouse(SDL_VideoDevice *_this);
extern void X11_QuitMouse(SDL_VideoDevice *_this);
+extern void X11_SetHitTestCursor(SDL_HitTestResult rc);
#endif /* SDL_x11mouse_h_ */
diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c
index e17113cf25b5..c750ea76090a 100644
--- a/src/video/x11/SDL_x11window.c
+++ b/src/video/x11/SDL_x11window.c
@@ -317,6 +317,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, Window w)
}
data->window = window;
data->xwindow = w;
+ data->hit_test_result = SDL_HITTEST_NORMAL;
#ifdef X_HAVE_UTF8_STRING
if (SDL_X11_HAVE_UTF8 && videodata->im) {
diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h
index 56bc6193b63d..d1f5b8b67a09 100644
--- a/src/video/x11/SDL_x11window.h
+++ b/src/video/x11/SDL_x11window.h
@@ -79,6 +79,7 @@ struct SDL_WindowData
PointerBarrier barrier[4];
SDL_Rect barrier_rect;
#endif /* SDL_VIDEO_DRIVER_X11_XFIXES */
+ SDL_HitTestResult hit_test_result;
};
extern void X11_SetNetWMState(SDL_VideoDevice *_this, Window xwindow, Uint32 flags);
diff --git a/src/video/x11/SDL_x11xinput2.c b/src/video/x11/SDL_x11xinput2.c
index 68eaaf5d889d..ef97d33c31c3 100644
--- a/src/video/x11/SDL_x11xinput2.c
+++ b/src/video/x11/SDL_x11xinput2.c
@@ -395,11 +395,10 @@ int X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
/* button 1 is the pen tip */
if (pressed && SDL_PenPerformHitTest()) {
/* Check whether we should handle window resize / move events */
- const SDL_WindowData *windowdata = X11_FindWindow(_this, xev->event);
-
- if (X11_ProcessHitTest(_this, windowdata, pen->last.x, pen->last.y)) {
- SDL_SendWindowEvent(windowdata->window, SDL_EVENT_WINDOW_HIT_TEST, 0, 0);
- return 1; /* Don't pass on this event */
+ SDL_WindowData *windowdata = X11_FindWindow(_this, xev->event);
+ if (windowdata && X11_TriggerHitTestAction(_this, windowdata, pen->last.x, pen->last.y)) {
+ SDL_SendWindowEvent(windowdata->window, SDL_EVENT_WINDOW_HIT_TEST, 0, 0);
+ return 1; /* Don't pass on this event */
}
}
SDL_SendPenTipEvent(0, pen->header.id,
@@ -467,6 +466,7 @@ int X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
if (!mouse->relative_mode || mouse->relative_mode_warp) {
SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event);
if (window) {
+ X11_ProcessHitTest(_this, window->driverdata, (float)xev->event_x, (float)xev->event_y, SDL_FALSE);
SDL_SendMouseMotion(0, window, 0, 0, (float)xev->event_x, (float)xev->event_y);
}
}