[hackers] [wmii] Better, cleaner error handling. || Kris Maglione

From: <hg_AT_suckless.org>
Date: Sun, 12 Oct 2008 00:31:21 +0000 (UTC)

changeset: 2349:fe9282224a76
user: Kris Maglione <jg_AT_suckless.org>
date: Sat Oct 11 19:05:24 2008 -0400
files: cmd/wmii/client.c cmd/wmii/layout.c cmd/wmii/main.c cmd/wmii/view.c cmd/wmii/x11.c include/x11.h
description:
Better, cleaner error handling.

diff -r 8044f5372bf7 -r fe9282224a76 cmd/wmii/client.c
--- a/cmd/wmii/client.c Mon Sep 29 11:10:54 2008 -0400
+++ b/cmd/wmii/client.c Sat Oct 11 19:05:24 2008 -0400
@@ -159,7 +159,6 @@
 
         p.x = def.border;
         p.y = labelh(def.font);
- reparentwindow(&c->w, c->framewin, p);
 
         group_init(c);
 
@@ -172,6 +171,20 @@
                         break;
                 }
 
+
+ /*
+ * It's actually possible for a window to be destroyed
+ * before we get a chance to reparant it. Check for that
+ * now, because otherwise we'll wind up mapping an empty
+ * frame.
+ */
+ traperrors(true);
+ reparentwindow(&c->w, c->framewin, p);
+ if(traperrors(false)) {
+ client_destroy(c);
+ return nil;
+ }
+
         ewmh_initclient(c);
 
         event("CreateClient %C\n", c);
@@ -181,7 +194,7 @@
 
 void
 client_manage(Client *c) {
- Client *trans;
+ Client *leader;
         Frame *f;
         char *tags;
 
@@ -192,14 +205,14 @@
 
         tags = getprop_string(&c->w, "_WMII_TAGS");
 
- trans = win2client(c->trans);
- if(trans == nil && c->group)
- trans = group_leader(c->group);
+ leader = win2client(c->trans);
+ if(leader == nil && c->group)
+ leader = group_leader(c->group);
 
- if(tags && (!trans || starting))
+ if(tags && (!leader || leader == c || starting))
                 utflcpy(c->tags, tags, sizeof c->tags);
- else if(trans)
- utflcpy(c->tags, trans->tags, sizeof c->tags);
+ else if(leader)
+ utflcpy(c->tags, leader->tags, sizeof c->tags);
         free(tags);
 
         if(!c->tags[0])
@@ -231,15 +244,8 @@
         }
 }
 
-static int /* Temporary Xlib error handler */
-ignoreerrors(Display *d, XErrorEvent *e) {
- USED(d, e);
- return 0;
-}
-
 void
 client_destroy(Client *c) {
- int (*handler)(Display*, XErrorEvent*);
         Rectangle r;
         char *none;
         Client **tc;
@@ -261,8 +267,9 @@
                 hide = true;
 
         XGrabServer(display);
+
         /* In case the client is already destroyed. */
- handler = XSetErrorHandler(ignoreerrors);
+ traperrors(true);
 
         sethandler(&c->w, nil);
         if(hide)
@@ -270,8 +277,7 @@
         else
                 reparentwindow(&c->w, &scr.root, r.min);
 
- sync();
- XSetErrorHandler(handler);
+ traperrors(false);
         XUngrabServer(display);
 
         none = nil;
diff -r 8044f5372bf7 -r fe9282224a76 cmd/wmii/layout.c
--- a/cmd/wmii/layout.c Mon Sep 29 11:10:54 2008 -0400
+++ b/cmd/wmii/layout.c Sat Oct 11 19:05:24 2008 -0400
@@ -235,10 +235,15 @@
 trampoline(int fn, Frame *f) {
 
         while(fn > 0) {
+ resizing = fn != TFloat;
+ view_update(f->view);
+ warppointer(grabboxcenter(f));
                 //f->collapsed = false;
                 fn = tramp[fn](f);
         }
         ungrabpointer();
+ resizing = false;
+ view_update(f->view);
 }
 
 void
@@ -255,17 +260,11 @@
                 y = (float)p.y / Dy(f->r);
         }
 
- resizing = true;
- view_update(f->view);
- warppointer(grabboxcenter(f));
-
         if(f->area->floating)
                 trampoline(TFloat, f);
         else
                 trampoline(THCol, f);
 
