mirror of https://github.com/0intro/wmii
Better, cleaner error handling.
This commit is contained in:
parent
f4f492efd8
commit
812f07a6a1
|
@ -159,7 +159,6 @@ client_create(XWindow w, XWindowAttributes *wa) {
|
|||
|
||||
p.x = def.border;
|
||||
p.y = labelh(def.font);
|
||||
reparentwindow(&c->w, c->framewin, p);
|
||||
|
||||
group_init(c);
|
||||
|
||||
|
@ -172,6 +171,20 @@ client_create(XWindow w, XWindowAttributes *wa) {
|
|||
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 @@ client_create(XWindow w, XWindowAttributes *wa) {
|
|||
|
||||
void
|
||||
client_manage(Client *c) {
|
||||
Client *trans;
|
||||
Client *leader;
|
||||
Frame *f;
|
||||
char *tags;
|
||||
|
||||
|
@ -192,14 +205,14 @@ client_manage(Client *c) {
|
|||
|
||||
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 @@ client_manage(Client *c) {
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ client_destroy(Client *c) {
|
|||
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 @@ client_destroy(Client *c) {
|
|||
else
|
||||
reparentwindow(&c->w, &scr.root, r.min);
|
||||
|
||||
sync();
|
||||
XSetErrorHandler(handler);
|
||||
traperrors(false);
|
||||
XUngrabServer(display);
|
||||
|
||||
none = nil;
|
||||
|
|
|
@ -235,10 +235,15 @@ static void
|
|||
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 @@ mouse_movegrabbox(Client *c, bool grabmod) {
|
|||
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))));
|
||||
|
|
|
@ -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 @@ init_cursors(void) {
|
|||
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) {
|
||||
|
||||
|
@ -157,51 +172,6 @@ cleanup(void) {
|
|||
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
|
||||
cleanup_handler(int signal) {
|
||||
sa.sa_handler = SIG_DFL;
|
||||
|
@ -338,14 +308,12 @@ extern int fmtevent(Fmt*);
|
|||
|
||||
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);
|
||||
|
|
|
@ -252,10 +252,11 @@ view_update(View *v) {
|
|||
|
||||
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 @@ view_attach(View *v, Frame *f) {
|
|||
|
||||
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 @@ view_attach(View *v, Frame *f) {
|
|||
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 @@ view_attach(View *v, Frame *f) {
|
|||
|
||||
if(oldsel)
|
||||
v->oldsel = oldsel;
|
||||
print("< sel: %a oldsel: %a\n", v->sel, oldsel);
|
||||
|
||||
if(c->sel == nil)
|
||||
c->sel = f;
|
||||
|
|
|
@ -27,6 +27,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 */
|
||||
XRectangle
|
||||
|
@ -185,6 +188,46 @@ initdisplay(void) {
|
|||
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 */
|
||||
|
|
|
@ -48,6 +48,7 @@ struct Rectangle {
|
|||
};
|
||||
|
||||
typedef struct CTuple CTuple;
|
||||
typedef struct ErrorCode ErrorCode;
|
||||
typedef struct Ewmh Ewmh;
|
||||
typedef struct Font Font;
|
||||
typedef struct Handlers Handlers;
|
||||
|
@ -63,6 +64,11 @@ struct CTuple {
|
|||
char colstr[24]; /* #RRGGBB #RRGGBB #RRGGBB */
|
||||
};
|
||||
|
||||
struct ErrorCode {
|
||||
uchar rcode;
|
||||
uchar ecode;
|
||||
};
|
||||
|
||||
struct Ewmh {
|
||||
long type;
|
||||
long ping;
|
||||
|
@ -234,6 +240,7 @@ Point subpt(Point, Point);
|
|||
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*);
|
||||
|
|
Loading…
Reference in New Issue