mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-08 08:10:30 -10:00
wayland: dedupe GL/VK shell-surface listeners into common code
The xdg_toplevel and libdecor configure handlers in wayland_ctx.c and wayland_vk_ctx.c were near-identical copies: ignore_configuration check, call into the shared *_configure_common body, clear 'configured'. The only per-backend delta is the EGL block that resizes (or lazily creates) the wl_egl_window between the common call and the flag clear; Vulkan takes no additional action. Move the concrete handlers and listener structs into wayland_common.c, parameterized by a driver_configure_handler_t hook invoked at exactly the point the EGL block occupied. The EGL context passes gfx_ctx_wl_egl_configure; Vulkan passes NULL; webos ignores the parameter as it ignored the listener before. gfx_ctx_wl_init_common takes the handler instead of a toplevel_listener_t, and the type, the five exported handler declarations, the libdecor_interface extern, and the header's libdecor.h include all become private to wayland_common.c. Also drops the unused zero-initialised xdg_toplevel_listener instance from wayland_ctx.c. Zero behavior change intended, and verified: full builds of master and this commit (wayland + EGL + Vulkan + libdecor enabled) run under headless Weston 13 with WAYLAND_DEBUG=1 produce structurally identical protocol traces - the complete xdg_wm_base/xdg_surface/ xdg_toplevel init sequence, the toplevel-configure -> surface-configure -> ack_configure -> commit cycle, and the orderly destroy sequence are event-for-event identical after stripping serials and timestamps (36 shell-surface events, zero-line diff). Compile coverage includes the HAVE_LIBDECOR paths; the runtime trace exercises the plain xdg-shell path. The webos TU could not be compiled here (its generated webos-shell.h requires the webos NDK staging tree); its change is a parameter-type swap on an argument the function never reads. This deliberately preserves the current (protocol-questionable) practice of applying toplevel-configure state immediately and blind- acking xdg_surface.configure; restructuring that to latch pending state at surface-configure time is a separate, behavior-affecting change requiring real-compositor testing. Net -73 lines, -368 bytes .text on the reference Linux build.
This commit is contained in:
1 parent
4590c23058
commit
89f38ace73
6 files changed
+81
-154
No files matched your search
+57
-22
@@ -102,7 +102,7 @@ static bool gfx_ctx_wl_should_use_legacy_fullscreen_configure(
|
||||
return false;
|
||||
}
|
||||
|
||||
void xdg_toplevel_handle_configure_common(gfx_ctx_wayland_data_t *wl,
|
||||
static void xdg_toplevel_handle_configure_common(gfx_ctx_wayland_data_t *wl,
|
||||
void *toplevel,
|
||||
int32_t width, int32_t height, struct wl_array *states)
|
||||
{
|
||||
@@ -179,14 +179,14 @@ void xdg_toplevel_handle_configure_common(gfx_ctx_wayland_data_t *wl,
|
||||
}
|
||||
}
|
||||
|
||||
void xdg_toplevel_handle_close(void *data,
|
||||
static void xdg_toplevel_handle_close(void *data,
|
||||
struct xdg_toplevel *xdg_toplevel)
|
||||
{
|
||||
frontend_driver_set_signal_handler_state(1);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
void libdecor_frame_handle_configure_common(struct libdecor_frame *frame,
|
||||
static void libdecor_frame_handle_configure_common(struct libdecor_frame *frame,
|
||||
struct libdecor_configuration *configuration,
|
||||
gfx_ctx_wayland_data_t *wl)
|
||||
{
|
||||
@@ -265,15 +265,61 @@ void libdecor_frame_handle_configure_common(struct libdecor_frame *frame,
|
||||
}
|
||||
}
|
||||
|
||||
void libdecor_frame_handle_close(struct libdecor_frame *frame,
|
||||
static void libdecor_frame_handle_close(struct libdecor_frame *frame,
|
||||
void *data)
|
||||
{
|
||||
frontend_driver_set_signal_handler_state(1);
|
||||
}
|
||||
void libdecor_frame_handle_commit(struct libdecor_frame *frame,
|
||||
static void libdecor_frame_handle_commit(struct libdecor_frame *frame,
|
||||
void *data) { }
|
||||
|
||||
static void libdecor_frame_handle_configure(struct libdecor_frame *frame,
|
||||
struct libdecor_configuration *configuration, void *data)
|
||||
{
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
if (wl->ignore_configuration)
|
||||
return;
|
||||
libdecor_frame_handle_configure_common(frame, configuration, wl);
|
||||
if (wl->driver_configure_handler)
|
||||
wl->driver_configure_handler(wl);
|
||||
wl->configured = false;
|
||||
}
|
||||
|
||||
static void libdecor_handle_err(struct libdecor *context,
|
||||
enum libdecor_error err, const char *message)
|
||||
{
|
||||
RARCH_ERR("[Wayland] libdecor Caught error (%d): %s.\n", err, message);
|
||||
}
|
||||
|
||||
static const struct libdecor_interface libdecor_interface = {
|
||||
.error = libdecor_handle_err,
|
||||
};
|
||||
|
||||
static const struct libdecor_frame_interface wl_libdecor_frame_interface = {
|
||||
libdecor_frame_handle_configure,
|
||||
libdecor_frame_handle_close,
|
||||
libdecor_frame_handle_commit,
|
||||
};
|
||||
#endif
|
||||
|
||||
static void xdg_toplevel_handle_configure(void *data,
|
||||
struct xdg_toplevel *toplevel,
|
||||
int32_t width, int32_t height, struct wl_array *states)
|
||||
{
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
if (wl->ignore_configuration)
|
||||
return;
|
||||
xdg_toplevel_handle_configure_common(wl, toplevel, width, height, states);
|
||||
if (wl->driver_configure_handler)
|
||||
wl->driver_configure_handler(wl);
|
||||
wl->configured = false;
|
||||
}
|
||||
|
||||
static const struct xdg_toplevel_listener wl_xdg_toplevel_listener = {
|
||||
xdg_toplevel_handle_configure,
|
||||
xdg_toplevel_handle_close,
|
||||
};
|
||||
|
||||
void gfx_ctx_wl_get_video_size_common(void *data,
|
||||
unsigned *width, unsigned *height)
|
||||
{
|
||||
@@ -729,7 +775,8 @@ static bool wl_draw_splash_screen(gfx_ctx_wayland_data_t *wl)
|
||||
#endif
|
||||
|
||||
bool gfx_ctx_wl_init_common(
|
||||
const toplevel_listener_t *toplevel_listener, gfx_ctx_wayland_data_t **wwl)
|
||||
driver_configure_handler_t driver_configure_handler,
|
||||
gfx_ctx_wayland_data_t **wwl)
|
||||
{
|
||||
int i;
|
||||
gfx_ctx_wayland_data_t *wl;
|
||||
@@ -752,6 +799,8 @@ bool gfx_ctx_wl_init_common(
|
||||
#endif
|
||||
#endif
|
||||
|
||||
wl->driver_configure_handler = driver_configure_handler;
|
||||
|
||||
wl_list_init(&wl->all_outputs);
|
||||
wl_list_init(&wl->current_outputs);
|
||||
|
||||
@@ -896,7 +945,7 @@ bool gfx_ctx_wl_init_common(
|
||||
|
||||
if (wl->libdecor)
|
||||
{
|
||||
wl->libdecor_frame = wl->libdecor_decorate(wl->libdecor_context, wl->surface, &toplevel_listener->libdecor_frame_interface, wl);
|
||||
wl->libdecor_frame = wl->libdecor_decorate(wl->libdecor_context, wl->surface, &wl_libdecor_frame_interface, wl);
|
||||
if (!wl->libdecor_frame)
|
||||
{
|
||||
RARCH_ERR("[Wayland] Failed to create libdecor frame.\n");
|
||||
@@ -942,7 +991,7 @@ bool gfx_ctx_wl_init_common(
|
||||
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, &toplevel_listener->xdg_toplevel_listener, wl);
|
||||
xdg_toplevel_add_listener(wl->xdg_toplevel, &wl_xdg_toplevel_listener, wl);
|
||||
|
||||
xdg_toplevel_set_app_id(wl->xdg_toplevel, WAYLAND_APP_ID);
|
||||
xdg_toplevel_set_title(wl->xdg_toplevel, DEFAULT_WINDOW_TITLE);
|
||||
@@ -1204,20 +1253,6 @@ static void xdg_surface_handle_configure(void *data,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
static void libdecor_handle_err(struct libdecor *context,
|
||||
enum libdecor_error err, const char *message)
|
||||
{
|
||||
RARCH_ERR("[Wayland] libdecor Caught error (%d): %s.\n", err, message);
|
||||
}
|
||||
#endif
|
||||
|
||||
const struct wl_buffer_listener shm_buffer_listener = {
|
||||
shm_buffer_handle_release,
|
||||
};
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
const struct libdecor_interface libdecor_interface = {
|
||||
.error = libdecor_handle_err,
|
||||
};
|
||||
#endif
|
||||
@@ -15,22 +15,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
#include <libdecor.h>
|
||||
#endif
|
||||
|
||||
#include "../../input/common/wayland_common.h"
|
||||
|
||||
#define WAYLAND_APP_ID "com.libretro.RetroArch"
|
||||
|
||||
typedef struct toplevel_listener
|
||||
{
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
struct libdecor_frame_interface libdecor_frame_interface;
|
||||
#endif
|
||||
struct xdg_toplevel_listener xdg_toplevel_listener;
|
||||
} toplevel_listener_t;
|
||||
|
||||
typedef struct shm_buffer
|
||||
{
|
||||
struct wl_buffer *wl_buffer;
|
||||
@@ -38,23 +26,6 @@ typedef struct shm_buffer
|
||||
size_t data_size;
|
||||
} shm_buffer_t;
|
||||
|
||||
void xdg_toplevel_handle_configure_common(gfx_ctx_wayland_data_t *wl, void *toplevel,
|
||||
int32_t width, int32_t height, struct wl_array *states);
|
||||
|
||||
void xdg_toplevel_handle_close(void *data,
|
||||
struct xdg_toplevel *xdg_toplevel);
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
void libdecor_frame_handle_configure_common(struct libdecor_frame *frame,
|
||||
struct libdecor_configuration *configuration, gfx_ctx_wayland_data_t *wl);
|
||||
|
||||
void libdecor_frame_handle_close(struct libdecor_frame *frame,
|
||||
void *data);
|
||||
|
||||
void libdecor_frame_handle_commit(struct libdecor_frame *frame,
|
||||
void *data);
|
||||
#endif
|
||||
|
||||
void gfx_ctx_wl_get_video_size_common(void *data, unsigned *width,
|
||||
unsigned *height);
|
||||
|
||||
@@ -64,7 +35,7 @@ void gfx_ctx_wl_update_title_common(void *data);
|
||||
|
||||
|
||||
bool gfx_ctx_wl_init_common(
|
||||
const toplevel_listener_t *toplevel_listener,
|
||||
driver_configure_handler_t driver_configure_handler,
|
||||
gfx_ctx_wayland_data_t **wl);
|
||||
|
||||
bool gfx_ctx_wl_set_video_mode_common_size(gfx_ctx_wayland_data_t *wl,
|
||||
@@ -85,7 +56,3 @@ bool gfx_ctx_wl_has_focus(void *data);
|
||||
void gfx_ctx_wl_check_window_common(gfx_ctx_wayland_data_t *wl,
|
||||
void (*get_video_size)(void*, unsigned*, unsigned*), bool *quit,
|
||||
bool *resize, unsigned *width, unsigned *height);
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
extern const struct libdecor_interface libdecor_interface;
|
||||
#endif
|
||||
@@ -55,7 +55,7 @@
|
||||
extern void gfx_ctx_wl_get_video_size_webos(void*, unsigned*, unsigned*);
|
||||
extern void gfx_ctx_wl_destroy_resources_webos(gfx_ctx_wayland_data_t*);
|
||||
extern void gfx_ctx_wl_update_title_webos(void*);
|
||||
extern bool gfx_ctx_wl_init_webos(const toplevel_listener_t*, gfx_ctx_wayland_data_t**);
|
||||
extern bool gfx_ctx_wl_init_webos(driver_configure_handler_t, gfx_ctx_wayland_data_t**);
|
||||
extern bool gfx_ctx_wl_set_video_mode_common_size_webos(gfx_ctx_wayland_data_t*, unsigned, unsigned, bool);
|
||||
extern bool gfx_ctx_wl_set_video_mode_common_fullscreen_webos(gfx_ctx_wayland_data_t*, bool);
|
||||
extern bool gfx_ctx_wl_suppress_screensaver_webos(void*, bool);
|
||||
@@ -73,16 +73,12 @@ extern void gfx_ctx_wl_check_window_webos(gfx_ctx_wayland_data_t*, void (*)(void
|
||||
|
||||
static enum gfx_ctx_api wl_api = GFX_CTX_NONE;
|
||||
|
||||
/* Shell surface callbacks. */
|
||||
static void xdg_toplevel_handle_configure(void *data,
|
||||
struct xdg_toplevel *toplevel,
|
||||
int32_t width, int32_t height, struct wl_array *states)
|
||||
{
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
if (wl->ignore_configuration)
|
||||
return;
|
||||
xdg_toplevel_handle_configure_common(wl, toplevel, width, height, states);
|
||||
#ifdef HAVE_EGL
|
||||
/* Invoked from the common shell-surface configure handlers after the
|
||||
* shared configure processing; resizes (or lazily creates) the
|
||||
* wl_egl_window to the new buffer dimensions. */
|
||||
static void gfx_ctx_wl_egl_configure(gfx_ctx_wayland_data_t *wl)
|
||||
{
|
||||
if (wl->win)
|
||||
wl_egl_window_resize(wl->win,
|
||||
wl->buffer_width,
|
||||
@@ -92,10 +88,8 @@ static void xdg_toplevel_handle_configure(void *data,
|
||||
wl->win = wl_egl_window_create(wl->surface,
|
||||
wl->buffer_width,
|
||||
wl->buffer_height);
|
||||
#endif
|
||||
|
||||
wl->configured = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void gfx_ctx_wl_destroy_resources(gfx_ctx_wayland_data_t *wl)
|
||||
{
|
||||
@@ -139,49 +133,6 @@ static bool gfx_ctx_wl_set_resize(void *data, unsigned width, unsigned height)
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
static void
|
||||
libdecor_frame_handle_configure(struct libdecor_frame *frame,
|
||||
struct libdecor_configuration *configuration, void *data)
|
||||
{
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
if (wl->ignore_configuration)
|
||||
return;
|
||||
libdecor_frame_handle_configure_common(frame, configuration, wl);
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
if (wl->win)
|
||||
wl_egl_window_resize(wl->win,
|
||||
wl->buffer_width,
|
||||
wl->buffer_height,
|
||||
0, 0);
|
||||
else
|
||||
wl->win = wl_egl_window_create(
|
||||
wl->surface,
|
||||
wl->buffer_width,
|
||||
wl->buffer_height);
|
||||
#endif
|
||||
|
||||
wl->configured = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const toplevel_listener_t toplevel_listener = {
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
.libdecor_frame_interface = {
|
||||
libdecor_frame_handle_configure,
|
||||
libdecor_frame_handle_close,
|
||||
libdecor_frame_handle_commit,
|
||||
},
|
||||
#endif
|
||||
.xdg_toplevel_listener = {
|
||||
xdg_toplevel_handle_configure,
|
||||
xdg_toplevel_handle_close,
|
||||
},
|
||||
};
|
||||
|
||||
static const toplevel_listener_t xdg_toplevel_listener = {0};
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
#define WL_EGL_ATTRIBS_BASE \
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, \
|
||||
@@ -280,7 +231,13 @@ static void *gfx_ctx_wl_init(void *data)
|
||||
{
|
||||
int i;
|
||||
gfx_ctx_wayland_data_t *wl = NULL;
|
||||
if (!gfx_ctx_wl_init_common(&toplevel_listener, &wl))
|
||||
if (!gfx_ctx_wl_init_common(
|
||||
#ifdef HAVE_EGL
|
||||
gfx_ctx_wl_egl_configure,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
&wl))
|
||||
goto error;
|
||||
#ifdef HAVE_EGL
|
||||
if (!gfx_ctx_wl_egl_init_context(wl))
|
||||
|
||||
@@ -45,17 +45,6 @@
|
||||
#endif
|
||||
|
||||
/* Shell surface callbacks. */
|
||||
static void xdg_toplevel_handle_configure(void *data,
|
||||
struct xdg_toplevel *toplevel,
|
||||
int32_t width, int32_t height, struct wl_array *states)
|
||||
{
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
if (wl->ignore_configuration)
|
||||
return;
|
||||
xdg_toplevel_handle_configure_common(wl, toplevel, width, height, states);
|
||||
wl->configured = false;
|
||||
}
|
||||
|
||||
static void gfx_ctx_wl_destroy_resources(gfx_ctx_wayland_data_t *wl)
|
||||
{
|
||||
if (!wl)
|
||||
@@ -103,40 +92,12 @@ static bool gfx_ctx_wl_set_resize(void *data, unsigned width, unsigned height)
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
static void
|
||||
libdecor_frame_handle_configure(struct libdecor_frame *frame,
|
||||
struct libdecor_configuration *configuration, void *data)
|
||||
{
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
if (wl->ignore_configuration)
|
||||
return;
|
||||
libdecor_frame_handle_configure_common(frame, configuration, wl);
|
||||
|
||||
wl->configured = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const toplevel_listener_t toplevel_listener = {
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
.libdecor_frame_interface = {
|
||||
libdecor_frame_handle_configure,
|
||||
libdecor_frame_handle_close,
|
||||
libdecor_frame_handle_commit,
|
||||
},
|
||||
#endif
|
||||
.xdg_toplevel_listener = {
|
||||
xdg_toplevel_handle_configure,
|
||||
xdg_toplevel_handle_close,
|
||||
},
|
||||
};
|
||||
|
||||
static void *gfx_ctx_wl_init(void *data)
|
||||
{
|
||||
int i;
|
||||
gfx_ctx_wayland_data_t *wl = NULL;
|
||||
|
||||
if (!gfx_ctx_wl_init_common(&toplevel_listener, &wl))
|
||||
if (!gfx_ctx_wl_init_common(NULL, &wl))
|
||||
goto error;
|
||||
|
||||
if (!vulkan_context_init(&wl->vk, VULKAN_WSI_WAYLAND))
|
||||
|
||||
@@ -156,6 +156,12 @@ typedef struct data_offer_ctx
|
||||
enum wl_data_device_manager_dnd_action supported_actions;
|
||||
} data_offer_ctx;
|
||||
|
||||
/* Per-backend hook invoked from the common shell-surface configure
|
||||
* handlers, between the shared configure processing and the clearing
|
||||
* of 'configured'. EGL uses it to resize/create the wl_egl_window;
|
||||
* Vulkan needs no additional action and passes NULL. */
|
||||
typedef void (*driver_configure_handler_t)(struct gfx_ctx_wayland_data *wl);
|
||||
|
||||
typedef struct gfx_ctx_wayland_data
|
||||
{
|
||||
#ifdef HAVE_EGL
|
||||
@@ -261,6 +267,7 @@ typedef struct gfx_ctx_wayland_data
|
||||
bool resize;
|
||||
bool configured;
|
||||
bool ignore_configuration;
|
||||
driver_configure_handler_t driver_configure_handler;
|
||||
bool activated;
|
||||
bool reported_display_size;
|
||||
bool swap_complete;
|
||||
|
||||
@@ -493,7 +493,7 @@ void gfx_ctx_wl_update_title_webos(void *data)
|
||||
}
|
||||
|
||||
bool gfx_ctx_wl_init_webos(
|
||||
const toplevel_listener_t *toplevel_listener, gfx_ctx_wayland_data_t **wwl)
|
||||
driver_configure_handler_t driver_configure_handler, gfx_ctx_wayland_data_t **wwl)
|
||||
{
|
||||
int i;
|
||||
gfx_ctx_wayland_data_t *wl;
|
||||
|
||||
Reference in new issue
Block a user