mirror of
https://github.com/libretro/RetroArch
synced 2025-02-19 12:41:00 +00:00
Split up wayland code
This commit is contained in:
parent
6a27bbfb42
commit
1f4a27abba
@ -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 \
|
||||
|
@ -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; j<MAX_TOUCHES; j++)
|
||||
{
|
||||
if (wl->active_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)
|
||||
|
@ -710,6 +710,7 @@ INPUT
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include "../input/common/wayland_common.c"
|
||||
#include "../input/drivers/wayland_input.c"
|
||||
#endif
|
||||
|
||||
|
453
input/common/wayland_common.c
Normal file
453
input/common/wayland_common.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#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; j<MAX_TOUCHES; j++)
|
||||
{
|
||||
if (wl->active_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,
|
||||
};
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user