diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 2e3dfe7e26..8f14cb3147 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -36,7 +36,7 @@ jobs: languages: ${{ matrix.language }} # Install dependencies - - run: sudo apt update && sudo apt install libxext-dev libxcb1-dev libxcb-dpms0-dev libxcb-damage0-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-render-util0-dev libxcb-render0-dev libxcb-randr0-dev libxcb-composite0-dev libxcb-image0-dev libxcb-present-dev libxcb-glx0-dev libpixman-1-dev libdbus-1-dev libconfig-dev libgl1-mesa-dev libpcre2-dev libevdev-dev uthash-dev libev-dev libx11-xcb-dev meson ninja-build + - run: sudo apt update && sudo apt install libconfig-dev libdbus-1-dev libev-dev libevdev-dev libgl1-mesa-dev libpcre2-dev libpixman-1-dev libx11-xcb-dev libxcb-composite0-dev libxcb-damage0-dev libxcb-dpms0-dev libxcb-glx0-dev libxcb-image0-dev libxcb-present-dev libxcb-randr0-dev libxcb-render-util0-dev libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev libxcb1-dev libxext-dev meson ninja-build uthash-dev if: ${{ matrix.language == 'cpp' }} # Autobuild diff --git a/README.md b/README.md index 0fecde197e..c7ddbaa8fb 100644 --- a/README.md +++ b/README.md @@ -17,43 +17,43 @@ See [Releases](https://github.com/yshui/picom/releases) Assuming you already have all the usual building tools installed (e.g. gcc, python, meson, ninja, etc.), you still need: +* libconfig (optional, use the `-Dconfig_file=false` meson configure flag to disable) +* libdbus (optional, use the `-Ddbus=false` meson configure flag to disable) +* libev +* libgl, libegl (optional, use the `-Dopengl=false` meson configure flag to disable) +* libpcre2 (optional, use the `-Dregex=false` meson configure flag to disable) * libx11 * libx11-xcb -* libXext -* xproto +* libxext +* pixman +* uthash * xcb +* xcb-composite * xcb-damage * xcb-dpms -* xcb-xfixes -* xcb-shape -* xcb-renderutil -* xcb-render -* xcb-randr -* xcb-composite +* xcb-glx * xcb-image * xcb-present -* xcb-glx -* pixman -* libdbus (optional, disable with the `-Ddbus=false` meson configure flag) -* libconfig (optional, disable with the `-Dconfig_file=false` meson configure flag) -* libGL, libEGL (optional, disable with the `-Dopengl=false` meson configure flag) -* libpcre2 (optional, disable with the `-Dregex=false` meson configure flag) -* libev -* uthash +* xcb-randr +* xcb-render +* xcb-renderutil +* xcb-shape +* xcb-xfixes +* xproto -On Debian based distributions (e.g. Ubuntu), the needed packages are +On Debian-based distributions (e.g. Ubuntu) the needed packages are: ``` -libxext-dev libxcb1-dev libxcb-damage0-dev libxcb-dpms0-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-render-util0-dev libxcb-render0-dev libxcb-randr0-dev libxcb-composite0-dev libxcb-image0-dev libxcb-present-dev libxcb-glx0-dev libpixman-1-dev libdbus-1-dev libconfig-dev libgl-dev libegl-dev libpcre2-dev libevdev-dev uthash-dev libev-dev libx11-xcb-dev meson +libconfig-dev libdbus-1-dev libegl-dev libev-dev libevdev-dev libgl-dev libpcre2-dev libpixman-1-dev libx11-xcb-dev libxcb-composite0-dev libxcb-damage0-dev libxcb-dpms0-dev libxcb-glx0-dev libxcb-image0-dev libxcb-present-dev libxcb-randr0-dev libxcb-render-util0-dev libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev libxcb1-dev libxext-dev meson uthash-dev ``` -On Fedora, the needed packages are +On Fedora the needed packages are: ``` -dbus-devel gcc git libconfig-devel libdrm-devel libev-devel libX11-devel libX11-xcb libXext-devel libxcb-devel libGL-devel libEGL-devel meson pcre2-devel pixman-devel uthash-devel xcb-util-image-devel xcb-util-renderutil-devel xorg-x11-proto-devel +dbus-devel gcc git libconfig-devel libdrm-devel libegl-devel libev-devel libgl-devel libx11-devel libx11-xcb libxcb-devel libxext-devel meson pcre2-devel pixman-devel uthash-devel xcb-util-image-devel xcb-util-renderutil-devel xorg-x11-proto-devel ``` -To build the documents, you need `asciidoc` +To build the documentation you need asciidoc. ### To build diff --git a/src/backend/backend.c b/src/backend/backend.c index 59ddcaf2a0..2100953452 100644 --- a/src/backend/backend.c +++ b/src/backend/backend.c @@ -87,13 +87,13 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) { return handle_device_reset(ps); } if (ps->o.xrender_sync_fence) { - if (ps->xsync_exists && !x_fence_sync(ps->c, ps->sync_fence)) { + if (ps->has_sync && !x_fence_sync(ps->c, ps->sync_fence)) { log_error("x_fence_sync failed, xrender-sync-fence will be " "disabled from now on."); xcb_sync_destroy_fence(ps->c, ps->sync_fence); ps->sync_fence = XCB_NONE; ps->o.xrender_sync_fence = false; - ps->xsync_exists = false; + ps->has_sync = false; } } // All painting will be limited to the damage, if _some_ of diff --git a/src/backend/gl/glx.c b/src/backend/gl/glx.c index 109bec9429..aaa317fe62 100644 --- a/src/backend/gl/glx.c +++ b/src/backend/gl/glx.c @@ -244,7 +244,7 @@ static backend_t *glx_init(session_t *ps) { XVisualInfo *pvis = NULL; // Check for GLX extension - if (!ps->glx_exists) { + if (!ps->has_glx) { log_error("No GLX extension."); goto end; } diff --git a/src/backend/xrender/xrender.c b/src/backend/xrender/xrender.c index 686e6deb8c..ee8a6a6f76 100644 --- a/src/backend/xrender/xrender.c +++ b/src/backend/xrender/xrender.c @@ -900,7 +900,7 @@ static backend_t *backend_xrender_init(session_t *ps) { } xd->vsync = ps->o.vsync; - if (ps->present_exists) { + if (ps->has_present) { auto eid = x_new_id(ps->c); auto e = xcb_request_check(ps->c, xcb_present_select_input_checked( diff --git a/src/common.h b/src/common.h index 8f307dc9fd..8aa75ca566 100644 --- a/src/common.h +++ b/src/common.h @@ -327,59 +327,41 @@ typedef struct session { int drm_fd; #endif - // === 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. + // === X extensions related === + /// Event base number of the X Damage extension. int damage_event; - /// Error base number for X Damage extension. + /// Error base number of the 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 DPMS extension exists - bool dpms_exists; - /// 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. + /// If the X GLX extension available. + bool has_glx; + /// Error base number of the X GLX extension. int glx_error; + /// If the X Present extension available. + bool has_present; + /// If the X RandR extension available. + bool has_randr; + /// Event base number of the X RandR extension. + int randr_event; /// Number of X RandR monitors. int randr_nmonitors; - /// X RandR monitor regions. + /// X RandR monitors regions. region_t *randr_monitor_regs; - /// 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; - /// Whether X Render convolution filter exists. - bool xrfilter_convolution_exists; + /// Error base number of the X Render extension. + int render_error; + /// If the X Shape extension available. + bool has_shape; + /// Event base number of the X Shape extension. + int shape_event; + /// If the X Sync extension available. + bool has_sync; + /// Event base number of the X Sync extension. + int sync_event; + /// Error base number of the X Sync extension. + int sync_error; + /// Error base number of the X Fixes extension. + int fixes_error; + /// If the X Render extension's convolution filter available. + bool has_convolution_xrfilter; // === Atoms === struct atom *atoms; diff --git a/src/diagnostic.c b/src/diagnostic.c index 1159d9eabc..248abd41b1 100644 --- a/src/diagnostic.c +++ b/src/diagnostic.c @@ -15,9 +15,9 @@ void print_diagnostics(session_t *ps, const char *config_file, bool compositor_r printf("**Version:** " PICOM_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->has_shape ? "Yes" : "No"); + printf("* RandR: %s\n", ps->has_randr ? "Yes" : "No"); + printf("* Present: %s\n", ps->has_present ? "Yes" : "No"); 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 afaa02c490..5ec37f3fd1 100644 --- a/src/event.c +++ b/src/event.c @@ -93,7 +93,7 @@ static inline xcb_window_t attr_pure ev_window(session_t *ps, xcb_generic_event_ return ((xcb_damage_notify_event_t *)ev)->drawable; } - if (ps->shape_exists && ev->response_type == ps->shape_event) { + if (ps->has_shape && ev->response_type == ps->shape_event) { return ((xcb_shape_notify_event_t *)ev)->affected_window; } @@ -125,12 +125,12 @@ static inline const char *ev_name(session_t *ps, xcb_generic_event_t *ev) { return "Damage"; } - if (ps->shape_exists && ev->response_type == ps->shape_event) { + if (ps->has_shape && ev->response_type == ps->shape_event) { return "ShapeNotify"; } - if (ps->xsync_exists) { - int o = ev->response_type - ps->xsync_event; + if (ps->has_sync) { + int o = ev->response_type - ps->sync_event; switch (o) { CASESTRRET(XSyncCounterNotify); CASESTRRET(XSyncAlarmNotify); @@ -735,11 +735,11 @@ void ev_handle(session_t *ps, xcb_generic_event_t *ev) { break; case 0: ev_xcb_error(ps, (xcb_generic_error_t *)ev); break; default: - if (ps->shape_exists && ev->response_type == ps->shape_event) { + if (ps->has_shape && ev->response_type == ps->shape_event) { ev_shape_notify(ps, (xcb_shape_notify_event_t *)ev); break; } - if (ps->randr_exists && + if (ps->has_randr && ev->response_type == (ps->randr_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY)) { set_root_flags(ps, ROOT_FLAGS_SCREEN_CHANGE); break; diff --git a/src/meson.build b/src/meson.build index 0cd87c896d..514240a55b 100644 --- a/src/meson.build +++ b/src/meson.build @@ -15,12 +15,14 @@ picom_inc = include_directories('.') cflags = [] required_xcb_packages = [ - 'xcb-render', 'xcb-damage', 'xcb-randr', 'xcb-sync', 'xcb-composite', - 'xcb-shape', 'xcb-xfixes', 'xcb-present', 'xcb-glx', 'xcb-dpms', 'xcb' + 'xcb', 'xcb-composite', 'xcb-damage', 'xcb-dpms', 'xcb-glx', 'xcb-present', + 'xcb-randr', 'xcb-render', 'xcb-shape', 'xcb-sync', 'xcb-xfixes' ] +# xcb-image and xcb-renderutil are here because their versioning doesn't match +# other xcb packages versioning (checked below) required_packages = [ - 'x11', 'x11-xcb', 'xcb-renderutil', 'xcb-image', 'xext', 'pixman-1' + 'pixman-1', 'x11', 'x11-xcb', 'xcb-image', 'xcb-renderutil', 'xext' ] foreach i : required_packages diff --git a/src/opengl.c b/src/opengl.c index 5d2d66cb8c..51fda0434d 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -50,7 +50,7 @@ bool glx_init(session_t *ps, bool need_render) { XVisualInfo *pvis = NULL; // Check for GLX extension - if (!ps->glx_exists) { + if (!ps->has_glx) { log_error("No GLX extension."); goto glx_init_end; } diff --git a/src/picom.c b/src/picom.c index 8a7a967039..cf08e21045 100644 --- a/src/picom.c +++ b/src/picom.c @@ -14,10 +14,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -29,9 +31,6 @@ #include #include -#include -#include - #include "common.h" #include "compiler.h" #include "config.h" @@ -1677,6 +1676,7 @@ static session_t *session_init(int argc, char **argv, Display *dpy, #ifdef CONFIG_OPENGL .glx_prog_win = GLX_PROG_MAIN_INIT, #endif + .sync_fence = XCB_NONE, .redirected = false, .alpha_picts = NULL, .fade_time = 0L, @@ -1701,25 +1701,23 @@ static session_t *session_init(int argc, char **argv, Display *dpy, .drm_fd = -1, #endif - .xfixes_event = 0, - .xfixes_error = 0, .damage_event = 0, .damage_error = 0, - .render_event = 0, + .has_glx = false, + .glx_error = 0, + .has_present = false, + .has_randr = false, + .randr_event = 0, + .randr_nmonitors = 0, + .randr_monitor_regs = NULL, .render_error = 0, - .composite_event = 0, - .composite_error = 0, - .composite_opcode = 0, - .shape_exists = false, + .has_shape = 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, - .xrfilter_convolution_exists = false, + .has_sync = false, + .sync_event = 0, + .sync_error = 0, + .fixes_error = 0, + .has_convolution_xrfilter = false, .atoms_wintypes = {0}, .track_atom_lst = NULL, @@ -1751,8 +1749,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy, ps->dpy = dpy; ps->c = XGetXCBConnection(ps->dpy); - const xcb_query_extension_reply_t *ext_info; - ps->previous_xerror_handler = XSetErrorHandler(xerror); ps->scr = DefaultScreen(ps->dpy); @@ -1777,99 +1773,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy, free(e); } - xcb_prefetch_extension_data(ps->c, &xcb_render_id); - xcb_prefetch_extension_data(ps->c, &xcb_composite_id); - xcb_prefetch_extension_data(ps->c, &xcb_damage_id); - xcb_prefetch_extension_data(ps->c, &xcb_shape_id); - xcb_prefetch_extension_data(ps->c, &xcb_xfixes_id); - xcb_prefetch_extension_data(ps->c, &xcb_randr_id); - xcb_prefetch_extension_data(ps->c, &xcb_present_id); - xcb_prefetch_extension_data(ps->c, &xcb_sync_id); - xcb_prefetch_extension_data(ps->c, &xcb_glx_id); - xcb_prefetch_extension_data(ps->c, &xcb_dpms_id); - - ext_info = xcb_get_extension_data(ps->c, &xcb_render_id); - if (!ext_info || !ext_info->present) { - 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, &xcb_composite_id); - if (!ext_info || !ext_info->present) { - 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( - ps->c, - xcb_composite_query_version(ps->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, &xcb_damage_id); - if (!ext_info || !ext_info->present) { - log_fatal("No damage extension"); - exit(1); - } - ps->damage_event = ext_info->first_event; - ps->damage_error = ext_info->first_error; - xcb_discard_reply(ps->c, xcb_damage_query_version(ps->c, XCB_DAMAGE_MAJOR_VERSION, - XCB_DAMAGE_MINOR_VERSION) - .sequence); - - ext_info = xcb_get_extension_data(ps->c, &xcb_xfixes_id); - if (!ext_info || !ext_info->present) { - 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, xcb_xfixes_query_version(ps->c, XCB_XFIXES_MAJOR_VERSION, - XCB_XFIXES_MINOR_VERSION) - .sequence); - - ps->damaged_region = x_new_id(ps->c); - if (!XCB_AWAIT_VOID(xcb_xfixes_create_region, ps->c, ps->damaged_region, 0, NULL)) { - log_fatal("Failed to create a XFixes region"); - goto err; - } - - ext_info = xcb_get_extension_data(ps->c, &xcb_glx_id); - if (ext_info && ext_info->present) { - ps->glx_exists = true; - ps->glx_error = ext_info->first_error; - ps->glx_event = ext_info->first_event; - } - - ext_info = xcb_get_extension_data(ps->c, &xcb_dpms_id); - ps->dpms_exists = ext_info && ext_info->present; - if (ps->dpms_exists) { - auto r = xcb_dpms_info_reply(ps->c, xcb_dpms_info(ps->c), NULL); - if (!r) { - log_fatal("Failed to query DPMS info"); - goto err; - } - ps->screen_is_off = dpms_screen_is_off(r); - // Check screen status every half second - ev_timer_init(&ps->dpms_check_timer, check_dpms_status, 0, 0.5); - ev_timer_start(ps->loop, &ps->dpms_check_timer); - free(r); - } - // Parse configuration file win_option_mask_t winopt_mask[NUM_WINTYPES] = {{0}}; bool shadow_enabled = false, fading_enable = false, hasneg = false; @@ -1973,76 +1876,163 @@ static session_t *session_init(int argc, char **argv, Display *dpy, rebuild_shadow_exclude_reg(ps); - // Query X Shape - ext_info = xcb_get_extension_data(ps->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; + // Query the X Composite extension + xcb_prefetch_extension_data(ps->c, &xcb_composite_id); + const xcb_query_extension_reply_t *ext_data = + xcb_get_extension_data(ps->c, &xcb_composite_id); + if (ext_data && ext_data->present) { + xcb_composite_query_version_reply_t *r = xcb_composite_query_version_reply( + ps->c, + xcb_composite_query_version(ps->c, XCB_COMPOSITE_MAJOR_VERSION, + XCB_COMPOSITE_MINOR_VERSION), + NULL); + if (!r || (r->major_version == 0 && r->minor_version < 2)) { + log_fatal("The X server doesn't support the X Composite " + "extension 0.2."); + goto err; + } + free(r); + } else { + log_fatal("No X Composite extension."); + goto err; } - ext_info = xcb_get_extension_data(ps->c, &xcb_randr_id); - if (ext_info && ext_info->present) { - ps->randr_exists = true; - ps->randr_event = ext_info->first_event; - ps->randr_error = ext_info->first_error; + // Query the X Damage extension + xcb_prefetch_extension_data(ps->c, &xcb_damage_id); + ext_data = xcb_get_extension_data(ps->c, &xcb_damage_id); + if (ext_data && ext_data->present) { + xcb_discard_reply(ps->c, xcb_damage_query_version(ps->c, XCB_DAMAGE_MAJOR_VERSION, + XCB_DAMAGE_MINOR_VERSION) + .sequence); + ps->damage_event = ext_data->first_event; + ps->damage_error = ext_data->first_error; + } else { + log_fatal("No X Damage extension."); + goto err; } - ext_info = xcb_get_extension_data(ps->c, &xcb_present_id); - if (ext_info && ext_info->present) { - auto r = xcb_present_query_version_reply( - ps->c, - xcb_present_query_version(ps->c, XCB_PRESENT_MAJOR_VERSION, - XCB_PRESENT_MINOR_VERSION), - NULL); - if (r) { - ps->present_exists = true; - free(r); + // Query the X DPMS extension + xcb_prefetch_extension_data(ps->c, &xcb_dpms_id); + ext_data = xcb_get_extension_data(ps->c, &xcb_dpms_id); + if (ext_data && ext_data->present) { + xcb_dpms_info_reply_t *r = + xcb_dpms_info_reply(ps->c, xcb_dpms_info(ps->c), NULL); + if (!r) { + log_fatal("Failed to get information about the current DPMS " + "state of the display."); + goto err; + } + ps->screen_is_off = dpms_screen_is_off(r); + free(r); + + // Check the DPMS status every half a second + ev_timer_init(&ps->dpms_check_timer, check_dpms_status, 0, 0.5); + ev_timer_start(ps->loop, &ps->dpms_check_timer); + } + + // Query the X GLX extension + xcb_prefetch_extension_data(ps->c, &xcb_glx_id); + ext_data = xcb_get_extension_data(ps->c, &xcb_glx_id); + if (ext_data && ext_data->present) { + ps->has_glx = true; + ps->glx_error = ext_data->first_error; + } + + // Query the X Present extension + xcb_prefetch_extension_data(ps->c, &xcb_present_id); + ext_data = xcb_get_extension_data(ps->c, &xcb_present_id); + if (ext_data && ext_data->present) { + ps->has_present = true; + } + + // Query the X RandR extension + xcb_prefetch_extension_data(ps->c, &xcb_randr_id); + ext_data = xcb_get_extension_data(ps->c, &xcb_randr_id); + if (ext_data && ext_data->present) { + ps->has_randr = true; + ps->randr_event = ext_data->first_event; + + if (ps->o.crop_shadow_to_monitor) { + xcb_randr_select_input(ps->c, ps->root, + XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE); } + x_update_randr_monitors(ps); + } else if (ps->o.crop_shadow_to_monitor) { + log_fatal("No X RandR extension, the crop-shadow-to-monitor option can't " + "be enabled."); + goto err; + } + + // Query the X Render extension + xcb_prefetch_extension_data(ps->c, &xcb_render_id); + ext_data = xcb_get_extension_data(ps->c, &xcb_render_id); + if (ext_data && ext_data->present) { + ps->render_error = ext_data->first_error; + } else { + log_fatal("No X Render extension."); + goto err; + } + + // Query the X Shape extension + xcb_prefetch_extension_data(ps->c, &xcb_shape_id); + ext_data = xcb_get_extension_data(ps->c, &xcb_shape_id); + if (ext_data && ext_data->present) { + ps->has_shape = true; + ps->shape_event = ext_data->first_event; } - // Query X Sync - ext_info = xcb_get_extension_data(ps->c, &xcb_sync_id); - if (ext_info && ext_info->present) { - ps->xsync_error = ext_info->first_error; - ps->xsync_event = ext_info->first_event; - // Need X Sync 3.1 for fences - auto r = xcb_sync_initialize_reply( + // Query the X Sync extension + xcb_prefetch_extension_data(ps->c, &xcb_sync_id); + ext_data = xcb_get_extension_data(ps->c, &xcb_sync_id); + if (ext_data && ext_data->present) { + // The X Sync extension 3.1 is required for fences + xcb_sync_initialize_reply_t *r = xcb_sync_initialize_reply( ps->c, xcb_sync_initialize(ps->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->xsync_exists = true; + if (r && ((r->major_version == 3 && r->minor_version >= 1) || + r->major_version > 3)) { + ps->has_sync = true; + ps->sync_event = ext_data->first_event; + ps->sync_error = ext_data->first_error; free(r); - } - } - ps->sync_fence = XCB_NONE; - if (ps->xsync_exists) { - ps->sync_fence = x_new_id(ps->c); - e = xcb_request_check(ps->c, xcb_sync_create_fence_checked( - ps->c, ps->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"); + ps->sync_fence = x_new_id(ps->c); + e = xcb_request_check( + ps->c, xcb_sync_create_fence_checked(ps->c, ps->root, + ps->sync_fence, false)); + if (e && ps->o.xrender_sync_fence) { + log_error_x_error(e, "Failed to create an X Sync fence, " + "the xrender-sync-fence option will " + "be disabled."); ps->o.xrender_sync_fence = false; + ps->sync_fence = XCB_NONE; + free(e); } - ps->sync_fence = XCB_NONE; - free(e); } } else if (ps->o.xrender_sync_fence) { - log_error("XSync extension not found. No XSync fence sync is " - "possible. (xrender-sync-fence can't be enabled)"); + log_warn("No X Sync extension, the xrender-sync-fence option can't be " + "enabled."); ps->o.xrender_sync_fence = false; } - // Query X RandR - if (ps->o.crop_shadow_to_monitor && !ps->randr_exists) { - log_fatal("No X RandR extension. crop-shadow-to-monitor cannot be " - "enabled."); + // Query the X Fixes extension + xcb_prefetch_extension_data(ps->c, &xcb_xfixes_id); + ext_data = xcb_get_extension_data(ps->c, &xcb_xfixes_id); + if (ext_data && ext_data->present) { + xcb_discard_reply(ps->c, xcb_xfixes_query_version(ps->c, XCB_XFIXES_MAJOR_VERSION, + XCB_XFIXES_MINOR_VERSION) + .sequence); + ps->fixes_error = ext_data->first_error; + + ps->damaged_region = x_new_id(ps->c); + if (!XCB_AWAIT_VOID(xcb_xfixes_create_region, ps->c, ps->damaged_region, + 0, NULL)) { + log_fatal("Failed to create an X Fixes region."); + goto err; + } + } else { + log_fatal("No X Fixes extension."); goto err; } @@ -2137,14 +2127,6 @@ 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 && ps->o.crop_shadow_to_monitor) { - xcb_randr_select_input(ps->c, ps->root, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE); - } - - x_update_randr_monitors(ps); - { xcb_render_create_picture_value_list_t pa = { .subwindowmode = IncludeInferiors, diff --git a/src/render.c b/src/render.c index afde7db82b..fe2050ca79 100644 --- a/src/render.c +++ b/src/render.c @@ -971,13 +971,13 @@ win_blur_background(session_t *ps, struct managed_win *w, xcb_render_picture_t t /// region_real = the damage region void paint_all(session_t *ps, struct managed_win *t, bool ignore_damage) { if (ps->o.xrender_sync_fence || (ps->drivers & DRIVER_NVIDIA)) { - if (ps->xsync_exists && !x_fence_sync(ps->c, ps->sync_fence)) { + if (ps->has_sync && !x_fence_sync(ps->c, ps->sync_fence)) { log_error("x_fence_sync failed, xrender-sync-fence will be " "disabled from now on."); xcb_sync_destroy_fence(ps->c, ps->sync_fence); ps->sync_fence = XCB_NONE; ps->o.xrender_sync_fence = false; - ps->xsync_exists = false; + ps->has_sync = false; } } @@ -1315,13 +1315,13 @@ static bool xr_init_blur(session_t *ps) { // Check for the convolution filter if (strlen(XRFILTER_CONVOLUTION) == len && !memcmp(XRFILTER_CONVOLUTION, name, strlen(XRFILTER_CONVOLUTION))) - ps->xrfilter_convolution_exists = true; + ps->has_convolution_xrfilter = true; } free(pf); } // Turn features off if any required filter is not present - if (!ps->xrfilter_convolution_exists) { + if (!ps->has_convolution_xrfilter) { log_error("Xrender convolution filter " "unsupported by your X server. " "Background blur is not possible."); diff --git a/src/win.c b/src/win.c index a97733dbd4..e4eb41b445 100644 --- a/src/win.c +++ b/src/win.c @@ -694,7 +694,7 @@ static int win_update_role(session_t *ps, struct managed_win *w) { * Check if a window is bounding-shaped. */ static inline bool win_bounding_shaped(const session_t *ps, xcb_window_t wid) { - if (ps->shape_exists) { + if (ps->has_shape) { xcb_shape_query_extents_reply_t *reply; Bool bounding_shaped; @@ -1688,7 +1688,7 @@ struct win *fill_win(session_t *ps, struct win *w) { (const uint32_t[]){determine_evmask(ps, new->base.id, WIN_EVMODE_FRAME)}); // Get notification when the shape of a window changes - if (ps->shape_exists) { + if (ps->has_shape) { xcb_shape_select_input(ps->c, new->base.id, 1); } @@ -1931,7 +1931,7 @@ gen_by_val(win_extents); * Mark the window shape as updated */ void win_update_bounding_shape(session_t *ps, struct managed_win *w) { - if (ps->shape_exists) { + if (ps->has_shape) { w->bounding_shaped = win_bounding_shaped(ps, w->base.id); } @@ -2094,7 +2094,7 @@ void win_ev_stop(session_t *ps, const struct win *w) { (const uint32_t[]){0}); } - if (ps->shape_exists) { + if (ps->has_shape) { xcb_shape_select_input(ps->c, w->id, 0); } } diff --git a/src/x.c b/src/x.c index 6121e77344..2c961919e7 100644 --- a/src/x.c +++ b/src/x.c @@ -489,7 +489,7 @@ _x_strerror(unsigned long serial, uint8_t major, uint16_t minor, uint8_t error_c 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->fixes_error; switch (o) { CASESTRRET2(XFIXES_BAD_REGION); } o = error_code - ps->damage_error; @@ -504,7 +504,7 @@ _x_strerror(unsigned long serial, uint8_t major, uint16_t minor, uint8_t error_c CASESTRRET2(RENDER_GLYPH); } - if (ps->glx_exists) { + if (ps->has_glx) { o = error_code - ps->glx_error; switch (o) { CASESTRRET2(GLX_BAD_CONTEXT); @@ -524,8 +524,8 @@ _x_strerror(unsigned long serial, uint8_t major, uint16_t minor, uint8_t error_c } } - if (ps->xsync_exists) { - o = error_code - ps->xsync_error; + if (ps->has_sync) { + o = error_code - ps->sync_error; switch (o) { CASESTRRET(XSyncBadCounter); CASESTRRET(XSyncBadAlarm); @@ -792,7 +792,7 @@ xcb_screen_t *x_screen_of_display(xcb_connection_t *c, int screen) { void x_update_randr_monitors(session_t *ps) { x_free_randr_info(ps); - if (!ps->o.crop_shadow_to_monitor || !ps->randr_exists) { + if (!ps->o.crop_shadow_to_monitor || !ps->has_randr) { return; }