From 61e1b178e5e4a41a92f1f86349bebdc5ab23b0f7 Mon Sep 17 00:00:00 2001 From: Maxim Solovyov Date: Fri, 18 Oct 2024 20:30:18 +0300 Subject: [PATCH 1/7] common: remove unused information about the x extensions --- src/common.h | 16 ---------------- src/picom.c | 16 ---------------- 2 files changed, 32 deletions(-) diff --git a/src/common.h b/src/common.h index aaa3bf7a6c..11193d428d 100644 --- a/src/common.h +++ b/src/common.h @@ -207,42 +207,26 @@ typedef struct session { long paint_tm_offset; // === X extension related === - /// Event base number for X Fixes extension. - int xfixes_event; /// Error base number for X Fixes extension. int xfixes_error; /// Event base number for X Damage extension. int damage_event; /// Error base number for X Damage extension. int damage_error; - /// Event base number for X Render extension. - int render_event; /// Error base number for X Render extension. int render_error; - /// Event base number for X Composite extension. - int composite_event; - /// Error base number for X Composite extension. - int composite_error; - /// Major opcode for X Composite extension. - int composite_opcode; /// Whether X Shape extension exists. bool shape_exists; /// Event base number for X Shape extension. int shape_event; - /// Error base number for X Shape extension. - int shape_error; /// Whether X RandR extension exists. bool randr_exists; /// Event base number for X RandR extension. int randr_event; - /// Error base number for X RandR extension. - int randr_error; /// Whether X Present extension exists. bool present_exists; /// Whether X GLX extension exists. bool glx_exists; - /// Event base number for X GLX extension. - int glx_event; /// Error base number for X GLX extension. int glx_error; /// Information about monitors. diff --git a/src/picom.c b/src/picom.c index b1bcb7095a..50b079d607 100644 --- a/src/picom.c +++ b/src/picom.c @@ -1979,23 +1979,15 @@ static session_t *session_init(int argc, char **argv, Display *dpy, .last_msc = 0, - .xfixes_event = 0, .xfixes_error = 0, .damage_event = 0, .damage_error = 0, - .render_event = 0, .render_error = 0, - .composite_event = 0, - .composite_error = 0, - .composite_opcode = 0, .shape_exists = false, .shape_event = 0, - .shape_error = 0, .randr_exists = 0, .randr_event = 0, - .randr_error = 0, .glx_exists = false, - .glx_event = 0, .glx_error = 0, #ifdef CONFIG_DBUS @@ -2042,7 +2034,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy, log_fatal("No render extension"); exit(1); } - ps->render_event = ext_info->first_event; ps->render_error = ext_info->first_error; ext_info = xcb_get_extension_data(ps->c.c, &xcb_composite_id); @@ -2050,9 +2041,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy, log_fatal("No composite extension"); exit(1); } - ps->composite_opcode = ext_info->major_opcode; - ps->composite_event = ext_info->first_event; - ps->composite_error = ext_info->first_error; { xcb_composite_query_version_reply_t *reply = xcb_composite_query_version_reply( @@ -2085,7 +2073,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy, log_fatal("No XFixes extension"); exit(1); } - ps->xfixes_event = ext_info->first_event; ps->xfixes_error = ext_info->first_error; xcb_discard_reply(ps->c.c, xcb_xfixes_query_version(ps->c.c, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION) @@ -2101,7 +2088,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy, if (ext_info && ext_info->present) { ps->glx_exists = true; ps->glx_error = ext_info->first_error; - ps->glx_event = ext_info->first_event; } // Parse configuration file @@ -2194,7 +2180,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy, ext_info = xcb_get_extension_data(ps->c.c, &xcb_shape_id); if (ext_info && ext_info->present) { ps->shape_event = ext_info->first_event; - ps->shape_error = ext_info->first_error; ps->shape_exists = true; } @@ -2202,7 +2187,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy, if (ext_info && ext_info->present) { ps->randr_exists = true; ps->randr_event = ext_info->first_event; - ps->randr_error = ext_info->first_error; } ext_info = xcb_get_extension_data(ps->c.c, &xcb_present_id); From 97ec926a9f2ffac374d02d20c5ca43de7de859dd Mon Sep 17 00:00:00 2001 From: Maxim Solovyov Date: Fri, 18 Oct 2024 20:56:26 +0300 Subject: [PATCH 2/7] core: move information about the x extensions into a separate structure --- src/backend/gl/glx.c | 2 +- src/backend/xrender/xrender.c | 2 +- src/common.h | 28 --------------------- src/diagnostic.c | 6 ++--- src/event.c | 23 +++++++++-------- src/picom.c | 47 ++++++++++++++--------------------- src/wm/win.c | 4 +-- src/x.c | 15 ++++++----- src/x.h | 33 ++++++++++++++++++++++++ 9 files changed, 77 insertions(+), 83 deletions(-) diff --git a/src/backend/gl/glx.c b/src/backend/gl/glx.c index b15f5c96c6..7105069ff0 100644 --- a/src/backend/gl/glx.c +++ b/src/backend/gl/glx.c @@ -233,7 +233,7 @@ static backend_t *glx_init(session_t *ps, xcb_window_t target) { XVisualInfo *pvis = NULL; // Check for GLX extension - if (!ps->glx_exists) { + if (!ps->c.e.has_glx) { log_error("No GLX extension."); goto end; } diff --git a/src/backend/xrender/xrender.c b/src/backend/xrender/xrender.c index b9fc33d71c..48fb6cbce4 100644 --- a/src/backend/xrender/xrender.c +++ b/src/backend/xrender/xrender.c @@ -892,7 +892,7 @@ static backend_t *xrender_init(session_t *ps, xcb_window_t target) { XCB_RENDER_CP_SUBWINDOW_MODE, &pa); xd->vsync = ps->o.vsync; - if (ps->present_exists) { + if (ps->c.e.has_present) { auto eid = x_new_id(&ps->c); auto e = xcb_request_check(ps->c.c, xcb_present_select_input_checked( diff --git a/src/common.h b/src/common.h index 11193d428d..cc58a4c3a1 100644 --- a/src/common.h +++ b/src/common.h @@ -207,36 +207,8 @@ typedef struct session { long paint_tm_offset; // === X extension related === - /// Error base number for X Fixes extension. - int xfixes_error; - /// Event base number for X Damage extension. - int damage_event; - /// Error base number for X Damage extension. - int damage_error; - /// Error base number for X Render extension. - int render_error; - /// Whether X Shape extension exists. - bool shape_exists; - /// Event base number for X Shape extension. - int shape_event; - /// Whether X RandR extension exists. - bool randr_exists; - /// Event base number for X RandR extension. - int randr_event; - /// Whether X Present extension exists. - bool present_exists; - /// Whether X GLX extension exists. - bool glx_exists; - /// Error base number for X GLX extension. - int glx_error; /// Information about monitors. struct x_monitors monitors; - /// Whether X Sync extension exists. - bool xsync_exists; - /// Event base number for X Sync extension. - int xsync_event; - /// Error base number for X Sync extension. - int xsync_error; // === Atoms === struct atom *atoms; diff --git a/src/diagnostic.c b/src/diagnostic.c index 46c9d57652..69f7455943 100644 --- a/src/diagnostic.c +++ b/src/diagnostic.c @@ -16,9 +16,9 @@ void print_diagnostics(session_t *ps, const char *config_file, bool compositor_r printf("**Version:** " PICOM_FULL_VERSION "\n"); // printf("**CFLAGS:** %s\n", "??"); printf("\n### Extensions:\n\n"); - printf("* Shape: %s\n", ps->shape_exists ? "Yes" : "No"); - printf("* RandR: %s\n", ps->randr_exists ? "Yes" : "No"); - printf("* Present: %s\n", ps->present_exists ? "Present" : "Not Present"); + printf("* Shape: %s\n", ps->c.e.has_shape ? "Yes" : "No"); + printf("* RandR: %s\n", ps->c.e.has_randr ? "Yes" : "No"); + printf("* Present: %s\n", ps->c.e.has_present ? "Present" : "Not Present"); printf("\n### Misc:\n\n"); printf("* Use Overlay: %s\n", ps->overlay != XCB_NONE ? "Yes" : "No"); if (ps->overlay == XCB_NONE) { diff --git a/src/event.c b/src/event.c index 1b06181622..112fb6da97 100644 --- a/src/event.c +++ b/src/event.c @@ -101,11 +101,11 @@ static inline xcb_window_t attr_pure ev_window(session_t *ps, xcb_generic_event_ case XCB_PROPERTY_NOTIFY: return ((xcb_property_notify_event_t *)ev)->window; case XCB_CLIENT_MESSAGE: return ((xcb_client_message_event_t *)ev)->window; default: - if (ps->damage_event + XCB_DAMAGE_NOTIFY == ev->response_type) { + if (ps->c.e.damage_event + XCB_DAMAGE_NOTIFY == ev->response_type) { return ((xcb_damage_notify_event_t *)ev)->drawable; } - if (ps->shape_exists && ev->response_type == ps->shape_event) { + if (ps->c.e.has_shape && ev->response_type == ps->c.e.shape_event) { return ((xcb_shape_notify_event_t *)ev)->affected_window; } @@ -133,16 +133,16 @@ static inline const char *ev_name(session_t *ps, xcb_generic_event_t *ev) { CASESTRRET(CLIENT_MESSAGE); } - if (ps->damage_event + XCB_DAMAGE_NOTIFY == ev->response_type) { + if (ps->c.e.damage_event + XCB_DAMAGE_NOTIFY == ev->response_type) { return "DAMAGE_NOTIFY"; } - if (ps->shape_exists && ev->response_type == ps->shape_event) { + if (ps->c.e.has_shape && ev->response_type == ps->c.e.shape_event) { return "SHAPE_NOTIFY"; } - if (ps->xsync_exists) { - int o = ev->response_type - ps->xsync_event; + if (ps->c.e.has_sync) { + int o = ev->response_type - ps->c.e.sync_event; switch (o) { CASESTRRET(SYNC_COUNTER_NOTIFY); CASESTRRET(SYNC_ALARM_NOTIFY); @@ -717,7 +717,7 @@ ev_selection_clear(session_t *ps, xcb_selection_clear_event_t attr_unused *ev) { void ev_handle(session_t *ps, xcb_generic_event_t *ev) { xcb_window_t wid = ev_window(ps, ev); - if (ev->response_type != ps->damage_event + XCB_DAMAGE_NOTIFY) { + if (ev->response_type != ps->c.e.damage_event + XCB_DAMAGE_NOTIFY) { log_debug("event %10.10s serial %#010x window %#010x \"%s\"", ev_name(ps, ev), ev->full_sequence, wid, ev_window_name(ps, wid)); } else { @@ -786,16 +786,17 @@ void ev_handle(session_t *ps, xcb_generic_event_t *ev) { ev_selection_clear(ps, (xcb_selection_clear_event_t *)ev); break; default: - if (ps->shape_exists && ev->response_type == ps->shape_event) { + if (ps->c.e.has_shape && ev->response_type == ps->c.e.shape_event) { ev_shape_notify(ps, (xcb_shape_notify_event_t *)ev); break; } - if (ps->randr_exists && - ev->response_type == (ps->randr_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY)) { + if (ps->c.e.has_randr && + ev->response_type == + (ps->c.e.randr_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY)) { x_update_monitors_async(&ps->c, &ps->monitors); break; } - if (ps->damage_event + XCB_DAMAGE_NOTIFY == ev->response_type) { + if (ps->c.e.damage_event + XCB_DAMAGE_NOTIFY == ev->response_type) { ev_damage_notify(ps, (xcb_damage_notify_event_t *)ev); break; } diff --git a/src/picom.c b/src/picom.c index 50b079d607..a42bebdc08 100644 --- a/src/picom.c +++ b/src/picom.c @@ -1204,7 +1204,7 @@ static bool redirect_start(session_t *ps) { ps->drivers = detect_driver(ps->c.c, ps->backend_data, ps->c.screen_info->root); apply_driver_workarounds(ps, ps->drivers); - if (ps->present_exists && ps->frame_pacing) { + if (ps->c.e.has_present && ps->frame_pacing) { // Initialize rendering and frame timing statistics, and frame pacing // states. ps->last_msc_instant = 0; @@ -1979,17 +1979,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy, .last_msc = 0, - .xfixes_error = 0, - .damage_event = 0, - .damage_error = 0, - .render_error = 0, - .shape_exists = false, - .shape_event = 0, - .randr_exists = 0, - .randr_event = 0, - .glx_exists = false, - .glx_error = 0, - #ifdef CONFIG_DBUS .dbus_data = NULL, #endif @@ -2034,7 +2023,7 @@ static session_t *session_init(int argc, char **argv, Display *dpy, log_fatal("No render extension"); exit(1); } - ps->render_error = ext_info->first_error; + ps->c.e.render_error = ext_info->first_error; ext_info = xcb_get_extension_data(ps->c.c, &xcb_composite_id); if (!ext_info || !ext_info->present) { @@ -2062,8 +2051,8 @@ static session_t *session_init(int argc, char **argv, Display *dpy, log_fatal("No damage extension"); exit(1); } - ps->damage_event = ext_info->first_event; - ps->damage_error = ext_info->first_error; + ps->c.e.damage_event = ext_info->first_event; + ps->c.e.damage_error = ext_info->first_error; xcb_discard_reply(ps->c.c, xcb_damage_query_version(ps->c.c, XCB_DAMAGE_MAJOR_VERSION, XCB_DAMAGE_MINOR_VERSION) .sequence); @@ -2073,7 +2062,7 @@ static session_t *session_init(int argc, char **argv, Display *dpy, log_fatal("No XFixes extension"); exit(1); } - ps->xfixes_error = ext_info->first_error; + ps->c.e.fixes_error = ext_info->first_error; xcb_discard_reply(ps->c.c, xcb_xfixes_query_version(ps->c.c, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION) .sequence); @@ -2086,8 +2075,8 @@ static session_t *session_init(int argc, char **argv, Display *dpy, ext_info = xcb_get_extension_data(ps->c.c, &xcb_glx_id); if (ext_info && ext_info->present) { - ps->glx_exists = true; - ps->glx_error = ext_info->first_error; + ps->c.e.has_glx = true; + ps->c.e.glx_error = ext_info->first_error; } // Parse configuration file @@ -2179,14 +2168,14 @@ static session_t *session_init(int argc, char **argv, Display *dpy, // Query X Shape ext_info = xcb_get_extension_data(ps->c.c, &xcb_shape_id); if (ext_info && ext_info->present) { - ps->shape_event = ext_info->first_event; - ps->shape_exists = true; + ps->c.e.shape_event = ext_info->first_event; + ps->c.e.has_shape = true; } ext_info = xcb_get_extension_data(ps->c.c, &xcb_randr_id); if (ext_info && ext_info->present) { - ps->randr_exists = true; - ps->randr_event = ext_info->first_event; + ps->c.e.has_randr = true; + ps->c.e.randr_event = ext_info->first_event; } ext_info = xcb_get_extension_data(ps->c.c, &xcb_present_id); @@ -2197,7 +2186,7 @@ static session_t *session_init(int argc, char **argv, Display *dpy, XCB_PRESENT_MINOR_VERSION), NULL); if (r) { - ps->present_exists = true; + ps->c.e.has_present = true; free(r); } } @@ -2205,8 +2194,8 @@ static session_t *session_init(int argc, char **argv, Display *dpy, // Query X Sync ext_info = xcb_get_extension_data(ps->c.c, &xcb_sync_id); if (ext_info && ext_info->present) { - ps->xsync_error = ext_info->first_error; - ps->xsync_event = ext_info->first_event; + ps->c.e.sync_error = ext_info->first_error; + ps->c.e.sync_event = ext_info->first_event; // Need X Sync 3.1 for fences auto r = xcb_sync_initialize_reply( ps->c.c, @@ -2214,13 +2203,13 @@ static session_t *session_init(int argc, char **argv, Display *dpy, NULL); if (r && (r->major_version > 3 || (r->major_version == 3 && r->minor_version >= 1))) { - ps->xsync_exists = true; + ps->c.e.has_sync = true; free(r); } } ps->sync_fence = XCB_NONE; - if (ps->xsync_exists) { + if (ps->c.e.has_sync) { ps->sync_fence = x_new_id(&ps->c); e = xcb_request_check( ps->c.c, xcb_sync_create_fence_checked( @@ -2242,7 +2231,7 @@ static session_t *session_init(int argc, char **argv, Display *dpy, } // Query X RandR - if (ps->o.crop_shadow_to_monitor && !ps->randr_exists) { + if (ps->o.crop_shadow_to_monitor && !ps->c.e.has_randr) { log_fatal("No X RandR extension. crop-shadow-to-monitor cannot be " "enabled."); goto err; @@ -2290,7 +2279,7 @@ static session_t *session_init(int argc, char **argv, Display *dpy, // Monitor screen changes if vsync_sw is enabled and we are using // an auto-detected refresh rate, or when X RandR features are enabled - if (ps->randr_exists) { + if (ps->c.e.has_randr) { xcb_randr_select_input(ps->c.c, ps->c.screen_info->root, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE); x_update_monitors_async(&ps->c, &ps->monitors); diff --git a/src/wm/win.c b/src/wm/win.c index e588cfd571..c70b9a2543 100644 --- a/src/wm/win.c +++ b/src/wm/win.c @@ -391,7 +391,7 @@ void win_process_primary_flags(session_t *ps, struct win *w) { if (win_check_flags_all(w, WIN_FLAGS_SIZE_STALE)) { win_on_win_size_change(w, ps->o.shadow_offset_x, ps->o.shadow_offset_y, ps->o.shadow_radius); - win_update_bounding_shape(&ps->c, w, ps->shape_exists, + win_update_bounding_shape(&ps->c, w, ps->c.e.has_shape, ps->o.detect_rounded_corners); win_clear_flags(w, WIN_FLAGS_SIZE_STALE); @@ -1308,7 +1308,7 @@ struct win *win_maybe_allocate(session_t *ps, struct wm_ref *cursor, (const uint32_t[]){frame_event_mask})); // Get notification when the shape of a window changes - if (ps->shape_exists) { + if (ps->c.e.has_shape) { x_set_error_action_ignore(&ps->c, xcb_shape_select_input(ps->c.c, wid, 1)); } diff --git a/src/x.c b/src/x.c index f4df1a9a7c..a124810255 100644 --- a/src/x.c +++ b/src/x.c @@ -64,14 +64,13 @@ static const char *x_error_code_to_string(unsigned long serial, uint8_t major, #define CASESTRRET2(s) \ case XCB_##s: name = #s; break - // TODO(yshui) separate error code out from session_t - o = error_code - ps->xfixes_error; + o = error_code - ps->c.e.fixes_error; switch (o) { CASESTRRET2(XFIXES_BAD_REGION); } - o = error_code - ps->damage_error; + o = error_code - ps->c.e.damage_error; switch (o) { CASESTRRET2(DAMAGE_BAD_DAMAGE); } - o = error_code - ps->render_error; + o = error_code - ps->c.e.render_error; switch (o) { CASESTRRET2(RENDER_PICT_FORMAT); CASESTRRET2(RENDER_PICTURE); @@ -80,8 +79,8 @@ static const char *x_error_code_to_string(unsigned long serial, uint8_t major, CASESTRRET2(RENDER_GLYPH); } - if (ps->glx_exists) { - o = error_code - ps->glx_error; + if (ps->c.e.has_glx) { + o = error_code - ps->c.e.glx_error; switch (o) { CASESTRRET2(GLX_BAD_CONTEXT); CASESTRRET2(GLX_BAD_CONTEXT_STATE); @@ -100,8 +99,8 @@ static const char *x_error_code_to_string(unsigned long serial, uint8_t major, } } - if (ps->xsync_exists) { - o = error_code - ps->xsync_error; + if (ps->c.e.has_sync) { + o = error_code - ps->c.e.sync_error; switch (o) { CASESTRRET(XSyncBadCounter); CASESTRRET(XSyncBadAlarm); diff --git a/src/x.h b/src/x.h index 46f9f294db..4b23e5b61c 100644 --- a/src/x.h +++ b/src/x.h @@ -45,6 +45,37 @@ enum x_error_action { PENDING_REPLY_ACTION_DEBUG_ABORT, }; +struct x_extensions { + /// The X Damage extension's base event number. + int damage_event; + /// The X Damage extension's base error number. + int damage_error; + /// The X Fixes extension's base error number. + int fixes_error; + /// The X GLX extension's presence. + bool has_glx; + /// The X GLX extension's base error number. + int glx_error; + /// The X Present extension's presence. + bool has_present; + /// The X RandR extension's presence. + bool has_randr; + /// The X RandR extension's base event number. + int randr_event; + /// The X Render extension's base error number. + int render_error; + /// The X Shape extension's presence. + bool has_shape; + /// The X Shape extension's base event number. + int shape_event; + /// The X Sync extension's presence. + bool has_sync; + /// The X Sync extension's base event number. + int sync_event; + /// The X Sync extension's base error number. + int sync_error; +}; + struct x_connection { // Public fields // These are part of the public ABI, changing these @@ -55,6 +86,8 @@ struct x_connection { Display *dpy; /// Default screen int screen; + /// Information about the X extensions. + struct x_extensions e; // Private fields /// The list of pending async requests that we have From b3af0f3c31bb7427b74a4c03a6a413252cc0c806 Mon Sep 17 00:00:00 2001 From: Maxim Solovyov Date: Fri, 18 Oct 2024 22:03:15 +0300 Subject: [PATCH 3/7] core: move initialization of the x extensions into a separate function --- src/picom.c | 112 +----------------------------------------- src/x.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/x.h | 7 +++ 3 files changed, 147 insertions(+), 110 deletions(-) diff --git a/src/picom.c b/src/picom.c index a42bebdc08..cb3e801a0b 100644 --- a/src/picom.c +++ b/src/picom.c @@ -2005,67 +2005,9 @@ static session_t *session_init(int argc, char **argv, Display *dpy, // Use the same Display across reset, primarily for resource leak checking x_connection_init(&ps->c, dpy); - - const xcb_query_extension_reply_t *ext_info; - - xcb_prefetch_extension_data(ps->c.c, &xcb_render_id); - xcb_prefetch_extension_data(ps->c.c, &xcb_composite_id); - xcb_prefetch_extension_data(ps->c.c, &xcb_damage_id); - xcb_prefetch_extension_data(ps->c.c, &xcb_shape_id); - xcb_prefetch_extension_data(ps->c.c, &xcb_xfixes_id); - xcb_prefetch_extension_data(ps->c.c, &xcb_randr_id); - xcb_prefetch_extension_data(ps->c.c, &xcb_present_id); - xcb_prefetch_extension_data(ps->c.c, &xcb_sync_id); - xcb_prefetch_extension_data(ps->c.c, &xcb_glx_id); - - ext_info = xcb_get_extension_data(ps->c.c, &xcb_render_id); - if (!ext_info || !ext_info->present) { - log_fatal("No render extension"); - exit(1); - } - ps->c.e.render_error = ext_info->first_error; - - ext_info = xcb_get_extension_data(ps->c.c, &xcb_composite_id); - if (!ext_info || !ext_info->present) { - log_fatal("No composite extension"); - exit(1); - } - - { - xcb_composite_query_version_reply_t *reply = xcb_composite_query_version_reply( - ps->c.c, - xcb_composite_query_version(ps->c.c, XCB_COMPOSITE_MAJOR_VERSION, - XCB_COMPOSITE_MINOR_VERSION), - NULL); - - if (!reply || (reply->major_version == 0 && reply->minor_version < 2)) { - log_fatal("Your X server doesn't have Composite >= 0.2 support, " - "we cannot proceed."); - exit(1); - } - free(reply); - } - - ext_info = xcb_get_extension_data(ps->c.c, &xcb_damage_id); - if (!ext_info || !ext_info->present) { - log_fatal("No damage extension"); - exit(1); - } - ps->c.e.damage_event = ext_info->first_event; - ps->c.e.damage_error = ext_info->first_error; - xcb_discard_reply(ps->c.c, xcb_damage_query_version(ps->c.c, XCB_DAMAGE_MAJOR_VERSION, - XCB_DAMAGE_MINOR_VERSION) - .sequence); - - ext_info = xcb_get_extension_data(ps->c.c, &xcb_xfixes_id); - if (!ext_info || !ext_info->present) { - log_fatal("No XFixes extension"); - exit(1); + if (!x_extensions_init(&ps->c)) { + goto err; } - ps->c.e.fixes_error = ext_info->first_error; - xcb_discard_reply(ps->c.c, xcb_xfixes_query_version(ps->c.c, XCB_XFIXES_MAJOR_VERSION, - XCB_XFIXES_MINOR_VERSION) - .sequence); ps->x_region = x_new_id(&ps->c); if (!XCB_AWAIT_VOID(xcb_xfixes_create_region, ps->c.c, ps->x_region, 0, NULL)) { @@ -2073,12 +2015,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy, goto err; } - ext_info = xcb_get_extension_data(ps->c.c, &xcb_glx_id); - if (ext_info && ext_info->present) { - ps->c.e.has_glx = true; - ps->c.e.glx_error = ext_info->first_error; - } - // Parse configuration file if (!parse_config(&ps->o, config_file)) { return NULL; @@ -2165,49 +2101,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy, } } - // Query X Shape - ext_info = xcb_get_extension_data(ps->c.c, &xcb_shape_id); - if (ext_info && ext_info->present) { - ps->c.e.shape_event = ext_info->first_event; - ps->c.e.has_shape = true; - } - - ext_info = xcb_get_extension_data(ps->c.c, &xcb_randr_id); - if (ext_info && ext_info->present) { - ps->c.e.has_randr = true; - ps->c.e.randr_event = ext_info->first_event; - } - - ext_info = xcb_get_extension_data(ps->c.c, &xcb_present_id); - if (ext_info && ext_info->present) { - auto r = xcb_present_query_version_reply( - ps->c.c, - xcb_present_query_version(ps->c.c, XCB_PRESENT_MAJOR_VERSION, - XCB_PRESENT_MINOR_VERSION), - NULL); - if (r) { - ps->c.e.has_present = true; - free(r); - } - } - - // Query X Sync - ext_info = xcb_get_extension_data(ps->c.c, &xcb_sync_id); - if (ext_info && ext_info->present) { - ps->c.e.sync_error = ext_info->first_error; - ps->c.e.sync_event = ext_info->first_event; - // Need X Sync 3.1 for fences - auto r = xcb_sync_initialize_reply( - ps->c.c, - xcb_sync_initialize(ps->c.c, XCB_SYNC_MAJOR_VERSION, XCB_SYNC_MINOR_VERSION), - NULL); - if (r && (r->major_version > 3 || - (r->major_version == 3 && r->minor_version >= 1))) { - ps->c.e.has_sync = true; - free(r); - } - } - ps->sync_fence = XCB_NONE; if (ps->c.e.has_sync) { ps->sync_fence = x_new_id(&ps->c); @@ -2230,7 +2123,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy, ps->o.xrender_sync_fence = false; } - // Query X RandR if (ps->o.crop_shadow_to_monitor && !ps->c.e.has_randr) { log_fatal("No X RandR extension. crop-shadow-to-monitor cannot be " "enabled."); diff --git a/src/x.c b/src/x.c index a124810255..41bd1f1a5a 100644 --- a/src/x.c +++ b/src/x.c @@ -221,6 +221,144 @@ static int xerror(Display attr_unused *dpy, XErrorEvent *ev) { return 0; } +/// Initialize the used X extensions and populate the x_extensions structure in an +/// x_connection structure with the information about them. +/// +/// Returns false if the X server doesn't have or support the required version of at least +/// one required X extension, true otherwise. +bool x_extensions_init(struct x_connection *c) { + xcb_prefetch_extension_data(c->c, &xcb_composite_id); + xcb_prefetch_extension_data(c->c, &xcb_damage_id); + xcb_prefetch_extension_data(c->c, &xcb_xfixes_id); + xcb_prefetch_extension_data(c->c, &xcb_glx_id); + xcb_prefetch_extension_data(c->c, &xcb_present_id); + xcb_prefetch_extension_data(c->c, &xcb_randr_id); + xcb_prefetch_extension_data(c->c, &xcb_render_id); + xcb_prefetch_extension_data(c->c, &xcb_shape_id); + xcb_prefetch_extension_data(c->c, &xcb_sync_id); + + // Initialize the X Composite extension. + auto extension = xcb_get_extension_data(c->c, &xcb_composite_id); + if (!extension || !extension->present) { + log_fatal("The X server doesn't have the X Composite extension."); + + return false; + } + + // The NameWindowPixmap request was introduced in the X Composite extension v0.2. + auto composite = xcb_composite_query_version_reply( + c->c, + xcb_composite_query_version(c->c, XCB_COMPOSITE_MAJOR_VERSION, + XCB_COMPOSITE_MINOR_VERSION), + NULL); + if (!composite || (composite->major_version == 0 && composite->minor_version < 2)) { + log_fatal("The X server doesn't support the X Composite extension v0.2."); + + if (composite) { + free(composite); + } + + return false; + } + + free(composite); + + // Initialize the X Damage extension. + extension = xcb_get_extension_data(c->c, &xcb_damage_id); + if (!extension || !extension->present) { + log_fatal("The X server doesn't have the X Damage extension."); + + return false; + } + + c->e.damage_event = extension->first_event; + c->e.damage_error = extension->first_error; + + // According to the X Damage extension's specification: + // "The client must negotiate the version of the extension before executing + // extension requests. Otherwise, the server will return BadRequest for any + // operations other than QueryVersion." + xcb_discard_reply(c->c, xcb_damage_query_version(c->c, XCB_DAMAGE_MAJOR_VERSION, + XCB_DAMAGE_MINOR_VERSION) + .sequence); + + // Initialize the X Fixes extension. + extension = xcb_get_extension_data(c->c, &xcb_xfixes_id); + if (!extension || !extension->present) { + log_fatal("The X server doesn't have the X Fixes extension."); + + return false; + } + + c->e.fixes_error = extension->first_error; + + // According to the X Fixes extension's specification: + // "The client must negotiate the version of the extension before executing + // extension requests. Behavior of the server is undefined otherwise." + xcb_discard_reply(c->c, xcb_xfixes_query_version(c->c, XCB_XFIXES_MAJOR_VERSION, + XCB_XFIXES_MINOR_VERSION) + .sequence); + + // Initialize the X GLX extension. + extension = xcb_get_extension_data(c->c, &xcb_glx_id); + if (extension && extension->present) { + c->e.has_glx = true; + c->e.glx_error = extension->first_error; + } + + // Initialize the X Present extension. + extension = xcb_get_extension_data(c->c, &xcb_present_id); + if (extension && extension->present) { + c->e.has_present = true; + } + + // Initialize the X RandR extension. + extension = xcb_get_extension_data(c->c, &xcb_randr_id); + if (extension && extension->present) { + c->e.has_randr = true; + c->e.randr_event = extension->first_event; + } + + // Initialize the X Render extension. + extension = xcb_get_extension_data(c->c, &xcb_render_id); + if (!extension || !extension->present) { + log_fatal("The X server doesn't have the X Render extension."); + + return false; + } + + c->e.render_error = extension->first_error; + + // Initialize the X Shape extension. + extension = xcb_get_extension_data(c->c, &xcb_shape_id); + if (extension && extension->present) { + c->e.has_shape = true; + c->e.shape_event = extension->first_event; + } + + // Initialize the X Sync extension. + extension = xcb_get_extension_data(c->c, &xcb_sync_id); + if (extension && extension->present) { + // Fences were introduced in the X Sync extension v3.1. + auto sync = xcb_sync_initialize_reply( + c->c, + xcb_sync_initialize(c->c, XCB_SYNC_MAJOR_VERSION, XCB_SYNC_MINOR_VERSION), + NULL); + if (sync && (sync->major_version > 3 || + (sync->major_version == 3 && sync->minor_version >= 1))) { + c->e.has_sync = true; + c->e.sync_event = extension->first_event; + c->e.sync_error = extension->first_error; + } + + if (sync) { + free(sync); + } + } + + return true; +} + static void x_connection_init_inner(struct x_connection *c) { list_init_head(&c->pending_x_requests); c->previous_xerror_handler = XSetErrorHandler(xerror); diff --git a/src/x.h b/src/x.h index 4b23e5b61c..220399f5c8 100644 --- a/src/x.h +++ b/src/x.h @@ -233,6 +233,13 @@ static inline void attr_unused free_x_connection(struct x_connection *c) { XSetErrorHandler(c->previous_xerror_handler); } +/// Initialize the used X extensions and populate the x_extensions structure in an +/// x_connection structure with the information about them. +/// +/// Returns false if the X server doesn't have or support the required version of at least +/// one required X extension, true otherwise. +bool x_extensions_init(struct x_connection *c); + /// Initialize x_connection struct from an Xlib Display. /// /// Note this function doesn't take ownership of the Display, the caller is still From 522e5fe25f6fe94d7a50a60984b864dd53de950d Mon Sep 17 00:00:00 2001 From: Maxim Solovyov Date: Fri, 18 Oct 2024 22:23:27 +0300 Subject: [PATCH 4/7] diagnostic: unify the optional x extensions presence reporting --- src/diagnostic.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/diagnostic.c b/src/diagnostic.c index 69f7455943..0aad9ec19e 100644 --- a/src/diagnostic.c +++ b/src/diagnostic.c @@ -15,10 +15,12 @@ void print_diagnostics(session_t *ps, const char *config_file, bool compositor_running) { printf("**Version:** " PICOM_FULL_VERSION "\n"); // printf("**CFLAGS:** %s\n", "??"); - printf("\n### Extensions:\n\n"); - printf("* Shape: %s\n", ps->c.e.has_shape ? "Yes" : "No"); - printf("* RandR: %s\n", ps->c.e.has_randr ? "Yes" : "No"); - printf("* Present: %s\n", ps->c.e.has_present ? "Present" : "Not Present"); + printf("\n### X extensions:\n\n"); + printf("* GLX: %s\n", ps->c.e.has_glx ? "present" : "absent"); + printf("* Present: %s\n", ps->c.e.has_present ? "present" : "absent"); + printf("* RandR: %s\n", ps->c.e.has_randr ? "present" : "absent"); + printf("* Shape: %s\n", ps->c.e.has_shape ? "present" : "absent"); + printf("* Sync: %s\n", ps->c.e.has_sync ? "present" : "absent"); printf("\n### Misc:\n\n"); printf("* Use Overlay: %s\n", ps->overlay != XCB_NONE ? "Yes" : "No"); if (ps->overlay == XCB_NONE) { From 150339f34e592c4cb5649cd9c20a32be6d7c7121 Mon Sep 17 00:00:00 2001 From: Maxim Solovyov Date: Fri, 18 Oct 2024 22:29:05 +0300 Subject: [PATCH 5/7] wm/win: win_update_bounding_shape doesn't need shape_exists anymore --- src/wm/win.c | 7 +++---- src/wm/win.h | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/wm/win.c b/src/wm/win.c index c70b9a2543..12dcad84da 100644 --- a/src/wm/win.c +++ b/src/wm/win.c @@ -391,8 +391,7 @@ void win_process_primary_flags(session_t *ps, struct win *w) { if (win_check_flags_all(w, WIN_FLAGS_SIZE_STALE)) { win_on_win_size_change(w, ps->o.shadow_offset_x, ps->o.shadow_offset_y, ps->o.shadow_radius); - win_update_bounding_shape(&ps->c, w, ps->c.e.has_shape, - ps->o.detect_rounded_corners); + win_update_bounding_shape(&ps->c, w, ps->o.detect_rounded_corners); win_clear_flags(w, WIN_FLAGS_SIZE_STALE); // Window shape/size changed, invalidate the images we built @@ -1444,7 +1443,7 @@ gen_by_val(win_extents); * * Mark the window shape as updated */ -void win_update_bounding_shape(struct x_connection *c, struct win *w, bool shape_exists, +void win_update_bounding_shape(struct x_connection *c, struct win *w, bool detect_rounded_corners) { // We don't handle property updates of non-visible windows until they are // mapped. @@ -1454,7 +1453,7 @@ void win_update_bounding_shape(struct x_connection *c, struct win *w, bool shape // Start with the window rectangular region win_get_region_local(w, &w->bounding_shape); - if (shape_exists) { + if (c->e.has_shape) { w->bounding_shaped = win_bounding_shaped(c, win_id(w)); } diff --git a/src/wm/win.h b/src/wm/win.h index 08551656ca..5dc503b1cc 100644 --- a/src/wm/win.h +++ b/src/wm/win.h @@ -512,7 +512,7 @@ int win_update_role(struct x_connection *c, struct atom *atoms, struct win *w); int win_update_name(struct x_connection *c, struct atom *atoms, struct win *w); void win_on_win_size_change(struct win *w, int shadow_offset_x, int shadow_offset_y, int shadow_radius); -void win_update_bounding_shape(struct x_connection *c, struct win *w, bool shape_exists, +void win_update_bounding_shape(struct x_connection *c, struct win *w, bool detect_rounded_corners); bool win_update_prop_fullscreen(struct x_connection *c, const struct atom *atoms, struct win *w); From da1db39d049c3184ae432d13b99818a07c698345 Mon Sep 17 00:00:00 2001 From: Maxim Solovyov Date: Fri, 18 Oct 2024 23:46:08 +0300 Subject: [PATCH 6/7] x: x_error_code_to_string doesn't need ps_g anymore --- src/backend/xrender/xrender.c | 5 ++- src/event.c | 14 +++---- src/inspect.c | 11 +++--- src/picom.c | 36 +++++++++--------- src/utils/ui.c | 32 ++++++++-------- src/wm/win.c | 14 ++++--- src/wm/wm.c | 12 +++--- src/x.c | 70 +++++++++++++++++------------------ src/x.h | 56 ++++++++++++++-------------- 9 files changed, 127 insertions(+), 123 deletions(-) diff --git a/src/backend/xrender/xrender.c b/src/backend/xrender/xrender.c index 48fb6cbce4..b9d2afe6bd 100644 --- a/src/backend/xrender/xrender.c +++ b/src/backend/xrender/xrender.c @@ -172,7 +172,7 @@ xrender_make_rounded_corner_cache(struct x_connection *c, xcb_render_picture_t s } #undef ADD_POINT - XCB_AWAIT_VOID(xcb_render_tri_strip, c->c, XCB_RENDER_PICT_OP_SRC, src, picture, + XCB_AWAIT_VOID(xcb_render_tri_strip, c, XCB_RENDER_PICT_OP_SRC, src, picture, x_get_pictfmt_for_standard(c, XCB_PICT_STANDARD_A_8), 0, 0, (uint32_t)point_count, points); free(points); @@ -641,7 +641,8 @@ xrender_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fm auto r = xcb_get_geometry_reply(base->c->c, xcb_get_geometry(base->c->c, pixmap), &e); if (!r) { log_error("Invalid pixmap: %#010x", pixmap); - x_print_error(e->full_sequence, e->major_code, e->minor_code, e->error_code); + x_print_error(base->c, e->full_sequence, e->major_code, e->minor_code, + e->error_code); free(e); return NULL; } diff --git a/src/event.c b/src/event.c index 112fb6da97..2d0bced66f 100644 --- a/src/event.c +++ b/src/event.c @@ -199,7 +199,7 @@ struct ev_ewmh_active_win_request { /// Does not change anything if we fail to get the attribute or the window /// returned could not be found. static void -update_ewmh_active_win(struct x_connection * /*c*/, struct x_async_request_base *req_base, +update_ewmh_active_win(struct x_connection *c, struct x_async_request_base *req_base, const xcb_raw_generic_event_t *reply_or_error) { auto ps = ((struct ev_ewmh_active_win_request *)req_base)->ps; free(req_base); @@ -213,7 +213,7 @@ update_ewmh_active_win(struct x_connection * /*c*/, struct x_async_request_base if (reply_or_error->response_type == 0) { log_error("Failed to get _NET_ACTIVE_WINDOW: %s", - x_strerror(((xcb_generic_error_t *)reply_or_error))); + x_strerror(c, (xcb_generic_error_t *)reply_or_error)); return; } @@ -246,7 +246,7 @@ struct ev_recheck_focus_request { * @param ps current session * @return struct _win of currently focused window, NULL if not found */ -static void recheck_focus(struct x_connection * /*c*/, struct x_async_request_base *req_base, +static void recheck_focus(struct x_connection *c, struct x_async_request_base *req_base, const xcb_raw_generic_event_t *reply_or_error) { auto ps = ((struct ev_ewmh_active_win_request *)req_base)->ps; free(req_base); @@ -263,7 +263,7 @@ static void recheck_focus(struct x_connection * /*c*/, struct x_async_request_ba if (reply_or_error->response_type == 0) { // Not able to get input focus means very not good things... auto e = (xcb_generic_error_t *)reply_or_error; - log_error_x_error(e, "Failed to get focused window."); + log_error_x_error(c, e, "Failed to get focused window."); return; } @@ -419,7 +419,7 @@ static inline void ev_map_notify(session_t *ps, xcb_map_notify_event_t *ev) { if (!ps->redirected) { log_debug("Overlay is mapped while we are not redirected"); auto succeeded = - XCB_AWAIT_VOID(xcb_unmap_window, ps->c.c, ps->overlay); + XCB_AWAIT_VOID(xcb_unmap_window, &ps->c, ps->overlay); if (!succeeded) { log_error("Failed to unmap the overlay window"); } @@ -641,8 +641,8 @@ static inline void repair_win(session_t *ps, struct win *w) { xcb_damage_subtract_checked(ps->c.c, w->damage, XCB_NONE, XCB_NONE)); if (e) { if (ps->o.show_all_xerrors) { - x_print_error(e->sequence, e->major_code, e->minor_code, - e->error_code); + x_print_error(&ps->c, e->sequence, e->major_code, + e->minor_code, e->error_code); } free(e); } diff --git a/src/inspect.c b/src/inspect.c index 097ba77c08..d604ed4c52 100644 --- a/src/inspect.c +++ b/src/inspect.c @@ -27,11 +27,11 @@ xcb_window_t inspect_select_window(struct x_connection *c) { xcb_cursor_t cursor = x_new_id(c); const char font_name[] = "cursor"; static const uint16_t CROSSHAIR_CHAR = 34; - XCB_AWAIT_VOID(xcb_open_font, c->c, font, sizeof(font_name) - 1, font_name); - XCB_AWAIT_VOID(xcb_create_glyph_cursor, c->c, cursor, font, font, CROSSHAIR_CHAR, + XCB_AWAIT_VOID(xcb_open_font, c, font, sizeof(font_name) - 1, font_name); + XCB_AWAIT_VOID(xcb_create_glyph_cursor, c, cursor, font, font, CROSSHAIR_CHAR, CROSSHAIR_CHAR + 1, 0, 0, 0, 0xffff, 0xffff, 0xffff); auto grab_reply = XCB_AWAIT( - xcb_grab_pointer, c->c, false, c->screen_info->root, + xcb_grab_pointer, c, false, c->screen_info->root, XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, c->screen_info->root, cursor, XCB_CURRENT_TIME); if (grab_reply->status != XCB_GRAB_STATUS_SUCCESS) { @@ -45,8 +45,7 @@ xcb_window_t inspect_select_window(struct x_connection *c) { xcb_window_t target = XCB_NONE; int buttons_pressed = 0; while ((target == XCB_NONE) || (buttons_pressed > 0)) { - XCB_AWAIT_VOID(xcb_allow_events, c->c, XCB_ALLOW_ASYNC_POINTER, - XCB_CURRENT_TIME); + XCB_AWAIT_VOID(xcb_allow_events, c, XCB_ALLOW_ASYNC_POINTER, XCB_CURRENT_TIME); xcb_generic_event_t *ev = xcb_wait_for_event(c->c); if (!ev) { log_fatal("Connection to X server lost"); @@ -74,7 +73,7 @@ xcb_window_t inspect_select_window(struct x_connection *c) { } free(ev); } - XCB_AWAIT_VOID(xcb_ungrab_pointer, c->c, XCB_CURRENT_TIME); + XCB_AWAIT_VOID(xcb_ungrab_pointer, c, XCB_CURRENT_TIME); return target; } diff --git a/src/picom.c b/src/picom.c index cb3e801a0b..a6ce8672f1 100644 --- a/src/picom.c +++ b/src/picom.c @@ -601,7 +601,7 @@ static bool initialize_backend(session_t *ps) { void configure_root(session_t *ps) { // TODO(yshui) re-initializing backend should be done outside of the // critical section. Probably set a flag and do it in draw_callback_impl. - auto r = XCB_AWAIT(xcb_get_geometry, ps->c.c, ps->c.screen_info->root); + auto r = XCB_AWAIT(xcb_get_geometry, &ps->c, ps->c.screen_info->root); if (!r) { log_fatal("Failed to fetch root geometry"); abort(); @@ -949,7 +949,7 @@ static int register_cm(session_t *ps) { prop_is_utf8[i] ? ps->atoms->aUTF8_STRING : XCB_ATOM_STRING, 8, strlen("picom"), "picom")); if (e) { - log_error_x_error(e, "Failed to set window property %d", + log_error_x_error(&ps->c, e, "Failed to set window property %d", prop_atoms[i]); free(e); } @@ -961,7 +961,7 @@ static int register_cm(session_t *ps) { ps->atoms->aWM_CLASS, XCB_ATOM_STRING, 8, ARR_SIZE(picom_class), picom_class)); if (e) { - log_error_x_error(e, "Failed to set the WM_CLASS property"); + log_error_x_error(&ps->c, e, "Failed to set the WM_CLASS property"); free(e); } @@ -978,8 +978,9 @@ static int register_cm(session_t *ps) { ps->atoms->aWM_CLIENT_MACHINE, XCB_ATOM_STRING, 8, (uint32_t)strlen(hostname), hostname)); if (e) { - log_error_x_error(e, "Failed to set the WM_CLIENT_MACHINE" - " property"); + log_error_x_error(&ps->c, e, + "Failed to set the WM_CLIENT_MACHINE" + " property"); free(e); } } else { @@ -1002,7 +1003,7 @@ static int register_cm(session_t *ps) { ps->atoms->aCOMPTON_VERSION, XCB_ATOM_STRING, 8, (uint32_t)strlen(PICOM_VERSION), PICOM_VERSION)); if (e) { - log_error_x_error(e, "Failed to set COMPTON_VERSION."); + log_error_x_error(&ps->c, e, "Failed to set COMPTON_VERSION."); free(e); } @@ -1066,13 +1067,13 @@ static bool init_overlay(session_t *ps) { if (ps->overlay != XCB_NONE) { // Set window region of the overlay window, code stolen from // compiz-0.8.8 - if (!XCB_AWAIT_VOID(xcb_shape_mask, ps->c.c, XCB_SHAPE_SO_SET, + if (!XCB_AWAIT_VOID(xcb_shape_mask, &ps->c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, ps->overlay, 0, 0, 0)) { log_fatal("Failed to set the bounding shape of overlay, giving " "up."); return false; } - if (!XCB_AWAIT_VOID(xcb_shape_rectangles, ps->c.c, XCB_SHAPE_SO_SET, + if (!XCB_AWAIT_VOID(xcb_shape_rectangles, &ps->c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, XCB_CLIP_ORDERING_UNSORTED, ps->overlay, 0, 0, 0, NULL)) { log_fatal("Failed to set the input shape of overlay, giving up."); @@ -1088,7 +1089,7 @@ static bool init_overlay(session_t *ps) { // root_damage = XDamageCreate(ps->dpy, root, XDamageReportNonEmpty); // Unmap the overlay, we will map it when needed in redirect_start - XCB_AWAIT_VOID(xcb_unmap_window, ps->c.c, ps->overlay); + XCB_AWAIT_VOID(xcb_unmap_window, &ps->c, ps->overlay); } else { log_error("Cannot get X Composite overlay window. Falling " "back to painting on root window."); @@ -1174,7 +1175,7 @@ static bool redirect_start(session_t *ps) { xcb_map_window(ps->c.c, ps->overlay); } - bool success = XCB_AWAIT_VOID(xcb_composite_redirect_subwindows, ps->c.c, + bool success = XCB_AWAIT_VOID(xcb_composite_redirect_subwindows, &ps->c, ps->c.screen_info->root, session_redirection_mode(ps)); if (!success) { log_fatal("Another composite manager is already running " @@ -2010,7 +2011,7 @@ static session_t *session_init(int argc, char **argv, Display *dpy, } ps->x_region = x_new_id(&ps->c); - if (!XCB_AWAIT_VOID(xcb_xfixes_create_region, ps->c.c, ps->x_region, 0, NULL)) { + if (!XCB_AWAIT_VOID(xcb_xfixes_create_region, &ps->c, ps->x_region, 0, NULL)) { log_fatal("Failed to create a XFixes region"); goto err; } @@ -2109,9 +2110,10 @@ static session_t *session_init(int argc, char **argv, Display *dpy, ps->c.c, ps->c.screen_info->root, ps->sync_fence, 0)); if (e) { if (ps->o.xrender_sync_fence) { - log_error_x_error(e, "Failed to create a XSync fence. " - "xrender-sync-fence will be " - "disabled"); + log_error_x_error(&ps->c, e, + "Failed to create a XSync fence. " + "xrender-sync-fence will be " + "disabled"); ps->o.xrender_sync_fence = false; } ps->sync_fence = XCB_NONE; @@ -2236,14 +2238,14 @@ static session_t *session_init(int argc, char **argv, Display *dpy, XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE})); if (e) { - log_error_x_error(e, "Failed to setup root window event mask"); + log_error_x_error(&ps->c, e, "Failed to setup root window event mask"); free(e); goto err; } // Query the size of the root window. We need the size information before any // window can be managed. - auto r = XCB_AWAIT(xcb_get_geometry, ps->c.c, ps->c.screen_info->root); + auto r = XCB_AWAIT(xcb_get_geometry, &ps->c, ps->c.screen_info->root); if (!r) { log_fatal("Failed to get geometry of the root window"); goto err; @@ -2277,7 +2279,7 @@ static session_t *session_init(int argc, char **argv, Display *dpy, // release it. auto get_overlay = xcb_composite_get_overlay_window(ps->c.c, ps->c.screen_info->root); - XCB_AWAIT_VOID(xcb_composite_release_overlay_window, ps->c.c, + XCB_AWAIT_VOID(xcb_composite_release_overlay_window, &ps->c, ps->c.screen_info->root); auto overlay_reply = xcb_composite_get_overlay_window_reply(ps->c.c, get_overlay, NULL); diff --git a/src/utils/ui.c b/src/utils/ui.c index 0ae00c0c97..feeba32bb7 100644 --- a/src/utils/ui.c +++ b/src/utils/ui.c @@ -23,7 +23,7 @@ ui_message_box_draw_text(struct ui *ui, struct x_connection *c, xcb_window_t win content->size.width > UINT16_MAX ? UINT16_MAX : (uint16_t)content->size.width; uint16_t height = content->size.height > UINT16_MAX ? UINT16_MAX : (uint16_t)content->size.height; - if (!XCB_AWAIT_VOID(xcb_create_pixmap, c->c, c->screen_info->root_depth, pixmap, + if (!XCB_AWAIT_VOID(xcb_create_pixmap, c, c->screen_info->root_depth, pixmap, window, width, height)) { return XCB_NONE; } @@ -34,7 +34,7 @@ ui_message_box_draw_text(struct ui *ui, struct x_connection *c, xcb_window_t win uint32_t value_list[3] = {c->screen_info->black_pixel, c->screen_info->black_pixel}; - if (!XCB_AWAIT_VOID(xcb_create_gc, c->c, gc, pixmap, mask, value_list)) { + if (!XCB_AWAIT_VOID(xcb_create_gc, c, gc, pixmap, mask, value_list)) { return XCB_NONE; } } @@ -45,14 +45,14 @@ ui_message_box_draw_text(struct ui *ui, struct x_connection *c, xcb_window_t win const char yellow_name[] = "yellow"; const char red_name[] = "red"; - auto r = XCB_AWAIT(xcb_alloc_named_color, c->c, c->screen_info->default_colormap, + auto r = XCB_AWAIT(xcb_alloc_named_color, c, c->screen_info->default_colormap, ARR_SIZE(yellow_name) - 1, yellow_name); if (r == NULL) { return XCB_NONE; } auto yellow_pixel = r->pixel; free(r); - r = XCB_AWAIT(xcb_alloc_named_color, c->c, c->screen_info->default_colormap, + r = XCB_AWAIT(xcb_alloc_named_color, c, c->screen_info->default_colormap, ARR_SIZE(red_name) - 1, red_name); if (r == NULL) { return XCB_NONE; @@ -85,12 +85,11 @@ ui_message_box_draw_text(struct ui *ui, struct x_connection *c, xcb_window_t win void ui_message_box_place(struct x_connection *c, struct ui_message_box_content *content, int16_t *x, int16_t *y) { - auto r = - XCB_AWAIT(xcb_randr_get_screen_resources_current, c->c, c->screen_info->root); + auto r = XCB_AWAIT(xcb_randr_get_screen_resources_current, c, c->screen_info->root); if (r == NULL) { return; } - auto pointer = XCB_AWAIT(xcb_query_pointer, c->c, c->screen_info->root); + auto pointer = XCB_AWAIT(xcb_query_pointer, c, c->screen_info->root); if (pointer == NULL) { free(r); return; @@ -100,7 +99,7 @@ void ui_message_box_place(struct x_connection *c, struct ui_message_box_content auto crtcs = xcb_randr_get_screen_resources_current_crtcs(r); for (int i = 0; i < num_crtc; i++) { auto crtc_info_ptr = - XCB_AWAIT(xcb_randr_get_crtc_info, c->c, crtcs[i], r->config_timestamp); + XCB_AWAIT(xcb_randr_get_crtc_info, c, crtcs[i], r->config_timestamp); if (crtc_info_ptr == NULL || crtc_info_ptr->status != XCB_RANDR_SET_CONFIG_SUCCESS) { free(crtc_info_ptr); @@ -166,7 +165,7 @@ bool ui_message_box_show(struct ui *ui, struct x_connection *c, XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW}; - bool success = XCB_AWAIT_VOID(xcb_create_window, c->c, c->screen_info->root_depth, + bool success = XCB_AWAIT_VOID(xcb_create_window, c, c->screen_info->root_depth, win, c->screen_info->root, x, y, width, height, /*border_width=*/0, XCB_WINDOW_CLASS_INPUT_OUTPUT, c->screen_info->root_visual, mask, values); @@ -187,17 +186,17 @@ bool ui_message_box_show(struct ui *ui, struct x_connection *c, .matrix22 = DOUBLE_TO_XFIXED(1.0F / content->scale), .matrix33 = DOUBLE_TO_XFIXED(1.0), }; - if (!XCB_AWAIT_VOID(xcb_render_set_picture_transform, c->c, content_picture, transform)) { + if (!XCB_AWAIT_VOID(xcb_render_set_picture_transform, c, content_picture, transform)) { return false; } const char filter_name[] = "bilinear"; - if (!XCB_AWAIT_VOID(xcb_render_set_picture_filter, c->c, content_picture, + if (!XCB_AWAIT_VOID(xcb_render_set_picture_filter, c, content_picture, ARR_SIZE(filter_name) - 1, filter_name, 0, NULL)) { return false; } - if (!XCB_AWAIT_VOID(xcb_map_window, c->c, win)) { + if (!XCB_AWAIT_VOID(xcb_map_window, c, win)) { xcb_destroy_window(c->c, win); return false; } @@ -304,7 +303,7 @@ static bool ui_message_box_line_extent(struct ui *ui, struct x_connection *c, text16[i].byte1 = 0; text16[i].byte2 = (uint8_t)line->text[i]; } - auto r = XCB_AWAIT(xcb_query_text_extents, c->c, font, len, text16); + auto r = XCB_AWAIT(xcb_query_text_extents, c, font, len, text16); free(text16); if (!r) { @@ -367,15 +366,16 @@ struct ui *ui_new(struct x_connection *c) { xcb_generic_error_t *e = xcb_request_check(c->c, cookie1); if (e != NULL) { - log_error_x_error(e, "Cannot open the fixed font"); + log_error_x_error(c, e, "Cannot open the fixed font"); free(e); return NULL; } e = xcb_request_check(c->c, cookie2); if (e != NULL) { ui->bold_font = ui->normal_font; - log_error_x_error(e, "Cannot open the bold font, falling back to normal " - "font"); + log_error_x_error(c, e, + "Cannot open the bold font, falling back to normal " + "font"); free(e); } return ui; diff --git a/src/wm/win.c b/src/wm/win.c index 12dcad84da..26a24fee09 100644 --- a/src/wm/win.c +++ b/src/wm/win.c @@ -501,7 +501,7 @@ void win_process_image_flags(session_t *ps, struct win *w) { if (e != NULL) { log_debug("Failed to get named pixmap for window %#010x(%s): %s. " "Retaining its current window image", - win_id(w), w->name, x_strerror(e)); + win_id(w), w->name, x_strerror(&ps->c, e)); free(e); return; } @@ -1180,7 +1180,7 @@ void win_on_client_update(session_t *ps, struct win *w) { // Update everything related to conditions win_set_flags(w, WIN_FLAGS_FACTOR_CHANGED); - auto r = XCB_AWAIT(xcb_get_window_attributes, ps->c.c, client_win_id); + auto r = XCB_AWAIT(xcb_get_window_attributes, &ps->c, client_win_id); if (!r) { return; } @@ -1268,7 +1268,8 @@ struct win *win_maybe_allocate(session_t *ps, struct wm_ref *cursor, xcb_generic_error_t *e; auto g = xcb_get_geometry_reply(ps->c.c, xcb_get_geometry(ps->c.c, wid), &e); if (!g) { - log_debug("Failed to get geometry of window %#010x: %s", wid, x_strerror(e)); + log_debug("Failed to get geometry of window %#010x: %s", wid, + x_strerror(&ps->c, e)); free(e); free(new); return NULL; @@ -1289,7 +1290,8 @@ struct win *win_maybe_allocate(session_t *ps, struct wm_ref *cursor, ps->c.c, xcb_damage_create_checked(ps->c.c, new->damage, wid, XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY)); if (e) { - log_debug("Failed to create damage for window %#010x: %s", wid, x_strerror(e)); + log_debug("Failed to create damage for window %#010x: %s", wid, + x_strerror(&ps->c, e)); free(e); free(new); return NULL; @@ -1981,7 +1983,7 @@ struct win_get_geometry_request { xcb_window_t wid; }; -static void win_handle_get_geometry_reply(struct x_connection * /*c*/, +static void win_handle_get_geometry_reply(struct x_connection *c, struct x_async_request_base *req_base, const xcb_raw_generic_event_t *reply_or_error) { auto req = (struct win_get_geometry_request *)req_base; @@ -1996,7 +1998,7 @@ static void win_handle_get_geometry_reply(struct x_connection * /*c*/, if (reply_or_error->response_type == 0) { log_debug("Failed to get geometry of window %#010x: %s", wid, - x_strerror((xcb_generic_error_t *)reply_or_error)); + x_strerror(c, (xcb_generic_error_t *)reply_or_error)); return; } diff --git a/src/wm/wm.c b/src/wm/wm.c index 2b3eecad56..53ee13983d 100644 --- a/src/wm/wm.c +++ b/src/wm/wm.c @@ -560,7 +560,7 @@ wm_handle_query_tree_reply(struct x_connection *c, struct x_async_request_base * // be impossible. xcb_generic_error_t *err = (xcb_generic_error_t *)reply_or_error; log_error("Query tree request for window %#010x failed with error %s.", - node == NULL ? 0 : node->id.x, x_strerror(err)); + node == NULL ? 0 : node->id.x, x_strerror(c, err)); BUG_ON(false); } @@ -585,9 +585,9 @@ wm_handle_query_tree_reply(struct x_connection *c, struct x_async_request_base * } } -static void wm_handle_get_wm_state_reply(struct x_connection * /*c*/, - struct x_async_request_base *base, - const xcb_raw_generic_event_t *reply_or_error) { +static void +wm_handle_get_wm_state_reply(struct x_connection *c, struct x_async_request_base *base, + const xcb_raw_generic_event_t *reply_or_error) { auto req = (struct wm_get_property_request *)base; if (reply_or_error == NULL) { free(req); @@ -605,7 +605,7 @@ static void wm_handle_get_wm_state_reply(struct x_connection * /*c*/, xcb_generic_error_t *err = (xcb_generic_error_t *)reply_or_error; log_debug("Get WM_STATE request for window %#010x failed with " "error %s", - req->wid, x_strerror(err)); + req->wid, x_strerror(c, err)); free(req); return; } @@ -646,7 +646,7 @@ wm_handle_set_event_mask_reply(struct x_connection *c, struct x_async_request_ba if (reply_or_error->response_type == 0) { log_debug("Failed to set event mask for window %#010x: %s, ignoring this " "window.", - wid, x_strerror((const xcb_generic_error_t *)reply_or_error)); + wid, x_strerror(c, (const xcb_generic_error_t *)reply_or_error)); goto end_import; } diff --git a/src/x.c b/src/x.c index 41bd1f1a5a..659079048a 100644 --- a/src/x.c +++ b/src/x.c @@ -51,10 +51,8 @@ enum { /// /// @return a pointer to a string. this pointer shouldn NOT be freed, same buffer is used /// for multiple calls to this function, -static const char *x_error_code_to_string(unsigned long serial, uint8_t major, - uint16_t minor, uint8_t error_code) { - session_t *const ps = ps_g; - +static const char *x_error_code_to_string(struct x_connection *c, unsigned long serial, + uint8_t major, uint16_t minor, uint8_t error_code) { int o = 0; const char *name = "Unknown"; @@ -64,13 +62,13 @@ static const char *x_error_code_to_string(unsigned long serial, uint8_t major, #define CASESTRRET2(s) \ case XCB_##s: name = #s; break - o = error_code - ps->c.e.fixes_error; + o = error_code - c->e.fixes_error; switch (o) { CASESTRRET2(XFIXES_BAD_REGION); } - o = error_code - ps->c.e.damage_error; + o = error_code - c->e.damage_error; switch (o) { CASESTRRET2(DAMAGE_BAD_DAMAGE); } - o = error_code - ps->c.e.render_error; + o = error_code - c->e.render_error; switch (o) { CASESTRRET2(RENDER_PICT_FORMAT); CASESTRRET2(RENDER_PICTURE); @@ -79,8 +77,8 @@ static const char *x_error_code_to_string(unsigned long serial, uint8_t major, CASESTRRET2(RENDER_GLYPH); } - if (ps->c.e.has_glx) { - o = error_code - ps->c.e.glx_error; + if (c->e.has_glx) { + o = error_code - c->e.glx_error; switch (o) { CASESTRRET2(GLX_BAD_CONTEXT); CASESTRRET2(GLX_BAD_CONTEXT_STATE); @@ -99,8 +97,8 @@ static const char *x_error_code_to_string(unsigned long serial, uint8_t major, } } - if (ps->c.e.has_sync) { - o = error_code - ps->c.e.sync_error; + if (c->e.has_sync) { + o = error_code - c->e.sync_error; switch (o) { CASESTRRET(XSyncBadCounter); CASESTRRET(XSyncBadAlarm); @@ -137,11 +135,11 @@ static const char *x_error_code_to_string(unsigned long serial, uint8_t major, return buffer; } -void x_print_error_impl(unsigned long serial, uint8_t major, uint16_t minor, - uint8_t error_code, const char *func) { +void x_print_error_impl(struct x_connection *c, unsigned long serial, uint8_t major, + uint16_t minor, uint8_t error_code, const char *func) { if (unlikely(LOG_LEVEL_DEBUG >= log_get_level_tls())) { log_printf(tls_logger, LOG_LEVEL_DEBUG, func, "%s", - x_error_code_to_string(serial, major, minor, error_code)); + x_error_code_to_string(c, serial, major, minor, error_code)); } } @@ -153,9 +151,9 @@ struct x_generic_async_request { int line; }; -static void x_generic_async_callback(struct x_connection * /*c*/, - struct x_async_request_base *req_base, - const xcb_raw_generic_event_t *reply_or_error) { +static void +x_generic_async_callback(struct x_connection *c, struct x_async_request_base *req_base, + const xcb_raw_generic_event_t *reply_or_error) { auto req = (struct x_generic_async_request *)req_base; auto error_action = req->error_action; auto func = req->func == NULL ? "(unknown)" : req->func; @@ -170,11 +168,11 @@ static void x_generic_async_callback(struct x_connection * /*c*/, auto error = (xcb_generic_error_t *)reply_or_error; if (error_action != PENDING_REPLY_ACTION_IGNORE) { log_error("X error for request in %s at %s:%d: %s", func, file, line, - x_error_code_to_string(error->full_sequence, error->major_code, + x_error_code_to_string(c, error->full_sequence, error->major_code, error->minor_code, error->error_code)); } else { log_debug("Expected X error for request in %s at %s:%d: %s", func, file, line, - x_error_code_to_string(error->full_sequence, error->major_code, + x_error_code_to_string(c, error->full_sequence, error->major_code, error->minor_code, error->error_code)); } switch (error_action) { @@ -460,7 +458,7 @@ bool wid_get_text_prop(struct x_connection *c, struct atom *atoms, xcb_window_t auto r = xcb_get_property_reply( c->c, xcb_get_property(c->c, 0, wid, prop, XCB_ATOM_ANY, 0, UINT_MAX), &e); if (!r) { - log_debug_x_error(e, "Failed to get window property for %#010x", wid); + log_debug_x_error(c, e, "Failed to get window property for %#010x", wid); free(e); return false; } @@ -645,7 +643,7 @@ x_create_picture_with_pictfmt_and_pixmap(struct x_connection *c, xcb_render_pict c->c, tmp_picture, pixmap, pictfmt, valuemask, buf)); free(buf); if (e) { - log_error_x_error(e, "failed to create picture"); + log_error_x_error(c, e, "failed to create picture"); free(e); abort(); return XCB_NONE; @@ -719,7 +717,7 @@ bool x_fetch_region(struct x_connection *c, xcb_xfixes_region_t r, pixman_region xcb_xfixes_fetch_region_reply_t *xr = xcb_xfixes_fetch_region_reply(c->c, xcb_xfixes_fetch_region(c->c, r), &e); if (!xr) { - log_error_x_error(e, "Failed to fetch rectangles"); + log_error_x_error(c, e, "Failed to fetch rectangles"); return false; } @@ -759,7 +757,7 @@ bool x_set_region(struct x_connection *c, xcb_xfixes_region_t dst, const region_ } bool success = - XCB_AWAIT_VOID(xcb_xfixes_set_region, c->c, dst, to_u32_checked(nrects), xrects); + XCB_AWAIT_VOID(xcb_xfixes_set_region, c, dst, to_u32_checked(nrects), xrects); free(xrects); @@ -786,8 +784,8 @@ uint32_t x_create_region(struct x_connection *c, const region_t *reg) { } xcb_xfixes_region_t ret = x_new_id(c); - bool success = XCB_AWAIT_VOID(xcb_xfixes_create_region, c->c, ret, - to_u32_checked(nrects), xrects); + bool success = + XCB_AWAIT_VOID(xcb_xfixes_create_region, c, ret, to_u32_checked(nrects), xrects); free(xrects); if (!success) { return XCB_NONE; @@ -843,7 +841,7 @@ void x_set_picture_clip_region(struct x_connection *c, xcb_render_picture_t pict c->c, pict, clip_x_origin, clip_y_origin, to_u32_checked(nrects), xrects)); if (e) { - log_error_x_error(e, "Failed to set clip region"); + log_error_x_error(c, e, "Failed to set clip region"); free(e); } free(xrects); @@ -855,7 +853,7 @@ void x_clear_picture_clip_region(struct x_connection *c, xcb_render_picture_t pi xcb_generic_error_t *e = xcb_request_check( c->c, xcb_render_change_picture_checked(c->c, pict, XCB_RENDER_CP_CLIP_MASK, &v)); if (e) { - log_error_x_error(e, "failed to clear clip region"); + log_error_x_error(c, e, "failed to clear clip region"); free(e); } } @@ -877,11 +875,11 @@ void x_free_picture(struct x_connection *c, xcb_render_picture_t p) { * @return a pointer to a string. this pointer shouldn NOT be freed, same buffer is used * for multiple calls to this function, */ -const char *x_strerror(const xcb_generic_error_t *e) { +const char *x_strerror(struct x_connection *c, const xcb_generic_error_t *e) { if (!e) { return "No error"; } - return x_error_code_to_string(e->full_sequence, e->major_code, e->minor_code, + return x_error_code_to_string(c, e->full_sequence, e->major_code, e->minor_code, e->error_code); } @@ -902,7 +900,7 @@ xcb_pixmap_t x_create_pixmap(struct x_connection *c, uint8_t depth, int width, i return pix; } - log_error_x_error(err, "Failed to create pixmap"); + log_error_x_error(c, err, "Failed to create pixmap"); free(err); return XCB_NONE; } @@ -954,19 +952,19 @@ bool x_fence_sync(struct x_connection *c, xcb_sync_fence_t f) { auto e = xcb_request_check(c->c, xcb_sync_trigger_fence_checked(c->c, f)); if (e) { - log_error_x_error(e, "Failed to trigger the fence"); + log_error_x_error(c, e, "Failed to trigger the fence"); goto err; } e = xcb_request_check(c->c, xcb_sync_await_fence_checked(c->c, 1, &f)); if (e) { - log_error_x_error(e, "Failed to await on a fence"); + log_error_x_error(c, e, "Failed to await on a fence"); goto err; } e = xcb_request_check(c->c, xcb_sync_reset_fence_checked(c->c, f)); if (e) { - log_error_x_error(e, "Failed to reset the fence"); + log_error_x_error(c, e, "Failed to reset the fence"); goto err; } return true; @@ -1071,7 +1069,7 @@ struct x_update_monitors_request { struct x_monitors *monitors; }; -static void x_handle_update_monitors_reply(struct x_connection * /*c*/, +static void x_handle_update_monitors_reply(struct x_connection *c, struct x_async_request_base *req_base, const xcb_raw_generic_event_t *reply_or_error) { auto m = ((struct x_update_monitors_request *)req_base)->monitors; @@ -1084,7 +1082,7 @@ static void x_handle_update_monitors_reply(struct x_connection * /*c*/, if (reply_or_error->response_type == 0) { log_warn("Failed to get monitor information using RandR: %s", - x_strerror((xcb_generic_error_t *)reply_or_error)); + x_strerror(c, (xcb_generic_error_t *)reply_or_error)); return; } @@ -1188,7 +1186,7 @@ static bool x_feed_event(struct x_connection *c, xcb_generic_event_t *e) { head->callback(c, head, (xcb_raw_generic_event_t *)e); } else { log_warn("Stray X error: %s", - x_error_code_to_string(error->full_sequence, error->major_code, + x_error_code_to_string(c, error->full_sequence, error->major_code, error->minor_code, error->error_code)); } return false; diff --git a/src/x.h b/src/x.h index 220399f5c8..4e1ee32797 100644 --- a/src/x.h +++ b/src/x.h @@ -132,38 +132,40 @@ struct x_monitors { region_t *regions; }; -#define XCB_AWAIT_VOID(func, c, ...) \ - /* NOLINTBEGIN(bugprone-assignment-in-if-condition) */ \ - ({ \ - bool __success = true; \ - __auto_type __e = xcb_request_check(c, func##_checked(c, __VA_ARGS__)); \ - if (__e) { \ - x_print_error(__e->sequence, __e->major_code, __e->minor_code, \ - __e->error_code); \ - free(__e); \ - __success = false; \ - } \ - __success; \ +#define XCB_AWAIT_VOID(func, conn, ...) \ + /* NOLINTBEGIN(bugprone-assignment-in-if-condition) */ \ + ({ \ + bool __success = true; \ + __auto_type __e = \ + xcb_request_check((conn)->c, func##_checked((conn)->c, __VA_ARGS__)); \ + if (__e) { \ + x_print_error(conn, __e->sequence, __e->major_code, \ + __e->minor_code, __e->error_code); \ + free(__e); \ + __success = false; \ + } \ + __success; \ }) /* NOLINTEND(bugprone-assignment-in-if-condition) */ -#define XCB_AWAIT(func, c, ...) \ +#define XCB_AWAIT(func, conn, ...) \ ({ \ xcb_generic_error_t *__e = NULL; \ - __auto_type __r = func##_reply(c, func(c, __VA_ARGS__), &__e); \ + __auto_type __r = \ + func##_reply((conn)->c, func((conn)->c, __VA_ARGS__), &__e); \ if (__e) { \ - x_print_error(__e->sequence, __e->major_code, __e->minor_code, \ - __e->error_code); \ + x_print_error(conn, __e->sequence, __e->major_code, \ + __e->minor_code, __e->error_code); \ free(__e); \ } \ __r; \ }) -#define log_debug_x_error(e, fmt, ...) \ - LOG(DEBUG, fmt " (%s)", ##__VA_ARGS__, x_strerror(e)) -#define log_error_x_error(e, fmt, ...) \ - LOG(ERROR, fmt " (%s)", ##__VA_ARGS__, x_strerror(e)) -#define log_fatal_x_error(e, fmt, ...) \ - LOG(FATAL, fmt " (%s)", ##__VA_ARGS__, x_strerror(e)) +#define log_debug_x_error(c, e, fmt, ...) \ + LOG(DEBUG, fmt " (%s)", ##__VA_ARGS__, x_strerror(c, e)) +#define log_error_x_error(c, e, fmt, ...) \ + LOG(ERROR, fmt " (%s)", ##__VA_ARGS__, x_strerror(c, e)) +#define log_fatal_x_error(c, e, fmt, ...) \ + LOG(FATAL, fmt " (%s)", ##__VA_ARGS__, x_strerror(c, e)) // xcb-render specific macros #define XFIXED_TO_DOUBLE(value) (((double)(value)) / 65536) @@ -377,10 +379,10 @@ void x_free_picture(struct x_connection *c, xcb_render_picture_t p); /** * Log a X11 error */ -void x_print_error_impl(unsigned long serial, uint8_t major, uint16_t minor, - uint8_t error_code, const char *func); -#define x_print_error(serial, major, minor, error_code) \ - x_print_error_impl(serial, major, minor, error_code, __func__) +void x_print_error_impl(struct x_connection *c, unsigned long serial, uint8_t major, + uint16_t minor, uint8_t error_code, const char *func); +#define x_print_error(c, serial, major, minor, error_code) \ + x_print_error_impl(c, serial, major, minor, error_code, __func__) /* * Convert a xcb_generic_error_t to a string that describes the error @@ -388,7 +390,7 @@ void x_print_error_impl(unsigned long serial, uint8_t major, uint16_t minor, * @return a pointer to a string. this pointer shouldn NOT be freed, same buffer is used * for multiple calls to this function, */ -const char *x_strerror(const xcb_generic_error_t *e); +const char *x_strerror(struct x_connection *c, const xcb_generic_error_t *e); void x_flush(struct x_connection *c); From ea391c24291f712f8d12b140fa4332b0b1ebd123 Mon Sep 17 00:00:00 2001 From: Maxim Solovyov Date: Sat, 19 Oct 2024 00:06:33 +0300 Subject: [PATCH 7/7] utils/process: initialize the used x extensions --- src/utils/process.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/utils/process.c b/src/utils/process.c index 2f7dd4dd1d..1b7c0dba2d 100644 --- a/src/utils/process.c +++ b/src/utils/process.c @@ -51,8 +51,15 @@ int spawn_picomling(struct x_connection *c) { setsid(); x_connection_init_xcb(c, new_c, screen); - xcb_prefetch_extension_data(c->c, &xcb_render_id); - xcb_prefetch_extension_data(c->c, &xcb_randr_id); + if (!x_extensions_init(c)) { + return -1; + } + + if (!c->e.has_randr) { + log_error("The X server doesn't have the X RandR extension."); + + return -1; + } return 0; }