X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=scrotwm.c;h=eda9f72fc63ab64a31f967725ea8fb71219c0f32;hb=2a69629d9bbb9d93bf0dc26709b0b27a8bccfc77;hp=eed00fb7b560c85dc7c2922caad13c535bb16c4f;hpb=ddfbb2ee98303fe16c6f8cc0c5279b9513365b26;p=spectrwm.git diff --git a/scrotwm.c b/scrotwm.c index eed00fb..eda9f72 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -52,7 +52,7 @@ static const char *cvstag = "$scrotwm$"; -#define SWM_VERSION "1.0" +#define SWM_VERSION "0.9.12" #include #include @@ -941,6 +941,7 @@ set_win_state(struct ws_win *win, long state) long data[] = {state, None}; XEvent ev; XWindowAttributes wa; + int putback; DNPRINTF(SWM_D_EVENT, "set_win_state: window: %lu\n", win->id); @@ -957,8 +958,11 @@ set_win_state(struct ws_win *win, long state) (unsigned char *)data, 2); /* wait for completion of XChangeProperty */ + putback = 0; while (XCheckIfEvent(display, &ev, set_win_notify_cb, (char *)win)) - ; + putback = 1; + if (putback) + XPutBackEvent(display, &ev); } long @@ -997,6 +1001,9 @@ client_msg(struct ws_win *win, Atom a) { XClientMessageEvent cm; + if (win == NULL) + return; + bzero(&cm, sizeof cm); cm.type = ClientMessage; cm.window = win->id; @@ -1014,6 +1021,10 @@ config_win(struct ws_win *win) DNPRINTF(SWM_D_MISC, "config_win: win %lu x %d y %d w %d h %d\n", win->id, win->g.x, win->g.y, win->g.w, win->g.h); + + if (win == NULL) + return; + ce.type = ConfigureNotify; ce.display = display; ce.event = win->id; @@ -1033,21 +1044,6 @@ count_win(struct workspace *ws, int count_transient) { struct ws_win *win; int count = 0; - int state; - - /* - * Under stress conditions windows sometimes do not get removed from - * the managed list quickly enough. Use a very large hammer to get rid - * of them. A smaller hammer would be nice. - */ - TAILQ_FOREACH(win, &ws->winlist, entry) { - state = getstate(win->id); - if (state == -1) { - DNPRINTF(SWM_D_MISC, "count_win:removing: %lu\n", - win->id); - unmanage_window(win); - } - } TAILQ_FOREACH(win, &ws->winlist, entry) { if (count_transient == 0 && win->floating) @@ -1083,6 +1079,7 @@ unmap_window(struct ws_win *win) { XEvent ev; XWindowAttributes wa; + int putback; if (win == NULL) return; @@ -1102,8 +1099,11 @@ unmap_window(struct ws_win *win) XUnmapWindow(display, win->id); /* make sure we wait for XUnmapWindow completion */ + putback = 0; while (XCheckIfEvent(display, &ev, unmap_window_cb, (char *)win)) - ; + putback = 1; + if (putback) + XPutBackEvent(display, &ev); } void @@ -1123,6 +1123,9 @@ fake_keypress(struct ws_win *win, int keysym, int modifiers) { XKeyEvent event; + if (win == NULL) + return; + event.display = display; /* Ignored, but what the hell */ event.window = win->id; event.root = win->s->root; @@ -1261,7 +1264,8 @@ unfocus_win(struct ws_win *win) { if (win == NULL) return; - + if (win->ws == NULL) + return; if (win->ws->r == NULL) return; @@ -1296,6 +1300,8 @@ focus_win(struct ws_win *win) if (win == NULL) return; + if (win->ws == NULL) + return; /* use big hammer to make sure it works under all use cases */ unfocus_all(); @@ -1321,6 +1327,15 @@ switchws(struct swm_region *r, union arg *args) struct ws_win *win, *winfocus = NULL, *parent = NULL; struct workspace *new_ws, *old_ws; + if (!(r && r->s)) { + fprintf(stderr, "r && r->s failed\n"); + abort(); + } + if (wsid < 0 || wsid > SWM_WS_MAX) { + fprintf(stderr, "illegal wsid\n"); + abort(); + } + this_r = r; old_ws = this_r->ws; new_ws = &this_r->s->ws[wsid]; @@ -1329,6 +1344,11 @@ switchws(struct swm_region *r, union arg *args) "%d -> %d\n", r->s->idx, WIDTH(r), HEIGHT(r), X(r), Y(r), old_ws->idx, wsid); + if (new_ws == NULL || old_ws == NULL) { + fprintf(stderr, "new_ws = %p old_ws = %p\n", new_ws, old_ws); + abort(); + } + if (new_ws == old_ws) return; @@ -1518,6 +1538,8 @@ swapwin(struct swm_region *r, union arg *args) else return; } + if (target == NULL || source == NULL) + return; source->ws->focus_prev = target; TAILQ_REMOVE(wl, target, entry); TAILQ_INSERT_BEFORE(source, target, entry); @@ -1638,6 +1660,10 @@ stack(void) { "(screen %d, region %d)\n", r->ws->idx, i, j++); /* start with screen geometry, adjust for bar */ + if (r == NULL) { + fprintf(stderr, "illegal r\n"); + abort(); + } g = r->g; g.w -= 2; g.h -= 2; @@ -1645,8 +1671,19 @@ stack(void) { g.y += bar_height; g.h -= bar_height; } - + if (r->ws == NULL) { + fprintf(stderr, "illegal ws\n"); + abort(); + } + if (r->ws->cur_layout == NULL) { + fprintf(stderr, "illegal cur_layout\n"); + abort(); + } r->ws->restack = 0; + if (r->ws->cur_layout->l_stack == NULL) { + fprintf(stderr, "illegal l_stack\n"); + abort(); + } r->ws->cur_layout->l_stack(r->ws, &g); } } @@ -3499,6 +3536,9 @@ unmanage_window(struct ws_win *win) DNPRINTF(SWM_D_MISC, "unmanage_window: %lu\n", win->id); + /* needed for restart wm */ + set_win_state(win, WithdrawnState); + if (win->transient) { parent = find_window(win->transient); if (parent) @@ -3536,6 +3576,15 @@ focus_magic(struct ws_win *win) } } +Bool +destroy_notify_cb(Display *d, XEvent *e, char *arg) +{ + struct ws_win *win = (struct ws_win *)arg; + if (win && win->id == e->xany.window && e->xany.type == DestroyNotify) + return (True); + return (False); +} + void expose(XEvent *e) { @@ -3676,10 +3725,11 @@ configurenotify(XEvent *e) void destroynotify(XEvent *e) { - struct ws_win *win, *winfocus = NULL; + struct ws_win *win, *w, *winfocus = NULL; struct workspace *ws; struct ws_win_list *wl; XDestroyWindowEvent *ev = &e->xdestroywindow; + XEvent de; DNPRINTF(SWM_D_EVENT, "destroynotify: window %lu\n", ev->window); @@ -3715,6 +3765,26 @@ destroynotify(XEvent *e) } unmanage_window(win); + /* + * Under stress conditions windows sometimes do not get removed + * from the managed list. Use a very large hammer to get rid + * of them. A smaller hammer would be nice. + */ + TAILQ_FOREACH(w, &ws->winlist, entry) { + if (win == w) + continue; /* can't happen but oh well */ + + if (getstate(w->id) != -1) + continue; + + /* see if we have a destroy event */ + if (XCheckIfEvent(display, &de, destroy_notify_cb, + (char *)w) == False) + unmanage_window(w); /* no event, help it */ + else + XPutBackEvent(display, &de); /* oops */ + } + ignore_enter = 1; stack(); if (winfocus) @@ -4181,7 +4251,6 @@ setup_screens(void) /* attach windows to a region */ /* normal windows */ for (j = 0; j < no; j++) { - XGetWindowAttributes(display, wins[j], &wa); if (!XGetWindowAttributes(display, wins[j], &wa) || wa.override_redirect || XGetTransientForHint(display, wins[j], &d1)) @@ -4194,7 +4263,8 @@ setup_screens(void) } /* transient windows */ for (j = 0; j < no; j++) { - if (!XGetWindowAttributes(display, wins[j], &wa)) + if (!XGetWindowAttributes(display, wins[j], &wa) || + wa.override_redirect) continue; state = getstate(wins[j]); @@ -4252,6 +4322,7 @@ main(int argc, char *argv[]) struct passwd *pwd; struct swm_region *r, *rr; struct ws_win *winfocus = NULL; + struct timeval tv; char conf[PATH_MAX], *cfile = NULL; struct stat sb; XEvent e; @@ -4365,7 +4436,9 @@ main(int argc, char *argv[]) FD_ZERO(&rd); FD_SET(xfd, &rd); - if (select(xfd + 1, &rd, NULL, NULL, NULL) == -1) + tv.tv_sec = 1; + tv.tv_usec = 0; + if (select(xfd + 1, &rd, NULL, NULL, &tv) == -1) if (errno != EINTR) DNPRINTF(SWM_D_MISC, "select failed"); if (running == 0)