From bad03394e067eb6ca85523d5a66ac482c4147364 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 28 Jul 2023 14:09:51 +0200 Subject: [PATCH] xwayland: introduce wlr_xwm_reply_handler This is a helper to asynchronously wait for a reply from the X11 server. --- include/xwayland/xwm.h | 16 ++++++++++++++++ xwayland/xwm.c | 32 +++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/include/xwayland/xwm.h b/include/xwayland/xwm.h index 7db5d6cb8..0701d8f66 100644 --- a/include/xwayland/xwm.h +++ b/include/xwayland/xwm.h @@ -91,6 +91,17 @@ enum atom_name { ATOM_LAST // keep last }; +struct wlr_xwm_reply_handler; + +typedef void (*xwm_reply_handler_func_t)(struct wlr_xwm *xwm, + struct wlr_xwm_reply_handler *reply_handler, xcb_generic_reply_t *reply); + +struct wlr_xwm_reply_handler { + unsigned int request; + xwm_reply_handler_func_t callback; + struct wl_list link; +}; + struct wlr_xwm { struct wlr_xwayland *xwayland; struct wl_event_source *event_source; @@ -106,6 +117,8 @@ struct wlr_xwm { xcb_render_pictformat_t render_format_id; xcb_cursor_t cursor; + struct wl_list reply_handlers; // wlr_xwm_reply_handler.link + struct wlr_xwm_selection clipboard_selection; struct wlr_xwm_selection primary_selection; struct wlr_xwm_selection dnd_selection; @@ -160,4 +173,7 @@ char *xwm_get_atom_name(struct wlr_xwm *xwm, xcb_atom_t atom); bool xwm_atoms_contains(struct wlr_xwm *xwm, xcb_atom_t *atoms, size_t num_atoms, enum atom_name needle); +void xwm_init_reply_handler(struct wlr_xwm *xwm, struct wlr_xwm_reply_handler *handler, + unsigned int request, xwm_reply_handler_func_t callback); + #endif diff --git a/xwayland/xwm.c b/xwayland/xwm.c index 6597af9ad..405eb32a9 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "xwayland/xwm.h" @@ -1644,7 +1645,6 @@ static void xwm_handle_unhandled_event(struct wlr_xwm *xwm, xcb_generic_event_t static int x11_event_handler(int fd, uint32_t mask, void *data) { int count = 0; - xcb_generic_event_t *event; struct wlr_xwm *xwm = data; if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) { @@ -1652,6 +1652,18 @@ static int x11_event_handler(int fd, uint32_t mask, void *data) { return 0; } + struct wlr_xwm_reply_handler *reply_handler, *reply_handler_tmp; + wl_list_for_each_safe(reply_handler, reply_handler_tmp, &xwm->reply_handlers, link) { + void *reply = NULL; + if (!xcb_poll_for_reply(xwm->xcb_conn, reply_handler->request, &reply, NULL)) { + break; + } + wl_list_remove(&reply_handler->link); + reply_handler->callback(xwm, reply_handler, reply); + free(reply); + } + + xcb_generic_event_t *event; while ((event = xcb_poll_for_event(xwm->xcb_conn))) { count++; @@ -1716,6 +1728,18 @@ static int x11_event_handler(int fd, uint32_t mask, void *data) { return count; } +void xwm_init_reply_handler(struct wlr_xwm *xwm, struct wlr_xwm_reply_handler *handler, + uint32_t request, xwm_reply_handler_func_t callback) { + if (request == 0) { + // Failed to send the request + callback(xwm, handler, NULL); + return; + } + handler->request = request; + handler->callback = callback; + wl_list_insert(xwm->reply_handlers.prev, &handler->link); +} + static void handle_compositor_new_surface(struct wl_listener *listener, void *data) { struct wlr_xwm *xwm = @@ -1887,6 +1911,11 @@ void xwm_destroy(struct wlr_xwm *xwm) { wl_list_for_each_safe(xsurface, tmp, &xwm->unpaired_surfaces, unpaired_link) { xwayland_surface_destroy(xsurface); } + struct wlr_xwm_reply_handler *reply_handler, *reply_handler_tmp; + wl_list_for_each_safe(reply_handler, reply_handler_tmp, &xwm->reply_handlers, link) { + wl_list_remove(&reply_handler->link); + reply_handler->callback(xwm, reply_handler, NULL); + } wl_list_remove(&xwm->compositor_new_surface.link); wl_list_remove(&xwm->compositor_destroy.link); wl_list_remove(&xwm->shell_v1_new_surface.link); @@ -2139,6 +2168,7 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) { wl_list_init(&xwm->surfaces_in_stack_order); wl_list_init(&xwm->unpaired_surfaces); wl_list_init(&xwm->pending_startup_ids); + wl_list_init(&xwm->reply_handlers); xwm->ping_timeout = 10000; xwm->xcb_conn = xcb_connect_to_fd(wm_fd, NULL);