- resizing = false;
- view_update(f->view);
         if(grabmod)
                 warppointer(addpt(f->r.min, Pt(x * Dx(f->r),
                                                y * Dy(f->r))));
diff -r 8044f5372bf7 -r fe9282224a76 cmd/wmii/main.c
--- a/cmd/wmii/main.c Mon Sep 29 11:10:54 2008 -0400
+++ b/cmd/wmii/main.c Sat Oct 11 19:05:24 2008 -0400
@@ -17,10 +17,8 @@
 static const char
         version[] = "wmii-"VERSION", ©2008 Kris Maglione\n";
 
-static int (*xlib_errorhandler) (Display*, XErrorEvent*);
 static char* address;
 static char* ns_path;
-static bool check_other_wm;
 static int sleeperfd;
 static int sock;
 static int exitsignal;
@@ -136,6 +134,23 @@
         XFreePixmap(display, pix);
 }
 
+/*
+ * There's no way to check accesses to destroyed windows, thus
+ * those cases are ignored (especially on UnmapNotifies).
+ * Other types of errors call Xlib's default error handler, which
+ * calls exit().
+ */
+ErrorCode ignored_xerrors[] = {
+ { 0, BadWindow },
+ { X_SetInputFocus, BadMatch },
+ { X_PolyText8, BadDrawable },
+ { X_PolyFillRectangle, BadDrawable },
+ { X_PolySegment, BadDrawable },
+ { X_ConfigureWindow, BadMatch },
+ { X_GrabKey, BadAccess },
+ { X_GetAtomName, BadAtom },
+};
+
 void
 init_screen(WMScreen *screen) {
 
@@ -155,51 +170,6 @@
                 client_destroy(client);
         ixp_server_close(&srv);
         close(sleeperfd);
-}
-
-/*
- * There's no way to check accesses to destroyed windows, thus
- * those cases are ignored (especially on UnmapNotifies).
- * Other types of errors call Xlib's default error handler, which
- * calls exit().
- */
-static int
-errorhandler(Display *dpy, XErrorEvent *error) {
- static struct {
- uchar rcode, ecode;
- } itab[] = {
- { 0, BadWindow },
- { X_SetInputFocus, BadMatch },
- { X_PolyText8, BadDrawable },
- { X_PolyFillRectangle, BadDrawable },
- { X_PolySegment, BadDrawable },
- { X_ConfigureWindow, BadMatch },
- { X_GrabKey, BadAccess },
- { X_GetAtomName, BadAtom },
- };
- static int dead;
- int i;
-
- USED(dpy);
-
- if(check_other_wm)
- fatal("another window manager is already running");
-
- for(i = 0; i < nelem(itab); i++)
- if((itab[i].rcode == 0 || itab[i].rcode == error->request_code)
- && (itab[i].ecode == 0 || itab[i].ecode == error->error_code))
- return 0;
-
- fprint(2, "%s: fatal error: Xrequest code=%d, Xerror code=%d\n",
- argv0, error->request_code, error->error_code);
-
- /* Try to cleanup, but only try once, in case we're called recursively. */
- USED(dead);
-#ifdef notdef
- if(!dead++)
- cleanup();
-#endif
- return xlib_errorhandler(display, error); /* calls exit() */
 }
 
 static void
@@ -338,14 +308,12 @@
 
         initdisplay();
 
- xlib_errorhandler = XSetErrorHandler(errorhandler);
-
- check_other_wm = true;
+ traperrors(true);
         selectinput(&scr.root, SubstructureRedirectMask
                              | EnterWindowMask);
         sync();
-
- check_other_wm = false;
+ if(traperrors(false))
+ fatal("another window manager is already running");
 
         passwd = getpwuid(getuid());
         user = estrdup(passwd->pw_name);
