Implemented SetWindowHitTest() for Wayland (thanks, x414e54!). Fixes Bugzilla #2941.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c
index e3c9782..59280b5 100644
--- a/src/video/wayland/SDL_waylandevents.c
+++ b/src/video/wayland/SDL_waylandevents.c
@@ -52,6 +52,10 @@ struct SDL_WaylandInput {
SDL_WindowData *pointer_focus;
SDL_WindowData *keyboard_focus;
+ /* Last motion location */
+ wl_fixed_t sx_w;
+ wl_fixed_t sy_w;
+
struct {
struct xkb_keymap *keymap;
struct xkb_state *state;
@@ -119,6 +123,8 @@ pointer_handle_motion(void *data, struct wl_pointer *pointer,
{
struct SDL_WaylandInput *input = data;
SDL_WindowData *window = input->pointer_focus;
+ input->sx_w = sx_w;
+ input->sy_w = sy_w;
int sx = wl_fixed_to_int(sx_w);
int sy = wl_fixed_to_int(sy_w);
if (input->pointer_focus) {
@@ -126,6 +132,70 @@ pointer_handle_motion(void *data, struct wl_pointer *pointer,
}
}
+static SDL_bool
+ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
+{
+ SDL_WindowData *window_data = input->pointer_focus;
+ SDL_Window *window = window_data->sdlwindow;
+ SDL_bool ret = SDL_FALSE;
+
+ if (window->hit_test) {
+ const SDL_Point point = { wl_fixed_to_int(input->sx_w), wl_fixed_to_int(input->sy_w) };
+ const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
+ switch (rc) {
+ case SDL_HITTEST_DRAGGABLE: {
+ wl_shell_surface_move(window_data->shell_surface, input->seat, serial);
+ ret = SDL_TRUE;
+ }
+ break;
+ case SDL_HITTEST_RESIZE_TOPLEFT: {
+ wl_shell_surface_resize(window_data->shell_surface, input->seat, serial, WL_SHELL_SURFACE_RESIZE_TOP_LEFT);
+ ret = SDL_TRUE;
+ }
+ break;
+ case SDL_HITTEST_RESIZE_TOP: {
+ wl_shell_surface_resize(window_data->shell_surface, input->seat, serial, WL_SHELL_SURFACE_RESIZE_TOP);
+ ret = SDL_TRUE;
+ }
+ break;
+ case SDL_HITTEST_RESIZE_TOPRIGHT: {
+ wl_shell_surface_resize(window_data->shell_surface, input->seat, serial, WL_SHELL_SURFACE_RESIZE_TOP_RIGHT);
+ ret = SDL_TRUE;
+ }
+ break;
+ case SDL_HITTEST_RESIZE_RIGHT: {
+ wl_shell_surface_resize(window_data->shell_surface, input->seat, serial, WL_SHELL_SURFACE_RESIZE_RIGHT);
+ ret = SDL_TRUE;
+ }
+ break;
+ case SDL_HITTEST_RESIZE_BOTTOMRIGHT: {
+ wl_shell_surface_resize(window_data->shell_surface, input->seat, serial, WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT);
+ ret = SDL_TRUE;
+ }
+ break;
+ case SDL_HITTEST_RESIZE_BOTTOM: {
+ wl_shell_surface_resize(window_data->shell_surface, input->seat, serial, WL_SHELL_SURFACE_RESIZE_BOTTOM);
+ ret = SDL_TRUE;
+ }
+ break;
+ case SDL_HITTEST_RESIZE_BOTTOMLEFT: {
+ wl_shell_surface_resize(window_data->shell_surface, input->seat, serial, WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT);
+ ret = SDL_TRUE;
+ }
+ break;
+ case SDL_HITTEST_RESIZE_LEFT: {
+ wl_shell_surface_resize(window_data->shell_surface, input->seat, serial, WL_SHELL_SURFACE_RESIZE_LEFT);
+ ret = SDL_TRUE;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ return ret;
+}
+
static void
pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
uint32_t time, uint32_t button, uint32_t state_w)
@@ -139,6 +209,9 @@ pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
switch (button) {
case BTN_LEFT:
sdl_button = SDL_BUTTON_LEFT;
+ if (ProcessHitTest(data, serial)) {
+ return; /* don't pass this event on to app. */
+ }
break;
case BTN_MIDDLE:
sdl_button = SDL_BUTTON_MIDDLE;
@@ -364,7 +437,8 @@ Wayland_display_add_input(SDL_VideoData *d, uint32_t id)
input->display = d;
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);
diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c
index 2e74a08..8f36efa 100644
--- a/src/video/wayland/SDL_waylandvideo.c
+++ b/src/video/wayland/SDL_waylandvideo.c
@@ -119,6 +119,7 @@ Wayland_CreateDevice(int devindex)
device->SetWindowFullscreen = Wayland_SetWindowFullscreen;
device->SetWindowSize = Wayland_SetWindowSize;
device->DestroyWindow = Wayland_DestroyWindow;
+ device->SetWindowHitTest = Wayland_SetWindowHitTest;
device->free = Wayland_DeleteDevice;
diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c
index 4f00fc0..3cfb1a8 100644
--- a/src/video/wayland/SDL_waylandwindow.c
+++ b/src/video/wayland/SDL_waylandwindow.c
@@ -109,6 +109,12 @@ Wayland_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
return SDL_TRUE;
}
+int
+Wayland_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
+{
+ return 0; /* just succeed, the real work is done elsewhere. */
+}
+
void Wayland_ShowWindow(_THIS, SDL_Window *window)
{
SDL_WindowData *wind = window->driverdata;
diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h
index c1190d5..d80512d 100644
--- a/src/video/wayland/SDL_waylandwindow.h
+++ b/src/video/wayland/SDL_waylandwindow.h
@@ -55,6 +55,7 @@ extern void Wayland_DestroyWindow(_THIS, SDL_Window *window);
extern SDL_bool
Wayland_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info);
+extern int Wayland_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
#endif /* _SDL_waylandwindow_h */