aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Angelilli <code@fedang.net>2023-11-15 23:19:27 +0100
committerFederico Angelilli <code@fedang.net>2023-11-15 23:19:27 +0100
commit72719852caee7076227cc999d086e3847609dc1f (patch)
tree45a05a10573474eae40b5290a09246f0842b48cf
parent22086e50382b99de092899a203e520c30f50b618 (diff)
Move event source from window to connection
The draw pipeline has been momentarily disconnected
-rw-r--r--connection.c135
-rw-r--r--connection.h3
-rw-r--r--window.c122
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);