Very WIP: xdg-shell support

This commit is contained in:
Sunderland93 2018-11-17 16:01:51 +04:00
parent 292249b79a
commit c32c98e667
4 changed files with 114 additions and 77 deletions

View File

@ -858,6 +858,15 @@ ifeq ($(TARGET), retroarch_switch)
endif endif
ifeq ($(HAVE_WAYLAND), 1) ifeq ($(HAVE_WAYLAND), 1)
OBJ += gfx/drivers_context/wayland_ctx.o \
input/drivers/wayland_input.o \
gfx/common/wayland/xdg-shell.o
ifeq ($(HAVE_EGL), 1)
LIBS += $(EGL_LIBS)
endif
DEFINES += $(WAYLAND_CFLAGS) $(WAYLAND_CURSOR_CFLAGS)
LIBS += $(WAYLAND_LIBS) $(WAYLAND_CURSOR_LIBS)
OBJ += gfx/drivers_context/wayland_ctx.o \ OBJ += gfx/drivers_context/wayland_ctx.o \
input/drivers/wayland_input.o input/drivers/wayland_input.o
ifeq ($(HAVE_EGL), 1) ifeq ($(HAVE_EGL), 1)
@ -865,6 +874,7 @@ ifeq ($(HAVE_WAYLAND), 1)
endif endif
DEFINES += $(WAYLAND_CFLAGS) $(WAYLAND_CURSOR_CFLAGS) DEFINES += $(WAYLAND_CFLAGS) $(WAYLAND_CURSOR_CFLAGS)
LIBS += $(WAYLAND_LIBS) $(WAYLAND_CURSOR_LIBS) LIBS += $(WAYLAND_LIBS) $(WAYLAND_CURSOR_LIBS)
endif endif
#Input #Input

View File

@ -0,0 +1,12 @@
#!/bin/sh
WAYSCAN=/usr/bin/wayland-scanner
WAYLAND_PROTOS=/usr/share/wayland-protocols
OUTPUT=gfx/common/wayland
if [ ! -d $OUTPUT ]; then
mkdir $OUTPUT
fi
#Generate xdg-shell header and .c files
$WAYSCAN client-header $WAYLAND_PROTOS/stable/xdg-shell/xdg-shell.xml $OUTPUT/xdg-shell.h
$WAYSCAN private-code $WAYLAND_PROTOS/stable/xdg-shell/xdg-shell.xml $OUTPUT/xdg-shell.c

View File

