From 00bc1936ebf3f492c3689ea7549ecf50c3350179 Mon Sep 17 00:00:00 2001 From: Ningyuan Li Date: Mon, 25 Mar 2024 18:23:08 +0900 Subject: [PATCH] webOS relative mouse hack --- src/events/SDL_mouse.c | 8 ++++++++ src/events/SDL_mouse_c.h | 3 +++ src/video/wayland/SDL_waylandevents.c | 29 +++++++++++++++++++++++++++ src/video/wayland/SDL_waylandmouse.c | 11 ++++++++++ src/video/wayland/SDL_waylandwindow.c | 5 +++++ src/video/wayland/SDL_waylandwindow.h | 3 ++- 6 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index 431354f88b39b..846f244fde777 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -231,6 +231,14 @@ void SDL_MousePostInit(void) SDL_FreeSurface(surface); } } +#if __WEBOS__ + { + SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, 1, 1, 32, SDL_PIXELFORMAT_RGBA32); + SDL_memset(surface->pixels, 0, (size_t)surface->h * surface->pitch); + mouse->hidden_cursor = SDL_CreateColorCursor(surface, 0, 0); + SDL_FreeSurface(surface); + } +#endif /* __WEBOS__ */ } void SDL_SetDefaultCursor(SDL_Cursor *cursor) diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h index 0ec9650e8fb1f..db655e96d355f 100644 --- a/src/events/SDL_mouse_c.h +++ b/src/events/SDL_mouse_c.h @@ -129,6 +129,9 @@ typedef struct SDL_Cursor *cursors; SDL_Cursor *def_cursor; SDL_Cursor *cur_cursor; +#ifdef __WEBOS__ + SDL_Cursor *hidden_cursor; +#endif SDL_bool cursor_shown; /* Driver-dependent data. */ diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index 15e4ed76bdaa7..9f807ac61a8b6 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -417,6 +417,28 @@ static void pointer_handle_motion(void *data, struct wl_pointer *pointer, { struct SDL_WaylandInput *input = data; SDL_WindowData *window = input->pointer_focus; +#ifdef SDL_VIDEO_DRIVER_WAYLAND_WEBOS + static bool warping = false; + if (window && window->waylandData->relative_mouse_mode && time != input->pointer_enter_serial) { + if (!warping) { + SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window->sdlwindow); + SDL_WaylandOutputData *output = (SDL_WaylandOutputData *)display->driverdata; + int cx = output->width / 2, cy = output->height / 2; + warping = true; + wl_starfish_pointer_set_cursor_position(window->waylandData->starfish_pointer, cx, cy); + } else { + const float dx_f = (float)wl_fixed_to_double(input->sx_w) - (float)wl_fixed_to_double(sx_w); + const float dy_f = (float)wl_fixed_to_double(input->sy_w) - (float)wl_fixed_to_double(sy_w); + const int dx = (int)SDL_floorf(dx_f * window->pointer_scale_x); + const int dy = (int)SDL_floorf(dy_f * window->pointer_scale_y); + warping = false; + SDL_SendMouseMotion(window->sdlwindow, 0, 1, dx, dy); + } + input->sx_w = sx_w; + input->sy_w = sy_w; + return; + } +#endif input->sx_w = sx_w; input->sy_w = sy_w; if (input->pointer_focus) { @@ -2777,6 +2799,13 @@ int Wayland_input_lock_pointer(struct SDL_WaylandInput *input) SDL_Window *window; struct zwp_relative_pointer_v1 *relative_pointer; +#ifdef SDL_VIDEO_DRIVER_WAYLAND_WEBOS + if (d->starfish_pointer) { + d->relative_mouse_mode = 1; + return 0; + } +#endif + if (!d->relative_pointer_manager) { return -1; } diff --git a/src/video/wayland/SDL_waylandmouse.c b/src/video/wayland/SDL_waylandmouse.c index 284230d1fc03b..7812b84d7af66 100644 --- a/src/video/wayland/SDL_waylandmouse.c +++ b/src/video/wayland/SDL_waylandmouse.c @@ -586,7 +586,18 @@ static int Wayland_ShowCursor(SDL_Cursor *cursor) } else { input->cursor_visible = SDL_FALSE; +#ifdef SDL_VIDEO_DRIVER_WAYLAND_WEBOS + { + SDL_Cursor *hidden_cur = SDL_GetMouse()->hidden_cursor; + Wayland_CursorData *data = hidden_cur->driverdata; + wl_pointer_set_cursor(pointer, input->pointer_enter_serial, data->surface, 0, 0); + wl_surface_attach(data->surface, data->buffer, 0, 0); + wl_surface_damage(data->surface, 0, 0, data->w, data->h); + wl_surface_commit(data->surface); + } +#else wl_pointer_set_cursor(pointer, input->pointer_enter_serial, NULL, 0, 0); +#endif } return 0; diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index 4bc62a7fd37eb..05d40f2de5fc5 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -2177,6 +2177,11 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window) if (c->shell.libdecor && !IS_POPUP(window)) { data->shell_surface_type = WAYLAND_SURFACE_LIBDECOR; } else +#endif +#ifdef SDL_VIDEO_DRIVER_WAYLAND_WEBOS + if (c->shell.webos) { + data->shell_surface_type = WAYLAND_SURFACE_WEBOS; + } else #endif if (c->shell.xdg) { if (IS_POPUP(window)) { diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h index 3c96cef556570..c9d69e022a1df 100644 --- a/src/video/wayland/SDL_waylandwindow.h +++ b/src/video/wayland/SDL_waylandwindow.h @@ -79,7 +79,8 @@ typedef struct WAYLAND_SURFACE_UNKNOWN = 0, WAYLAND_SURFACE_XDG_TOPLEVEL, WAYLAND_SURFACE_XDG_POPUP, - WAYLAND_SURFACE_LIBDECOR + WAYLAND_SURFACE_LIBDECOR, + WAYLAND_SURFACE_WEBOS, } shell_surface_type; struct wl_egl_window *egl_window;