(Wayland) Add libdecor for client side decoration (#13397)
This commit is contained in:
parent
b67b93ebfe
commit
f0392474f2
|
@ -1264,6 +1264,12 @@ ifeq ($(HAVE_WAYLAND), 1)
|
|||
DEF_FLAGS += $(WAYLAND_CFLAGS) $(WAYLAND_CURSOR_CFLAGS)
|
||||
LIBS += $(WAYLAND_LIBS) $(WAYLAND_CURSOR_LIBS)
|
||||
|
||||
ifeq ($(HAVE_LIBDECOR), 1)
|
||||
DEFINES += -DHAVE_LIBDECOR
|
||||
LIBS += $(LIBDECOR_LIBS)
|
||||
DEF_FLAGS += $(LIBDECOR_CFLAGS)
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
# XML
|
||||
|
|
|
@ -30,6 +30,10 @@
|
|||
#include "../common/egl_common.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBDECOR
|
||||
#include <libdecor.h>
|
||||
#endif
|
||||
|
||||
#include "../../frontend/frontend_driver.h"
|
||||
#include "../../input/common/wayland_common.h"
|
||||
#include "../../input/input_driver.h"
|
||||
|
@ -246,6 +250,11 @@ static void gfx_ctx_wl_update_title(void *data)
|
|||
|
||||
video_driver_get_window_title(title, sizeof(title));
|
||||
|
||||
#ifdef HAVE_LIBDECOR
|
||||
if (wl && title[0]) {
|
||||
libdecor_frame_set_title(wl->libdecor_frame, title);
|
||||
}
|
||||
#else
|
||||
if (wl && title[0])
|
||||
{
|
||||
if (wl->deco)
|
||||
|
@ -255,6 +264,7 @@ static void gfx_ctx_wl_update_title(void *data)
|
|||
}
|
||||
xdg_toplevel_set_title(wl->xdg_toplevel, title);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool gfx_ctx_wl_get_metrics(void *data,
|
||||
|
@ -287,6 +297,95 @@ static bool gfx_ctx_wl_get_metrics(void *data,
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBDECOR
|
||||
static void
|
||||
handle_libdecor_error(struct libdecor *context,
|
||||
enum libdecor_error error, const char *message)
|
||||
{
|
||||
RARCH_ERR("[Wayland]: libdecor Caught error (%d): %s\n", error, message);
|
||||
}
|
||||
|
||||
static struct libdecor_interface libdecor_interface = {
|
||||
.error = handle_libdecor_error,
|
||||
};
|
||||
|
||||
static void
|
||||
handle_libdecor_frame_configure(struct libdecor_frame *frame,
|
||||
struct libdecor_configuration *configuration, void *data)
|
||||
{
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
struct libdecor_state *state;
|
||||
int width, height;
|
||||
|
||||
static const enum libdecor_window_state tiled_states = (
|
||||
LIBDECOR_WINDOW_STATE_TILED_LEFT | LIBDECOR_WINDOW_STATE_TILED_RIGHT |
|
||||
LIBDECOR_WINDOW_STATE_TILED_TOP | LIBDECOR_WINDOW_STATE_TILED_BOTTOM
|
||||
);
|
||||
|
||||
enum libdecor_window_state window_state;
|
||||
bool focused = false;
|
||||
wl->fullscreen = false;
|
||||
wl->maximized = false;
|
||||
bool tiled = false;
|
||||
if (libdecor_configuration_get_window_state(configuration, &window_state)) {
|
||||
wl->fullscreen = (window_state & LIBDECOR_WINDOW_STATE_FULLSCREEN) != 0;
|
||||
wl->maximized = (window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED) != 0;
|
||||
focused = (window_state & LIBDECOR_WINDOW_STATE_ACTIVE) != 0;
|
||||
tiled = (window_state & tiled_states) != 0;
|
||||
}
|
||||
|
||||
if (!libdecor_configuration_get_content_size(configuration, frame,
|
||||
&width, &height)) {
|
||||
width = wl->prev_width;
|
||||
height = wl->prev_height;
|
||||
}
|
||||
|
||||
if (width > 0 && height > 0)
|
||||
{
|
||||
wl->prev_width = width;
|
||||
wl->prev_height = height;
|
||||
wl->width = width;
|
||||
wl->height = height;
|
||||
}
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
if (wl->win)
|
||||
wl_egl_window_resize(wl->win, wl->width, wl->height, 0, 0);
|
||||
else
|
||||
wl->win = wl_egl_window_create(wl->surface,
|
||||
wl->width * wl->buffer_scale,
|
||||
wl->height * wl->buffer_scale);
|
||||
#endif
|
||||
|
||||
state = libdecor_state_new(wl->width, wl->height);
|
||||
libdecor_frame_commit(frame, state, configuration);
|
||||
libdecor_state_free(state);
|
||||
|
||||
wl->configured = false;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_libdecor_frame_close(struct libdecor_frame *frame,
|
||||
void *data)
|
||||
{
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
command_event(CMD_EVENT_QUIT, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_libdecor_frame_commit(struct libdecor_frame *frame,
|
||||
void *data)
|
||||
{
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
}
|
||||
|
||||
static struct libdecor_frame_interface libdecor_frame_interface = {
|
||||
handle_libdecor_frame_configure,
|
||||
handle_libdecor_frame_close,
|
||||
handle_libdecor_frame_commit,
|
||||
};
|
||||
#endif
|
||||
|
||||
#define DEFAULT_WINDOWED_WIDTH 640
|
||||
#define DEFAULT_WINDOWED_HEIGHT 480
|
||||
|
||||
|
@ -594,6 +693,30 @@ static bool gfx_ctx_wl_set_video_mode(void *data,
|
|||
wl->win = wl_egl_window_create(wl->surface, wl->width * wl->buffer_scale, wl->height * wl->buffer_scale);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBDECOR
|
||||
wl->libdecor_context = libdecor_new(wl->input.dpy, &libdecor_interface);
|
||||
if (wl->libdecor_context) {
|
||||
wl->libdecor_frame = libdecor_decorate(wl->libdecor_context, wl->surface, &libdecor_frame_interface, wl);
|
||||
if (wl->libdecor_frame == NULL) {
|
||||
RARCH_ERR("[Wayland]: Failed to crate libdecor frame\n");
|
||||
goto error;
|
||||
} else {
|
||||
libdecor_frame_set_app_id(wl->libdecor_frame, "retroarch");
|
||||
libdecor_frame_set_title(wl->libdecor_frame, "RetroArch");
|
||||
libdecor_frame_map(wl->libdecor_frame);
|
||||
}
|
||||
}
|
||||
|
||||
/* Waiting for libdecor to be configured before starting to draw */
|
||||
wl_surface_commit(wl->surface);
|
||||
wl->configured = true;
|
||||
|
||||
while (wl->configured)
|
||||
if (libdecor_dispatch(wl->libdecor_context, 0) < 0) {
|
||||
RARCH_ERR("[Wayland]: libdecor failed to dispatch\n");
|
||||
goto error;
|
||||
};
|
||||
#else
|
||||
wl->xdg_surface = xdg_wm_base_get_xdg_surface(wl->xdg_shell, wl->surface);
|
||||
xdg_surface_add_listener(wl->xdg_surface, &xdg_surface_listener, wl);
|
||||
|
||||
|
@ -615,6 +738,7 @@ static bool gfx_ctx_wl_set_video_mode(void *data,
|
|||
|
||||
while (wl->configured)
|
||||
wl_display_dispatch(wl->input.dpy);
|
||||
#endif
|
||||
|
||||
wl_display_roundtrip(wl->input.dpy);
|
||||
xdg_wm_base_add_listener(wl->xdg_shell, &xdg_shell_listener, NULL);
|
||||
|
@ -634,7 +758,11 @@ static bool gfx_ctx_wl_set_video_mode(void *data,
|
|||
|
||||
if (fullscreen)
|
||||
{
|
||||
#ifdef HAVE_LIBDECOR
|
||||
libdecor_frame_set_fullscreen(wl->libdecor_frame, NULL);
|
||||
#else
|
||||
xdg_toplevel_set_fullscreen(wl->xdg_toplevel, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
flush_wayland_fd(&wl->input);
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
#include "../../config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBDECOR
|
||||
#include <libdecor.h>
|
||||
#endif
|
||||
|
||||
#include "../common/vulkan_common.h"
|
||||
|
||||
#include "../../frontend/frontend_driver.h"
|
||||
|
@ -238,6 +242,11 @@ static void gfx_ctx_wl_update_title(void *data)
|
|||
|
||||
video_driver_get_window_title(title, sizeof(title));
|
||||
|
||||
#ifdef HAVE_LIBDECOR
|
||||
if (wl && title[0]) {
|
||||
libdecor_frame_set_title(wl->libdecor_frame, title);
|
||||
}
|
||||
#else
|
||||
if (wl && title[0])
|
||||
{
|
||||
if (wl->deco)
|
||||
|
@ -248,6 +257,7 @@ static void gfx_ctx_wl_update_title(void *data)
|
|||
|
||||
xdg_toplevel_set_title(wl->xdg_toplevel, title);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool gfx_ctx_wl_get_metrics(void *data,
|
||||
|
@ -280,6 +290,86 @@ static bool gfx_ctx_wl_get_metrics(void *data,
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBDECOR
|
||||
static void
|
||||
handle_libdecor_error(struct libdecor *context,
|
||||
enum libdecor_error error, const char *message)
|
||||
{
|
||||
RARCH_ERR("[Wayland/Vulkan]: libdecor Caught error (%d): %s\n", error, message);
|
||||
}
|
||||
|
||||
static struct libdecor_interface libdecor_interface = {
|
||||
.error = handle_libdecor_error,
|
||||
};
|
||||
|
||||
static void
|
||||
handle_libdecor_frame_configure(struct libdecor_frame *frame,
|
||||
struct libdecor_configuration *configuration, void *data)
|
||||
{
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
struct libdecor_state *state;
|
||||
int width, height;
|
||||
|
||||
static const enum libdecor_window_state tiled_states = (
|
||||
LIBDECOR_WINDOW_STATE_TILED_LEFT | LIBDECOR_WINDOW_STATE_TILED_RIGHT |
|
||||
LIBDECOR_WINDOW_STATE_TILED_TOP | LIBDECOR_WINDOW_STATE_TILED_BOTTOM
|
||||
);
|
||||
|
||||
enum libdecor_window_state window_state;
|
||||
bool focused = false;
|
||||
wl->fullscreen = false;
|
||||
wl->maximized = false;
|
||||
bool tiled = false;
|
||||
if (libdecor_configuration_get_window_state(configuration, &window_state)) {
|
||||
wl->fullscreen = (window_state & LIBDECOR_WINDOW_STATE_FULLSCREEN) != 0;
|
||||
wl->maximized = (window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED) != 0;
|
||||
focused = (window_state & LIBDECOR_WINDOW_STATE_ACTIVE) != 0;
|
||||
tiled = (window_state & tiled_states) != 0;
|
||||
}
|
||||
|
||||
if (!libdecor_configuration_get_content_size(configuration, frame,
|
||||
&width, &height)) {
|
||||
width = wl->prev_width;
|
||||
height = wl->prev_height;
|
||||
}
|
||||
|
||||
if (width > 0 && height > 0)
|
||||
{
|
||||
wl->prev_width = width;
|
||||
wl->prev_height = height;
|
||||
wl->width = width;
|
||||
wl->height = height;
|
||||
}
|
||||
|
||||
state = libdecor_state_new(wl->width, wl->height);
|
||||
libdecor_frame_commit(frame, state, configuration);
|
||||
libdecor_state_free(state);
|
||||
|
||||
wl->configured = false;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_libdecor_frame_close(struct libdecor_frame *frame,
|
||||
void *data)
|
||||
{
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
command_event(CMD_EVENT_QUIT, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_libdecor_frame_commit(struct libdecor_frame *frame,
|
||||
void *data)
|
||||
{
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
}
|
||||
|
||||
static struct libdecor_frame_interface libdecor_frame_interface = {
|
||||
handle_libdecor_frame_configure,
|
||||
handle_libdecor_frame_close,
|
||||
handle_libdecor_frame_commit,
|
||||
};
|
||||
#endif
|
||||
|
||||
#define DEFAULT_WINDOWED_WIDTH 640
|
||||
#define DEFAULT_WINDOWED_HEIGHT 480
|
||||
|
||||
|
@ -420,6 +510,30 @@ static bool gfx_ctx_wl_set_video_mode(void *data,
|
|||
wl_surface_set_buffer_scale(wl->surface, wl->buffer_scale);
|
||||
wl_surface_add_listener(wl->surface, &wl_surface_listener, wl);
|
||||
|
||||
#ifdef HAVE_LIBDECOR
|
||||
wl->libdecor_context = libdecor_new(wl->input.dpy, &libdecor_interface);
|
||||
if (wl->libdecor_context) {
|
||||
wl->libdecor_frame = libdecor_decorate(wl->libdecor_context, wl->surface, &libdecor_frame_interface, wl);
|
||||
if (wl->libdecor_frame == NULL) {
|
||||
RARCH_ERR("[Wayland/Vulkan]: Failed to crate libdecor frame\n");
|
||||
goto error;
|
||||
} else {
|
||||
libdecor_frame_set_app_id(wl->libdecor_frame, "retroarch");
|
||||
libdecor_frame_set_title(wl->libdecor_frame, "RetroArch");
|
||||
libdecor_frame_map(wl->libdecor_frame);
|
||||
}
|
||||
}
|
||||
|
||||
/* Waiting for libdecor to be configured before starting to draw */
|
||||
wl_surface_commit(wl->surface);
|
||||
wl->configured = true;
|
||||
|
||||
while (wl->configured)
|
||||
if (libdecor_dispatch(wl->libdecor_context, 0) < 0) {
|
||||
RARCH_ERR("[Wayland/Vulkan]: libdecor failed to dispatch\n");
|
||||
goto error;
|
||||
};
|
||||
#else
|
||||
wl->xdg_surface = xdg_wm_base_get_xdg_surface(wl->xdg_shell, wl->surface);
|
||||
xdg_surface_add_listener(wl->xdg_surface, &xdg_surface_listener, wl);
|
||||
|
||||
|
@ -441,13 +555,18 @@ static bool gfx_ctx_wl_set_video_mode(void *data,
|
|||
|
||||
while (wl->configured)
|
||||
wl_display_dispatch(wl->input.dpy);
|
||||
#endif
|
||||
|
||||
wl_display_roundtrip(wl->input.dpy);
|
||||
xdg_wm_base_add_listener(wl->xdg_shell, &xdg_shell_listener, NULL);
|
||||
|
||||
if (fullscreen)
|
||||
{
|
||||
#ifdef HAVE_LIBDECOR
|
||||
libdecor_frame_set_fullscreen(wl->libdecor_frame, NULL);
|
||||
#else
|
||||
xdg_toplevel_set_fullscreen(wl->xdg_toplevel, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
flush_wayland_fd(&wl->input);
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
|
||||
#include <string/stdstring.h>
|
||||
|
||||
#ifdef HAVE_LIBDECOR
|
||||
#include <libdecor.h>
|
||||
#endif
|
||||
|
||||
#include "wayland_common.h"
|
||||
|
||||
#include "../input_keymaps.h"
|
||||
|
@ -208,7 +212,11 @@ static void pointer_handle_button(void *data,
|
|||
|
||||
if (BIT_GET(wl->input.key_state, KEY_LEFTALT))
|
||||
{
|
||||
#ifdef HAVE_LIBDECOR
|
||||
libdecor_frame_move(wl->libdecor_frame, wl->seat, serial);
|
||||
#else
|
||||
xdg_toplevel_move(wl->xdg_toplevel, wl->seat, serial);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case BTN_RIGHT:
|
||||
|
|
|
@ -126,6 +126,10 @@ typedef struct gfx_ctx_wayland_data
|
|||
struct wl_touch *wl_touch;
|
||||
struct wl_seat *seat;
|
||||
struct wl_shm *shm;
|
||||
#ifdef HAVE_LIBDECOR
|
||||
struct libdecor *libdecor_context;
|
||||
struct libdecor_frame *libdecor_frame;
|
||||
#endif
|
||||
struct zxdg_decoration_manager_v1 *deco_manager;
|
||||
struct zxdg_toplevel_decoration_v1 *deco;
|
||||
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager;
|
||||
|
|
|
@ -534,6 +534,8 @@ if [ "$HAVE_WAYLAND_SCANNER" = yes ] &&
|
|||
-p "$HAVE_WAYLAND_PROTOS" \
|
||||
-s "$SHARE_DIR" ||
|
||||
die 1 'Error: Failed generating wayland protocols.'
|
||||
|
||||
check_pkgconf LIBDECOR libdecor-0
|
||||
else
|
||||
die : 'Notice: wayland libraries not found, disabling wayland support.'
|
||||
HAVE_WAYLAND='no'
|
||||
|
|
|
@ -97,6 +97,7 @@ HAVE_EXYNOS=no # Exynos video support
|
|||
HAVE_DISPMANX=no # Dispmanx video support
|
||||
HAVE_SUNXI=no # Sunxi video support
|
||||
HAVE_WAYLAND=auto # Wayland support
|
||||
HAVE_LIBDECOR=auto # libdecor support
|
||||
C89_WAYLAND=no
|
||||
CXX_WAYLAND=no
|
||||
HAVE_DYNAMIC_EGL=no # Dynamic library EGL support
|
||||
|
|
Loading…
Reference in New Issue