diff -r 8044f5372bf7 -r fe9282224a76 cmd/wmii/view.c
--- a/cmd/wmii/view.c Mon Sep 29 11:10:54 2008 -0400
+++ b/cmd/wmii/view.c Sat Oct 11 19:05:24 2008 -0400
@@ -252,10 +252,11 @@
 
         for(c=client; c; c=c->next) {
                 f = c->sel;
- if(f && f->view == v
- && !(f->area && f->area->max && f->area->floating && f->area != v->sel))
- client_resize(c, f->r);
- else {
+ if((f && f->view == v)
+ && (f->area == v->sel || !(f->area && f->area->max && f->area->floating))) {
+ if(f->area)
+ client_resize(c, f->r);
+ }else {
                         unmap_frame(c);
                         client_unmap(c, IconicState);
                 }
@@ -304,8 +305,11 @@
         
         c = f->client;
 
- oldsel = nil;
+ oldsel = v->oldsel;
         a = v->sel;
+ print("view: %s\n", v->name);
+ print("client: %C\n", c);
+ print("< sel: %a\n", v->sel);
         if(client_floats_p(c)) {
                 if(v->sel != v->area)
                         oldsel = v->sel;
@@ -323,6 +327,7 @@
                 else if(starting || c->sel && c->sel->area && !c->sel->area->floating)
                         a = v->area->next;
         }
+ print("< sel: %a oldsel: %a\n", v->sel, oldsel);
 
         area_attach(a, f);
         /* TODO: Decide whether to focus this frame */
@@ -341,6 +346,7 @@
 
         if(oldsel)
                 v->oldsel = oldsel;
+ print("< sel: %a oldsel: %a\n", v->sel, oldsel);
 
         if(c->sel == nil)
                 c->sel = f;
diff -r 8044f5372bf7 -r fe9282224a76 cmd/wmii/x11.c
--- a/cmd/wmii/x11.c Mon Sep 29 11:10:54 2008 -0400
+++ b/cmd/wmii/x11.c Sat Oct 11 19:05:24 2008 -0400
@@ -26,6 +26,9 @@
 static Map atommap;
 static MapEnt* wbucket[137];
 static MapEnt* abucket[137];
+
+static int errorhandler(Display*, XErrorEvent*);
+static int (*xlib_errorhandler) (Display*, XErrorEvent*);
 
 
 /* Rectangles/Points */
@@ -185,6 +188,46 @@
         fmtinstall('R', Rfmt);
         fmtinstall('P', Pfmt);
         fmtinstall('W', Wfmt);
+
+ xlib_errorhandler = XSetErrorHandler(errorhandler);
+}
+
+/* Error handling */
+
+ErrorCode ignored_xerrors[];
+static bool _trap_errors;
+static long nerrors;
+
+static int
+errorhandler(Display *dpy, XErrorEvent *error) {
+ ErrorCode *e;
+
+ USED(dpy);
+
+ if(_trap_errors)
+ nerrors++;
+
+ e = ignored_xerrors;
+ if(e)
+ for(; e->rcode || e->ecode; e++)
+ if((e->rcode == 0 || e->rcode == error->request_code)
+ && (e->ecode == 0 || e->ecode == error->error_code))
+ return 0;
+
+ fprint(2, "%s: fatal error: Xrequest code=%d, Xerror code=%d\n",
+ argv0, error->request_code, error->error_code);
+ return xlib_errorhandler(display, error); /* calls exit() */
+}
+
+int
+traperrors(bool enable) {
+
+ sync();
+ _trap_errors = enable;
+ if (enable)
+ nerrors = 0;
+ return nerrors;
+
 }
 
 /* Images */
diff -r 8044f5372bf7 -r fe9282224a76 include/x11.h
--- a/include/x11.h Mon Sep 29 11:10:54 2008 -0400
+++ b/include/x11.h Sat Oct 11 19:05:24 2008 -0400
@@ -48,6 +48,7 @@
 };
 
 typedef struct CTuple CTuple;
+typedef struct ErrorCode ErrorCode;
 typedef struct Ewmh Ewmh;
 typedef struct Font Font;
 typedef struct Handlers Handlers;
@@ -61,6 +62,11 @@
         ulong fg;
         ulong border;
         char colstr[24]; /* #RRGGBB #RRGGBB #RRGGBB */
+};
+
+struct ErrorCode {
+ uchar rcode;
+ uchar ecode;
 };
 
 struct Ewmh {
@@ -234,6 +240,7 @@
 void sync(void);
 uint textwidth(Font*, char*);
 uint textwidth_l(Font*, char*, uint len);
+int traperrors(bool);
 Point translate(Window*, Window*, Point);
 void ungrabpointer(void);
 int unmapwin(Window*);
Received on Sun Oct 12 2008 - 00:31:21 UTC

This archive was generated by hypermail 2.2.0 : Sun Oct 12 2008 - 00:36:05 UTC