From 7188054825f2cab5cd3b3d37e8d544261168eee1 Mon Sep 17 00:00:00 2001 From: Richard Grenville Date: Wed, 9 Jan 2013 20:25:01 +0800 Subject: [PATCH] Bug fix #77 incorrect border_width handling & #73 window data issue - (Hopefully) fix all incorrect handling of w->a.border_width in compton (#77). Thanks to baskerville for reporting. - Attempt to fix #73 by correcting a mistake that window data is fetched from the wrong function. Thanks to zakkak. - Add git commit/tag detection to Makefile for automatic versioning. - Change -lGL linking order, to fix a segmentation fault caused by something in nvidia-drivers under FreeBSD, mentioned in #74. Thanks for the report from DachiChang. - Link to -levent_core instead of -levent in Makefile. We might move to libev soon, though. - Increase SWOPTI_TOLERANCE to handle the extraordinary delay of kqueue() under FreeBSD. Thanks for DachiChang's report. - Add helper function dump_drawable() for debugging. - Replace XInternAtom() calls with get_atom(). - Remove -lrt as it's unneeded. --- Makefile | 16 ++++---- src/compton.c | 112 +++++++++++++++++++++++++------------------------- src/compton.h | 27 +++++++++--- 3 files changed, 87 insertions(+), 68 deletions(-) diff --git a/Makefile b/Makefile index ba47769..44450c5 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ BINDIR ?= $(PREFIX)/bin MANDIR ?= $(PREFIX)/share/man/man1 PACKAGES = x11 xcomposite xfixes xdamage xrender xext xrandr -LIBS = -lm -lrt +LIBS = -lm INCS = # === Configuration flags === @@ -22,11 +22,11 @@ ifeq "$(shell pkg-config --modversion --print-errors libevent)" "" CFG += -DCONFIG_LIBEVENT_LEGACY LIBS += -levent else - # Using pkg-config for linking with libevent will result in linking with - # libevent.so instead of the smaller libevent_core.so. But FreeBSD keeps - # libevent2 .so files at a separate place, and we must learn it from - # pkg-config. - LIBS += $(shell pkg-config --libs libevent) + # Using pkg-config --libs for linking with libevent will result in + # linking with libevent.so instead of the smaller libevent_core.so. + # FreeBSD keeps libevent2 .so files at a separate place, and we must + # learn it from pkg-config. + LIBS += $(shell pkg-config --libs-only-L libevent) -levent_core INCS += $(shell pkg-config --cflags libevent) endif @@ -58,7 +58,7 @@ endif # ==== OpenGL VSync ==== ifeq "$(NO_VSYNC_OPENGL)" "" CFG += -DCONFIG_VSYNC_OPENGL - LIBS += -lGL + LIBS := -lGL $(LIBS) endif # ==== D-Bus ==== @@ -68,7 +68,7 @@ endif # endif # === Version string === -COMPTON_VERSION ?= git-$(shell git describe --always) +COMPTON_VERSION ?= git-$(shell git describe --always --dirty)-$(shell git log -1 --date=short --pretty=format:%cd) CFG += -DCOMPTON_VERSION="\"$(COMPTON_VERSION)\"" LDFLAGS ?= -Wl,-O1 -Wl,--as-needed diff --git a/src/compton.c b/src/compton.c index 7707126..e1b8ade 100644 --- a/src/compton.c +++ b/src/compton.c @@ -939,7 +939,7 @@ root_tile_f(session_t *ps) { // Get the values of background attributes for (p = 0; background_props_str[p]; p++) { winprop_t prop = wid_get_prop(ps, ps->root, - XInternAtom(ps->dpy, background_props_str[p], false), + get_atom(ps, background_props_str[p]), 1L, XA_PIXMAP, 32); if (prop.nitems) { pixmap = *prop.data.p32; @@ -1517,10 +1517,11 @@ win_paint_win(session_t *ps, win *w, Picture tgt_buffer) { tgt_buffer, 0, 0, 0, 0, x, y, wid, hei); } else { - int t = w->top_width; - int l = w->left_width; - int b = w->bottom_width; - int r = w->right_width; + // Painting parameters + const int t = w->a.border_width + w->top_width; + const int l = w->a.border_width + w->left_width; + const int b = w->a.border_width + w->bottom_width; + const int r = w->a.border_width + w->right_width; #define COMP_BDR(cx, cy, cwid, chei) \ XRenderComposite(ps->dpy, PictOpOver, w->picture, w->frame_alpha_pict, \ @@ -1895,13 +1896,6 @@ map_win(session_t *ps, Window id) { // Detect if the window is shaped or has rounded corners win_update_shape_raw(ps, w); - // Get window name and class if we are tracking them - if (ps->o.track_wdata) { - win_get_name(ps, w); - win_get_class(ps, w); - win_get_role(ps, w); - } - // Occasionally compton does not seem able to get a FocusIn event from // a window just mapped. I suspect it's a timing issue again when the // XSelectInput() is called too late. We have to recheck the focused @@ -2287,6 +2281,14 @@ win_mark_client(session_t *ps, win *w, Window client) { if (ps->o.track_leader) win_update_leader(ps, w); + // Get window name and class if we are tracking them + if (ps->o.track_wdata) { + win_get_name(ps, w); + win_get_class(ps, w); + win_get_role(ps, w); + } + + // Update window focus state win_update_focused(ps, w); } @@ -2586,7 +2588,8 @@ configure_win(session_t *ps, XConfigureEvent *ce) { // If window geometry did not change, don't free extents here if (w->a.x != ce->x || w->a.y != ce->y - || w->a.width != ce->width || w->a.height != ce->height) { + || w->a.width != ce->width || w->a.height != ce->height + || w->a.border_width != ce->border_width) { free_region(ps, &w->extents); free_region(ps, &w->border_size); } @@ -2594,7 +2597,8 @@ configure_win(session_t *ps, XConfigureEvent *ce) { w->a.x = ce->x; w->a.y = ce->y; - if (w->a.width != ce->width || w->a.height != ce->height) { + if (w->a.width != ce->width || w->a.height != ce->height + || w->a.border_width != ce->border_width) { free_pixmap(ps, &w->pixmap); free_picture(ps, &w->picture); } @@ -3415,8 +3419,7 @@ ev_property_notify(session_t *ps, XPropertyEvent *ev) { else { // Destroy the root "image" if the wallpaper probably changed for (int p = 0; background_props_str[p]; p++) { - if (ev->atom == - XInternAtom(ps->dpy, background_props_str[p], false)) { + if (ev->atom == get_atom(ps, background_props_str[p])) { root_damaged(ps); break; } @@ -3911,7 +3914,7 @@ register_cm(session_t *ps, bool want_glxct) { buf = malloc(len); snprintf(buf, len, REGISTER_PROP"%d", ps->scr); - a = XInternAtom(ps->dpy, buf, false); + a = get_atom(ps, buf); free(buf); XSetSelectionOwner(ps->dpy, a, ps->reg_win, 0); @@ -4598,49 +4601,48 @@ get_cfg(session_t *ps, int argc, char *const *argv) { */ static void init_atoms(session_t *ps) { - ps->atom_opacity = XInternAtom(ps->dpy, "_NET_WM_WINDOW_OPACITY", False); - ps->atom_frame_extents = XInternAtom(ps->dpy, "_NET_FRAME_EXTENTS", False); - ps->atom_client = XInternAtom(ps->dpy, "WM_STATE", False); + ps->atom_opacity = get_atom(ps, "_NET_WM_WINDOW_OPACITY"); + ps->atom_frame_extents = get_atom(ps, "_NET_FRAME_EXTENTS"); + ps->atom_client = get_atom(ps, "WM_STATE"); ps->atom_name = XA_WM_NAME; - ps->atom_name_ewmh = XInternAtom(ps->dpy, "_NET_WM_NAME", False); + ps->atom_name_ewmh = get_atom(ps, "_NET_WM_NAME"); ps->atom_class = XA_WM_CLASS; - ps->atom_role = XInternAtom(ps->dpy, "WM_WINDOW_ROLE", False); + ps->atom_role = get_atom(ps, "WM_WINDOW_ROLE"); ps->atom_transient = XA_WM_TRANSIENT_FOR; - ps->atom_client_leader = XInternAtom(ps->dpy, "WM_CLIENT_LEADER", False); - ps->atom_ewmh_active_win = XInternAtom(ps->dpy, "_NET_ACTIVE_WINDOW", False); - ps->atom_compton_shadow = XInternAtom(ps->dpy, "_COMPTON_SHADOW", False); + ps->atom_client_leader = get_atom(ps, "WM_CLIENT_LEADER"); + ps->atom_ewmh_active_win = get_atom(ps, "_NET_ACTIVE_WINDOW"); + ps->atom_compton_shadow = get_atom(ps, "_COMPTON_SHADOW"); - ps->atom_win_type = XInternAtom(ps->dpy, - "_NET_WM_WINDOW_TYPE", False); + ps->atom_win_type = get_atom(ps, "_NET_WM_WINDOW_TYPE"); ps->atoms_wintypes[WINTYPE_UNKNOWN] = 0; - ps->atoms_wintypes[WINTYPE_DESKTOP] = XInternAtom(ps->dpy, - "_NET_WM_WINDOW_TYPE_DESKTOP", False); - ps->atoms_wintypes[WINTYPE_DOCK] = XInternAtom(ps->dpy, - "_NET_WM_WINDOW_TYPE_DOCK", False); - ps->atoms_wintypes[WINTYPE_TOOLBAR] = XInternAtom(ps->dpy, - "_NET_WM_WINDOW_TYPE_TOOLBAR", False); - ps->atoms_wintypes[WINTYPE_MENU] = XInternAtom(ps->dpy, - "_NET_WM_WINDOW_TYPE_MENU", False); - ps->atoms_wintypes[WINTYPE_UTILITY] = XInternAtom(ps->dpy, - "_NET_WM_WINDOW_TYPE_UTILITY", False); - ps->atoms_wintypes[WINTYPE_SPLASH] = XInternAtom(ps->dpy, - "_NET_WM_WINDOW_TYPE_SPLASH", False); - ps->atoms_wintypes[WINTYPE_DIALOG] = XInternAtom(ps->dpy, - "_NET_WM_WINDOW_TYPE_DIALOG", False); - ps->atoms_wintypes[WINTYPE_NORMAL] = XInternAtom(ps->dpy, - "_NET_WM_WINDOW_TYPE_NORMAL", False); - ps->atoms_wintypes[WINTYPE_DROPDOWN_MENU] = XInternAtom(ps->dpy, - "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", False); - ps->atoms_wintypes[WINTYPE_POPUP_MENU] = XInternAtom(ps->dpy, - "_NET_WM_WINDOW_TYPE_POPUP_MENU", False); - ps->atoms_wintypes[WINTYPE_TOOLTIP] = XInternAtom(ps->dpy, - "_NET_WM_WINDOW_TYPE_TOOLTIP", False); - ps->atoms_wintypes[WINTYPE_NOTIFY] = XInternAtom(ps->dpy, - "_NET_WM_WINDOW_TYPE_NOTIFICATION", False); - ps->atoms_wintypes[WINTYPE_COMBO] = XInternAtom(ps->dpy, - "_NET_WM_WINDOW_TYPE_COMBO", False); - ps->atoms_wintypes[WINTYPE_DND] = XInternAtom(ps->dpy, - "_NET_WM_WINDOW_TYPE_DND", False); + ps->atoms_wintypes[WINTYPE_DESKTOP] = get_atom(ps, + "_NET_WM_WINDOW_TYPE_DESKTOP"); + ps->atoms_wintypes[WINTYPE_DOCK] = get_atom(ps, + "_NET_WM_WINDOW_TYPE_DOCK"); + ps->atoms_wintypes[WINTYPE_TOOLBAR] = get_atom(ps, + "_NET_WM_WINDOW_TYPE_TOOLBAR"); + ps->atoms_wintypes[WINTYPE_MENU] = get_atom(ps, + "_NET_WM_WINDOW_TYPE_MENU"); + ps->atoms_wintypes[WINTYPE_UTILITY] = get_atom(ps, + "_NET_WM_WINDOW_TYPE_UTILITY"); + ps->atoms_wintypes[WINTYPE_SPLASH] = get_atom(ps, + "_NET_WM_WINDOW_TYPE_SPLASH"); + ps->atoms_wintypes[WINTYPE_DIALOG] = get_atom(ps, + "_NET_WM_WINDOW_TYPE_DIALOG"); + ps->atoms_wintypes[WINTYPE_NORMAL] = get_atom(ps, + "_NET_WM_WINDOW_TYPE_NORMAL"); + ps->atoms_wintypes[WINTYPE_DROPDOWN_MENU] = get_atom(ps, + "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"); + ps->atoms_wintypes[WINTYPE_POPUP_MENU] = get_atom(ps, + "_NET_WM_WINDOW_TYPE_POPUP_MENU"); + ps->atoms_wintypes[WINTYPE_TOOLTIP] = get_atom(ps, + "_NET_WM_WINDOW_TYPE_TOOLTIP"); + ps->atoms_wintypes[WINTYPE_NOTIFY] = get_atom(ps, + "_NET_WM_WINDOW_TYPE_NOTIFICATION"); + ps->atoms_wintypes[WINTYPE_COMBO] = get_atom(ps, + "_NET_WM_WINDOW_TYPE_COMBO"); + ps->atoms_wintypes[WINTYPE_DND] = get_atom(ps, + "_NET_WM_WINDOW_TYPE_DND"); } /** diff --git a/src/compton.h b/src/compton.h index c7d65d3..9bf25e2 100644 --- a/src/compton.h +++ b/src/compton.h @@ -128,7 +128,7 @@ typedef void(* event_callback_fn)(evutil_socket_t, short, void *); #define REGISTER_PROP "_NET_WM_CM_S" #define FADE_DELTA_TOLERANCE 0.2 -#define SWOPTI_TOLERANCE 1000 +#define SWOPTI_TOLERANCE 3000 #define WIN_GET_LEADER_MAX_RECURSION 20 #define SEC_WRAP (15L * 24L * 60L * 60L) @@ -879,10 +879,10 @@ static int should_ignore(session_t *ps, unsigned long sequence); /** - * Wrapper of XInternAtom() for convience. + * Wrapper of XInternAtom() for convenience. */ static inline Atom -get_atom(session_t *ps, char *atom_name) { +get_atom(session_t *ps, const char *atom_name) { return XInternAtom(ps->dpy, atom_name, False); } @@ -1530,8 +1530,25 @@ update_reg_ignore_expire(session_t *ps, const win *w) { */ static inline bool __attribute__((const)) win_has_frame(const win *w) { - return w->top_width || w->left_width || w->right_width - || w->bottom_width; + return w->a.border_width + || w->top_width || w->left_width || w->right_width || w->bottom_width; +} + +/** + * Dump an drawable's info. + */ +static inline void +dump_drawable(session_t *ps, Drawable drawable) { + Window rroot = None; + int x = 0, y = 0; + unsigned width = 0, height = 0, border = 0, depth = 0; + if (XGetGeometry(ps->dpy, drawable, &rroot, &x, &y, &width, &height, + &border, &depth)) { + printf_dbgf("(%#010lx): x = %u, y = %u, wid = %u, hei = %d, b = %u, d = %u\n", drawable, x, y, width, height, border, depth); + } + else { + printf_dbgf("(%#010lx): Failed\n", drawable); + } } /**