wayland: fix XWayland startup speed and swapchain exhaustion
Two fixes: 1. Handle request_configure for XWayland surfaces. Without this, X clients block waiting for ConfigureNotify on startup (5s timeout). Now we immediately ACK with wlr_xwayland_surface_configure. 2. Replace direct wlr_scene_output_commit in wl_event_flush with wlr_output_schedule_frame. Rendering happens in handle_output_frame when the output is ready. Eliminates 'No free output buffer slot' spam and prevents reentrant dispatch crashes.
This commit is contained in:
parent
0e0847b48b
commit
04f9a36da7
|
|
@ -3,6 +3,7 @@
|
|||
#endif
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/types/wlr_scene.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
#include <wlr/backend/session.h>
|
||||
#include "../../screen.h"
|
||||
#include "wl_types.h"
|
||||
|
|
@ -11,12 +12,14 @@
|
|||
void wl_event_flush(void)
|
||||
{
|
||||
wl_xdisplay_flush();
|
||||
/* Commit the scene so intermediate animation frames are visible */
|
||||
if (wl_state.scene_output && wl_state.allocator &&
|
||||
(!wl_state.session || wl_state.session->active)) {
|
||||
wlr_scene_output_commit(wl_state.scene_output, NULL);
|
||||
/* Schedule a frame so the output callback commits the scene.
|
||||
* Do NOT commit directly here — reentrant commits exhaust the
|
||||
* swapchain ("No free output buffer slot") and cause UAF when
|
||||
* the dispatch processes unmap signals recursively. */
|
||||
if (wl_state.output)
|
||||
wlr_output_schedule_frame(wl_state.output);
|
||||
if (wl_state.display)
|
||||
wl_display_flush_clients(wl_state.display);
|
||||
}
|
||||
}
|
||||
void wl_event_flush_expose(void) {}
|
||||
void wl_event_sync(int discard)
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ struct wl_toplevel_view {
|
|||
struct wlr_xwayland_surface *xw_surface;
|
||||
/* Path 1: geometry listener — keeps scene node in sync when X11 window moves. */
|
||||
struct wl_listener xw_geometry_listener;
|
||||
struct wl_listener xw_request_configure_listener;
|
||||
struct wl_listener xw_surface_map_listener; /* fires when wlr_surface maps */
|
||||
/* Phase 18: scene graph tree for this surface (NULL if scene unavailable). */
|
||||
struct wlr_scene_tree *scene_node;
|
||||
|
|
|
|||
|
|
@ -97,6 +97,15 @@ handle_or_set_geometry(struct wl_listener *listener, void *data)
|
|||
|
||||
/* --- Managed XWayland surface handlers --- */
|
||||
|
||||
static void
|
||||
handle_xwayland_request_configure(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct wl_toplevel_view *view = VIEW_FROM_LISTENER(listener, xw_request_configure_listener);
|
||||
struct wlr_xwayland_surface_configure_event *ev = data;
|
||||
wlr_xwayland_surface_configure(view->xw_surface,
|
||||
ev->x, ev->y, ev->width, ev->height);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_xwayland_request_fullscreen(struct wl_listener *listener, void *data)
|
||||
{
|
||||
|
|
@ -244,6 +253,7 @@ handle_xwayland_destroy(struct wl_listener *listener, void *data)
|
|||
wl_list_remove(&view->destroy_listener.link);
|
||||
wl_list_remove(&view->title_listener.link);
|
||||
wl_list_remove(&view->request_fullscreen_listener.link);
|
||||
wl_list_remove(&view->xw_request_configure_listener.link);
|
||||
if (view->xw_surface_map_listener.link.next &&
|
||||
view->xw_surface_map_listener.link.next != &view->xw_surface_map_listener.link)
|
||||
wl_list_remove(&view->xw_surface_map_listener.link);
|
||||
|
|
@ -407,6 +417,7 @@ handle_xwayland_new_surface(struct wl_listener *listener, void *data)
|
|||
view->destroy_listener.notify = handle_xwayland_destroy;
|
||||
view->title_listener.notify = handle_xwayland_set_class;
|
||||
view->xw_geometry_listener.notify = handle_xwayland_set_geometry;
|
||||
view->xw_request_configure_listener.notify = handle_xwayland_request_configure;
|
||||
view->request_fullscreen_listener.notify = handle_xwayland_request_fullscreen;
|
||||
|
||||
wl_signal_add(&xw->events.associate, &view->map_listener);
|
||||
|
|
@ -414,6 +425,7 @@ handle_xwayland_new_surface(struct wl_listener *listener, void *data)
|
|||
wl_signal_add(&xw->events.destroy, &view->destroy_listener);
|
||||
wl_signal_add(&xw->events.set_class, &view->title_listener);
|
||||
wl_signal_add(&xw->events.set_geometry, &view->xw_geometry_listener);
|
||||
wl_signal_add(&xw->events.request_configure, &view->xw_request_configure_listener);
|
||||
wl_signal_add(&xw->events.request_fullscreen, &view->request_fullscreen_listener);
|
||||
|
||||
wl_list_insert(&wl_state.toplevel_list, &view->link);
|
||||
|
|
|
|||
Loading…
Reference in New Issue