From 1f4a27abba6e55b89a725e97950769b1a19e0a53 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Tue, 14 Jul 2020 15:56:37 +0200 Subject: [PATCH] Split up wayland code --- Makefile.common | 1 + gfx/drivers_context/wayland_ctx.c | 520 +----------------------------- griffin/griffin.c | 1 + input/common/wayland_common.c | 453 ++++++++++++++++++++++++++ input/common/wayland_common.h | 110 +++++++ 5 files changed, 569 insertions(+), 516 deletions(-) create mode 100644 input/common/wayland_common.c diff --git a/Makefile.common b/Makefile.common index 4d6f646cda..880b755841 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1052,6 +1052,7 @@ endif ifeq ($(HAVE_WAYLAND), 1) OBJ += gfx/drivers_context/wayland_ctx.o \ + input/common/wayland_common.o \ input/drivers/wayland_input.o \ gfx/common/wayland/xdg-shell.o \ gfx/common/wayland/xdg-shell-unstable-v6.o \ diff --git a/gfx/drivers_context/wayland_ctx.c b/gfx/drivers_context/wayland_ctx.c index 5fc73f6be0..e5a376f5ce 100644 --- a/gfx/drivers_context/wayland_ctx.c +++ b/gfx/drivers_context/wayland_ctx.c @@ -60,92 +60,6 @@ /* Generated from xdg-decoration-unstable-v1.h */ #include "../common/wayland/xdg-decoration-unstable-v1.h" -#define WL_ARRAY_FOR_EACH(pos, array, type) \ - for (pos = (type)(array)->data; \ - (const char *) pos < ((const char *) (array)->data + (array)->size); \ - (pos)++) - -typedef struct touch_pos -{ - bool active; - int32_t id; - unsigned x; - unsigned y; -} touch_pos_t; - -typedef struct output_info -{ - struct wl_output *output; - uint32_t global_id; - unsigned width; - unsigned height; - unsigned physical_width; - unsigned physical_height; - int refresh_rate; - unsigned scale; - struct wl_list link; /* wl->all_outputs */ -} output_info_t; - - -typedef struct gfx_ctx_wayland_data -{ -#ifdef HAVE_EGL - egl_ctx_data_t egl; - struct wl_egl_window *win; -#endif - bool fullscreen; - bool maximized; - bool resize; - bool configured; - bool activated; - unsigned prev_width; - unsigned prev_height; - unsigned width; - unsigned height; - struct wl_registry *registry; - struct wl_compositor *compositor; - struct wl_surface *surface; - struct zxdg_surface_v6 *zxdg_surface; - struct zxdg_shell_v6 *zxdg_shell; - struct zxdg_toplevel_v6 *zxdg_toplevel; - struct xdg_surface *xdg_surface; - struct xdg_wm_base *xdg_shell; - struct xdg_toplevel *xdg_toplevel; - struct wl_keyboard *wl_keyboard; - struct wl_pointer *wl_pointer; - struct wl_touch *wl_touch; - struct wl_seat *seat; - struct wl_shm *shm; - struct zxdg_decoration_manager_v1 *deco_manager; - struct zxdg_toplevel_decoration_v1 *deco; - struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager; - struct zwp_idle_inhibitor_v1 *idle_inhibitor; - struct wl_list all_outputs; - output_info_t *current_output; - int swap_interval; - bool core_hw_context_enable; - - unsigned last_buffer_scale; - unsigned buffer_scale; - - struct - { - struct wl_cursor *default_cursor; - struct wl_cursor_theme *theme; - struct wl_surface *surface; - uint32_t serial; - bool visible; - } cursor; - - input_ctx_wayland_data_t input; - -#ifdef HAVE_VULKAN - gfx_ctx_vulkan_data_t vk; -#endif - int num_active_touches; - touch_pos_t active_touch_positions[MAX_TOUCHES]; -} gfx_ctx_wayland_data_t; - static enum gfx_ctx_api wl_api = GFX_CTX_NONE; #ifndef EGL_OPENGL_ES3_BIT_KHR @@ -156,435 +70,6 @@ static enum gfx_ctx_api wl_api = GFX_CTX_NONE; #define EGL_PLATFORM_WAYLAND_KHR 0x31D8 #endif -#ifdef HAVE_XKBCOMMON -/* FIXME: Move this into a header? */ -int init_xkb(int fd, size_t size); -int handle_xkb(int code, int value); -void handle_xkb_state_mask(uint32_t depressed, - uint32_t latched, uint32_t locked, uint32_t group); -void free_xkb(void); -#endif - -static void keyboard_handle_keymap(void* data, - struct wl_keyboard* keyboard, - uint32_t format, - int fd, - uint32_t size) -{ - (void)data; - if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) - { - close(fd); - return; - } - -#ifdef HAVE_XKBCOMMON - if (init_xkb(fd, size) < 0) - RARCH_ERR("[Wayland]: Failed to init keymap.\n"); -#endif - close(fd); - - RARCH_LOG("[Wayland]: Loaded keymap.\n"); -} - -static void keyboard_handle_enter(void* data, - struct wl_keyboard* keyboard, - uint32_t serial, - struct wl_surface* surface, - struct wl_array* keys) -{ - gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - wl->input.keyboard_focus = true; -} - -static void keyboard_handle_leave(void *data, - struct wl_keyboard *keyboard, - uint32_t serial, - struct wl_surface *surface) -{ - gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - wl->input.keyboard_focus = false; -} - -static void keyboard_handle_key(void *data, - struct wl_keyboard *keyboard, - uint32_t serial, - uint32_t time, - uint32_t key, - uint32_t state) -{ - (void)serial; - (void)time; - (void)keyboard; - - int value = 1; - gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - - if (state == WL_KEYBOARD_KEY_STATE_PRESSED) - { - BIT_SET(wl->input.key_state, key); - value = 1; - } - else if (state == WL_KEYBOARD_KEY_STATE_RELEASED) - { - BIT_CLEAR(wl->input.key_state, key); - value = 0; - } - -#ifdef HAVE_XKBCOMMON - if (handle_xkb(key, value) == 0) - return; -#endif - input_keyboard_event(value, - input_keymaps_translate_keysym_to_rk(key), - 0, 0, RETRO_DEVICE_KEYBOARD); -} - -static void keyboard_handle_modifiers(void *data, - struct wl_keyboard *keyboard, - uint32_t serial, - uint32_t modsDepressed, - uint32_t modsLatched, - uint32_t modsLocked, - uint32_t group) -{ - (void)data; - (void)keyboard; - (void)serial; -#ifdef HAVE_XKBCOMMON - handle_xkb_state_mask(modsDepressed, modsLatched, modsLocked, group); -#else - (void)modsDepressed; - (void)modsLatched; - (void)modsLocked; - (void)group; -#endif -} - -void keyboard_handle_repeat_info(void *data, - struct wl_keyboard *wl_keyboard, - int32_t rate, - int32_t delay) -{ - (void)data; - (void)wl_keyboard; - (void)rate; - (void)delay; - /* TODO: Seems like we'll need this to get - * repeat working. We'll have to do it on our own. */ -} - -static const struct wl_keyboard_listener keyboard_listener = { - keyboard_handle_keymap, - keyboard_handle_enter, - keyboard_handle_leave, - keyboard_handle_key, - keyboard_handle_modifiers, - keyboard_handle_repeat_info -}; - -static void gfx_ctx_wl_show_mouse(void *data, bool state); - -static void pointer_handle_enter(void *data, - struct wl_pointer *pointer, - uint32_t serial, - struct wl_surface *surface, - wl_fixed_t sx, - wl_fixed_t sy) -{ - gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - (void)pointer; - (void)serial; - (void)surface; - - wl->input.mouse.last_x = wl_fixed_to_int(sx * (wl_fixed_t)wl->buffer_scale); - wl->input.mouse.last_y = wl_fixed_to_int(sy * (wl_fixed_t)wl->buffer_scale); - wl->input.mouse.x = wl->input.mouse.last_x; - wl->input.mouse.y = wl->input.mouse.last_y; - wl->input.mouse.focus = true; - wl->cursor.serial = serial; - - gfx_ctx_wl_show_mouse(data, wl->cursor.visible); -} - -static void pointer_handle_leave(void *data, - struct wl_pointer *pointer, - uint32_t serial, - struct wl_surface *surface) -{ - gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - wl->input.mouse.focus = false; - (void)pointer; - (void)serial; - (void)surface; -} - -static void pointer_handle_motion(void *data, - struct wl_pointer *pointer, - uint32_t time, - wl_fixed_t sx, - wl_fixed_t sy) -{ - gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - wl->input.mouse.x = wl_fixed_to_int( - (wl_fixed_t)wl->buffer_scale * sx); - wl->input.mouse.y = wl_fixed_to_int( - (wl_fixed_t)wl->buffer_scale * sy); -} - -static void pointer_handle_button(void *data, - struct wl_pointer *wl_pointer, - uint32_t serial, - uint32_t time, - uint32_t button, - uint32_t state) -{ - gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - - if (state == WL_POINTER_BUTTON_STATE_PRESSED) - { - if (button == BTN_LEFT) - { - wl->input.mouse.left = true; - - if (BIT_GET(wl->input.key_state, KEY_LEFTALT)) - { - if (wl->xdg_toplevel) - xdg_toplevel_move(wl->xdg_toplevel, wl->seat, serial); - else if (wl->zxdg_toplevel) - zxdg_toplevel_v6_move(wl->zxdg_toplevel, wl->seat, serial); - } - } - else if (button == BTN_RIGHT) - wl->input.mouse.right = true; - else if (button == BTN_MIDDLE) - wl->input.mouse.middle = true; - } - else - { - if (button == BTN_LEFT) - wl->input.mouse.left = false; - else if (button == BTN_RIGHT) - wl->input.mouse.right = false; - else if (button == BTN_MIDDLE) - wl->input.mouse.middle = false; - } -} - -static void pointer_handle_axis(void *data, - struct wl_pointer *wl_pointer, - uint32_t time, - uint32_t axis, - wl_fixed_t value) -{ - (void)data; - (void)wl_pointer; - (void)time; - (void)axis; - (void)value; -} - -static const struct wl_pointer_listener pointer_listener = { - pointer_handle_enter, - pointer_handle_leave, - pointer_handle_motion, - pointer_handle_button, - pointer_handle_axis, -}; - -/* TODO: implement check for resize */ - -static void touch_handle_down(void *data, - struct wl_touch *wl_touch, - uint32_t serial, - uint32_t time, - struct wl_surface *surface, - int32_t id, - wl_fixed_t x, - wl_fixed_t y) -{ - int i; - gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - - if (wl->num_active_touches < MAX_TOUCHES) - { - for (i = 0; i < MAX_TOUCHES; i++) - { - /* Use next empty slot */ - if (!wl->active_touch_positions[i].active) - { - wl->active_touch_positions[wl->num_active_touches].active = true; - wl->active_touch_positions[wl->num_active_touches].id = id; - wl->active_touch_positions[wl->num_active_touches].x = (unsigned) - wl_fixed_to_int(x); - wl->active_touch_positions[wl->num_active_touches].y = (unsigned) - wl_fixed_to_int(y); - wl->num_active_touches++; - break; - } - } - } -} -static void reorder_touches(gfx_ctx_wayland_data_t *wl) -{ - int i, j; - if (wl->num_active_touches == 0) - return; - - for (i = 0; i < MAX_TOUCHES; i++) - { - if (!wl->active_touch_positions[i].active) - { - for (j=i+1; jactive_touch_positions[j].active) - { - wl->active_touch_positions[i].active = - wl->active_touch_positions[j].active; - wl->active_touch_positions[i].id = - wl->active_touch_positions[j].id; - wl->active_touch_positions[i].x = wl->active_touch_positions[j].x; - wl->active_touch_positions[i].y = wl->active_touch_positions[j].y; - wl->active_touch_positions[j].active = false; - wl->active_touch_positions[j].id = -1; - wl->active_touch_positions[j].x = (unsigned) 0; - wl->active_touch_positions[j].y = (unsigned) 0; - break; - } - - if (j == MAX_TOUCHES) - return; - } - } - } -} - -static void touch_handle_up(void *data, - struct wl_touch *wl_touch, - uint32_t serial, - uint32_t time, - int32_t id) -{ - int i; - gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - - for (i = 0; i < MAX_TOUCHES; i++) - { - if ( wl->active_touch_positions[i].active && - wl->active_touch_positions[i].id == id) - { - wl->active_touch_positions[i].active = false; - wl->active_touch_positions[i].id = -1; - wl->active_touch_positions[i].x = (unsigned)0; - wl->active_touch_positions[i].y = (unsigned)0; - wl->num_active_touches--; - } - } - reorder_touches(wl); -} - -static void touch_handle_motion(void *data, - struct wl_touch *wl_touch, - uint32_t time, - int32_t id, - wl_fixed_t x, - wl_fixed_t y) -{ - int i; - gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - - for (i = 0; i < MAX_TOUCHES; i++) - { - if ( wl->active_touch_positions[i].active && - wl->active_touch_positions[i].id == id) - { - wl->active_touch_positions[i].x = (unsigned) wl_fixed_to_int(x); - wl->active_touch_positions[i].y = (unsigned) wl_fixed_to_int(y); - } - } -} -static void touch_handle_frame(void *data, - struct wl_touch *wl_touch) -{ - /* TODO */ -} -static void touch_handle_cancel(void *data, - struct wl_touch *wl_touch) -{ - /* If i understand the spec correctly we have to reset all touches here - * since they were not ment for us anyway */ - int i; - gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - - for (i = 0; i < MAX_TOUCHES; i++) - { - wl->active_touch_positions[i].active = false; - wl->active_touch_positions[i].id = -1; - wl->active_touch_positions[i].x = (unsigned) 0; - wl->active_touch_positions[i].y = (unsigned) 0; - } - - wl->num_active_touches = 0; -} -static const struct wl_touch_listener touch_listener = { - touch_handle_down, - touch_handle_up, - touch_handle_motion, - touch_handle_frame, - touch_handle_cancel, -}; - -static void seat_handle_capabilities(void *data, - struct wl_seat *seat, unsigned caps) -{ - gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - - if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !wl->wl_keyboard) - { - wl->wl_keyboard = wl_seat_get_keyboard(seat); - wl_keyboard_add_listener(wl->wl_keyboard, &keyboard_listener, wl); - } - else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && wl->wl_keyboard) - { - wl_keyboard_destroy(wl->wl_keyboard); - wl->wl_keyboard = NULL; - } - if ((caps & WL_SEAT_CAPABILITY_POINTER) && !wl->wl_pointer) - { - wl->wl_pointer = wl_seat_get_pointer(seat); - wl_pointer_add_listener(wl->wl_pointer, &pointer_listener, wl); - } - else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && wl->wl_pointer) - { - wl_pointer_destroy(wl->wl_pointer); - wl->wl_pointer = NULL; - } - if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !wl->wl_touch) - { - wl->wl_touch = wl_seat_get_touch(seat); - wl_touch_add_listener(wl->wl_touch, &touch_listener, wl); - } - else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && wl->wl_touch) - { - wl_touch_destroy(wl->wl_touch); - wl->wl_touch = NULL; - } - -} - -static void seat_handle_name(void *data, - struct wl_seat *seat, const char *name) -{ - (void)data; - (void)seat; - RARCH_LOG("[Wayland]: Seat name: %s.\n", name); -} - -static const struct wl_seat_listener seat_listener = { - seat_handle_capabilities, - seat_handle_name, -}; - /* Touch handle functions */ bool wayland_context_gettouchpos(void *data, unsigned id, @@ -1542,6 +1027,9 @@ static void gfx_ctx_wl_set_swap_interval(void *data, int swap_interval) } } +/* Forward declaration */ +void gfx_ctx_wl_show_mouse(void *data, bool state); + static bool gfx_ctx_wl_set_video_mode(void *data, unsigned width, unsigned height, bool fullscreen) @@ -1928,7 +1416,7 @@ static void gfx_ctx_wl_set_flags(void *data, uint32_t flags) wl->core_hw_context_enable = true; } -static void gfx_ctx_wl_show_mouse(void *data, bool state) +void gfx_ctx_wl_show_mouse(void *data, bool state) { gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; if (!wl->wl_pointer) diff --git a/griffin/griffin.c b/griffin/griffin.c index 3ab1550b8c..a94a3db079 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -710,6 +710,7 @@ INPUT #endif #ifdef HAVE_WAYLAND +#include "../input/common/wayland_common.c" #include "../input/drivers/wayland_input.c" #endif diff --git a/input/common/wayland_common.c b/input/common/wayland_common.c new file mode 100644 index 0000000000..41e1f5e56d --- /dev/null +++ b/input/common/wayland_common.c @@ -0,0 +1,453 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2011-2020 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include +#include + +#include + +#include "wayland_common.h" + +#include "../input_keymaps.h" + +/* Generated from xdg-shell-unstable-v6.xml */ +#include "../../gfx/common/wayland/xdg-shell-unstable-v6.h" + +/* Generated from xdg-shell.xml */ +#include "../../gfx/common/wayland/xdg-shell.h" + +static void keyboard_handle_keymap(void* data, + struct wl_keyboard* keyboard, + uint32_t format, + int fd, + uint32_t size) +{ + (void)data; + if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) + { + close(fd); + return; + } + +#ifdef HAVE_XKBCOMMON + if (init_xkb(fd, size) < 0) + RARCH_ERR("[Wayland]: Failed to init keymap.\n"); +#endif + close(fd); + + RARCH_LOG("[Wayland]: Loaded keymap.\n"); +} + +static void keyboard_handle_enter(void* data, + struct wl_keyboard* keyboard, + uint32_t serial, + struct wl_surface* surface, + struct wl_array* keys) +{ + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + wl->input.keyboard_focus = true; +} + +static void keyboard_handle_leave(void *data, + struct wl_keyboard *keyboard, + uint32_t serial, + struct wl_surface *surface) +{ + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + wl->input.keyboard_focus = false; +} + +static void keyboard_handle_key(void *data, + struct wl_keyboard *keyboard, + uint32_t serial, + uint32_t time, + uint32_t key, + uint32_t state) +{ + (void)serial; + (void)time; + (void)keyboard; + + int value = 1; + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + + if (state == WL_KEYBOARD_KEY_STATE_PRESSED) + { + BIT_SET(wl->input.key_state, key); + value = 1; + } + else if (state == WL_KEYBOARD_KEY_STATE_RELEASED) + { + BIT_CLEAR(wl->input.key_state, key); + value = 0; + } + +#ifdef HAVE_XKBCOMMON + if (handle_xkb(key, value) == 0) + return; +#endif + input_keyboard_event(value, + input_keymaps_translate_keysym_to_rk(key), + 0, 0, RETRO_DEVICE_KEYBOARD); +} + +static void keyboard_handle_modifiers(void *data, + struct wl_keyboard *keyboard, + uint32_t serial, + uint32_t modsDepressed, + uint32_t modsLatched, + uint32_t modsLocked, + uint32_t group) +{ + (void)data; + (void)keyboard; + (void)serial; +#ifdef HAVE_XKBCOMMON + handle_xkb_state_mask(modsDepressed, modsLatched, modsLocked, group); +#else + (void)modsDepressed; + (void)modsLatched; + (void)modsLocked; + (void)group; +#endif +} + +void keyboard_handle_repeat_info(void *data, + struct wl_keyboard *wl_keyboard, + int32_t rate, + int32_t delay) +{ + (void)data; + (void)wl_keyboard; + (void)rate; + (void)delay; + /* TODO: Seems like we'll need this to get + * repeat working. We'll have to do it on our own. */ +} + +void gfx_ctx_wl_show_mouse(void *data, bool state); + +static void pointer_handle_enter(void *data, + struct wl_pointer *pointer, + uint32_t serial, + struct wl_surface *surface, + wl_fixed_t sx, + wl_fixed_t sy) +{ + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + (void)pointer; + (void)serial; + (void)surface; + + wl->input.mouse.last_x = wl_fixed_to_int(sx * (wl_fixed_t)wl->buffer_scale); + wl->input.mouse.last_y = wl_fixed_to_int(sy * (wl_fixed_t)wl->buffer_scale); + wl->input.mouse.x = wl->input.mouse.last_x; + wl->input.mouse.y = wl->input.mouse.last_y; + wl->input.mouse.focus = true; + wl->cursor.serial = serial; + + gfx_ctx_wl_show_mouse(data, wl->cursor.visible); +} + +static void pointer_handle_leave(void *data, + struct wl_pointer *pointer, + uint32_t serial, + struct wl_surface *surface) +{ + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + wl->input.mouse.focus = false; + (void)pointer; + (void)serial; + (void)surface; +} + +static void pointer_handle_motion(void *data, + struct wl_pointer *pointer, + uint32_t time, + wl_fixed_t sx, + wl_fixed_t sy) +{ + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + wl->input.mouse.x = wl_fixed_to_int( + (wl_fixed_t)wl->buffer_scale * sx); + wl->input.mouse.y = wl_fixed_to_int( + (wl_fixed_t)wl->buffer_scale * sy); +} + +static void pointer_handle_button(void *data, + struct wl_pointer *wl_pointer, + uint32_t serial, + uint32_t time, + uint32_t button, + uint32_t state) +{ + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + + if (state == WL_POINTER_BUTTON_STATE_PRESSED) + { + if (button == BTN_LEFT) + { + wl->input.mouse.left = true; + + if (BIT_GET(wl->input.key_state, KEY_LEFTALT)) + { + if (wl->xdg_toplevel) + xdg_toplevel_move(wl->xdg_toplevel, wl->seat, serial); + else if (wl->zxdg_toplevel) + zxdg_toplevel_v6_move(wl->zxdg_toplevel, wl->seat, serial); + } + } + else if (button == BTN_RIGHT) + wl->input.mouse.right = true; + else if (button == BTN_MIDDLE) + wl->input.mouse.middle = true; + } + else + { + if (button == BTN_LEFT) + wl->input.mouse.left = false; + else if (button == BTN_RIGHT) + wl->input.mouse.right = false; + else if (button == BTN_MIDDLE) + wl->input.mouse.middle = false; + } +} + +static void pointer_handle_axis(void *data, + struct wl_pointer *wl_pointer, + uint32_t time, + uint32_t axis, + wl_fixed_t value) +{ + (void)data; + (void)wl_pointer; + (void)time; + (void)axis; + (void)value; +} + +/* TODO: implement check for resize */ + +static void touch_handle_down(void *data, + struct wl_touch *wl_touch, + uint32_t serial, + uint32_t time, + struct wl_surface *surface, + int32_t id, + wl_fixed_t x, + wl_fixed_t y) +{ + int i; + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + + if (wl->num_active_touches < MAX_TOUCHES) + { + for (i = 0; i < MAX_TOUCHES; i++) + { + /* Use next empty slot */ + if (!wl->active_touch_positions[i].active) + { + wl->active_touch_positions[wl->num_active_touches].active = true; + wl->active_touch_positions[wl->num_active_touches].id = id; + wl->active_touch_positions[wl->num_active_touches].x = (unsigned) + wl_fixed_to_int(x); + wl->active_touch_positions[wl->num_active_touches].y = (unsigned) + wl_fixed_to_int(y); + wl->num_active_touches++; + break; + } + } + } +} + +static void reorder_touches(gfx_ctx_wayland_data_t *wl) +{ + int i, j; + if (wl->num_active_touches == 0) + return; + + for (i = 0; i < MAX_TOUCHES; i++) + { + if (!wl->active_touch_positions[i].active) + { + for (j=i+1; jactive_touch_positions[j].active) + { + wl->active_touch_positions[i].active = + wl->active_touch_positions[j].active; + wl->active_touch_positions[i].id = + wl->active_touch_positions[j].id; + wl->active_touch_positions[i].x = wl->active_touch_positions[j].x; + wl->active_touch_positions[i].y = wl->active_touch_positions[j].y; + wl->active_touch_positions[j].active = false; + wl->active_touch_positions[j].id = -1; + wl->active_touch_positions[j].x = (unsigned) 0; + wl->active_touch_positions[j].y = (unsigned) 0; + break; + } + + if (j == MAX_TOUCHES) + return; + } + } + } +} + +static void touch_handle_up(void *data, + struct wl_touch *wl_touch, + uint32_t serial, + uint32_t time, + int32_t id) +{ + int i; + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + + for (i = 0; i < MAX_TOUCHES; i++) + { + if ( wl->active_touch_positions[i].active && + wl->active_touch_positions[i].id == id) + { + wl->active_touch_positions[i].active = false; + wl->active_touch_positions[i].id = -1; + wl->active_touch_positions[i].x = (unsigned)0; + wl->active_touch_positions[i].y = (unsigned)0; + wl->num_active_touches--; + } + } + reorder_touches(wl); +} + +static void touch_handle_motion(void *data, + struct wl_touch *wl_touch, + uint32_t time, + int32_t id, + wl_fixed_t x, + wl_fixed_t y) +{ + int i; + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + + for (i = 0; i < MAX_TOUCHES; i++) + { + if ( wl->active_touch_positions[i].active && + wl->active_touch_positions[i].id == id) + { + wl->active_touch_positions[i].x = (unsigned) wl_fixed_to_int(x); + wl->active_touch_positions[i].y = (unsigned) wl_fixed_to_int(y); + } + } +} + +static void touch_handle_frame(void *data, + struct wl_touch *wl_touch) +{ + /* TODO */ +} + +static void touch_handle_cancel(void *data, + struct wl_touch *wl_touch) +{ + /* If i understand the spec correctly we have to reset all touches here + * since they were not ment for us anyway */ + int i; + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + + for (i = 0; i < MAX_TOUCHES; i++) + { + wl->active_touch_positions[i].active = false; + wl->active_touch_positions[i].id = -1; + wl->active_touch_positions[i].x = (unsigned) 0; + wl->active_touch_positions[i].y = (unsigned) 0; + } + + wl->num_active_touches = 0; +} + +static void seat_handle_capabilities(void *data, + struct wl_seat *seat, unsigned caps) +{ + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + + if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !wl->wl_keyboard) + { + wl->wl_keyboard = wl_seat_get_keyboard(seat); + wl_keyboard_add_listener(wl->wl_keyboard, &keyboard_listener, wl); + } + else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && wl->wl_keyboard) + { + wl_keyboard_destroy(wl->wl_keyboard); + wl->wl_keyboard = NULL; + } + if ((caps & WL_SEAT_CAPABILITY_POINTER) && !wl->wl_pointer) + { + wl->wl_pointer = wl_seat_get_pointer(seat); + wl_pointer_add_listener(wl->wl_pointer, &pointer_listener, wl); + } + else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && wl->wl_pointer) + { + wl_pointer_destroy(wl->wl_pointer); + wl->wl_pointer = NULL; + } + if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !wl->wl_touch) + { + wl->wl_touch = wl_seat_get_touch(seat); + wl_touch_add_listener(wl->wl_touch, &touch_listener, wl); + } + else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && wl->wl_touch) + { + wl_touch_destroy(wl->wl_touch); + wl->wl_touch = NULL; + } + +} + +static void seat_handle_name(void *data, + struct wl_seat *seat, const char *name) +{ + (void)data; + (void)seat; + RARCH_LOG("[Wayland]: Seat name: %s.\n", name); +} + +const struct wl_seat_listener seat_listener = { + seat_handle_capabilities, + seat_handle_name, +}; + +const struct wl_touch_listener touch_listener = { + touch_handle_down, + touch_handle_up, + touch_handle_motion, + touch_handle_frame, + touch_handle_cancel, +}; + +const struct wl_keyboard_listener keyboard_listener = { + keyboard_handle_keymap, + keyboard_handle_enter, + keyboard_handle_leave, + keyboard_handle_key, + keyboard_handle_modifiers, + keyboard_handle_repeat_info +}; + +const struct wl_pointer_listener pointer_listener = { + pointer_handle_enter, + pointer_handle_leave, + pointer_handle_motion, + pointer_handle_button, + pointer_handle_axis, +}; diff --git a/input/common/wayland_common.h b/input/common/wayland_common.h index a496ef9467..dea109356b 100644 --- a/input/common/wayland_common.h +++ b/input/common/wayland_common.h @@ -25,11 +25,24 @@ #include "../input_driver.h" +#ifdef HAVE_EGL +#include "../../gfx/common/egl_common.h" +#endif + +#ifdef HAVE_VULKAN +#include "../../gfx/common/vulkan_common.h" +#endif + #define UDEV_KEY_MAX 0x2ff #define UDEV_MAX_KEYS (UDEV_KEY_MAX + 7) / 8 #define MAX_TOUCHES 16 +#define WL_ARRAY_FOR_EACH(pos, array, type) \ + for (pos = (type)(array)->data; \ + (const char *) pos < ((const char *) (array)->data + (array)->size); \ + (pos)++) + typedef struct { bool active; @@ -37,6 +50,27 @@ typedef struct int16_t y; } wayland_touch_data_t; +typedef struct touch_pos +{ + bool active; + int32_t id; + unsigned x; + unsigned y; +} touch_pos_t; + +typedef struct output_info +{ + struct wl_output *output; + uint32_t global_id; + unsigned width; + unsigned height; + unsigned physical_width; + unsigned physical_height; + int refresh_rate; + unsigned scale; + struct wl_list link; /* wl->all_outputs */ +} output_info_t; + typedef struct input_ctx_wayland_data { /* Wayland uses Linux keysyms. */ @@ -63,4 +97,80 @@ typedef struct input_ctx_wayland_data } input_ctx_wayland_data_t; +typedef struct gfx_ctx_wayland_data +{ +#ifdef HAVE_EGL + egl_ctx_data_t egl; + struct wl_egl_window *win; +#endif + bool fullscreen; + bool maximized; + bool resize; + bool configured; + bool activated; + unsigned prev_width; + unsigned prev_height; + unsigned width; + unsigned height; + struct wl_registry *registry; + struct wl_compositor *compositor; + struct wl_surface *surface; + struct zxdg_surface_v6 *zxdg_surface; + struct zxdg_shell_v6 *zxdg_shell; + struct zxdg_toplevel_v6 *zxdg_toplevel; + struct xdg_surface *xdg_surface; + struct xdg_wm_base *xdg_shell; + struct xdg_toplevel *xdg_toplevel; + struct wl_keyboard *wl_keyboard; + struct wl_pointer *wl_pointer; + struct wl_touch *wl_touch; + struct wl_seat *seat; + struct wl_shm *shm; + struct zxdg_decoration_manager_v1 *deco_manager; + struct zxdg_toplevel_decoration_v1 *deco; + struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager; + struct zwp_idle_inhibitor_v1 *idle_inhibitor; + struct wl_list all_outputs; + output_info_t *current_output; + int swap_interval; + bool core_hw_context_enable; + + unsigned last_buffer_scale; + unsigned buffer_scale; + + struct + { + struct wl_cursor *default_cursor; + struct wl_cursor_theme *theme; + struct wl_surface *surface; + uint32_t serial; + bool visible; + } cursor; + + input_ctx_wayland_data_t input; + +#ifdef HAVE_VULKAN + gfx_ctx_vulkan_data_t vk; +#endif + int num_active_touches; + touch_pos_t active_touch_positions[MAX_TOUCHES]; +} gfx_ctx_wayland_data_t; + +#ifdef HAVE_XKBCOMMON +/* FIXME: Move this into a header? */ +int init_xkb(int fd, size_t size); +int handle_xkb(int code, int value); +void handle_xkb_state_mask(uint32_t depressed, + uint32_t latched, uint32_t locked, uint32_t group); +void free_xkb(void); +#endif + +extern const struct wl_keyboard_listener keyboard_listener; + +extern const struct wl_pointer_listener pointer_listener; + +extern const struct wl_touch_listener touch_listener; + +extern const struct wl_seat_listener seat_listener; + #endif