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:
libretroadmin authored and libretroadmin committed 2026-07-20 03:34:08 +02:00
1 parent 4590c23058
commit 89f38ace73
6 files changed
+81 -154

No files matched your search

+57 -22
View File
@@ -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
+1 -34
View File
@@ -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
+14 -57
View File
@@ -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))
+1 -40
View File
@@ -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))
+7
View File
@@ -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;
+1 -1
View File
@@ -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;