Commit d10201be08141c7db41d050156fb89abf035089e

Ryan C. Gordon 2015-04-12T20:40:06

Implemented SetWindowHitTest() for Wayland (thanks, x414e54!). Fixes Bugzilla #2941.

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 */