From 3c5d7555a46af04d6b210e1c21222083c80182f0 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 3 Oct 2018 13:51:00 +0200 Subject: [PATCH 01/18] XCBify X{Unm,M}apWindow Signed-off-by: Uli Schlachter --- src/compton.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/compton.c b/src/compton.c index 44f9cd2..c100b15 100644 --- a/src/compton.c +++ b/src/compton.c @@ -1995,7 +1995,7 @@ map_win(session_t *ps, Window id) { // Unmap overlay window if it got mapped but we are currently not // in redirected state. if (ps->overlay && id == ps->overlay && !ps->redirected) { - XUnmapWindow(ps->dpy, ps->overlay); + xcb_unmap_window(c, ps->overlay); XFlush(ps->dpy); } @@ -4550,7 +4550,7 @@ init_overlay(session_t *ps) { // Unmap overlay, firstly. But this typically does not work because // the window isn't created yet. - // XUnmapWindow(ps->dpy, ps->overlay); + // xcb_unmap_window(c, ps->overlay); // XFlush(ps->dpy); } else { @@ -4626,7 +4626,7 @@ redir_start(session_t *ps) { // Map overlay window. Done firstly according to this: // https://bugzilla.gnome.org/show_bug.cgi?id=597014 if (ps->overlay) - XMapWindow(ps->dpy, ps->overlay); + xcb_map_window(c, ps->overlay); xcb_composite_redirect_subwindows(c, ps->root, XCB_COMPOSITE_REDIRECT_MANUAL); @@ -4669,7 +4669,7 @@ redir_stop(session_t *ps) { xcb_composite_unredirect_subwindows(c, ps->root, XCB_COMPOSITE_REDIRECT_MANUAL); // Unmap overlay window if (ps->overlay) - XUnmapWindow(ps->dpy, ps->overlay); + xcb_unmap_window(c, ps->overlay); // Must call XSync() here XSync(ps->dpy, False); From b86190452cba3aae8e515dc1c1ce9459af1d259e Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 3 Oct 2018 13:52:52 +0200 Subject: [PATCH 02/18] XCBify X{Ung,G}abServer Signed-off-by: Uli Schlachter --- src/compton.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compton.c b/src/compton.c index c100b15..ced81eb 100644 --- a/src/compton.c +++ b/src/compton.c @@ -5389,7 +5389,7 @@ session_init(session_t *ps_old, int argc, char **argv) { ev_set_priority(&ps->event_check->w, EV_MINPRI); ev_prepare_start(ps->loop, &ps->event_check->w); - XGrabServer(ps->dpy); + xcb_grab_server(c); { Window root_return, parent_return; @@ -5410,8 +5410,8 @@ session_init(session_t *ps_old, int argc, char **argv) { recheck_focus(ps); } - XUngrabServer(ps->dpy); - // ALWAYS flush after XUngrabServer()! + xcb_ungrab_server(c); + // ALWAYS flush after xcb_ungrab_server()! XFlush(ps->dpy); // Initialize DBus From 28e9488e25f3a6581d791b0fdd5089bf271a81d0 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 3 Oct 2018 14:01:18 +0200 Subject: [PATCH 03/18] XCBify XCreateGC and XFreeGC Signed-off-by: Uli Schlachter --- src/compton.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/compton.c b/src/compton.c index ced81eb..ed51af0 100644 --- a/src/compton.c +++ b/src/compton.c @@ -659,7 +659,7 @@ win_build_shadow(session_t *ps, win *w, double opacity) { xcb_image_t *shadow_image = NULL; xcb_pixmap_t shadow_pixmap = None, shadow_pixmap_argb = None; xcb_render_picture_t shadow_picture = None, shadow_picture_argb = None; - GC gc = None; + xcb_gcontext_t gc = None; xcb_connection_t *c = XGetXCBConnection(ps->dpy); shadow_image = make_shadow(ps, opacity, width, height); @@ -683,13 +683,10 @@ win_build_shadow(session_t *ps, win *w, double opacity) { if (!shadow_picture || !shadow_picture_argb) goto shadow_picture_err; - gc = XCreateGC(ps->dpy, shadow_pixmap, 0, 0); - if (!gc) { - printf_errf("(): failed to create graphic context"); - goto shadow_picture_err; - } + gc = xcb_generate_id(c); + xcb_create_gc(c, gc, shadow_pixmap, 0, NULL); - xcb_image_put(c, shadow_pixmap, XGContextFromGC(gc), shadow_image, 0, 0, 0); + xcb_image_put(c, shadow_pixmap, gc, shadow_image, 0, 0, 0); xcb_render_composite(c, XCB_RENDER_PICT_OP_SRC, ps->cshadow_picture, shadow_picture, shadow_picture_argb, 0, 0, 0, 0, 0, 0, shadow_image->width, shadow_image->height); @@ -702,7 +699,7 @@ win_build_shadow(session_t *ps, win *w, double opacity) { // Sync it once and only once xr_sync(ps, w->shadow_paint.pixmap, NULL); - XFreeGC(ps->dpy, gc); + xcb_free_gc(c, gc); xcb_image_destroy(shadow_image); xcb_free_pixmap(c, shadow_pixmap); xcb_render_free_picture(c, shadow_picture); @@ -721,7 +718,7 @@ shadow_picture_err: if (shadow_picture_argb) xcb_render_free_picture(c, shadow_picture_argb); if (gc) - XFreeGC(ps->dpy, gc); + xcb_free_gc(c, gc); return false; } From e30ff25dd31cdc4bf63a9a0a8f2a4c549d38e341 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 3 Oct 2018 14:02:49 +0200 Subject: [PATCH 04/18] Replace XClearArea with xcb_clear_area Signed-off-by: Uli Schlachter --- src/compton.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compton.c b/src/compton.c index ed51af0..41192f8 100644 --- a/src/compton.c +++ b/src/compton.c @@ -2415,7 +2415,8 @@ destroy_win(session_t *ps, Window id) { static inline void root_damaged(session_t *ps) { if (ps->root_tile_paint.pixmap) { - XClearArea(ps->dpy, ps->root, 0, 0, 0, 0, true); + xcb_connection_t *c = XGetXCBConnection(ps->dpy); + xcb_clear_area(c, true, ps->root, 0, 0, 0, 0); free_root_tile(ps); } From 0cae42faaae1ae4b4bfc2c9edad1c18e4c06853c Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 3 Oct 2018 14:05:33 +0200 Subject: [PATCH 05/18] Replace XDestroyWindow with xcb_destroy_window Signed-off-by: Uli Schlachter --- src/compton.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compton.c b/src/compton.c index 41192f8..78a6f75 100644 --- a/src/compton.c +++ b/src/compton.c @@ -5603,7 +5603,7 @@ session_destroy(session_t *ps) { // Free reg_win if (ps->reg_win) { - XDestroyWindow(ps->dpy, ps->reg_win); + xcb_destroy_window(c, ps->reg_win); ps->reg_win = None; } From a192bfb1302d3db8383936944b047a90ca886724 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 3 Oct 2018 14:06:41 +0200 Subject: [PATCH 06/18] Replace XSetSelectionOwner with XCB Note that the argument order is different between Xlib and XCB. Signed-off-by: Uli Schlachter --- src/compton.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compton.c b/src/compton.c index 78a6f75..ca1c8e3 100644 --- a/src/compton.c +++ b/src/compton.c @@ -3565,7 +3565,7 @@ register_cm(session_t *ps) { fprintf(stderr, "Another composite manager is already running\n"); return false; } - XSetSelectionOwner(ps->dpy, atom, ps->reg_win, 0); + xcb_set_selection_owner(c, ps->reg_win, atom, 0); free(buf); } From 8db6473d32d7d6ed03c812c6071407b2b2aeaedf Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 3 Oct 2018 14:13:59 +0200 Subject: [PATCH 07/18] Convert property management to XCB I removed the error checking in compton.c because it was dead code. XChangeProperty() always returns 1. Signed-off-by: Uli Schlachter --- src/compton.c | 9 +++------ src/win.c | 10 ++++++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/compton.c b/src/compton.c index ca1c8e3..2ca970c 100644 --- a/src/compton.c +++ b/src/compton.c @@ -3532,12 +3532,9 @@ register_cm(session_t *ps) { // Set _NET_WM_PID { - long pid = getpid(); - if (!XChangeProperty(ps->dpy, ps->reg_win, - get_atom(ps, "_NET_WM_PID"), XCB_ATOM_CARDINAL, 32, PropModeReplace, - (unsigned char *) &pid, 1)) { - printf_errf("(): Failed to set _NET_WM_PID."); - } + uint32_t pid = getpid(); + xcb_change_property(c, XCB_PROP_MODE_REPLACE, ps->reg_win, + get_atom(ps, "_NET_WM_PID"), XCB_ATOM_CARDINAL, 32, 1, &pid); } // Set COMPTON_VERSION diff --git a/src/win.c b/src/win.c index 38e35a5..91bd4b1 100644 --- a/src/win.c +++ b/src/win.c @@ -27,14 +27,16 @@ clear_cache_win_leaders(session_t *ps) { static inline void wid_set_opacity_prop(session_t *ps, Window wid, opacity_t val) { - const unsigned long v = val; - XChangeProperty(ps->dpy, wid, ps->atom_opacity, XCB_ATOM_CARDINAL, 32, - PropModeReplace, (unsigned char *) &v, 1); + const uint32_t v = val; + xcb_connection_t *c = XGetXCBConnection(ps->dpy); + xcb_change_property(c, XCB_PROP_MODE_REPLACE, wid, ps->atom_opacity, + XCB_ATOM_CARDINAL, 32, 1, &v); } static inline void wid_rm_opacity_prop(session_t *ps, Window wid) { - XDeleteProperty(ps->dpy, wid, ps->atom_opacity); + xcb_connection_t *c = XGetXCBConnection(ps->dpy); + xcb_delete_property(c, wid, ps->atom_opacity); } /** From 2dc90e7d4da36db8985ae57475395124296bcebf Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 3 Oct 2018 14:17:08 +0200 Subject: [PATCH 08/18] Convert XGetInputFocus to XCB Signed-off-by: Uli Schlachter --- src/compton.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/compton.c b/src/compton.c index 2ca970c..c6a8aed 100644 --- a/src/compton.c +++ b/src/compton.c @@ -870,10 +870,15 @@ recheck_focus(session_t *ps) { // Determine the currently focused window so we can apply appropriate // opacity on it - Window wid = 0; - int revert_to; + xcb_connection_t *c = XGetXCBConnection(ps->dpy); + xcb_window_t wid = XCB_NONE; + xcb_get_input_focus_reply_t *reply = + xcb_get_input_focus_reply(c, xcb_get_input_focus(c), NULL); - XGetInputFocus(ps->dpy, &wid, &revert_to); + if (reply) { + wid = reply->focus; + free(reply); + } win *w = find_win_all(ps, wid); From 1b1b3456bc88a71b932b102d725c5ad29ed408d0 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 3 Oct 2018 14:20:33 +0200 Subject: [PATCH 09/18] Convert XGetSelectionOwner to XCB This also fixes a memory leak: buf was not freed if another composite manager was already running. Signed-off-by: Uli Schlachter --- src/compton.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/compton.c b/src/compton.c index c6a8aed..9f131a3 100644 --- a/src/compton.c +++ b/src/compton.c @@ -3562,13 +3562,19 @@ register_cm(session_t *ps) { snprintf(buf, len, REGISTER_PROP "%d", ps->scr); buf[len - 1] = '\0'; atom = get_atom(ps, buf); + free(buf); - if (XGetSelectionOwner(ps->dpy, atom) != None) { + xcb_get_selection_owner_reply_t *reply = + xcb_get_selection_owner_reply(c, + xcb_get_selection_owner(c, atom), NULL); + + if (reply && reply->owner != XCB_NONE) { + free(reply); fprintf(stderr, "Another composite manager is already running\n"); return false; } + free(reply); xcb_set_selection_owner(c, ps->reg_win, atom, 0); - free(buf); } return true; From 2da0ecdf668a26dc1ad3fbc73fb2cd517a131f64 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 3 Oct 2018 14:34:24 +0200 Subject: [PATCH 10/18] Convert XSelectInput() to XCB Signed-off-by: Uli Schlachter Signed-off-by: Yuxuan Shui --- src/compton.c | 42 ++++++++++++++++++++++++------------------ src/compton.h | 8 ++++---- src/win.c | 11 +++++++---- 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/src/compton.c b/src/compton.c index 9f131a3..5698e56 100644 --- a/src/compton.c +++ b/src/compton.c @@ -2019,9 +2019,10 @@ map_win(session_t *ps, Window id) { cxinerama_win_upd_scr(ps, w); - // Call XSelectInput() before reading properties so that no property + // Set window event mask before reading properties so that no property // changes are lost - XSelectInput(ps->dpy, id, determine_evmask(ps, id, WIN_EVMODE_FRAME)); + xcb_change_window_attributes(c, id, XCB_CW_EVENT_MASK, + (const uint32_t[]) { determine_evmask(ps, id, WIN_EVMODE_FRAME) }); // Notify compton when the shape of a window changes if (ps->shape_exists) { @@ -2527,14 +2528,15 @@ opts_init_track_focus(session_t *ps) { if (ps->o.track_focus) return; + xcb_connection_t *c = XGetXCBConnection(ps->dpy); ps->o.track_focus = true; if (!ps->o.use_ewmh_active_win) { // Start listening to FocusChange events for (win *w = ps->list; w; w = w->next) if (IsViewable == w->a.map_state) - XSelectInput(ps->dpy, w->id, - determine_evmask(ps, w->id, WIN_EVMODE_FRAME)); + xcb_change_window_attributes(c, w->id, XCB_CW_EVENT_MASK, + (const uint32_t[]) { determine_evmask(ps, w->id, WIN_EVMODE_FRAME) }); } // Recheck focus @@ -2750,11 +2752,13 @@ ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t *ev) { if (ev->parent == ps->root) { add_win(ps, ev->window, 0); } else { + xcb_connection_t *c = XGetXCBConnection(ps->dpy); + destroy_win(ps, ev->window); // Reset event mask in case something wrong happens - XSelectInput(ps->dpy, ev->window, - determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN)); + xcb_change_window_attributes(c, ev->window, XCB_CW_EVENT_MASK, + (const uint32_t[]) { determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN) }); // Check if the window is an undetected client window // Firstly, check if it's a known client window @@ -2773,9 +2777,8 @@ ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t *ev) { } // Otherwise, watch for WM_STATE on it else { - XSelectInput(ps->dpy, ev->window, - determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN) - | PropertyChangeMask); + xcb_change_window_attributes(c, ev->window, XCB_CW_EVENT_MASK, (const uint32_t[]) { + determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN) | PropertyChangeMask }); } } } @@ -2833,6 +2836,7 @@ update_ewmh_active_win(session_t *ps) { inline static void ev_property_notify(session_t *ps, xcb_property_notify_event_t *ev) { + xcb_connection_t *c = XGetXCBConnection(ps->dpy); #ifdef DEBUG_EVENTS { // Print out changed atom @@ -2866,8 +2870,8 @@ ev_property_notify(session_t *ps, xcb_property_notify_event_t *ev) { // Check whether it could be a client window if (!find_toplevel(ps, ev->window)) { // Reset event mask anyway - XSelectInput(ps->dpy, ev->window, - determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN)); + xcb_change_window_attributes(c, ev->window, XCB_CW_EVENT_MASK, (const uint32_t[]) { + determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN) }); win *w_top = find_toplevel2(ps, ev->window); // Initialize client_win as early as possible @@ -4548,7 +4552,8 @@ init_overlay(session_t *ps) { } // Listen to Expose events on the overlay - XSelectInput(ps->dpy, ps->overlay, ExposureMask); + xcb_change_window_attributes(c, ps->overlay, XCB_CW_EVENT_MASK, + (const uint32_t[]) { XCB_EVENT_MASK_EXPOSURE }); // Retrieve DamageNotify on root window if we are painting on an // overlay @@ -5104,11 +5109,11 @@ session_init(session_t *ps_old, int argc, char **argv) { // Start listening to events on root earlier to catch all possible // root geometry changes - XSelectInput(ps->dpy, ps->root, - SubstructureNotifyMask - | ExposureMask - | StructureNotifyMask - | PropertyChangeMask); + xcb_change_window_attributes(c, ps->root, XCB_CW_EVENT_MASK, (const uint32_t[]) { + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY + | XCB_EVENT_MASK_EXPOSURE + | XCB_EVENT_MASK_STRUCTURE_NOTIFY + | XCB_EVENT_MASK_PROPERTY_CHANGE }); XFlush(ps->dpy); ps->root_width = DisplayWidth(ps->dpy, ps->scr); @@ -5468,7 +5473,8 @@ session_destroy(session_t *ps) { redir_stop(ps); // Stop listening to events on root window - XSelectInput(ps->dpy, ps->root, 0); + xcb_change_window_attributes(c, ps->root, XCB_CW_EVENT_MASK, + (const uint32_t[]) { 0 }); #ifdef CONFIG_DBUS // Kill DBus connection diff --git a/src/compton.h b/src/compton.h index 85c95d9..bae513d 100644 --- a/src/compton.h +++ b/src/compton.h @@ -312,12 +312,12 @@ win_ev_stop(session_t *ps, win *w) { xcb_connection_t *c = XGetXCBConnection(ps->dpy); // Will get BadWindow if the window is destroyed - set_ignore_next(ps); - XSelectInput(ps->dpy, w->id, 0); + set_ignore_cookie(ps, + xcb_change_window_attributes(c, w->id, XCB_CW_EVENT_MASK, (const uint32_t[]) { 0 })); if (w->client_win) { - set_ignore_next(ps); - XSelectInput(ps->dpy, w->client_win, 0); + set_ignore_cookie(ps, + xcb_change_window_attributes(c, w->client_win, XCB_CW_EVENT_MASK, (const uint32_t[]) { 0 })); } if (ps->shape_exists) { diff --git a/src/win.c b/src/win.c index 91bd4b1..45c0d2a 100644 --- a/src/win.c +++ b/src/win.c @@ -639,8 +639,9 @@ void win_mark_client(session_t *ps, win *w, Window client) { if (IsViewable != w->a.map_state) return; - XSelectInput(ps->dpy, client, - determine_evmask(ps, client, WIN_EVMODE_CLIENT)); + xcb_connection_t *c = XGetXCBConnection(ps->dpy); + xcb_change_window_attributes(c, client, XCB_CW_EVENT_MASK, + (const uint32_t[]) { determine_evmask(ps, client, WIN_EVMODE_CLIENT) }); // Make sure the XSelectInput() requests are sent XFlush(ps->dpy); @@ -676,13 +677,15 @@ void win_mark_client(session_t *ps, win *w, Window client) { * @param w struct _win of the parent window */ void win_unmark_client(session_t *ps, win *w) { + xcb_connection_t *c = XGetXCBConnection(ps->dpy); + Window client = w->client_win; w->client_win = None; // Recheck event mask - XSelectInput(ps->dpy, client, - determine_evmask(ps, client, WIN_EVMODE_UNKNOWN)); + xcb_change_window_attributes(c, client, XCB_CW_EVENT_MASK, + (const uint32_t[]) { determine_evmask(ps, client, WIN_EVMODE_UNKNOWN) }); } /** From 7e71f46401b14d223a1161ecc704d83d177cbda3 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 3 Oct 2018 14:38:59 +0200 Subject: [PATCH 11/18] Convert XInternAtom to XCB Signed-off-by: Uli Schlachter Signed-off-by: Yuxuan Shui --- src/common.h | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/common.h b/src/common.h index 5afa605..ff85cbc 100644 --- a/src/common.h +++ b/src/common.h @@ -1696,12 +1696,30 @@ cxfree(void *data) { XFree(data); } +static inline void _Noreturn +die(const char *msg) { + puts(msg); + exit(1); +} + /** * Wrapper of XInternAtom() for convenience. */ -static inline Atom +static inline xcb_atom_t get_atom(session_t *ps, const char *atom_name) { - return XInternAtom(ps->dpy, atom_name, False); + xcb_connection_t *c = XGetXCBConnection(ps->dpy); + xcb_intern_atom_reply_t *reply = + xcb_intern_atom_reply(c, + xcb_intern_atom(c, False, strlen(atom_name), atom_name), + NULL); + + xcb_atom_t atom = XCB_NONE; + if (reply) { + atom = reply->atom; + free(reply); + } else + die("Failed to intern atoms, bail out"); + return atom; } /** From ca148c8f15be4f2d7a40cfbf156bcf82ac3cf13d Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 3 Oct 2018 14:46:14 +0200 Subject: [PATCH 12/18] Fix printf format with DEBUG_EVENTS Xlib uses unsigned long for XIDs, but xcb always uses uint32_t. Thus, this needs the format string for uint32_t now. Signed-off-by: Uli Schlachter --- src/compton.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compton.c b/src/compton.c index 5698e56..f0fcb01 100644 --- a/src/compton.c +++ b/src/compton.c @@ -884,7 +884,7 @@ recheck_focus(session_t *ps) { #ifdef DEBUG_EVENTS print_timestamp(ps); - printf_dbgf("(): %#010lx (%#010lx \"%s\") focused.\n", wid, + printf_dbgf("(): %#010" PRIx32 " (%#010lx \"%s\") focused.\n", wid, (w ? w->id: None), (w ? w->name: NULL)); #endif From b2bfbcdfb03bf4130767f4407f28f5633e2d359a Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 3 Oct 2018 14:54:03 +0200 Subject: [PATCH 13/18] Convert XGetAtomName to XCB Signed-off-by: Uli Schlachter Signed-off-by: Yuxuan Shui --- src/c2.c | 9 ++++++++- src/compton.c | 14 +++++++++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/c2.c b/src/c2.c index 8e2fcc6..685ab3f 100644 --- a/src/c2.c +++ b/src/c2.c @@ -1463,7 +1463,14 @@ c2_match_once_leaf(session_t *ps, win *w, const c2_l_t *pleaf, idx, 1L, c2_get_atom_type(pleaf), pleaf->format); Atom atom = winprop_get_int(prop); if (atom) { - tgt_free = XGetAtomName(ps->dpy, atom); + xcb_connection_t *c = XGetXCBConnection(ps->dpy); + xcb_get_atom_name_reply_t *reply = + xcb_get_atom_name_reply(c, xcb_get_atom_name(c, atom), NULL); + if (reply) { + tgt_free = strndup( + xcb_get_atom_name_name(reply), xcb_get_atom_name_name_length(reply)); + free(reply); + } } if (tgt_free) { tgt = tgt_free; diff --git a/src/compton.c b/src/compton.c index f0fcb01..96db232 100644 --- a/src/compton.c +++ b/src/compton.c @@ -2840,9 +2840,17 @@ ev_property_notify(session_t *ps, xcb_property_notify_event_t *ev) { #ifdef DEBUG_EVENTS { // Print out changed atom - char *name = XGetAtomName(ps->dpy, ev->atom); - printf_dbg(" { atom = %s }\n", name); - cxfree(name); + xcb_get_atom_name_reply_t *reply = + xcb_get_atom_name_reply(ps->c, xcb_get_atom_name(ps->c, ev->atom), NULL); + const char *name = "?"; + int name_len = 1; + if (reply) { + name = xcb_get_atom_name_name(reply); + name_len = xcb_get_atom_name_name_length(reply); + } + + printf_dbg(" { atom = %.*s }\n", name_len, name); + free(reply); } #endif From 6c6156932f95c6e4b31cc8f1fed77f4d098f773f Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 3 Oct 2018 14:59:27 +0200 Subject: [PATCH 14/18] Convert find_client_win() to XCB This function was the only caller of wid_get_children() which called XQueryTree(). Signed-off-by: Uli Schlachter --- src/compton.c | 22 ++++++++++++---------- src/compton.h | 26 ++------------------------ 2 files changed, 14 insertions(+), 34 deletions(-) diff --git a/src/compton.c b/src/compton.c index 96db232..75f437a 100644 --- a/src/compton.c +++ b/src/compton.c @@ -985,27 +985,29 @@ paint_root(session_t *ps, const region_t *reg_paint) { /** * Look for the client window of a particular window. */ -Window -find_client_win(session_t *ps, Window w) { +xcb_window_t +find_client_win(session_t *ps, xcb_window_t w) { if (wid_has_prop(ps, w, ps->atom_client)) { return w; } - Window *children; - unsigned int nchildren; - unsigned int i; - Window ret = 0; - - if (!wid_get_children(ps, w, &children, &nchildren)) { + xcb_connection_t *c = XGetXCBConnection(ps->dpy); + xcb_query_tree_reply_t *reply = xcb_query_tree_reply(c, + xcb_query_tree(c, w), NULL); + if (!reply) return 0; - } + + xcb_window_t *children = xcb_query_tree_children(reply); + int nchildren = xcb_query_tree_children_length(reply); + int i; + xcb_window_t ret = 0; for (i = 0; i < nchildren; ++i) { if ((ret = find_client_win(ps, children[i]))) break; } - cxfree(children); + free(reply); return ret; } diff --git a/src/compton.h b/src/compton.h index bae513d..5dea260 100644 --- a/src/compton.h +++ b/src/compton.h @@ -43,8 +43,8 @@ void add_damage(session_t *ps, const region_t *damage); long determine_evmask(session_t *ps, Window wid, win_evmode_t mode); -Window -find_client_win(session_t *ps, Window w); +xcb_window_t +find_client_win(session_t *ps, xcb_window_t w); win *find_toplevel2(session_t *ps, Window wid); @@ -326,28 +326,6 @@ win_ev_stop(session_t *ps, win *w) { } } -/** - * Get the children of a window. - * - * @param ps current session - * @param w window to check - * @param children [out] an array of child window IDs - * @param nchildren [out] number of children - * @return 1 if successful, 0 otherwise - */ -static inline bool -wid_get_children(session_t *ps, Window w, - Window **children, unsigned *nchildren) { - Window troot, tparent; - - if (!XQueryTree(ps->dpy, w, &troot, &tparent, children, nchildren)) { - *nchildren = 0; - return false; - } - - return true; -} - /** * Check whether a window has WM frames. */ From 54807342f45d1925101d3ec2de28430546d81dc4 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 3 Oct 2018 15:06:16 +0200 Subject: [PATCH 15/18] Convert XQueryTree to XCB Signed-off-by: Uli Schlachter --- src/compton.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/compton.c b/src/compton.c index 75f437a..c57ff61 100644 --- a/src/compton.c +++ b/src/compton.c @@ -827,27 +827,24 @@ long determine_evmask(session_t *ps, Window wid, win_evmode_t mode) { win *find_toplevel2(session_t *ps, Window wid) { // TODO this should probably be an "update tree", then find_toplevel. // current approach is a bit more "racy" + xcb_connection_t *c = XGetXCBConnection(ps->dpy); win *w = NULL; // We traverse through its ancestors to find out the frame while (wid && wid != ps->root && !(w = find_win(ps, wid))) { - Window troot; - Window parent; - Window *tchildren; - unsigned tnchildren; + xcb_query_tree_reply_t *reply; - // XQueryTree probably fails if you run compton when X is somehow + // xcb_query_tree probably fails if you run compton when X is somehow // initializing (like add it in .xinitrc). In this case // just leave it alone. - if (!XQueryTree(ps->dpy, wid, &troot, &parent, &tchildren, - &tnchildren)) { - parent = 0; + reply = xcb_query_tree_reply(c, xcb_query_tree(c, wid), NULL); + if (reply == NULL) { break; } - cxfree(tchildren); + wid = reply->parent; - wid = parent; + free(reply); } return w; @@ -5413,18 +5410,25 @@ session_init(session_t *ps_old, int argc, char **argv) { xcb_grab_server(c); { - Window root_return, parent_return; - Window *children; - unsigned int nchildren; + xcb_window_t *children; + int nchildren; - XQueryTree(ps->dpy, ps->root, &root_return, - &parent_return, &children, &nchildren); + xcb_query_tree_reply_t *reply = xcb_query_tree_reply(c, + xcb_query_tree(c, ps->root), NULL); - for (unsigned i = 0; i < nchildren; i++) { - add_win(ps, children[i], i ? children[i-1] : None); + if (reply) { + children = xcb_query_tree_children(reply); + nchildren = xcb_query_tree_children_length(reply); + } else { + children = NULL; + nchildren = 0; } - cxfree(children); + for (int i = 0; i < nchildren; i++) { + add_win(ps, children[i], i ? children[i-1] : XCB_NONE); + } + + free(reply); } if (ps->o.track_focus) { From 37ef9c5b8a649a9ea85abd9726af85343b02a90a Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 3 Oct 2018 15:27:48 +0200 Subject: [PATCH 16/18] Add the xcb_connection_t to session_t Signed-off-by: Uli Schlachter Signed-off-by: Yuxuan Shui --- src/c2.c | 3 +- src/common.h | 9 +- src/compton.c | 243 ++++++++++++++++++++++---------------------------- src/compton.h | 22 ++--- src/win.c | 38 ++++---- src/x.c | 28 +++--- src/x.h | 12 +++ 7 files changed, 159 insertions(+), 196 deletions(-) diff --git a/src/c2.c b/src/c2.c index 685ab3f..b59e90a 100644 --- a/src/c2.c +++ b/src/c2.c @@ -1463,9 +1463,8 @@ c2_match_once_leaf(session_t *ps, win *w, const c2_l_t *pleaf, idx, 1L, c2_get_atom_type(pleaf), pleaf->format); Atom atom = winprop_get_int(prop); if (atom) { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); xcb_get_atom_name_reply_t *reply = - xcb_get_atom_name_reply(c, xcb_get_atom_name(c, atom), NULL); + xcb_get_atom_name_reply(ps->c, xcb_get_atom_name(ps->c, atom), NULL); if (reply) { tgt_free = strndup( xcb_get_atom_name_name(reply), xcb_get_atom_name_name_length(reply)); diff --git a/src/common.h b/src/common.h index ff85cbc..b07914f 100644 --- a/src/common.h +++ b/src/common.h @@ -777,6 +777,8 @@ typedef struct session { Display *dpy; /// Default screen. int scr; + /// XCB connection. + xcb_connection_t *c; /// Default visual. xcb_visualid_t vis; /// Pict formats info @@ -1707,10 +1709,9 @@ die(const char *msg) { */ static inline xcb_atom_t get_atom(session_t *ps, const char *atom_name) { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); xcb_intern_atom_reply_t *reply = - xcb_intern_atom_reply(c, - xcb_intern_atom(c, False, strlen(atom_name), atom_name), + xcb_intern_atom_reply(ps->c, + xcb_intern_atom(ps->c, False, strlen(atom_name), atom_name), NULL); xcb_atom_t atom = XCB_NONE; @@ -2090,7 +2091,7 @@ xr_sync_(session_t *ps, Drawable d if (!ps->o.xrender_sync) return; - XSync(ps->dpy, False); + x_sync(ps->c); #ifdef CONFIG_XSYNC if (ps->o.xrender_sync_fence && ps->xsync_exists) { // TODO: If everybody just follows the rules stated in X Sync prototype, diff --git a/src/compton.c b/src/compton.c index c57ff61..e8be515 100644 --- a/src/compton.c +++ b/src/compton.c @@ -551,8 +551,7 @@ make_shadow(session_t *ps, double opacity, int x_diff; int opacity_int = (int)(opacity * 25); - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - ximage = xcb_image_create_native(c, swidth, sheight, XCB_IMAGE_FORMAT_Z_PIXMAP, 8, + ximage = xcb_image_create_native(ps->c, swidth, sheight, XCB_IMAGE_FORMAT_Z_PIXMAP, 8, 0, 0, NULL); if (!ximage) { @@ -660,7 +659,6 @@ win_build_shadow(session_t *ps, win *w, double opacity) { xcb_pixmap_t shadow_pixmap = None, shadow_pixmap_argb = None; xcb_render_picture_t shadow_picture = None, shadow_picture_argb = None; xcb_gcontext_t gc = None; - xcb_connection_t *c = XGetXCBConnection(ps->dpy); shadow_image = make_shadow(ps, opacity, width, height); if (!shadow_image) { @@ -683,11 +681,11 @@ win_build_shadow(session_t *ps, win *w, double opacity) { if (!shadow_picture || !shadow_picture_argb) goto shadow_picture_err; - gc = xcb_generate_id(c); - xcb_create_gc(c, gc, shadow_pixmap, 0, NULL); + gc = xcb_generate_id(ps->c); + xcb_create_gc(ps->c, gc, shadow_pixmap, 0, NULL); - xcb_image_put(c, shadow_pixmap, gc, shadow_image, 0, 0, 0); - xcb_render_composite(c, XCB_RENDER_PICT_OP_SRC, ps->cshadow_picture, shadow_picture, + xcb_image_put(ps->c, shadow_pixmap, gc, shadow_image, 0, 0, 0); + xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, ps->cshadow_picture, shadow_picture, shadow_picture_argb, 0, 0, 0, 0, 0, 0, shadow_image->width, shadow_image->height); @@ -699,10 +697,10 @@ win_build_shadow(session_t *ps, win *w, double opacity) { // Sync it once and only once xr_sync(ps, w->shadow_paint.pixmap, NULL); - xcb_free_gc(c, gc); + xcb_free_gc(ps->c, gc); xcb_image_destroy(shadow_image); - xcb_free_pixmap(c, shadow_pixmap); - xcb_render_free_picture(c, shadow_picture); + xcb_free_pixmap(ps->c, shadow_pixmap); + xcb_render_free_picture(ps->c, shadow_picture); return true; @@ -710,15 +708,15 @@ shadow_picture_err: if (shadow_image) xcb_image_destroy(shadow_image); if (shadow_pixmap) - xcb_free_pixmap(c, shadow_pixmap); + xcb_free_pixmap(ps->c, shadow_pixmap); if (shadow_pixmap_argb) - xcb_free_pixmap(c, shadow_pixmap_argb); + xcb_free_pixmap(ps->c, shadow_pixmap_argb); if (shadow_picture) - xcb_render_free_picture(c, shadow_picture); + xcb_render_free_picture(ps->c, shadow_picture); if (shadow_picture_argb) - xcb_render_free_picture(c, shadow_picture_argb); + xcb_render_free_picture(ps->c, shadow_picture_argb); if (gc) - xcb_free_gc(c, gc); + xcb_free_gc(ps->c, gc); return false; } @@ -734,7 +732,6 @@ solid_picture(session_t *ps, bool argb, double a, xcb_render_create_picture_value_list_t pa; xcb_render_color_t col; xcb_rectangle_t rect; - xcb_connection_t *c = XGetXCBConnection(ps->dpy); pixmap = x_create_pixmap(ps, argb ? 32 : 8, ps->root, 1, 1); if (!pixmap) return None; @@ -745,7 +742,7 @@ solid_picture(session_t *ps, bool argb, double a, XCB_RENDER_CP_REPEAT, &pa); if (!picture) { - xcb_free_pixmap(c, pixmap); + xcb_free_pixmap(ps->c, pixmap); return None; } @@ -759,8 +756,8 @@ solid_picture(session_t *ps, bool argb, double a, rect.width = 1; rect.height = 1; - xcb_render_fill_rectangles(c, XCB_RENDER_PICT_OP_SRC, picture, col, 1, &rect); - xcb_free_pixmap(c, pixmap); + xcb_render_fill_rectangles(ps->c, XCB_RENDER_PICT_OP_SRC, picture, col, 1, &rect); + xcb_free_pixmap(ps->c, pixmap); return picture; } @@ -827,7 +824,6 @@ long determine_evmask(session_t *ps, Window wid, win_evmode_t mode) { win *find_toplevel2(session_t *ps, Window wid) { // TODO this should probably be an "update tree", then find_toplevel. // current approach is a bit more "racy" - xcb_connection_t *c = XGetXCBConnection(ps->dpy); win *w = NULL; // We traverse through its ancestors to find out the frame @@ -837,7 +833,7 @@ win *find_toplevel2(session_t *ps, Window wid) { // xcb_query_tree probably fails if you run compton when X is somehow // initializing (like add it in .xinitrc). In this case // just leave it alone. - reply = xcb_query_tree_reply(c, xcb_query_tree(c, wid), NULL); + reply = xcb_query_tree_reply(ps->c, xcb_query_tree(ps->c, wid), NULL); if (reply == NULL) { break; } @@ -867,10 +863,9 @@ recheck_focus(session_t *ps) { // Determine the currently focused window so we can apply appropriate // opacity on it - xcb_connection_t *c = XGetXCBConnection(ps->dpy); xcb_window_t wid = XCB_NONE; xcb_get_input_focus_reply_t *reply = - xcb_get_input_focus_reply(c, xcb_get_input_focus(c), NULL); + xcb_get_input_focus_reply(ps->c, xcb_get_input_focus(ps->c), NULL); if (reply) { wid = reply->focus; @@ -900,7 +895,6 @@ get_root_tile(session_t *ps) { if (ps->o.paint_on_overlay) { return ps->root_picture; } */ - xcb_connection_t *c = XGetXCBConnection(ps->dpy); assert(!ps->root_tile_paint.pixmap); ps->root_tile_fill = false; @@ -954,7 +948,7 @@ get_root_tile(session_t *ps) { rect.x = rect.y = 0; rect.width = rect.height = 1; - xcb_render_fill_rectangles(c, XCB_RENDER_PICT_OP_SRC, ps->root_tile_paint.pict, col, 1, &rect); + xcb_render_fill_rectangles(ps->c, XCB_RENDER_PICT_OP_SRC, ps->root_tile_paint.pict, col, 1, &rect); } ps->root_tile_fill = fill; @@ -988,9 +982,8 @@ find_client_win(session_t *ps, xcb_window_t w) { return w; } - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - xcb_query_tree_reply_t *reply = xcb_query_tree_reply(c, - xcb_query_tree(c, w), NULL); + xcb_query_tree_reply_t *reply = xcb_query_tree_reply(ps->c, + xcb_query_tree(ps->c, w), NULL); if (!reply) return 0; @@ -1271,7 +1264,6 @@ static bool xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int x, int y, int wid, int hei, xcb_render_fixed_t **blur_kerns, const region_t *reg_clip) { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); assert(blur_kerns[0]); // Directly copying from tgt_buffer to it does not work, so we create a @@ -1297,9 +1289,9 @@ xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, // Copy from source picture to destination. The filter must // be applied on source picture, to get the nearby pixels outside the // window. - xcb_render_set_picture_filter(c, src_pict, strlen(XRFILTER_CONVOLUTION), XRFILTER_CONVOLUTION, + xcb_render_set_picture_filter(ps->c, src_pict, strlen(XRFILTER_CONVOLUTION), XRFILTER_CONVOLUTION, kwid * khei + 2, convolution_blur); - xcb_render_composite(c, XCB_RENDER_PICT_OP_SRC, src_pict, None, dst_pict, + xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, src_pict, None, dst_pict, (rd_from_tgt ? x: 0), (rd_from_tgt ? y: 0), 0, 0, (rd_from_tgt ? 0: x), (rd_from_tgt ? 0: y), wid, hei); xrfilter_reset(ps, src_pict); @@ -1312,7 +1304,7 @@ xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, } if (src_pict != tgt_buffer) - xcb_render_composite(c, XCB_RENDER_PICT_OP_SRC, src_pict, None, tgt_buffer, + xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, src_pict, None, tgt_buffer, 0, 0, 0, 0, x, y, wid, hei); free_picture(ps, &tmp_picture); @@ -1432,7 +1424,6 @@ render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, xcb_render_picture_t pict, glx_texture_t *ptex, const region_t *reg_paint, const glx_prog_main_t *pprogram) { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); switch (ps->o.backend) { case BKEND_XRENDER: case BKEND_XR_GLX_HYBRID: @@ -1440,7 +1431,7 @@ render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, xcb_render_picture_t alpha_pict = get_alpha_pict_d(ps, opacity); if (alpha_pict != ps->alpha_picts[0]) { int op = ((!argb && !alpha_pict) ? XCB_RENDER_PICT_OP_SRC: XCB_RENDER_PICT_OP_OVER); - xcb_render_composite(c, op, pict, alpha_pict, + xcb_render_composite(ps->c, op, pict, alpha_pict, ps->tgt_buffer.pict, x, y, 0, 0, dx, dy, wid, hei); } break; @@ -1462,14 +1453,13 @@ render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, */ static inline void paint_one(session_t *ps, win *w, const region_t *reg_paint) { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); glx_mark(ps, w->id, true); // Fetch Pixmap if (!w->paint.pixmap && ps->has_name_pixmap) { - w->paint.pixmap = xcb_generate_id(c); + w->paint.pixmap = xcb_generate_id(ps->c); set_ignore_cookie(ps, - xcb_composite_name_window_pixmap(c, w->id, w->paint.pixmap)); + xcb_composite_name_window_pixmap(ps->c, w->id, w->paint.pixmap)); if (w->paint.pixmap) free_fence(ps, &w->fence); } @@ -1527,14 +1517,14 @@ paint_one(session_t *ps, win *w, const region_t *reg_paint) { pixman_region32_fini(®); } - xcb_render_composite(c, XCB_RENDER_PICT_OP_SRC, pict, None, + xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, pict, None, newpict, 0, 0, 0, 0, 0, 0, wid, hei); - xcb_render_composite(c, XCB_RENDER_PICT_OP_DIFFERENCE, ps->white_picture, None, + xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_DIFFERENCE, ps->white_picture, None, newpict, 0, 0, 0, 0, 0, 0, wid, hei); // We use an extra PictOpInReverse operation to get correct pixel // alpha. There could be a better solution. if (win_has_alpha(w)) - xcb_render_composite(c, XCB_RENDER_PICT_OP_IN_REVERSE, pict, None, + xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_IN_REVERSE, pict, None, newpict, 0, 0, 0, 0, 0, 0, wid, hei); pict = newpict; } @@ -1634,7 +1624,7 @@ paint_region(ps, w, (cx), (cy), (cwid), (chei), w->frame_opacity * dopacity, \ .height = hei, }; - xcb_render_fill_rectangles(c, XCB_RENDER_PICT_OP_OVER, ps->tgt_buffer.pict, + xcb_render_fill_rectangles(ps->c, XCB_RENDER_PICT_OP_OVER, ps->tgt_buffer.pict, color, 1, &rect); } break; @@ -1676,7 +1666,6 @@ rebuild_shadow_exclude_reg(session_t *ps) { /// region_real = the damage region static void paint_all(session_t *ps, region_t *region, const region_t *region_real, win * const t) { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); if (!region_real) region_real = region; @@ -1831,7 +1820,7 @@ paint_all(session_t *ps, region_t *region, const region_t *region_real, win * co if (ps->o.vsync) { // Make sure all previous requests are processed to achieve best // effect - XSync(ps->dpy, False); + x_sync(ps->c); #ifdef CONFIG_OPENGL if (glx_has_context(ps)) { if (ps->o.vsync_use_glfinish) @@ -1863,14 +1852,14 @@ paint_all(session_t *ps, region_t *region, const region_t *region_real, win * co // No-DBE painting mode else if (ps->tgt_buffer.pict != ps->tgt_picture) { xcb_render_composite( - c, XCB_RENDER_PICT_OP_SRC, ps->tgt_buffer.pict, None, + ps->c, XCB_RENDER_PICT_OP_SRC, ps->tgt_buffer.pict, None, ps->tgt_picture, 0, 0, 0, 0, 0, 0, ps->root_width, ps->root_height); } break; #ifdef CONFIG_OPENGL case BKEND_XR_GLX_HYBRID: - XSync(ps->dpy, False); + x_sync(ps->c); if (ps->o.vsync_use_glfinish) glFinish(); else @@ -1942,24 +1931,23 @@ repair_win(session_t *ps, win *w) { if (IsViewable != w->a.map_state) return; - xcb_connection_t *c = XGetXCBConnection(ps->dpy); region_t parts; pixman_region32_init(&parts); if (!w->ever_damaged) { win_extents(w, &parts); set_ignore_cookie(ps, - xcb_damage_subtract(c, w->damage, XCB_NONE, XCB_NONE)); + xcb_damage_subtract(ps->c, w->damage, XCB_NONE, XCB_NONE)); } else { - xcb_xfixes_region_t tmp = xcb_generate_id(c); - xcb_xfixes_create_region(c, tmp, 0, NULL); + xcb_xfixes_region_t tmp = xcb_generate_id(ps->c); + xcb_xfixes_create_region(ps->c, tmp, 0, NULL); set_ignore_cookie(ps, - xcb_damage_subtract(c, w->damage, XCB_NONE, tmp)); - xcb_xfixes_translate_region(c, tmp, + xcb_damage_subtract(ps->c, w->damage, XCB_NONE, tmp)); + xcb_xfixes_translate_region(ps->c, tmp, w->g.x + w->g.border_width, w->g.y + w->g.border_width); x_fetch_region(ps, tmp, &parts); - xcb_xfixes_destroy_region(c, tmp); + xcb_xfixes_destroy_region(ps->c, tmp); } w->ever_damaged = true; @@ -1991,12 +1979,10 @@ finish_map_win(session_t *ps, win **_w) { void map_win(session_t *ps, Window id) { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - // Unmap overlay window if it got mapped but we are currently not // in redirected state. if (ps->overlay && id == ps->overlay && !ps->redirected) { - xcb_unmap_window(c, ps->overlay); + xcb_unmap_window(ps->c, ps->overlay); XFlush(ps->dpy); } @@ -2020,12 +2006,12 @@ map_win(session_t *ps, Window id) { // Set window event mask before reading properties so that no property // changes are lost - xcb_change_window_attributes(c, id, XCB_CW_EVENT_MASK, + xcb_change_window_attributes(ps->c, id, XCB_CW_EVENT_MASK, (const uint32_t[]) { determine_evmask(ps, id, WIN_EVMODE_FRAME) }); // Notify compton when the shape of a window changes if (ps->shape_exists) { - xcb_shape_select_input(c, id, 1); + xcb_shape_select_input(ps->c, id, 1); } // Make sure the XSelectInput() requests are sent @@ -2420,8 +2406,7 @@ destroy_win(session_t *ps, Window id) { static inline void root_damaged(session_t *ps) { if (ps->root_tile_paint.pixmap) { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - xcb_clear_area(c, true, ps->root, 0, 0, 0, 0); + xcb_clear_area(ps->c, true, ps->root, 0, 0, 0, 0); free_root_tile(ps); } @@ -2527,14 +2512,13 @@ opts_init_track_focus(session_t *ps) { if (ps->o.track_focus) return; - xcb_connection_t *c = XGetXCBConnection(ps->dpy); ps->o.track_focus = true; if (!ps->o.use_ewmh_active_win) { // Start listening to FocusChange events for (win *w = ps->list; w; w = w->next) if (IsViewable == w->a.map_state) - xcb_change_window_attributes(c, w->id, XCB_CW_EVENT_MASK, + xcb_change_window_attributes(ps->c, w->id, XCB_CW_EVENT_MASK, (const uint32_t[]) { determine_evmask(ps, w->id, WIN_EVMODE_FRAME) }); } @@ -2751,12 +2735,10 @@ ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t *ev) { if (ev->parent == ps->root) { add_win(ps, ev->window, 0); } else { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - destroy_win(ps, ev->window); // Reset event mask in case something wrong happens - xcb_change_window_attributes(c, ev->window, XCB_CW_EVENT_MASK, + xcb_change_window_attributes(ps->c, ev->window, XCB_CW_EVENT_MASK, (const uint32_t[]) { determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN) }); // Check if the window is an undetected client window @@ -2776,7 +2758,7 @@ ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t *ev) { } // Otherwise, watch for WM_STATE on it else { - xcb_change_window_attributes(c, ev->window, XCB_CW_EVENT_MASK, (const uint32_t[]) { + xcb_change_window_attributes(ps->c, ev->window, XCB_CW_EVENT_MASK, (const uint32_t[]) { determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN) | PropertyChangeMask }); } } @@ -2835,7 +2817,6 @@ update_ewmh_active_win(session_t *ps) { inline static void ev_property_notify(session_t *ps, xcb_property_notify_event_t *ev) { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); #ifdef DEBUG_EVENTS { // Print out changed atom @@ -2877,7 +2858,7 @@ ev_property_notify(session_t *ps, xcb_property_notify_event_t *ev) { // Check whether it could be a client window if (!find_toplevel(ps, ev->window)) { // Reset event mask anyway - xcb_change_window_attributes(c, ev->window, XCB_CW_EVENT_MASK, (const uint32_t[]) { + xcb_change_window_attributes(ps->c, ev->window, XCB_CW_EVENT_MASK, (const uint32_t[]) { determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN) }); win *w_top = find_toplevel2(ps, ev->window); @@ -3522,7 +3503,6 @@ static bool register_cm(session_t *ps) { assert(!ps->reg_win); - xcb_connection_t *c = XGetXCBConnection(ps->dpy); ps->reg_win = XCreateSimpleWindow(ps->dpy, ps->root, 0, 0, 1, 1, 0, None, None); @@ -3533,7 +3513,7 @@ register_cm(session_t *ps) { // Unredirect the window if it's redirected, just in case if (ps->redirected) - xcb_composite_unredirect_window(c, ps->reg_win, XCB_COMPOSITE_REDIRECT_MANUAL); + xcb_composite_unredirect_window(ps->c, ps->reg_win, XCB_COMPOSITE_REDIRECT_MANUAL); { XClassHint *h = XAllocClassHint(); @@ -3549,7 +3529,7 @@ register_cm(session_t *ps) { // Set _NET_WM_PID { uint32_t pid = getpid(); - xcb_change_property(c, XCB_PROP_MODE_REPLACE, ps->reg_win, + xcb_change_property(ps->c, XCB_PROP_MODE_REPLACE, ps->reg_win, get_atom(ps, "_NET_WM_PID"), XCB_ATOM_CARDINAL, 32, 1, &pid); } @@ -3576,8 +3556,8 @@ register_cm(session_t *ps) { free(buf); xcb_get_selection_owner_reply_t *reply = - xcb_get_selection_owner_reply(c, - xcb_get_selection_owner(c, atom), NULL); + xcb_get_selection_owner_reply(ps->c, + xcb_get_selection_owner(ps->c, atom), NULL); if (reply && reply->owner != XCB_NONE) { free(reply); @@ -3585,7 +3565,7 @@ register_cm(session_t *ps) { return false; } free(reply); - xcb_set_selection_owner(c, ps->reg_win, atom, 0); + xcb_set_selection_owner(ps->c, ps->reg_win, atom, 0); } return true; @@ -4180,10 +4160,9 @@ init_atoms(session_t *ps) { */ static void update_refresh_rate(session_t *ps) { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); xcb_randr_get_screen_info_reply_t *randr_info = - xcb_randr_get_screen_info_reply(c, - xcb_randr_get_screen_info(c, ps->root), NULL); + xcb_randr_get_screen_info_reply(ps->c, + xcb_randr_get_screen_info(ps->c, ps->root), NULL); if (!randr_info) return; @@ -4531,10 +4510,9 @@ init_dbe(session_t *ps) { */ static bool init_overlay(session_t *ps) { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); xcb_composite_get_overlay_window_reply_t *reply = - xcb_composite_get_overlay_window_reply(c, - xcb_composite_get_overlay_window(c, ps->root), NULL); + xcb_composite_get_overlay_window_reply(ps->c, + xcb_composite_get_overlay_window(ps->c, ps->root), NULL); if (reply) { ps->overlay = reply->overlay_win; free(reply); @@ -4545,13 +4523,13 @@ init_overlay(session_t *ps) { // Set window region of the overlay window, code stolen from // compiz-0.8.8 xcb_generic_error_t *e; - e = XCB_SYNCED_VOID(xcb_shape_mask, c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, + e = XCB_SYNCED_VOID(xcb_shape_mask, ps->c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, ps->overlay, 0, 0, 0); if (e) { printf_errf("(): failed to set the bounding shape of overlay, giving up."); exit(1); } - e = XCB_SYNCED_VOID(xcb_shape_rectangles, c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, + e = XCB_SYNCED_VOID(xcb_shape_rectangles, ps->c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, XCB_CLIP_ORDERING_UNSORTED, ps->overlay, 0, 0, 0, NULL); if (e) { printf_errf("(): failed to set the input shape of overlay, giving up."); @@ -4559,7 +4537,7 @@ init_overlay(session_t *ps) { } // Listen to Expose events on the overlay - xcb_change_window_attributes(c, ps->overlay, XCB_CW_EVENT_MASK, + xcb_change_window_attributes(ps->c, ps->overlay, XCB_CW_EVENT_MASK, (const uint32_t[]) { XCB_EVENT_MASK_EXPOSURE }); // Retrieve DamageNotify on root window if we are painting on an @@ -4588,7 +4566,6 @@ init_overlay(session_t *ps) { */ static bool init_filters(session_t *ps) { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); // Blur filter if (ps->o.blur_background || ps->o.blur_background_frame) { switch (ps->o.backend) { @@ -4596,8 +4573,8 @@ init_filters(session_t *ps) { case BKEND_XR_GLX_HYBRID: { // Query filters - xcb_render_query_filters_reply_t *pf = xcb_render_query_filters_reply(c, - xcb_render_query_filters(c, get_tgt_window(ps)), NULL); + xcb_render_query_filters_reply_t *pf = xcb_render_query_filters_reply(ps->c, + xcb_render_query_filters(ps->c, get_tgt_window(ps)), NULL); if (pf) { xcb_str_iterator_t iter = xcb_render_query_filters_filters_iterator(pf); for (; iter.rem; xcb_str_next(&iter)) { @@ -4639,14 +4616,12 @@ redir_start(session_t *ps) { printf_dbgf("(): Screen redirected.\n"); #endif - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - // Map overlay window. Done firstly according to this: // https://bugzilla.gnome.org/show_bug.cgi?id=597014 if (ps->overlay) - xcb_map_window(c, ps->overlay); + xcb_map_window(ps->c, ps->overlay); - xcb_composite_redirect_subwindows(c, ps->root, XCB_COMPOSITE_REDIRECT_MANUAL); + xcb_composite_redirect_subwindows(ps->c, ps->root, XCB_COMPOSITE_REDIRECT_MANUAL); /* // Unredirect GL context window as this may have an effect on VSync: @@ -4658,7 +4633,7 @@ redir_start(session_t *ps) { } */ // Must call XSync() here - XSync(ps->dpy, False); + x_sync(ps->c); ps->redirected = true; @@ -4673,7 +4648,6 @@ redir_start(session_t *ps) { static void redir_stop(session_t *ps) { if (ps->redirected) { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); #ifdef DEBUG_REDIR print_timestamp(ps); printf_dbgf("(): Screen unredirected.\n"); @@ -4684,13 +4658,13 @@ redir_stop(session_t *ps) { for (win *w = ps->list; w; w = w->next) free_wpaint(ps, w); - xcb_composite_unredirect_subwindows(c, ps->root, XCB_COMPOSITE_REDIRECT_MANUAL); + xcb_composite_unredirect_subwindows(ps->c, ps->root, XCB_COMPOSITE_REDIRECT_MANUAL); // Unmap overlay window if (ps->overlay) - xcb_unmap_window(c, ps->overlay); + xcb_unmap_window(ps->c, ps->overlay); // Must call XSync() here - XSync(ps->dpy, False); + x_sync(ps->c); ps->redirected = false; } @@ -4702,13 +4676,12 @@ handle_queued_x_events(EV_P_ ev_prepare *w, int revents) { ev_session_prepare *sw = (void *)w; session_t *ps = sw->ps; xcb_generic_event_t *ev; - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - while ((ev = xcb_poll_for_queued_event(c))) { + while ((ev = xcb_poll_for_queued_event(ps->c))) { ev_handle(ps, ev); free(ev); }; XFlush(ps->dpy); - xcb_flush(c); + xcb_flush(ps->c); } /** @@ -4840,8 +4813,7 @@ delayed_draw_callback(EV_P_ ev_idle *w, int revents) { static void x_event_callback(EV_P_ ev_io *w, int revents) { session_t *ps = (session_t *)w; - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - xcb_generic_event_t *ev = xcb_poll_for_event(c); + xcb_generic_event_t *ev = xcb_poll_for_event(ps->c); if (ev) { ev_handle(ps, ev); free(ev); @@ -4856,18 +4828,17 @@ cxinerama_upd_scrs(session_t *ps) { if (!ps->o.xinerama_shadow_crop || !ps->xinerama_exists) return; - xcb_connection_t *c = XGetXCBConnection(ps->dpy); xcb_xinerama_is_active_reply_t *active = - xcb_xinerama_is_active_reply(c, - xcb_xinerama_is_active(c), NULL); + xcb_xinerama_is_active_reply(ps->c, + xcb_xinerama_is_active(ps->c), NULL); if (!active || !active->state) { free(active); return; } free(active); - ps->xinerama_scrs = xcb_xinerama_query_screens_reply(c, - xcb_xinerama_query_screens(c), NULL); + ps->xinerama_scrs = xcb_xinerama_query_screens_reply(ps->c, + xcb_xinerama_query_screens(ps->c), NULL); if (!ps->xinerama_scrs) return; @@ -4896,6 +4867,7 @@ session_init(session_t *ps_old, int argc, char **argv) { static const session_t s_def = { .dpy = NULL, .scr = 0, + .c = NULL, .vis = 0, .depth = 0, .root = None, @@ -5100,7 +5072,7 @@ session_init(session_t *ps_old, int argc, char **argv) { } XSetEventQueueOwner(ps->dpy, XCBOwnsEventQueue); } - xcb_connection_t *c = XGetXCBConnection(ps->dpy); + ps->c = XGetXCBConnection(ps->dpy); const xcb_query_extension_reply_t *ext_info; XSetErrorHandler(xerror); @@ -5116,7 +5088,7 @@ session_init(session_t *ps_old, int argc, char **argv) { // Start listening to events on root earlier to catch all possible // root geometry changes - xcb_change_window_attributes(c, ps->root, XCB_CW_EVENT_MASK, (const uint32_t[]) { + xcb_change_window_attributes(ps->c, ps->root, XCB_CW_EVENT_MASK, (const uint32_t[]) { XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY @@ -5126,15 +5098,15 @@ session_init(session_t *ps_old, int argc, char **argv) { ps->root_width = DisplayWidth(ps->dpy, ps->scr); ps->root_height = DisplayHeight(ps->dpy, ps->scr); - xcb_prefetch_extension_data(c, &xcb_render_id); - xcb_prefetch_extension_data(c, &xcb_composite_id); - xcb_prefetch_extension_data(c, &xcb_damage_id); - xcb_prefetch_extension_data(c, &xcb_shape_id); - xcb_prefetch_extension_data(c, &xcb_xfixes_id); - xcb_prefetch_extension_data(c, &xcb_randr_id); - xcb_prefetch_extension_data(c, &xcb_xinerama_id); + 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_xinerama_id); - ext_info = xcb_get_extension_data(c, &xcb_render_id); + ext_info = xcb_get_extension_data(ps->c, &xcb_render_id); if (!ext_info || !ext_info->present) { fprintf(stderr, "No render extension\n"); exit(1); @@ -5142,7 +5114,7 @@ session_init(session_t *ps_old, int argc, char **argv) { ps->render_event = ext_info->first_event; ps->render_error = ext_info->first_error; - ext_info = xcb_get_extension_data(c, &xcb_composite_id); + ext_info = xcb_get_extension_data(ps->c, &xcb_composite_id); if (!ext_info || !ext_info->present) { fprintf(stderr, "No composite extension\n"); exit(1); @@ -5153,8 +5125,8 @@ session_init(session_t *ps_old, int argc, char **argv) { { xcb_composite_query_version_reply_t *reply = - xcb_composite_query_version_reply(c, - xcb_composite_query_version(c, XCB_COMPOSITE_MAJOR_VERSION, XCB_COMPOSITE_MINOR_VERSION), + xcb_composite_query_version_reply(ps->c, + xcb_composite_query_version(ps->c, XCB_COMPOSITE_MAJOR_VERSION, XCB_COMPOSITE_MINOR_VERSION), NULL); if (!ps->o.no_name_pixmap @@ -5164,25 +5136,25 @@ session_init(session_t *ps_old, int argc, char **argv) { free(reply); } - ext_info = xcb_get_extension_data(c, &xcb_damage_id); + ext_info = xcb_get_extension_data(ps->c, &xcb_damage_id); if (!ext_info || !ext_info->present) { fprintf(stderr, "No damage extension\n"); exit(1); } ps->damage_event = ext_info->first_event; ps->damage_error = ext_info->first_error; - xcb_discard_reply(c, - xcb_damage_query_version(c, XCB_DAMAGE_MAJOR_VERSION, XCB_DAMAGE_MINOR_VERSION).sequence); + 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(c, &xcb_xfixes_id); + ext_info = xcb_get_extension_data(ps->c, &xcb_xfixes_id); if (!ext_info || !ext_info->present) { fprintf(stderr, "No XFixes extension\n"); exit(1); } ps->xfixes_event = ext_info->first_event; ps->xfixes_error = ext_info->first_error; - xcb_discard_reply(c, - xcb_xfixes_query_version(c, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION).sequence); + xcb_discard_reply(ps->c, + xcb_xfixes_query_version(ps->c, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION).sequence); // Build a safe representation of display name { @@ -5209,7 +5181,7 @@ session_init(session_t *ps_old, int argc, char **argv) { get_cfg(ps, argc, argv, false); // Query X Shape - ext_info = xcb_get_extension_data(c, &xcb_shape_id); + 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; @@ -5239,7 +5211,7 @@ session_init(session_t *ps_old, int argc, char **argv) { // Query X RandR if ((ps->o.sw_opti && !ps->o.refresh_rate) || ps->o.xinerama_shadow_crop) { - ext_info = xcb_get_extension_data(c, &xcb_randr_id); + 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; @@ -5268,7 +5240,7 @@ session_init(session_t *ps_old, int argc, char **argv) { // Query X Xinerama extension if (ps->o.xinerama_shadow_crop) { #ifdef CONFIG_XINERAMA - ext_info = xcb_get_extension_data(c, &xcb_xinerama_id); + ext_info = xcb_get_extension_data(ps->c, &xcb_xinerama_id); ps->xinerama_exists = ext_info && ext_info->present; #else printf_errf("(): Xinerama support not compiled in."); @@ -5320,7 +5292,7 @@ session_init(session_t *ps_old, int argc, char **argv) { // an auto-detected refresh rate, or when Xinerama features are enabled if (ps->randr_exists && ((ps->o.sw_opti && !ps->o.refresh_rate) || ps->o.xinerama_shadow_crop)) - xcb_randr_select_input(c, ps->root, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE); + xcb_randr_select_input(ps->c, ps->root, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE); // Initialize VSync if (!vsync_init(ps)) @@ -5407,14 +5379,14 @@ session_init(session_t *ps_old, int argc, char **argv) { ev_set_priority(&ps->event_check->w, EV_MINPRI); ev_prepare_start(ps->loop, &ps->event_check->w); - xcb_grab_server(c); + xcb_grab_server(ps->c); { xcb_window_t *children; int nchildren; - xcb_query_tree_reply_t *reply = xcb_query_tree_reply(c, - xcb_query_tree(c, ps->root), NULL); + xcb_query_tree_reply_t *reply = xcb_query_tree_reply(ps->c, + xcb_query_tree(ps->c, ps->root), NULL); if (reply) { children = xcb_query_tree_children(reply); @@ -5435,7 +5407,7 @@ session_init(session_t *ps_old, int argc, char **argv) { recheck_focus(ps); } - xcb_ungrab_server(c); + xcb_ungrab_server(ps->c); // ALWAYS flush after xcb_ungrab_server()! XFlush(ps->dpy); @@ -5483,11 +5455,10 @@ session_init(session_t *ps_old, int argc, char **argv) { */ static void session_destroy(session_t *ps) { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); redir_stop(ps); // Stop listening to events on root window - xcb_change_window_attributes(c, ps->root, XCB_CW_EVENT_MASK, + xcb_change_window_attributes(ps->c, ps->root, XCB_CW_EVENT_MASK, (const uint32_t[]) { 0 }); #ifdef CONFIG_DBUS @@ -5625,18 +5596,18 @@ session_destroy(session_t *ps) { // Release overlay window if (ps->overlay) { - xcb_composite_release_overlay_window(c, ps->overlay); + xcb_composite_release_overlay_window(ps->c, ps->overlay); ps->overlay = None; } // Free reg_win if (ps->reg_win) { - xcb_destroy_window(c, ps->reg_win); + xcb_destroy_window(ps->c, ps->reg_win); ps->reg_win = None; } // Flush all events - XSync(ps->dpy, True); + x_sync(ps->c); ev_io_stop(ps->loop, &ps->xiow); #ifdef DEBUG_XRC diff --git a/src/compton.h b/src/compton.h index 5dea260..a58ec2a 100644 --- a/src/compton.h +++ b/src/compton.h @@ -62,8 +62,7 @@ render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, static inline void xrfilter_reset(session_t *ps, xcb_render_picture_t p) { #define FILTER "Nearest" - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - xcb_render_set_picture_filter(c, p, strlen(FILTER), FILTER, 0, NULL); + xcb_render_set_picture_filter(ps->c, p, strlen(FILTER), FILTER, 0, NULL); #undef FILTER } @@ -113,8 +112,7 @@ array_wid_exists(const Window *arr, int count, Window wid) { inline static void free_picture(session_t *ps, xcb_render_picture_t *p) { if (*p) { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - xcb_render_free_picture(c, *p); + xcb_render_free_picture(ps->c, *p); *p = None; } } @@ -127,7 +125,7 @@ free_damage(session_t *ps, xcb_damage_damage_t *p) { if (*p) { // BadDamage will be thrown if the window is destroyed set_ignore_cookie(ps, - xcb_damage_destroy(XGetXCBConnection(ps->dpy), *p)); + xcb_damage_destroy(ps->c, *p)); *p = None; } } @@ -196,11 +194,10 @@ free_texture(session_t *ps, glx_texture_t **t) { */ static inline void free_paint(session_t *ps, paint_t *ppaint) { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); free_paint_glx(ps, ppaint); free_picture(ps, &ppaint->pict); if (ppaint->pixmap) - xcb_free_pixmap(c, ppaint->pixmap); + xcb_free_pixmap(ps->c, ppaint->pixmap); ppaint->pixmap = XCB_NONE; } @@ -235,11 +232,10 @@ free_win_res(session_t *ps, win *w) { */ static inline void free_root_tile(session_t *ps) { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); free_picture(ps, &ps->root_tile_paint.pict); free_texture(ps, &ps->root_tile_paint.ptex); if (ps->root_tile_fill) { - xcb_free_pixmap(c, ps->root_tile_paint.pixmap); + xcb_free_pixmap(ps->c, ps->root_tile_paint.pixmap); ps->root_tile_paint.pixmap = XCB_NONE; } ps->root_tile_paint.pixmap = None; @@ -309,20 +305,18 @@ wid_set_text_prop(session_t *ps, Window wid, Atom prop_atom, char *str) { */ static inline void win_ev_stop(session_t *ps, win *w) { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - // Will get BadWindow if the window is destroyed set_ignore_cookie(ps, - xcb_change_window_attributes(c, w->id, XCB_CW_EVENT_MASK, (const uint32_t[]) { 0 })); + xcb_change_window_attributes(ps->c, w->id, XCB_CW_EVENT_MASK, (const uint32_t[]) { 0 })); if (w->client_win) { set_ignore_cookie(ps, - xcb_change_window_attributes(c, w->client_win, XCB_CW_EVENT_MASK, (const uint32_t[]) { 0 })); + xcb_change_window_attributes(ps->c, w->client_win, XCB_CW_EVENT_MASK, (const uint32_t[]) { 0 })); } if (ps->shape_exists) { set_ignore_cookie(ps, - xcb_shape_select_input(c, w->id, 0)); + xcb_shape_select_input(ps->c, w->id, 0)); } } diff --git a/src/win.c b/src/win.c index 45c0d2a..4c98fab 100644 --- a/src/win.c +++ b/src/win.c @@ -28,15 +28,13 @@ clear_cache_win_leaders(session_t *ps) { static inline void wid_set_opacity_prop(session_t *ps, Window wid, opacity_t val) { const uint32_t v = val; - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - xcb_change_property(c, XCB_PROP_MODE_REPLACE, wid, ps->atom_opacity, + xcb_change_property(ps->c, XCB_PROP_MODE_REPLACE, wid, ps->atom_opacity, XCB_ATOM_CARDINAL, 32, 1, &v); } static inline void wid_rm_opacity_prop(session_t *ps, Window wid) { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - xcb_delete_property(c, wid, ps->atom_opacity); + xcb_delete_property(ps->c, wid, ps->atom_opacity); } /** @@ -232,10 +230,9 @@ static inline bool win_bounding_shaped(const session_t *ps, Window wid) { if (ps->shape_exists) { xcb_shape_query_extents_reply_t *reply; Bool bounding_shaped; - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - reply = xcb_shape_query_extents_reply(c, - xcb_shape_query_extents(c, wid), NULL); + reply = xcb_shape_query_extents_reply(ps->c, + xcb_shape_query_extents(ps->c, wid), NULL); bounding_shaped = reply && reply->bounding_shaped; free(reply); @@ -639,8 +636,7 @@ void win_mark_client(session_t *ps, win *w, Window client) { if (IsViewable != w->a.map_state) return; - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - xcb_change_window_attributes(c, client, XCB_CW_EVENT_MASK, + xcb_change_window_attributes(ps->c, client, XCB_CW_EVENT_MASK, (const uint32_t[]) { determine_evmask(ps, client, WIN_EVMODE_CLIENT) }); // Make sure the XSelectInput() requests are sent @@ -677,14 +673,12 @@ void win_mark_client(session_t *ps, win *w, Window client) { * @param w struct _win of the parent window */ void win_unmark_client(session_t *ps, win *w) { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - Window client = w->client_win; w->client_win = None; // Recheck event mask - xcb_change_window_attributes(c, client, XCB_CW_EVENT_MASK, + xcb_change_window_attributes(ps->c, client, XCB_CW_EVENT_MASK, (const uint32_t[]) { determine_evmask(ps, client, WIN_EVMODE_UNKNOWN) }); } @@ -843,11 +837,10 @@ bool add_win(session_t *ps, Window id, Window prev) { // Fill structure new->id = id; - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - xcb_get_window_attributes_cookie_t acookie = xcb_get_window_attributes(c, id); - xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(c, id); - xcb_get_window_attributes_reply_t *a = xcb_get_window_attributes_reply(c, acookie, NULL); - xcb_get_geometry_reply_t *g = xcb_get_geometry_reply(c, gcookie, NULL); + xcb_get_window_attributes_cookie_t acookie = xcb_get_window_attributes(ps->c, id); + xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(ps->c, id); + xcb_get_window_attributes_reply_t *a = xcb_get_window_attributes_reply(ps->c, acookie, NULL); + xcb_get_geometry_reply_t *g = xcb_get_geometry_reply(ps->c, gcookie, NULL); if (!a || IsUnviewable == a->map_state) { // Failed to get window attributes probably means the window is gone // already. IsUnviewable means the window is already reparented @@ -876,9 +869,9 @@ bool add_win(session_t *ps, Window id, Window prev) { if (InputOutput == new->a._class) { // Create Damage for window - new->damage = xcb_generate_id(c); - xcb_generic_error_t *e = xcb_request_check(c, - xcb_damage_create_checked(c, new->damage, id, XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY)); + new->damage = xcb_generate_id(ps->c); + xcb_generic_error_t *e = xcb_request_check(ps->c, + xcb_damage_create_checked(ps->c, new->damage, id, XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY)); if (e) { free(e); free(new); @@ -1164,9 +1157,8 @@ void win_update_bounding_shape(session_t *ps, win *w) { * as well as not generate a region. */ - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - xcb_shape_get_rectangles_reply_t *r = xcb_shape_get_rectangles_reply(c, - xcb_shape_get_rectangles(c, w->id, XCB_SHAPE_SK_BOUNDING), NULL); + xcb_shape_get_rectangles_reply_t *r = xcb_shape_get_rectangles_reply(ps->c, + xcb_shape_get_rectangles(ps->c, w->id, XCB_SHAPE_SK_BOUNDING), NULL); if (!r) return; diff --git a/src/x.c b/src/x.c index 4b6e950..e7b6c57 100644 --- a/src/x.c +++ b/src/x.c @@ -104,12 +104,11 @@ bool wid_get_text_prop(session_t *ps, Window wid, Atom prop, static inline void x_get_server_pictfmts(session_t *ps) { if (ps->pictfmts) return; - xcb_connection_t *c = XGetXCBConnection(ps->dpy); xcb_generic_error_t *e = NULL; // Get window picture format ps->pictfmts = - xcb_render_query_pict_formats_reply(c, - xcb_render_query_pict_formats(c), &e); + xcb_render_query_pict_formats_reply(ps->c, + xcb_render_query_pict_formats(ps->c), &e); if (e || !ps->pictfmts) { printf_errf("(): failed to get pict formats\n"); abort(); @@ -146,10 +145,9 @@ x_create_picture_with_pictfmt_and_pixmap( } } - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - xcb_render_picture_t tmp_picture = xcb_generate_id(c); + xcb_render_picture_t tmp_picture = xcb_generate_id(ps->c); xcb_generic_error_t *e = - xcb_request_check(c, xcb_render_create_picture_checked(c, tmp_picture, + xcb_request_check(ps->c, xcb_render_create_picture_checked(ps->c, tmp_picture, pixmap, pictfmt->id, valuemask, buf)); free(buf); if (e) { @@ -209,17 +207,15 @@ x_create_picture(session_t *ps, int wid, int hei, xcb_render_picture_t picture = x_create_picture_with_pictfmt_and_pixmap(ps, pictfmt, tmp_pixmap, valuemask, attr); - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - xcb_free_pixmap(c, tmp_pixmap); + xcb_free_pixmap(ps->c, tmp_pixmap); return picture; } bool x_fetch_region(session_t *ps, xcb_xfixes_region_t r, pixman_region32_t *res) { xcb_generic_error_t *e = NULL; - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - xcb_xfixes_fetch_region_reply_t *xr = xcb_xfixes_fetch_region_reply(c, - xcb_xfixes_fetch_region(c, r), &e); + xcb_xfixes_fetch_region_reply_t *xr = xcb_xfixes_fetch_region_reply(ps->c, + xcb_xfixes_fetch_region(ps->c, r), &e); if (!xr) { printf_errf("(): failed to fetch rectangles"); return false; @@ -255,9 +251,8 @@ void x_set_picture_clip_region(session_t *ps, xcb_render_picture_t pict, .height = rects[i].y2 - rects[i].y1, }; - xcb_connection_t *c = XGetXCBConnection(ps->dpy); xcb_generic_error_t *e = - xcb_request_check(c, xcb_render_set_picture_clip_rectangles_checked(c, pict, + xcb_request_check(ps->c, xcb_render_set_picture_clip_rectangles_checked(ps->c, pict, clip_x_origin, clip_y_origin, nrects, xrects)); if (e) printf_errf("(): failed to set clip region"); @@ -371,10 +366,9 @@ x_print_error(unsigned long serial, uint8_t major, uint8_t minor, uint8_t error_ */ xcb_pixmap_t x_create_pixmap(session_t *ps, uint8_t depth, xcb_drawable_t drawable, uint16_t width, uint16_t height) { - xcb_connection_t *c = XGetXCBConnection(ps->dpy); - xcb_pixmap_t pix = xcb_generate_id(c); - xcb_void_cookie_t cookie = xcb_create_pixmap_checked(c, depth, pix, drawable, width, height); - xcb_generic_error_t *err = xcb_request_check(c, cookie); + xcb_pixmap_t pix = xcb_generate_id(ps->c); + xcb_void_cookie_t cookie = xcb_create_pixmap_checked(ps->c, depth, pix, drawable, width, height); + xcb_generic_error_t *err = xcb_request_check(ps->c, cookie); if (err == NULL) return pix; diff --git a/src/x.h b/src/x.h index b1686e6..b89acbd 100644 --- a/src/x.h +++ b/src/x.h @@ -24,6 +24,18 @@ typedef struct winprop winprop_t; r; \ }) +/** + * Send a request to X server and get the reply to make sure all previous + * requests are processed, and their replies received + * + * xcb_get_input_focus is used here because it is the same request used by + * libX11 + */ +static inline void +x_sync(xcb_connection_t *c) { + free(xcb_get_input_focus_reply(c, xcb_get_input_focus(c), NULL)); +} + /** * Get a specific attribute of a window. * From 1c1adc96c876b754142829570fc6f2ccb17e7dee Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Thu, 4 Oct 2018 09:15:38 +0200 Subject: [PATCH 17/18] Change event masks to XCB defines Signed-off-by: Uli Schlachter --- src/compton.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/compton.c b/src/compton.c index e8be515..342cb2d 100644 --- a/src/compton.c +++ b/src/compton.c @@ -792,15 +792,15 @@ should_ignore(session_t *ps, unsigned long sequence) { * Determine the event mask for a window. */ long determine_evmask(session_t *ps, Window wid, win_evmode_t mode) { - long evmask = NoEventMask; + long evmask = 0; win *w = NULL; // Check if it's a mapped frame window if (WIN_EVMODE_FRAME == mode || ((w = find_win(ps, wid)) && IsViewable == w->a.map_state)) { - evmask |= PropertyChangeMask; + evmask |= XCB_EVENT_MASK_PROPERTY_CHANGE; if (ps->o.track_focus && !ps->o.use_ewmh_active_win) - evmask |= FocusChangeMask; + evmask |= XCB_EVENT_MASK_FOCUS_CHANGE; } // Check if it's a mapped client window @@ -808,7 +808,7 @@ long determine_evmask(session_t *ps, Window wid, win_evmode_t mode) { || ((w = find_toplevel(ps, wid)) && IsViewable == w->a.map_state)) { if (ps->o.frame_opacity || ps->o.track_wdata || ps->track_atom_lst || ps->o.detect_client_opacity) - evmask |= PropertyChangeMask; + evmask |= XCB_EVENT_MASK_PROPERTY_CHANGE; } return evmask; @@ -2759,7 +2759,7 @@ ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t *ev) { // Otherwise, watch for WM_STATE on it else { xcb_change_window_attributes(ps->c, ev->window, XCB_CW_EVENT_MASK, (const uint32_t[]) { - determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN) | PropertyChangeMask }); + determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN) | XCB_EVENT_MASK_PROPERTY_CHANGE }); } } } From 9bb332754997a0acdcbab51d81fa93c5054a563d Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Thu, 4 Oct 2018 09:36:48 +0200 Subject: [PATCH 18/18] Die when the X11 connection breaks With libX11, the library calls an I/O error handler if the connection to the server breaks. The default I/O error handler prints an error message and calls exit(). This can be seen when running a "pre-xcb" compton against Xephyr and then closing the Xephyr window: XIO: fatal IO error 11 (Resource temporarily unavailable) on X server ":1" after 241 requests (241 known processed) with 0 events remaining. The current compton would just continue running. After this commit, it instead exits with this message: handle_queued_x_events(): X11 server connection broke (error 1) Signed-off-by: Uli Schlachter --- src/compton.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/compton.c b/src/compton.c index 342cb2d..ab8fbdd 100644 --- a/src/compton.c +++ b/src/compton.c @@ -4682,6 +4682,11 @@ handle_queued_x_events(EV_P_ ev_prepare *w, int revents) { }; XFlush(ps->dpy); xcb_flush(ps->c); + + int err = xcb_connection_has_error(ps->c); + if (err) { + printf_errfq(1, "(): X11 server connection broke (error %d)", err); + } } /**