From 72719852caee7076227cc999d086e3847609dc1f Mon Sep 17 00:00:00 2001 From: Federico Angelilli Date: Wed, 15 Nov 2023 23:19:27 +0100 Subject: Move event source from window to connection The draw pipeline has been momentarily disconnected --- connection.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ connection.h | 3 ++ window.c | 122 ----------------------------------------------------- 3 files changed, 125 insertions(+), 135 deletions(-) diff --git a/connection.c b/connection.c index 20c1e6d..5a869c4 100644 --- a/connection.c +++ b/connection.c @@ -8,18 +8,119 @@ #include "log.h" #include "connection.h" -struct Connection { - xcb_connection_t *connection; - xcb_screen_t *screen; - xcb_randr_screen_size_t *screen_size; - double screen_dpi; - xcb_visualtype_t *visual_type; - xcb_depth_t *depth; - xcb_xrm_database_t *database; - xcb_errors_context_t *errors; - xcb_ewmh_connection_t ewmh; +typedef struct { + GSource source; + Connection *con; + gpointer fd_tag; + xcb_generic_event_t *event; +} EventSource; + +static gboolean source_check(GSource *source) +{ + EventSource *xsource = (EventSource *)source; + xcb_flush(xsource->con->connection); + g_assert_null(xsource->event); + + GIOCondition flags = g_source_query_unix_fd(source, xsource->fd_tag); + if (flags & G_IO_IN) { + g_assert_false(xcb_connection_has_error(xsource->con->connection)); + xsource->event = xcb_poll_for_event(xsource->con->connection); + } + + return xsource->event != NULL; +} + +static gboolean source_dispatch(GSource *source, GSourceFunc callback, gpointer data) +{ + EventSource *xsource = (EventSource *)source; + g_assert_nonnull(xsource->event); + + do { + switch (xsource->event->response_type & ~0x80) { + case 0: { + xcb_generic_error_t *error = (xcb_generic_error_t *)xsource->event; + + const char *extension; + const char *name = xcb_errors_get_name_for_error(xsource->con->errors, error->error_code, &extension); + const char *major = xcb_errors_get_name_for_major_code(xsource->con->errors, error->major_code); + const char *minor = xcb_errors_get_name_for_minor_code(xsource->con->errors, error->major_code, error->minor_code); + + // TODO: Handle errors instead of aborting + log_error("Xcb error '%s' [extension=%s, major=%s, minor=%s, resource=%u, sequence=%u]", + name, + extension ? extension : "none", + major, + minor ? minor : "none", + (unsigned int)error->resource_id, + (unsigned int)error->sequence); + break; + } + + case XCB_EXPOSE: { + xcb_expose_event_t *expose = (xcb_expose_event_t *)xsource->event; + log_debug("Processing event 'Expose' [type=%d]", XCB_EXPOSE); + + // Redraw + //callback(data); + break; + } + + case XCB_BUTTON_RELEASE: { + log_debug("Mouse event"); + break; + } + + case XCB_PROPERTY_NOTIFY: { + xcb_property_notify_event_t *property = (xcb_property_notify_event_t *)xsource->event; + log_debug("Processing event 'PropertyNotify' [type=%d]", XCB_PROPERTY_NOTIFY); + + if (property->atom == XCB_ATOM_RESOURCE_MANAGER) { + //window_update_scale(data); + + // Redraw + //callback(data); + } + break; + } + + default: { + const char *extension; + const char *name = xcb_errors_get_name_for_xcb_event(xsource->con->errors, xsource->event, &extension); + + log_debug("Ignoring event '%s' [type=%d, extension=%s]", + name, + xsource->event->response_type & 0x7f, + extension ? extension : "none"); + } + } + } while ((xsource->event = xcb_poll_for_event(xsource->con->connection)) != NULL); + + return G_SOURCE_CONTINUE; +} + +static GSourceFuncs source_fns = { + NULL, + source_check, + source_dispatch, + NULL, }; +static void attach_source(Connection *con) +{ + EventSource *source = (EventSource *)g_source_new(&source_fns, sizeof(EventSource)); + con->source = (GSource *)source; + g_source_set_static_name(con->source, "EventSource"); + + source->con = con; + source->event = NULL; + source->fd_tag = g_source_add_unix_fd(con->source, xcb_get_file_descriptor(con->connection), G_IO_IN | G_IO_HUP | G_IO_ERR); + + // TODO: Draw should be decoupled from this file + //g_source_set_callback(con->source, G_SOURCE_FUNC(draw), win, NULL); + + g_source_attach(con->source, NULL); +} + static bool query_xrm(Connection *con, const char *res, char **value) { if (xcb_xrm_resource_get_string(con->database, res, res, value) >= 0) { @@ -46,7 +147,7 @@ static void update_scale(Connection *con) Connection *connection_create() { Connection *con = g_malloc0(sizeof(Connection)); - g_assert_nonnull(con); + g_assert_nonnull(con); int preferred_screen = 0; con->connection = xcb_connect(NULL, &preferred_screen); @@ -124,14 +225,22 @@ found_visual: xcb_flush(con->connection); log_debug("Xcb set up"); - return con; + attach_source(con); + log_debug("Xcb event loop attached"); + + return con; } void connection_destroy(Connection *con) { + g_source_destroy(con->source); + g_source_unref(con->source); + xcb_ewmh_connection_wipe(&con->ewmh); xcb_errors_context_free(con->errors); xcb_xrm_database_free(con->database); xcb_disconnect(con->connection); - g_free(con); + g_free(con); } + +// vim: ts=4 sw=4 et diff --git a/connection.h b/connection.h index d028cce..6d0a0cf 100644 --- a/connection.h +++ b/connection.h @@ -20,6 +20,7 @@ typedef struct { xcb_xrm_database_t *database; xcb_errors_context_t *errors; xcb_ewmh_connection_t ewmh; + GSource *source; } Connection; Connection *connection_create(); @@ -27,3 +28,5 @@ Connection *connection_create(); void connection_destroy(Connection *con); #endif + +// vim: ts=4 sw=4 et diff --git a/window.c b/window.c index 6bb9f50..77ecc7a 100644 --- a/window.c +++ b/window.c @@ -26,123 +26,8 @@ struct Window { cairo_t *cr; int x, y; int width, height; - GSource *source; }; -typedef struct { - GSource source; - Window *win; - xcb_generic_event_t *event; -} XcbSource; - -static gboolean xcb_source_check(GSource *source) -{ - XcbSource *xsource = (XcbSource *)source; - g_assert_null(xsource->event); - xsource->event = xcb_poll_for_event(xsource->win->con->connection); - return xsource->event != NULL; -} - -static gboolean xcb_source_dispatch(GSource *source, GSourceFunc callback, gpointer data) -{ - XcbSource *xsource = (XcbSource *)source; - g_assert_nonnull(xsource->event); - g_assert_nonnull(callback); - g_assert_nonnull(data); - - Window *win = (Window *)data; - - do { - switch (xsource->event->response_type & ~0x80) { - case 0: { - xcb_generic_error_t *error = (xcb_generic_error_t *)xsource->event; - - const char *extension; - const char *name = xcb_errors_get_name_for_error(win->con->errors, error->error_code, &extension); - const char *major = xcb_errors_get_name_for_major_code(win->con->errors, error->major_code); - const char *minor = xcb_errors_get_name_for_minor_code(win->con->errors, error->major_code, error->minor_code); - - // TODO: Handle errors instead of aborting - log_error("Xcb error '%s' [extension=%s, major=%s, minor=%s, resource=%u, sequence=%u]", - name, - extension ? extension : "none", - major, - minor ? minor : "none", - (unsigned int)error->resource_id, - (unsigned int)error->sequence); - break; - } - - case XCB_EXPOSE: { - xcb_expose_event_t *expose = (xcb_expose_event_t *)xsource->event; - log_debug("Processing event 'Expose' [type=%d]", XCB_EXPOSE); - - // Redraw - callback(data); - break; - } - - case XCB_BUTTON_RELEASE: { - log_debug("Mouse event"); - break; - } - - case XCB_PROPERTY_NOTIFY: { - xcb_property_notify_event_t *property = (xcb_property_notify_event_t *)xsource->event; - log_debug("Processing event 'PropertyNotify' [type=%d]", XCB_PROPERTY_NOTIFY); - - if (property->atom == XCB_ATOM_RESOURCE_MANAGER) { - //window_update_scale(data); - - // Redraw - callback(data); - } - break; - } - - default: { - const char *extension; - const char *name = xcb_errors_get_name_for_xcb_event(win->con->errors, xsource->event, &extension); - - log_debug("Ignoring event '%s' [extension=%s, type=%d]", - name, - extension ? extension : "none", - xsource->event->response_type & 0x7f); - } - } - } while ((xsource->event = xcb_poll_for_event(xsource->win->con->connection)) != NULL); - - return G_SOURCE_CONTINUE; -} - -static void xcb_source_finalize(GSource *source) -{ - log_debug("Xcb event loop finalized"); -} - -static GSourceFuncs source_fns = { - NULL, - xcb_source_check, - xcb_source_dispatch, - xcb_source_finalize, -}; - -static void attach_source(Window *win) -{ - XcbSource *source = (XcbSource *)g_source_new(&source_fns, sizeof(XcbSource)); - source->win = win; - source->event = NULL; - - win->source = (GSource *)source; - g_source_set_static_name(win->source, "XcbSource"); - - // TODO: Draw should be decoupled from this file - g_source_set_callback(win->source, G_SOURCE_FUNC(draw), win, NULL); - - g_source_add_unix_fd(win->source, xcb_get_file_descriptor(win->con->connection), G_IO_IN | G_IO_HUP | G_IO_ERR); - g_source_attach(win->source, NULL); -} - static xcb_atom_t intern_atom(Window *win, const char *atom) { xcb_generic_error_t *error; @@ -299,10 +184,6 @@ Window *window_create(Connection *con) g_assert_cmpint(cairo_status(win->cr), ==, CAIRO_STATUS_SUCCESS); log_debug("Cairo context created"); - - attach_source(win); - log_debug("Xcb event loop attached"); - return win; } @@ -443,9 +324,6 @@ void window_paint_surface(Window *win, cairo_surface_t *surface, int width, int void window_destroy(Window *win) { - g_source_destroy(win->source); - g_source_unref(win->source); - cairo_destroy(win->cr); cairo_surface_destroy(win->surface); -- cgit v1.2.3