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
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 \
input/drivers/wayland_input.o
ifeq ($(HAVE_EGL), 1)
@ -865,6 +874,7 @@ ifeq ($(HAVE_WAYLAND), 1)
endif
DEFINES += $(WAYLAND_CFLAGS) $(WAYLAND_CURSOR_CFLAGS)
LIBS += $(WAYLAND_LIBS) $(WAYLAND_CURSOR_LIBS)
endif
#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_keymaps.h"
// Generated from xdg-shell.xml
#include "../common/wayland/xdg-shell.h"
typedef struct touch_pos
{
@ -71,6 +73,8 @@ typedef struct gfx_ctx_wayland_data
struct wl_egl_window *win;
#endif
bool resize;
bool fullscreen;
bool maximized;
unsigned width;
unsigned height;
unsigned physical_width;
@ -79,8 +83,9 @@ typedef struct gfx_ctx_wayland_data
struct wl_registry *registry;
struct wl_compositor *compositor;
struct wl_surface *surface;
struct wl_shell_surface *shell_surf;
struct wl_shell *shell;
struct xdg_surface *xdg_surface;
struct xdg_wm_base *shell;
struct xdg_toplevel *xdg_toplevel;
struct wl_keyboard *wl_keyboard;
struct wl_pointer *wl_pointer;
struct wl_touch *wl_touch;
@ -242,7 +247,7 @@ static const struct wl_keyboard_listener keyboard_listener = {
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,
struct wl_pointer *pointer,
@ -303,9 +308,6 @@ static void pointer_handle_button(void *data,
{
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)
wl->input.mouse.right = true;
@ -344,6 +346,8 @@ static const struct wl_pointer_listener pointer_listener = {
pointer_handle_axis,
};
// Check for resize
static void touch_handle_down(void *data,
struct wl_touch *wl_touch,
uint32_t serial,
@ -542,41 +546,57 @@ bool wayland_context_gettouchpos(void *data, unsigned id,
/* Shell surface callbacks. */
static void shell_surface_handle_ping(void *data,
struct wl_shell_surface *shell_surface,
uint32_t serial)
static void xdg_shell_ping (void *data, struct xdg_wm_base *shell, uint32_t serial)
{
(void)data;
wl_shell_surface_pong(shell_surface, serial);
xdg_wm_base_pong(shell, 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,
struct wl_shell_surface *shell_surface,
uint32_t edges, int32_t width, int32_t height)
static const struct xdg_surface_listener xdg_surface_listener = {
handle_surface_config,
};
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;
(void)shell_surface;
(void)edges;
wl->width = wl->buffer_scale * width;
wl->height = wl->buffer_scale * height;
RARCH_LOG("[Wayland]: Surface configure: %u x %u.\n",
wl->width, wl->height);
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
int prev_fs_state = wl->fullscreen;
wl->maximized = false;
wl->fullscreen = false;
enum xdg_toplevel_state *state;
wl_array_for_each(state, states) {
switch (*state) {
case XDG_TOPLEVEL_STATE_FULLSCREEN:
wl->fullscreen = true;
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,
struct wl_shell_surface *shell_surface)
{
(void)data;
(void)shell_surface;
}
//TODO: Setup resize here
static const struct wl_shell_surface_listener shell_surface_listener = {
shell_surface_handle_ping,
shell_surface_handle_configure,
shell_surface_handle_popup_done,
static const struct xdg_toplevel_listener xdg_toplevel_listener = {
handle_toplevel_config,
};
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,
id, &wl_output_interface, 2);
wl_output_add_listener(output, &output_listener, wl);
wl_display_roundtrip(wl->input.dpy);
}
else if (string_is_equal(interface, "wl_shell"))
wl->shell = (struct wl_shell*)
wl_registry_bind(reg, id, &wl_shell_interface, 1);
else if (string_is_equal(interface, "xdg_wm_base"))
wl->shell = (struct xdg_wm_base*)
wl_registry_bind(reg, id, &xdg_wm_base_interface, 1);
else if (string_is_equal(interface, "wl_shm"))
wl->shm = (struct wl_shm*)wl_registry_bind(reg, id, &wl_shm_interface, 1);
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)
wl_seat_destroy(wl->seat);
if (wl->shell)
wl_shell_destroy(wl->shell);
xdg_wm_base_destroy(wl->shell);
if (wl->compositor)
wl_compositor_destroy(wl->compositor);
if (wl->registry)
wl_registry_destroy(wl->registry);
if (wl->shell_surf)
wl_shell_surface_destroy(wl->shell_surf);
if (wl->xdg_surface)
xdg_surface_destroy(wl->xdg_surface);
if (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->registry = NULL;
wl->input.dpy = NULL;
wl->shell_surf = NULL;
wl->xdg_surface = NULL;
wl->surface = NULL;
wl->width = 0;
@ -892,18 +911,18 @@ static bool gfx_ctx_wl_set_resize(void *data, unsigned width, unsigned height)
return true;
}
static void gfx_ctx_wl_update_title(void *data, void *data2)
{
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
char title[128];
//static void gfx_ctx_wl_update_title(void *data, void *data2)
//{
// gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
// 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])
wl_shell_surface_set_title(wl->shell_surf, title);
}
// if (wl && title[0])
// xdg_surface_set_title(wl->xdg_surface, title);
//}
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)
{
RARCH_ERR("[Wayland]: Failed to create shell.\n");
RARCH_ERR("[Wayland]: Compositor doesn't support xdg-shell interface.\n");
goto error;
}
@ -1293,12 +1312,15 @@ static bool gfx_ctx_wl_set_video_mode(void *data,
default:
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)
{
@ -1323,12 +1345,6 @@ static bool gfx_ctx_wl_set_video_mode(void *data,
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)
{
case GFX_CTX_VULKAN_API:
@ -1400,12 +1416,6 @@ static bool gfx_ctx_wl_suppress_screensaver(void *data, bool enable)
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)
{
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;
}
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;
if (!wl->wl_pointer)
return;
return 1;
if (state)
{
@ -1591,19 +1601,15 @@ const gfx_ctx_driver_t gfx_ctx_wayland = {
gfx_ctx_wl_bind_api,
gfx_ctx_wl_set_swap_interval,
gfx_ctx_wl_set_video_mode,
gfx_ctx_wl_get_video_size,
gfx_ctx_wl_get_refresh_rate,
NULL, /* get_video_output_size */
NULL, /* get_video_output_prev */
NULL, /* get_video_output_next */
gfx_ctx_wl_get_metrics,
NULL,
gfx_ctx_wl_update_title,
gfx_ctx_wl_check_window,
gfx_ctx_wl_set_resize,
gfx_ctx_wl_has_focus,
gfx_ctx_wl_suppress_screensaver,
gfx_ctx_wl_has_windowed,
gfx_ctx_wl_swap_buffers,
gfx_ctx_wl_input_driver,
gfx_ctx_wl_get_proc_address,

View File

@ -455,8 +455,9 @@ check_pkgconf V4L2 libv4l2
check_pkgconf FREETYPE freetype2
check_pkgconf X11 x11
check_pkgconf XCB xcb
check_pkgconf WAYLAND wayland-egl
check_pkgconf WAYLAND_CURSOR wayland-cursor
check_pkgconf WAYLAND wayland-egl 1.15
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 DBUS dbus-1
check_pkgconf XEXT xext
@ -472,6 +473,14 @@ check_val '' XKBCOMMON -lxkbcommon
check_val '' XEXT -lXext
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
HAVE_XEXT=no; HAVE_XF86VM=no; HAVE_XINERAMA=no; HAVE_XSHM=no
fi