diff --git a/src/event.c b/src/event.c index a1ca7fc7..19feb3e3 100644 --- a/src/event.c +++ b/src/event.c @@ -834,9 +834,9 @@ void ev_handle(session_t *ps, xcb_generic_event_t *ev) { ev_shape_notify(ps, (xcb_shape_notify_event_t *)ev); break; } - if (ps->randr_exists && + if (ps->randr_exists && ps->o.crop_shadow_to_monitor && ev->response_type == (ps->randr_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY)) { - set_root_flags(ps, ROOT_FLAGS_SCREEN_CHANGE); + x_update_monitors_async(&ps->c, &ps->monitors); break; } if (ps->damage_event + XCB_DAMAGE_NOTIFY == ev->response_type) { diff --git a/src/picom.c b/src/picom.c index e94eafac..b9f5250c 100644 --- a/src/picom.c +++ b/src/picom.c @@ -734,13 +734,6 @@ static void configure_root(session_t *ps) { } static void handle_root_flags(session_t *ps) { - if ((ps->root_flags & ROOT_FLAGS_SCREEN_CHANGE) != 0) { - if (ps->o.crop_shadow_to_monitor && ps->randr_exists) { - x_update_monitors(&ps->c, &ps->monitors); - } - ps->root_flags &= ~(uint64_t)ROOT_FLAGS_SCREEN_CHANGE; - } - if ((ps->root_flags & ROOT_FLAGS_CONFIGURED) != 0) { configure_root(ps); ps->root_flags &= ~(uint64_t)ROOT_FLAGS_CONFIGURED; @@ -2330,7 +2323,7 @@ static session_t *session_init(int argc, char **argv, Display *dpy, if (ps->randr_exists && ps->o.crop_shadow_to_monitor) { xcb_randr_select_input(ps->c.c, ps->c.screen_info->root, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE); - x_update_monitors(&ps->c, &ps->monitors); + x_update_monitors_async(&ps->c, &ps->monitors); } { diff --git a/src/picom.h b/src/picom.h index f6f7b309..9be745e0 100644 --- a/src/picom.h +++ b/src/picom.h @@ -25,8 +25,6 @@ #include "x.h" enum root_flags { - ROOT_FLAGS_SCREEN_CHANGE = 1, // Received RandR screen change notify, we - // use this to track refresh rate changes ROOT_FLAGS_CONFIGURED = 2 // Received configure notify on the root window }; diff --git a/src/x.c b/src/x.c index 62913069..538eab63 100644 --- a/src/x.c +++ b/src/x.c @@ -904,25 +904,43 @@ struct xvisual_info x_get_visual_info(struct x_connection *c, xcb_visualid_t vis }; } -void x_update_monitors(struct x_connection *c, struct x_monitors *m) { - x_free_monitor_info(m); +struct x_update_monitors_request { + struct x_async_request_base base; + struct x_monitors *monitors; +}; - xcb_randr_get_monitors_reply_t *r = xcb_randr_get_monitors_reply( - c->c, xcb_randr_get_monitors(c->c, c->screen_info->root, true), NULL); - if (!r) { +static void x_handle_update_monitors_reply(struct x_connection * /*c*/, + struct x_async_request_base *req_base, + xcb_raw_generic_event_t *reply_or_error) { + auto m = ((struct x_update_monitors_request *)req_base)->monitors; + free(req_base); + + 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)); return; } - m->count = xcb_randr_get_monitors_monitors_length(r); + x_free_monitor_info(m); + + auto reply = (xcb_randr_get_monitors_reply_t *)reply_or_error; + + m->count = xcb_randr_get_monitors_monitors_length(reply); m->regions = ccalloc(m->count, region_t); xcb_randr_monitor_info_iterator_t monitor_info_it = - xcb_randr_get_monitors_monitors_iterator(r); + xcb_randr_get_monitors_monitors_iterator(reply); for (int i = 0; monitor_info_it.rem; xcb_randr_monitor_info_next(&monitor_info_it)) { xcb_randr_monitor_info_t *mi = monitor_info_it.data; pixman_region32_init_rect(&m->regions[i++], mi->x, mi->y, mi->width, mi->height); } +} - free(r); +void x_update_monitors_async(struct x_connection *c, struct x_monitors *m) { + auto req = ccalloc(1, struct x_update_monitors_request); + req->base.callback = x_handle_update_monitors_reply; + req->base.sequence = xcb_randr_get_monitors(c->c, c->screen_info->root, 1).sequence; + req->monitors = m; + x_await_request(c, &req->base); } void x_free_monitor_info(struct x_monitors *m) { diff --git a/src/x.h b/src/x.h index 6afc5ddc..68bedccb 100644 --- a/src/x.h +++ b/src/x.h @@ -419,8 +419,8 @@ xcb_visualid_t x_get_visual_for_depth(xcb_screen_t *screen, uint8_t depth); xcb_render_pictformat_t x_get_pictfmt_for_standard(struct x_connection *c, xcb_pict_standard_t std); -/// Populates a `struct x_monitors` with the current monitor configuration. -void x_update_monitors(struct x_connection *, struct x_monitors *); +/// Populates a `struct x_monitors` with the current monitor configuration asynchronously. +void x_update_monitors_async(struct x_connection *, struct x_monitors *); /// Free memory allocated for a `struct x_monitors`. void x_free_monitor_info(struct x_monitors *);