summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Grenville <[email protected]>2012-09-11 21:33:03 +0800
committerRichard Grenville <[email protected]>2012-09-11 21:33:03 +0800
commitf7bf27f8380cda8c8c27cbfa19c9a656d638b39a (patch)
tree7fba94cc62ce1c52cde9c9625a07c049823b2c94
parentfe811d6451944e6643a8bfae13050b23bf7254c9 (diff)
downloadtdebase-f7bf27f8380cda8c8c27cbfa19c9a656d638b39a.tar.gz
tdebase-f7bf27f8380cda8c8c27cbfa19c9a656d638b39a.zip
Bug fix: Issue #36: Chromium window painting problems
More descriptions on issue #36. - Listens ShapeNotify event to get around the Chromium window painting issues. - Adds dependency on X Shape extension. - Adds a few functions for convenience, so a bit code clean up. - Better event debug support, adds restack_win() debug.
-rw-r--r--compton.c229
-rw-r--r--compton.h39
2 files changed, 244 insertions, 24 deletions
diff --git a/compton.c b/compton.c
index 0272615ba..c3af63213 100644
--- a/compton.c
+++ b/compton.c
@@ -10,6 +10,10 @@
#include "compton.h"
+#if DEBUG_EVENTS
+static int window_get_name(Window w, char **name);
+#endif
+
/**
* Shared
*/
@@ -36,6 +40,10 @@ ignore *ignore_head, **ignore_tail = &ignore_head;
int xfixes_event, xfixes_error;
int damage_event, damage_error;
int composite_event, composite_error;
+/// Whether X Shape extension exists.
+Bool shape_exists = True;
+/// Event base number and error base number for X Shape extension.
+int shape_event, shape_error;
int render_event, render_error;
int composite_opcode;
@@ -954,12 +962,7 @@ paint_all(Display *dpy, XserverRegion region) {
win *t = 0;
if (!region) {
- XRectangle r;
- r.x = 0;
- r.y = 0;
- r.width = root_width;
- r.height = root_height;
- region = XFixesCreateRegion(dpy, &r, 1);
+ region = get_screen_region(dpy);
}
#if MONITOR_REPAINT
@@ -1029,11 +1032,7 @@ paint_all(Display *dpy, XserverRegion region) {
#endif
if (clip_changed) {
- if (w->border_size) {
- set_ignore(dpy, NextRequest(dpy));
- XFixesDestroyRegion(dpy, w->border_size);
- w->border_size = None;
- }
+ win_free_border_size(dpy, w);
if (w->extents) {
XFixesDestroyRegion(dpy, w->extents);
w->extents = None;
@@ -1376,6 +1375,10 @@ map_win(Display *dpy, Window id,
so that no property changes are lost */
if (!override_redirect) {
XSelectInput(dpy, id, PropertyChangeMask | FocusChangeMask);
+ // Notify compton when the shape of a window changes
+ if (shape_exists) {
+ XShapeSelectInput(dpy, id, ShapeNotifyMask);
+ }
}
// this causes problems for inactive transparency
@@ -1429,11 +1432,7 @@ finish_unmap_win(Display *dpy, win *w) {
w->picture = None;
}
- if (w->border_size) {
- set_ignore(dpy, NextRequest(dpy));
- XFixesDestroyRegion(dpy, w->border_size);
- w->border_size = None;
- }
+ win_free_border_size(dpy, w);
if (w->shadow) {
XRenderFreePicture(dpy, w->shadow);
@@ -1696,6 +1695,33 @@ restack_win(Display *dpy, win *w, Window new_above) {
w->next = *prev;
*prev = w;
+
+#if DEBUG_RESTACK
+ {
+ const char *desc;
+ char *window_name;
+ Bool to_free;
+ win* c = list;
+
+ printf("restack_win(%#010lx, %#010lx): Window stack modified. Current stack:\n", w->id, new_above);
+ for (; c; c = c->next) {
+ window_name = "(Failed to get title)";
+ if (root == c->id)
+ window_name = "(Root window)";
+ else
+ to_free = window_get_name(c->id, &window_name);
+ desc = "";
+ if (c->destroyed)
+ desc = "(D) ";
+ printf("%#010lx \"%s\" %s-> ", c->id, window_name, desc);
+ if (to_free) {
+ XFree(window_name);
+ window_name = NULL;
+ }
+ }
+ fputs("\n", stdout);
+ }
+#endif
}
}
@@ -1961,6 +1987,60 @@ error(Display *dpy, XErrorEvent *ev) {
break;
}
+ switch (ev->error_code) {
+ case BadAccess:
+ name = "BadAccess";
+ break;
+ case BadAlloc:
+ name = "BadAlloc";
+ break;
+ case BadAtom:
+ name = "BadAtom";
+ break;
+ case BadColor:
+ name = "BadColor";
+ break;
+ case BadCursor:
+ name = "BadCursor";
+ break;
+ case BadDrawable:
+ name = "BadDrawable";
+ break;
+ case BadFont:
+ name = "BadFont";
+ break;
+ case BadGC:
+ name = "BadGC";
+ break;
+ case BadIDChoice:
+ name = "BadIDChoice";
+ break;
+ case BadImplementation:
+ name = "BadImplementation";
+ break;
+ case BadLength:
+ name = "BadLength";
+ break;
+ case BadMatch:
+ name = "BadMatch";
+ break;
+ case BadName:
+ name = "BadName";
+ break;
+ case BadPixmap:
+ name = "BadPixmap";
+ break;
+ case BadRequest:
+ name = "BadRequest";
+ break;
+ case BadValue:
+ name = "BadValue";
+ break;
+ case BadWindow:
+ name = "BadWindow";
+ break;
+ }
+
printf("error %d (%s) request %d minor %d serial %lu\n",
ev->error_code, name, ev->request_code,
ev->minor_code, ev->serial);
@@ -1974,10 +2054,36 @@ expose_root(Display *dpy, Window root, XRectangle *rects, int nrects) {
add_damage(dpy, region);
}
-#if DEBUG_EVENTS
+#if DEBUG_EVENTS || DEBUG_RESTACK
+static int window_get_name(Window w, char **name) {
+ Atom prop = XInternAtom(dpy, "_NET_WM_NAME", False);
+ Atom utf8_type = XInternAtom(dpy, "UTF8_STRING", False);
+ Atom actual_type;
+ int actual_format;
+ unsigned long nitems;
+ unsigned long leftover;
+ char *data = NULL;
+ Status ret;
+
+ set_ignore(dpy, NextRequest(dpy));
+ if (Success != (ret = XGetWindowProperty(dpy, w, prop, 0L, (long) BUFSIZ,
+ False, utf8_type, &actual_type, &actual_format, &nitems,
+ &leftover, (unsigned char **) &data))) {
+ if (BadWindow == ret)
+ return 0;
+ set_ignore(dpy, NextRequest(dpy));
+ printf("Window %#010lx: _NET_WM_NAME unset, falling back to WM_NAME.\n", w);
+ if (!XFetchName(dpy, w, &data))
+ return 0;
+ }
+ // if (actual_type == utf8_type && actual_format == 8)
+ *name = (char *) data;
+ return 1;
+}
+
static int
ev_serial(XEvent *ev) {
- if (ev->type & 0x7f != KeymapNotify) {
+ if ((ev->type & 0x7f) != KeymapNotify) {
return ev->xany.serial;
}
return NextRequest(ev->xany.display);
@@ -1987,8 +2093,16 @@ static char *
ev_name(XEvent *ev) {
static char buf[128];
switch (ev->type & 0x7f) {
- case Expose:
- return "Expose";
+ case FocusIn:
+ return "FocusIn";
+ case FocusOut:
+ return "FocusOut";
+ case CreateNotify:
+ return "CreateNotify";
+ case ConfigureNotify:
+ return "ConfigureNotify";
+ case DestroyNotify:
+ return "DestroyNotify";
case MapNotify:
return "Map";
case UnmapNotify:
@@ -1997,10 +2111,16 @@ ev_name(XEvent *ev) {
return "Reparent";
case CirculateNotify:
return "Circulate";
+ case Expose:
+ return "Expose";
+ case PropertyNotify:
+ return "PropertyNotify";
default:
if (ev->type == damage_event + XDamageNotify) {
return "Damage";
}
+ if (shape_exists && ev->type == shape_event)
+ return "ShapeNotify";
sprintf(buf, "Event %d", ev->type);
return buf;
}
@@ -2009,8 +2129,13 @@ ev_name(XEvent *ev) {
static Window
ev_window(XEvent *ev) {
switch (ev->type) {
- case Expose:
- return ev->xexpose.window;
+ case FocusIn:
+ case FocusOut:
+ return ev->xfocus.window;
+ case CreateNotify:
+ return ev->xcreatewindow.window;
+ case ConfigureNotify:
+ return ev->xconfigure.window;
case MapNotify:
return ev->xmap.window;
case UnmapNotify:
@@ -2019,10 +2144,16 @@ ev_window(XEvent *ev) {
return ev->xreparent.window;
case CirculateNotify:
return ev->xcirculate.window;
+ case Expose:
+ return ev->xexpose.window;
+ case PropertyNotify:
+ return ev->xproperty.window;
default:
if (ev->type == damage_event + XDamageNotify) {
return ((XDamageNotifyEvent *)ev)->drawable;
}
+ if (shape_exists && ev->type == shape_event)
+ return ((XShapeEvent *) ev)->window;
return 0;
}
}
@@ -2068,6 +2199,9 @@ ev_create_notify(XCreateWindowEvent *ev) {
inline static void
ev_configure_notify(XConfigureEvent *ev) {
+#if DEBUG_EVENTS
+ printf("{ send_event: %d, above: %#010lx, override_redirect: %d }\n", ev->send_event, ev->above, ev->override_redirect);
+#endif
configure_win(dpy, ev);
}
@@ -2168,16 +2302,56 @@ ev_damage_notify(XDamageNotifyEvent *ev) {
damage_win(dpy, ev);
}
+static void ev_shape_notify(XShapeEvent *ev) {
+ win *w = find_win(dpy, ev->window);
+
+ /*
+ * Empty border_size may indicated an
+ * unmapped/destroyed window, in which case
+ * seemingly BadRegion errors would be triggered
+ * if we attempt to rebuild border_size
+ */
+ if (w->border_size) {
+ // Mark the old border_size as damaged
+ add_damage(dpy, w->border_size);
+
+ w->border_size = border_size(dpy, w);
+
+ // Mark the new border_size as damaged
+ add_damage(dpy, copy_region(dpy, w->border_size));
+ }
+
+}
+
inline static void
ev_handle(XEvent *ev) {
+
+#if DEBUG_EVENTS
+ Window w;
+ char *window_name;
+ Bool to_free = False;
+#endif
+
if ((ev->type & 0x7f) != KeymapNotify) {
discard_ignore(dpy, ev->xany.serial);
}
#if DEBUG_EVENTS
+ w = ev_window(ev);
+ window_name = "(Failed to get title)";
+ if (w) {
+ if (root == w)
+ window_name = "(Root window)";
+ else
+ to_free = (Bool) window_get_name(w, &window_name);
+ }
if (ev->type != damage_event + XDamageNotify) {
- printf("event %10.10s serial 0x%08x window 0x%08x\n",
- ev_name(ev), ev_serial(ev), ev_window(ev));
+ printf("event %10.10s serial %#010x window %#010lx \"%s\"\n",
+ ev_name(ev), ev_serial(ev), w, window_name);
+ }
+ if (to_free) {
+ XFree(window_name);
+ window_name = NULL;
}
#endif
@@ -2216,6 +2390,10 @@ ev_handle(XEvent *ev) {
ev_property_notify((XPropertyEvent *)ev);
break;
default:
+ if (shape_exists && ev->type == shape_event) {
+ ev_shape_notify((XShapeEvent *) ev);
+ break;
+ }
if (ev->type == damage_event + XDamageNotify) {
ev_damage_notify((XDamageNotifyEvent *)ev);
}
@@ -2528,6 +2706,9 @@ main(int argc, char **argv) {
exit(1);
}
+ if (!XShapeQueryExtension(dpy, &shape_event, &shape_error))
+ shape_exists = False;
+
register_cm(scr);
if (fork_after_register) fork_after();
diff --git a/compton.h b/compton.h
index 18e385989..6f30391d0 100644
--- a/compton.h
+++ b/compton.h
@@ -20,6 +20,7 @@
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xdamage.h>
#include <X11/extensions/Xrender.h>
+#include <X11/extensions/shape.h>
#if COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 2
#define HAS_NAME_WINDOW_PIXMAP 1
@@ -28,6 +29,7 @@
#define CAN_DO_USABLE 0
#define DEBUG_REPAINT 0
#define DEBUG_EVENTS 0
+#define DEBUG_RESTACK 0
#define DEBUG_WINTYPE 0
#define MONITOR_REPAINT 0
@@ -124,6 +126,7 @@ typedef struct _fade {
Display *dpy;
} fade;
+extern int root_height, root_width;
/**
* Functions
*/
@@ -345,6 +348,42 @@ ev_property_notify(XPropertyEvent *ev);
inline static void
ev_damage_notify(XDamageNotifyEvent *ev);
+/**
+ * Destory the cached border_size of a window.
+ */
+inline static void win_free_border_size(Display *dpy, win *w) {
+ if (w->border_size) {
+ set_ignore(dpy, NextRequest(dpy));
+ XFixesDestroyRegion(dpy, w->border_size);
+ w->border_size = None;
+ }
+}
+
+/**
+ * Get a region of the screen size.
+ */
+inline static XserverRegion get_screen_region(Display *dpy) {
+ XRectangle r;
+
+ r.x = 0;
+ r.y = 0;
+ r.width = root_width;
+ r.height = root_height;
+ return XFixesCreateRegion(dpy, &r, 1);
+}
+
+/**
+ * Copies a region
+ */
+inline static XserverRegion copy_region(Display *dpy,
+ XserverRegion oldregion) {
+ XserverRegion region = XFixesCreateRegion(dpy, NULL, 0);
+
+ XFixesCopyRegion(dpy, region, oldregion);
+
+ return region;
+}
+
inline static void
ev_handle(XEvent *ev);