diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index e3c9782f6..59280b56f 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 2e74a0869..8f36efa59 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 4f00fc053..3cfb1a8ee 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 c1190d521..d80512d6e 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 */