@ -51,6 +51,8 @@
#include "../../input/input_driver.h" #include "../../input/input_driver.h"
#include "../../input/input_keymaps.h" #include "../../input/input_keymaps.h"
// Generated from xdg-shell.xml
#include "../common/wayland/xdg-shell.h"
typedef struct touch_pos typedef struct touch_pos
{ {
@ -71,6 +73,8 @@ typedef struct gfx_ctx_wayland_data
struct wl_egl_window *win; struct wl_egl_window *win;
#endif #endif
bool resize; bool resize;
bool fullscreen;
bool maximized;
unsigned width; unsigned width;
unsigned height; unsigned height;
unsigned physical_width; unsigned physical_width;
@ -79,8 +83,9 @@ typedef struct gfx_ctx_wayland_data
struct wl_registry *registry; struct wl_registry *registry;
struct wl_compositor *compositor; struct wl_compositor *compositor;
struct wl_surface *surface; struct wl_surface *surface;
struct wl_shell_surface *shell_surf; struct xdg_surface *xdg_surface;
struct wl_shell *shell; struct xdg_wm_base *shell;
struct xdg_toplevel *xdg_toplevel;
struct wl_keyboard *wl_keyboard; struct wl_keyboard *wl_keyboard;
struct wl_pointer *wl_pointer; struct wl_pointer *wl_pointer;
struct wl_touch *wl_touch; struct wl_touch *wl_touch;
@ -242,7 +247,7 @@ static const struct wl_keyboard_listener keyboard_listener = {
keyboard_handle_repeat_info keyboard_handle_repeat_info
}; };
static void gfx_ctx_wl_show_mouse(void *data, bool state); static int gfx_ctx_wl_show_mouse(void *data, bool state);
static void pointer_handle_enter(void *data, static void pointer_handle_enter(void *data,
struct wl_pointer *pointer, struct wl_pointer *pointer,
@ -303,9 +308,6 @@ static void pointer_handle_button(void *data,
{ {
wl->input.mouse.left = true; wl->input.mouse.left = true;
/* This behavior matches mpv, seems like a decent way to support window moving for now. */
if (BIT_GET(wl->input.key_state, KEY_LEFTALT) && wl->shell_surf)
wl_shell_surface_move(wl->shell_surf, wl->seat, serial);
} }
else if (button == BTN_RIGHT) else if (button == BTN_RIGHT)
wl->input.mouse.right = true; wl->input.mouse.right = true;
@ -344,6 +346,8 @@ static const struct wl_pointer_listener pointer_listener = {
pointer_handle_axis, pointer_handle_axis,
}; };
// Check for resize
static void touch_handle_down(void *data, static void touch_handle_down(void *data,
struct wl_touch *wl_touch, struct wl_touch *wl_touch,
uint32_t serial, uint32_t serial,
@ -542,41 +546,57 @@ bool wayland_context_gettouchpos(void *data, unsigned id,
/* Shell surface callbacks. */ /* Shell surface callbacks. */
static void shell_surface_handle_ping(void *data, static void xdg_shell_ping (void *data, struct xdg_wm_base *shell, uint32_t serial)
struct wl_shell_surface *shell_surface,
uint32_t serial)
{ {
(void)data; xdg_wm_base_pong(shell, serial);
wl_shell_surface_pong(shell_surface, serial); }
static const struct xdg_wm_base_listener xdg_shell_listener = {
xdg_shell_ping,
};
static void handle_surface_config(void *data, struct xdg_surface *surface,
uint32_t serial)
{
xdg_surface_ack_configure(surface, serial);
} }
static void shell_surface_handle_configure(void *data, static const struct xdg_surface_listener xdg_surface_listener = {
struct wl_shell_surface *shell_surface, handle_surface_config,
uint32_t edges, int32_t width, int32_t height) };
static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel,
int width, int height, struct wl_array *states)
{ {
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
int prev_fs_state = wl->fullscreen;
(void)shell_surface; wl->maximized = false;
(void)edges; wl->fullscreen = false;
enum xdg_toplevel_state *state;
wl->width = wl->buffer_scale * width; wl_array_for_each(state, states) {
wl->height = wl->buffer_scale * height; switch (*state) {
case XDG_TOPLEVEL_STATE_FULLSCREEN:
RARCH_LOG("[Wayland]: Surface configure: %u x %u.\n", wl->fullscreen = true;
wl->width, wl->height); break;
case XDG_TOPLEVEL_STATE_RESIZING:
wl->resize = true;
break;
case XDG_TOPLEVEL_STATE_ACTIVATED:
break;
case XDG_TOPLEVEL_STATE_TILED_TOP:
case XDG_TOPLEVEL_STATE_TILED_LEFT:
case XDG_TOPLEVEL_STATE_TILED_RIGHT:
case XDG_TOPLEVEL_STATE_TILED_BOTTOM:
case XDG_TOPLEVEL_STATE_MAXIMIZED:
wl->maximized = true;
break;
}
}
} }
static void shell_surface_handle_popup_done(void *data, //TODO: Setup resize here
struct wl_shell_surface *shell_surface)
{
(void)data;
(void)shell_surface;
}
static const struct wl_shell_surface_listener shell_surface_listener = { static const struct xdg_toplevel_listener xdg_toplevel_listener = {
shell_surface_handle_ping, handle_toplevel_config,
shell_surface_handle_configure,
shell_surface_handle_popup_done,
}; };
static void display_handle_geometry(void *data, static void display_handle_geometry(void *data,
@ -666,12 +686,11 @@ static void registry_handle_global(void *data, struct wl_registry *reg,
{ {
output = (struct wl_output*)wl_registry_bind(reg, output = (struct wl_output*)wl_registry_bind(reg,
id, &wl_output_interface, 2); id, &wl_output_interface, 2);
wl_output_add_listener(output, &output_listener, wl);
wl_display_roundtrip(wl->input.dpy); wl_display_roundtrip(wl->input.dpy);
} }
else if (string_is_equal(interface, "wl_shell")) else if (string_is_equal(interface, "xdg_wm_base"))
wl->shell = (struct wl_shell*) wl->shell = (struct xdg_wm_base*)
wl_registry_bind(reg, id, &wl_shell_interface, 1); wl_registry_bind(reg, id, &xdg_wm_base_interface, 1);
else if (string_is_equal(interface, "wl_shm")) else if (string_is_equal(interface, "wl_shm"))
wl->shm = (struct wl_shm*)wl_registry_bind(reg, id, &wl_shm_interface, 1); wl->shm = (struct wl_shm*)wl_registry_bind(reg, id, &wl_shm_interface, 1);
else if (string_is_equal(interface, "wl_seat")) else if (string_is_equal(interface, "wl_seat"))
@ -752,13 +771,13 @@ static void gfx_ctx_wl_destroy_resources(gfx_ctx_wayland_data_t *wl)
if (wl->seat) if (wl->seat)
wl_seat_destroy(wl->seat); wl_seat_destroy(wl->seat);
if (wl->shell) if (wl->shell)
wl_shell_destroy(wl->shell); xdg_wm_base_destroy(wl->shell);
if (wl->compositor) if (wl->compositor)
wl_compositor_destroy(wl->compositor); wl_compositor_destroy(wl->compositor);
if (wl->registry) if (wl->registry)
wl_registry_destroy(wl->registry); wl_registry_destroy(wl->registry);
if (wl->shell_surf) if (wl->xdg_surface)
wl_shell_surface_destroy(wl->shell_surf); xdg_surface_destroy(wl->xdg_surface);
if (wl->surface) if (wl->surface)
wl_surface_destroy(wl->surface); wl_surface_destroy(wl->surface);
@ -775,7 +794,7 @@ static void gfx_ctx_wl_destroy_resources(gfx_ctx_wayland_data_t *wl)
wl->compositor = NULL; wl->compositor = NULL;
wl->registry = NULL; wl->registry = NULL;
wl->input.dpy = NULL; wl->input.dpy = NULL;
wl->shell_surf = NULL; wl->xdg_surface = NULL;
wl->surface = NULL; wl->surface = NULL;
wl->width = 0; wl->width = 0;
@ -892,18 +911,18 @@ static bool gfx_ctx_wl_set_resize(void *data, unsigned width, unsigned height)
return true; return true;
} }
static void gfx_ctx_wl_update_title(void *data, void *data2) //static void gfx_ctx_wl_update_title(void *data, void *data2)
{ //{
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; // gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
char title[128]; // char title[128];
title[0] = '\0'; // title[0] = '\0';
video_driver_get_window_title(title, sizeof(title)); // video_driver_get_window_title(title, sizeof(title));
if (wl && title[0]) // if (wl && title[0])
wl_shell_surface_set_title(wl->shell_surf, title); // xdg_surface_set_title(wl->xdg_surface, title);
} //}
static bool gfx_ctx_wl_get_metrics(void *data, static bool gfx_ctx_wl_get_metrics(void *data,
@ -1064,7 +1083,7 @@ static void *gfx_ctx_wl_init(video_frame_info_t *video_info, void *video_driver)
if (!wl->shell) if (!wl->shell)
{ {
RARCH_ERR("[Wayland]: Failed to create shell.\n"); RARCH_ERR("[Wayland]: Compositor doesn't support xdg-shell interface.\n");
goto error; goto error;
} }
@ -1293,12 +1312,15 @@ static bool gfx_ctx_wl_set_video_mode(void *data,
default: default:
break; break;
} }
wl->shell_surf = wl_shell_get_shell_surface(wl->shell, wl->surface); wl->xdg_surface = xdg_wm_base_get_xdg_surface(wl->shell, wl->surface);
xdg_surface_add_listener(wl->xdg_surface, &xdg_surface_listener, wl);
wl->xdg_toplevel = xdg_surface_get_toplevel(wl->xdg_surface);
xdg_toplevel_add_listener(wl->xdg_toplevel, &xdg_toplevel_listener, wl);
xdg_toplevel_set_title (wl->xdg_toplevel, "RetroArch");
xdg_toplevel_set_app_id (wl->xdg_toplevel, "RetroArch");
wl_shell_surface_add_listener(wl->shell_surf, &shell_surface_listener, wl);
wl_shell_surface_set_toplevel(wl->shell_surf);
wl_shell_surface_set_class(wl->shell_surf, "RetroArch");
wl_shell_surface_set_title(wl->shell_surf, "RetroArch");
switch (wl_api) switch (wl_api)
{ {
@ -1323,12 +1345,6 @@ static bool gfx_ctx_wl_set_video_mode(void *data,
break; break;
} }
if (fullscreen)
wl_shell_surface_set_fullscreen(wl->shell_surf,
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0, NULL);
flush_wayland_fd(&wl->input);
switch (wl_api) switch (wl_api)
{ {
case GFX_CTX_VULKAN_API: case GFX_CTX_VULKAN_API:
@ -1400,12 +1416,6 @@ static bool gfx_ctx_wl_suppress_screensaver(void *data, bool enable)
return true; return true;
} }
static bool gfx_ctx_wl_has_windowed(void *data)
{
(void)data;
return true;
}
static enum gfx_ctx_api gfx_ctx_wl_get_api(void *data) static enum gfx_ctx_api gfx_ctx_wl_get_api(void *data)
{ {
return wl_api; return wl_api;
@ -1557,11 +1567,11 @@ static void gfx_ctx_wl_set_flags(void *data, uint32_t flags)
wl->core_hw_context_enable = true; wl->core_hw_context_enable = true;
} }
static void gfx_ctx_wl_show_mouse(void *data, bool state) static int gfx_ctx_wl_show_mouse(void *data, bool state)
{ {
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
if (!wl->wl_pointer) if (!wl->wl_pointer)
return; return 1;
if (state) if (state)
{ {
@ -1591,19 +1601,15 @@ const gfx_ctx_driver_t gfx_ctx_wayland = {
gfx_ctx_wl_bind_api, gfx_ctx_wl_bind_api,
gfx_ctx_wl_set_swap_interval, gfx_ctx_wl_set_swap_interval,
gfx_ctx_wl_set_video_mode, gfx_ctx_wl_set_video_mode,
gfx_ctx_wl_get_video_size,
gfx_ctx_wl_get_refresh_rate, gfx_ctx_wl_get_refresh_rate,
NULL, /* get_video_output_size */ NULL, /* get_video_output_size */
NULL, /* get_video_output_prev */ NULL, /* get_video_output_prev */
NULL, /* get_video_output_next */ NULL, /* get_video_output_next */
gfx_ctx_wl_get_metrics, gfx_ctx_wl_get_metrics,
NULL, NULL,
gfx_ctx_wl_update_title,
gfx_ctx_wl_check_window, gfx_ctx_wl_check_window,
gfx_ctx_wl_set_resize,
gfx_ctx_wl_has_focus, gfx_ctx_wl_has_focus,
gfx_ctx_wl_suppress_screensaver, gfx_ctx_wl_suppress_screensaver,
gfx_ctx_wl_has_windowed,
gfx_ctx_wl_swap_buffers, gfx_ctx_wl_swap_buffers,
gfx_ctx_wl_input_driver, gfx_ctx_wl_input_driver,
gfx_ctx_wl_get_proc_address, gfx_ctx_wl_get_proc_address,

View File

@ -455,8 +455,9 @@ check_pkgconf V4L2 libv4l2
check_pkgconf FREETYPE freetype2 check_pkgconf FREETYPE freetype2
check_pkgconf X11 x11 check_pkgconf X11 x11
check_pkgconf XCB xcb check_pkgconf XCB xcb
check_pkgconf WAYLAND wayland-egl check_pkgconf WAYLAND wayland-egl 1.15
check_pkgconf WAYLAND_CURSOR wayland-cursor check_pkgconf WAYLAND_CURSOR wayland-cursor 1.15
check_pkgconf WAYLAND_PROTOS wayland-protocols 1.15
check_pkgconf XKBCOMMON xkbcommon 0.3.2 check_pkgconf XKBCOMMON xkbcommon 0.3.2
check_pkgconf DBUS dbus-1 check_pkgconf DBUS dbus-1
check_pkgconf XEXT xext check_pkgconf XEXT xext
@ -472,6 +473,14 @@ check_val '' XKBCOMMON -lxkbcommon
check_val '' XEXT -lXext check_val '' XEXT -lXext
check_val '' XF86VM -lXxf86vm check_val '' XF86VM -lXxf86vm
if [ "$HAVE_WAYLAND_PROTOS" = yes ] && [ "$HAVE_WAYLAND" = yes ]; then
check_pkgconf WAYLAND_SCANNER wayland-scanner 1.15
./gfx/common/wayland/generate_wayland_protos.sh
else
die : 'Notice: wayland-egl or wayland-protocols not present. Skiping Wayland code paths.'
HAVE_WAYLAND='no'
fi
if [ "$HAVE_X11" = 'no' ]; then if [ "$HAVE_X11" = 'no' ]; then
HAVE_XEXT=no; HAVE_XF86VM=no; HAVE_XINERAMA=no; HAVE_XSHM=no HAVE_XEXT=no; HAVE_XF86VM=no; HAVE_XINERAMA=no; HAVE_XSHM=no
fi fi