Skip to content

Commit e22d788

Browse files
committed
wayland: Dedupe wayland GL/VK configure code again
Configurations of xdg_toplevels are pending until acked on xdg_surface configure. The vulkan backend doesn't need to take additional actions on configure.
1 parent ae79514 commit e22d788

File tree

6 files changed

+150
-214
lines changed

6 files changed

+150
-214
lines changed

gfx/common/wayland_common.c

Lines changed: 136 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -82,53 +82,125 @@ static const unsigned long retroarch_icon_data[] = {
8282
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000
8383
};
8484

85-
void xdg_toplevel_handle_configure_common(gfx_ctx_wayland_data_t *wl,
86-
void *toplevel,
85+
typedef struct shm_buffer
86+
{
87+
struct wl_buffer *wl_buffer;
88+
void *data;
89+
size_t data_size;
90+
} shm_buffer_t;
91+
92+
#ifdef HAVE_LIBDECOR_H
93+
static void libdecor_handle_error(struct libdecor *context,
94+
enum libdecor_error error, const char *message)
95+
{
96+
RARCH_ERR("[Wayland]: libdecor Caught error (%d): %s\n", error, message);
97+
}
98+
99+
const struct libdecor_interface libdecor_interface = {
100+
.error = libdecor_handle_error,
101+
};
102+
#endif
103+
104+
typedef struct wayland_configuration
105+
{
106+
unsigned width;
107+
unsigned height;
108+
bool fullscreen;
109+
bool maximized;
110+
bool floating;
111+
bool resizing;
112+
bool activated;
113+
bool has_size;
114+
bool has_window_state;
115+
} wayland_configuration_t;
116+
117+
void xdg_toplevel_handle_configure(void *data,
118+
struct xdg_toplevel *xdg_toplevel,
87119
int32_t width, int32_t height, struct wl_array *states)
88120
{
121+
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
89122
const uint32_t *state;
90-
bool floating = true;
91123

92-
wl->fullscreen = false;
93-
wl->maximized = false;
124+
wl->pending_configuration = (wayland_configuration_t*)calloc(1, sizeof(wayland_configuration_t));
125+
wayland_configuration_t *conf = wl->pending_configuration;
126+
127+
conf->has_window_state = true;
128+
129+
conf->floating = true;
94130

95131
WL_ARRAY_FOR_EACH(state, states, const uint32_t*)
96132
{
97133
switch (*state)
98134
{
99135
case XDG_TOPLEVEL_STATE_FULLSCREEN:
100-
wl->fullscreen = true;
101-
floating = false;
136+
conf->fullscreen = true;
137+
conf->floating = false;
102138
break;
103139
case XDG_TOPLEVEL_STATE_MAXIMIZED:
104-
wl->maximized = true;
140+
conf->maximized = true;
105141
/* fall-through */
106142
case XDG_TOPLEVEL_STATE_TILED_LEFT:
107143
case XDG_TOPLEVEL_STATE_TILED_RIGHT:
108144
case XDG_TOPLEVEL_STATE_TILED_TOP:
109145
case XDG_TOPLEVEL_STATE_TILED_BOTTOM:
110-
floating = false;
146+
conf->floating = false;
111147
break;
112148
case XDG_TOPLEVEL_STATE_RESIZING:
113-
wl->resize = true;
149+
conf->resizing = true;
114150
break;
115151
case XDG_TOPLEVEL_STATE_ACTIVATED:
116-
wl->activated = true;
152+
conf->activated = true;
117153
break;
118154
}
119155
}
120156

121-
if (width == 0 || height == 0)
157+
conf->has_size = true;
158+
conf->width = width;
159+
conf->height = height;
160+
}
161+
162+
void xdg_toplevel_handle_close(void *data,
163+
struct xdg_toplevel *xdg_toplevel)
164+
{
165+
frontend_driver_set_signal_handler_state(1);
166+
}
167+
168+
static struct xdg_toplevel_listener xdg_toplevel_listener = {
169+
.configure = xdg_toplevel_handle_configure,
170+
.close = xdg_toplevel_handle_close,
171+
};
172+
173+
static void xdg_surface_handle_configure(void *data,
174+
struct xdg_surface *xdg_surface, uint32_t serial)
175+
{
176+
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
177+
bool floating = true;
178+
wayland_configuration_t *conf;
179+
180+
conf = wl->pending_configuration;
181+
wl->pending_configuration = NULL;
182+
183+
if (conf == NULL)
184+
conf = (wayland_configuration_t*)calloc(1, sizeof(wayland_configuration_t));
185+
186+
if (conf->has_window_state) {
187+
wl->fullscreen = conf->fullscreen;
188+
wl->maximized = conf->maximized;
189+
wl->activated = conf->activated;
190+
floating = conf->floating;
191+
}
192+
193+
if (conf->width == 0 || conf->height == 0)
122194
{
123-
width = wl->floating_width;
124-
height = wl->floating_height;
195+
conf->width = wl->floating_width;
196+
conf->height = wl->floating_height;
125197
}
126198

127-
if ( (width > 0)
128-
&& (height > 0))
199+
if ( (conf->width > 0)
200+
&& (conf->height > 0))
129201
{
130-
wl->width = width;
131-
wl->height = height;
202+
wl->width = conf->width;
203+
wl->height = conf->height;
132204
wl->buffer_width = wl->fractional_scale ?
133205
FRACTIONAL_SCALE_MULT(wl->width, wl->fractional_scale_num) : wl->width * wl->buffer_scale;
134206
wl->buffer_height = wl->fractional_scale ?
@@ -138,28 +210,38 @@ void xdg_toplevel_handle_configure_common(gfx_ctx_wayland_data_t *wl,
138210
{
139211
/* Stretch old buffer to fill new size, commit/roundtrip to apply */
140212
wp_viewport_set_destination(wl->viewport, wl->width, wl->height);
141-
wl_surface_commit(wl->surface);
142213
}
143214
}
144215

145216
if (floating)
146217
{
147-
wl->floating_width = width;
148-
wl->floating_height = height;
218+
wl->floating_width = conf->width;
219+
wl->floating_height = conf->height;
149220
}
150-
}
151221

152-
void xdg_toplevel_handle_close(void *data,
153-
struct xdg_toplevel *xdg_toplevel)
154-
{
155-
frontend_driver_set_signal_handler_state(1);
222+
if (wl->driver_configure_handler != NULL)
223+
wl->driver_configure_handler(wl);
224+
xdg_surface_ack_configure(xdg_surface, serial);
225+
226+
wl_surface_commit(wl->surface);
227+
228+
if (conf != NULL)
229+
free(conf);
230+
231+
wl->configured = false;
156232
}
157233

234+
static struct xdg_surface_listener xdg_surface_listener = {
235+
.configure = xdg_surface_handle_configure,
236+
};
237+
158238
#ifdef HAVE_LIBDECOR_H
159-
void libdecor_frame_handle_configure_common(struct libdecor_frame *frame,
239+
void libdecor_frame_handle_configure(struct libdecor_frame *frame,
160240
struct libdecor_configuration *configuration,
161-
gfx_ctx_wayland_data_t *wl)
241+
void *data)
162242
{
243+
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
244+
163245
int width = 0, height = 0;
164246
struct libdecor_state *state = NULL;
165247
enum libdecor_window_state window_state;
@@ -210,7 +292,6 @@ void libdecor_frame_handle_configure_common(struct libdecor_frame *frame,
210292
{
211293
/* Stretch old buffer to fill new size, commit/roundtrip to apply */
212294
wp_viewport_set_destination(wl->viewport, wl->width, wl->height);
213-
wl_surface_commit(wl->surface);
214295
}
215296
}
216297

@@ -223,6 +304,13 @@ void libdecor_frame_handle_configure_common(struct libdecor_frame *frame,
223304
wl->floating_width = width;
224305
wl->floating_height = height;
225306
}
307+
308+
if (wl->driver_configure_handler != NULL)
309+
wl->driver_configure_handler(wl);
310+
311+
wl_surface_commit(wl->surface);
312+
313+
wl->configured = false;
226314
}
227315

228316
void libdecor_frame_handle_close(struct libdecor_frame *frame,
@@ -231,7 +319,17 @@ void libdecor_frame_handle_close(struct libdecor_frame *frame,
231319
frontend_driver_set_signal_handler_state(1);
232320
}
233321
void libdecor_frame_handle_commit(struct libdecor_frame *frame,
234-
void *data) { }
322+
void *data)
323+
{
324+
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
325+
wl_surface_commit(wl->surface);
326+
}
327+
328+
static struct libdecor_frame_interface libdecor_frame_interface = {
329+
.configure = libdecor_frame_handle_configure,
330+
.close = libdecor_frame_handle_close,
331+
.commit = libdecor_frame_handle_commit,
332+
};
235333
#endif
236334

237335
void gfx_ctx_wl_get_video_size_common(void *data,
@@ -662,7 +760,7 @@ static bool wl_draw_splash_screen(gfx_ctx_wayland_data_t *wl)
662760
}
663761

664762
bool gfx_ctx_wl_init_common(
665-
const toplevel_listener_t *toplevel_listener, gfx_ctx_wayland_data_t **wwl)
763+
const driver_configure_handler_t driver_configure_handler, gfx_ctx_wayland_data_t **wwl)
666764
{
667765
int i;
668766
gfx_ctx_wayland_data_t *wl;
@@ -802,7 +900,7 @@ bool gfx_ctx_wl_init_common(
802900
{
803901
wl->libdecor_context = wl->libdecor_new(wl->input.dpy, &libdecor_interface);
804902

805-
wl->libdecor_frame = wl->libdecor_decorate(wl->libdecor_context, wl->surface, &toplevel_listener->libdecor_frame_interface, wl);
903+
wl->libdecor_frame = wl->libdecor_decorate(wl->libdecor_context, wl->surface, &libdecor_frame_interface, wl);
806904
if (!wl->libdecor_frame)
807905
{
808906
RARCH_ERR("[Wayland]: Failed to create libdecor frame\n");
@@ -814,7 +912,6 @@ bool gfx_ctx_wl_init_common(
814912
wl->libdecor_frame_map(wl->libdecor_frame);
815913

816914
/* Waiting for libdecor to be configured before starting to draw */
817-
wl_surface_commit(wl->surface);
818915
wl->configured = true;
819916

820917
while (wl->configured)
@@ -832,8 +929,10 @@ bool gfx_ctx_wl_init_common(
832929
wl->xdg_surface = xdg_wm_base_get_xdg_surface(wl->xdg_shell, wl->surface);
833930
xdg_surface_add_listener(wl->xdg_surface, &xdg_surface_listener, wl);
834931

932+
wl->driver_configure_handler = driver_configure_handler;
933+
835934
wl->xdg_toplevel = xdg_surface_get_toplevel(wl->xdg_surface);
836-
xdg_toplevel_add_listener(wl->xdg_toplevel, &toplevel_listener->xdg_toplevel_listener, wl);
935+
xdg_toplevel_add_listener(wl->xdg_toplevel, &xdg_toplevel_listener, wl);
837936

838937
xdg_toplevel_set_app_id(wl->xdg_toplevel, WAYLAND_APP_ID);
839938
xdg_toplevel_set_title(wl->xdg_toplevel, WINDOW_TITLE);
@@ -880,9 +979,6 @@ bool gfx_ctx_wl_init_common(
880979
}
881980
}
882981

883-
// Ignore configure events until splash screen has been replaced
884-
wl->ignore_configuration = true;
885-
886982
wl->input.fd = wl_display_get_fd(wl->input.dpy);
887983

888984
wl->input.keyboard_focus = true;
@@ -946,6 +1042,8 @@ bool gfx_ctx_wl_set_video_mode_common_size(gfx_ctx_wayland_data_t *wl,
9461042
}
9471043
#endif
9481044

1045+
wl_surface_commit(wl->surface);
1046+
9491047
return true;
9501048
}
9511049

@@ -1089,28 +1187,7 @@ static void shm_buffer_handle_release(void *data,
10891187
free(buffer);
10901188
}
10911189

1092-
#if 0
1093-
static void xdg_surface_handle_configure(void *data,
1094-
struct xdg_surface *surface, uint32_t serial)
1095-
{
1096-
xdg_surface_ack_configure(surface, serial);
1097-
}
1098-
#endif
1099-
1100-
#ifdef HAVE_LIBDECOR_H
1101-
static void libdecor_handle_error(struct libdecor *context,
1102-
enum libdecor_error error, const char *message)
1103-
{
1104-
RARCH_ERR("[Wayland]: libdecor Caught error (%d): %s\n", error, message);
1105-
}
1106-
#endif
1107-
11081190
const struct wl_buffer_listener shm_buffer_listener = {
1109-
shm_buffer_handle_release,
1191+
.release = shm_buffer_handle_release,
11101192
};
11111193

1112-
#ifdef HAVE_LIBDECOR_H
1113-
const struct libdecor_interface libdecor_interface = {
1114-
.error = libdecor_handle_error,
1115-
};
1116-
#endif

gfx/common/wayland_common.h

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,46 +15,10 @@
1515

1616
#pragma once
1717

18-
#ifdef HAVE_LIBDECOR_H
19-
#include <libdecor.h>
20-
#endif
21-
2218
#include "../../input/common/wayland_common.h"
2319

2420
#define WAYLAND_APP_ID "com.libretro.RetroArch"
2521

26-
typedef struct toplevel_listener
27-
{
28-
#ifdef HAVE_LIBDECOR_H
29-
struct libdecor_frame_interface libdecor_frame_interface;
30-
#endif
31-
struct xdg_toplevel_listener xdg_toplevel_listener;
32-
} toplevel_listener_t;
33-
34-
typedef struct shm_buffer
35-
{
36-
struct wl_buffer *wl_buffer;
37-
void *data;
38-
size_t data_size;
39-
} shm_buffer_t;
40-
41-
void xdg_toplevel_handle_configure_common(gfx_ctx_wayland_data_t *wl, void *toplevel,
42-
int32_t width, int32_t height, struct wl_array *states);
43-
44-
void xdg_toplevel_handle_close(void *data,
45-
struct xdg_toplevel *xdg_toplevel);
46-
47-
#ifdef HAVE_LIBDECOR_H
48-
void libdecor_frame_handle_configure_common(struct libdecor_frame *frame,
49-
struct libdecor_configuration *configuration, gfx_ctx_wayland_data_t *wl);
50-
51-
void libdecor_frame_handle_close(struct libdecor_frame *frame,
52-
void *data);
53-
54-
void libdecor_frame_handle_commit(struct libdecor_frame *frame,
55-
void *data);
56-
#endif
57-
5822
void gfx_ctx_wl_get_video_size_common(void *data, unsigned *width,
5923
unsigned *height);
6024

@@ -66,7 +30,7 @@ bool gfx_ctx_wl_get_metrics_common(void *data,
6630
enum display_metric_types type, float *value);
6731

6832
bool gfx_ctx_wl_init_common(
69-
const toplevel_listener_t *toplevel_listener,
33+
const driver_configure_handler_t driver_configure_handler,
7034
gfx_ctx_wayland_data_t **wl);
7135

7236
bool gfx_ctx_wl_set_video_mode_common_size(gfx_ctx_wayland_data_t *wl,
@@ -89,6 +53,3 @@ void gfx_ctx_wl_check_window_common(gfx_ctx_wayland_data_t *wl,
8953
void (*get_video_size)(void*, unsigned*, unsigned*), bool *quit,
9054
bool *resize, unsigned *width, unsigned *height);
9155

92-
#ifdef HAVE_LIBDECOR_H
93-
extern const struct libdecor_interface libdecor_interface;
94-
#endif

0 commit comments

Comments
 (0)