X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=scrotwm.c;h=4ef1088eb5a8ce530bbf48d65079c64f6fb94360;hb=769cba6f7f9837b2f47b89aec44757fab8b9aeae;hp=eda9f72fc63ab64a31f967725ea8fb71219c0f32;hpb=1bf8fe932963ad840f2feee2a6f7b7b9b231ef41;p=spectrwm.git diff --git a/scrotwm.c b/scrotwm.c index eda9f72..4ef1088 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -52,7 +52,7 @@ static const char *cvstag = "$scrotwm$"; -#define SWM_VERSION "0.9.12" +#define SWM_VERSION "0.9.15" #include #include @@ -94,6 +94,7 @@ static const char *cvstag = "$scrotwm$"; #endif #endif +#define SWM_DEBUG /* #define SWM_DEBUG */ #ifdef SWM_DEBUG #define DPRINTF(x...) do { if (swm_debug) fprintf(stderr, x); } while (0) @@ -304,6 +305,7 @@ enum keyfuncid { kf_screenshot_wind, kf_float_toggle, kf_version, + kf_dumpwins, kf_spawn_lock, kf_spawn_initscr, kf_spawn_custom, @@ -321,6 +323,7 @@ void max_stack(struct workspace *, struct swm_geometry *); void grabbuttons(struct ws_win *, int); void new_region(struct swm_screen *, int, int, int, int); void unmanage_window(struct ws_win *); +long getstate(Window); struct layout { void (*l_stack)(struct workspace *, struct swm_geometry *); @@ -335,7 +338,7 @@ struct layout { { horizontal_stack, horizontal_config, 0, "[-]" }, { max_stack, NULL, SWM_L_FOCUSPREV | SWM_L_MAPONFOCUS, "[ ]"}, - { NULL, NULL, 0}, + { NULL, NULL, 0, NULL }, }; #define SWM_H_SLICE (32) @@ -344,13 +347,13 @@ struct layout { /* define work spaces */ struct workspace { int idx; /* workspace index */ - int restack; /* restack on switch */ struct layout *cur_layout; /* current layout handlers */ struct ws_win *focus; /* may be NULL */ struct ws_win *focus_prev; /* may be NULL */ struct swm_region *r; /* may be NULL */ struct swm_region *old_r; /* may be NULL */ struct ws_win_list winlist; /* list of windows in ws */ + struct ws_win_list unmanagedlist; /* list of dead windows in ws */ /* stacker state */ struct { @@ -367,9 +370,9 @@ enum { SWM_S_COLOR_BAR, SWM_S_COLOR_BAR_BORDER, SWM_S_COLOR_BAR_FONT, SWM_S_COLOR_FOCUS, SWM_S_COLOR_UNFOCUS, SWM_S_COLOR_MAX }; /* physical screen mapping */ -#define SWM_WS_MAX (10) /* XXX Too small? */ +#define SWM_WS_MAX (10) struct swm_screen { - int idx; /* screen index */ + int idx; /* screen index */ struct swm_region_list rl; /* list of regions on this screen */ struct swm_region_list orl; /* list of old regions */ Window root; @@ -546,8 +549,48 @@ dumpevent(XEvent *e) "remaining\n", e->xany.window, e->type, QLength(display)); } + +void +dumpwins(struct swm_region *r, union arg *args) +{ + struct ws_win *win; + unsigned int state; + XWindowAttributes wa; + + if (r->ws == NULL) { + fprintf(stderr, "invalid workspace\n"); + return; + } + + fprintf(stderr, "=== managed window list ws %02d ===\n", r->ws->idx); + + TAILQ_FOREACH(win, &r->ws->winlist, entry) { + state = getstate(win->id); + if (!XGetWindowAttributes(display, win->id, &wa)) + fprintf(stderr, "window: %lu failed " + "XGetWindowAttributes\n", win->id); + fprintf(stderr, "window: %lu map_state: %d state: %d\n", + win->id, wa.map_state, state); + } + + fprintf(stderr, "===== unmanaged window list =====\n"); + TAILQ_FOREACH(win, &r->ws->unmanagedlist, entry) { + state = getstate(win->id); + if (!XGetWindowAttributes(display, win->id, &wa)) + fprintf(stderr, "window: %lu failed " + "XGetWindowAttributes\n", win->id); + fprintf(stderr, "window: %lu map_state: %d state: %d\n", + win->id, wa.map_state, state); + } + + fprintf(stderr, "=================================\n"); +} #else #define dumpevent(e) +void +dumpwins(struct swm_region *r, union arg *args) +{ +} #endif /* SWM_DEBUG */ void expose(XEvent *); @@ -821,7 +864,7 @@ void bar_toggle(struct swm_region *r, union arg *args) { struct swm_region *tmpr; - int i, j, sc = ScreenCount(display); + int i, sc = ScreenCount(display); DNPRINTF(SWM_D_MISC, "bar_toggle\n"); @@ -835,9 +878,6 @@ bar_toggle(struct swm_region *r, union arg *args) XMapRaised(display, tmpr->bar_window); bar_enabled = !bar_enabled; - for (i = 0; i < sc; i++) - for (j = 0; j < SWM_WS_MAX; j++) - screens[i].ws[j].restack = 1; stack(); /* must be after stack */ @@ -925,44 +965,18 @@ bar_setup(struct swm_region *r) bar_refresh(); } -Bool -set_win_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 == PropertyNotify) - return (True); - return (False); -} - void 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); if (win == NULL) return; - /* make sure we drain everything */ - XSync(display, True); - - /* make sure we still exist too */ - if (XGetWindowAttributes(display, win->id, &wa) == BadWindow) - return; XChangeProperty(display, win->id, astate, astate, 32, PropModeReplace, (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 @@ -1015,6 +1029,28 @@ client_msg(struct ws_win *win, Atom a) } void +configreq_win(struct ws_win *win) +{ + XConfigureRequestEvent cr; + + if (win == NULL) + return; + + bzero(&cr, sizeof cr); + cr.type = ConfigureRequest; + cr.display = display; + cr.parent = win->id; + cr.window = win->id; + cr.x = win->g.x; + cr.y = win->g.y; + cr.width = win->g.w; + cr.height = win->g.h; + cr.border_width = 1; + + XSendEvent(display, win->id, False, StructureNotifyMask, (XEvent *)&cr); +} + +void config_win(struct ws_win *win) { XConfigureEvent ce; @@ -1064,46 +1100,19 @@ quit(struct swm_region *r, union arg *args) running = 0; } -Bool -unmap_window_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 == UnmapNotify) - return (True); - return (False); -} - void unmap_window(struct ws_win *win) { - XEvent ev; - XWindowAttributes wa; - int putback; - if (win == NULL) return; - /* make sure we still exist too */ - if (XGetWindowAttributes(display, win->id, &wa) == BadWindow) - return; - /* don't unmap again */ - if (wa.map_state == IsUnmapped && getstate(win->id) == IconicState) + if (getstate(win->id) == IconicState) return; - /* java shits itself when windows are set to iconic state */ - if (win->java == 0) - set_win_state(win, IconicState); + set_win_state(win, IconicState); 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 @@ -1197,6 +1206,21 @@ root_to_region(Window root) } struct ws_win * +find_unmanaged_window(Window id) +{ + struct ws_win *win; + int i, j; + + for (i = 0; i < ScreenCount(display); i++) + for (j = 0; j < SWM_WS_MAX; j++) + TAILQ_FOREACH(win, &screens[i].ws[j].unmanagedlist, + entry) + if (id == win->id) + return (win); + return (NULL); +} + +struct ws_win * find_window(Window id) { struct ws_win *win; @@ -1308,11 +1332,11 @@ focus_win(struct ws_win *win) win->ws->focus = win; if (win->ws->r != NULL) { - XSetWindowBorder(display, win->id, - win->ws->r->s->c[SWM_S_COLOR_FOCUS].color); grabbuttons(win, 1); if (win->ws->cur_layout->flags & SWM_L_MAPONFOCUS) XMapRaised(display, win->id); + XSetWindowBorder(display, win->id, + win->ws->r->s->c[SWM_S_COLOR_FOCUS].color); if (win->java == 0) XSetInputFocus(display, win->id, RevertToPointerRoot, CurrentTime); @@ -1327,14 +1351,8 @@ 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(); - } + if (!(r && r->s)) + return; this_r = r; old_ws = this_r->ws; @@ -1344,11 +1362,8 @@ 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 == NULL || old_ws == NULL) + return; if (new_ws == old_ws) return; @@ -1366,17 +1381,6 @@ switchws(struct swm_region *r, union arg *args) if (old_ws->r != NULL) old_ws->old_r = old_ws->r; old_ws->r = NULL; - old_ws->restack = 1; - - /* - * Map new windows first if they were here before - * to minimize ugly blinking. - */ - if (new_ws->old_r == this_r) - TAILQ_FOREACH(win, &new_ws->winlist, entry) - if (!(win->ws->cur_layout->flags & - SWM_L_MAPONFOCUS)) - XMapRaised(display, win->id); TAILQ_FOREACH(win, &old_ws->winlist, entry) unmap_window(win); @@ -1660,10 +1664,6 @@ 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; @@ -1671,19 +1671,6 @@ 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); } } @@ -1702,8 +1689,8 @@ stack_floater(struct ws_win *win, struct swm_region *r) bzero(&wc, sizeof wc); mask = CWX | CWY | CWBorderWidth | CWWidth | CWHeight; - if ((win->quirks & SWM_Q_FULLSCREEN) && (win->g.w == WIDTH(r)) && - (win->g.h == HEIGHT(r))) + if ((win->quirks & SWM_Q_FULLSCREEN) && (win->g.w >= WIDTH(r)) && + (win->g.h >= HEIGHT(r))) wc.border_width = 0; else wc.border_width = 1; @@ -1722,13 +1709,21 @@ stack_floater(struct ws_win *win, struct swm_region *r) } /* adjust for region */ - wc.x += r->g.x; - wc.y += r->g.y; + if (wc.x < r->g.x) + wc.x += r->g.x; + if (wc.y < r->g.y) + wc.y += r->g.y; - DNPRINTF(SWM_D_STACK, "stack_floater: win %lu x %d y %d w %d h %d\n", + win->g.x = wc.x; + win->g.y = wc.y; + win->g.w = wc.width; + win->g.h = wc.height; + + DNPRINTF(SWM_D_MISC, "stack_floater: win %lu x %d y %d w %d h %d\n", win->id, wc.x, wc.y, wc.width, wc.height); XConfigureWindow(display, win->id, mask, &wc); + configreq_win(win); } /* @@ -1775,7 +1770,7 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip) int w_inc = 1, h_inc, w_base = 1, h_base; int hrh, extra = 0, h_slice, last_h = 0; int split, colno, winno, mwin, msize, mscale; - int remain, missing, v_slice; + int remain, missing, v_slice, reconfigure; unsigned int mask; DNPRINTF(SWM_D_STACK, "stack_master: workspace: %d\n rot=%s flip=%s", @@ -1896,20 +1891,32 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip) bzero(&wc, sizeof wc); wc.border_width = 1; + reconfigure = 0; if (rot) { - win->g.x = wc.x = win_g.y; - win->g.y = wc.y = win_g.x; - win->g.w = wc.width = win_g.h; - win->g.h = wc.height = win_g.w; + if (win->g.x != win_g.y || win->g.y != win_g.x || + win->g.w != win_g.h || win->g.h != win_g.w) { + reconfigure = 1; + win->g.x = wc.x = win_g.y; + win->g.y = wc.y = win_g.x; + win->g.w = wc.width = win_g.h; + win->g.h = wc.height = win_g.w; + } } else { - win->g.x = wc.x = win_g.x; - win->g.y = wc.y = win_g.y; - win->g.w = wc.width = win_g.w; - win->g.h = wc.height = win_g.h; + if (win->g.x != win_g.x || win->g.y != win_g.y || + win->g.w != win_g.w || win->g.h != win_g.h) { + reconfigure = 1; + win->g.x = wc.x = win_g.x; + win->g.y = wc.y = win_g.y; + win->g.w = wc.width = win_g.w; + win->g.h = wc.height = win_g.h; + } + } + if (reconfigure) { + adjust_font(win); + mask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth; + XConfigureWindow(display, win->id, mask, &wc); + configreq_win(win); } - adjust_font(win); - mask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth; - XConfigureWindow(display, win->id, mask, &wc); XMapRaised(display, win->id); last_h = win_g.h; @@ -2042,9 +2049,14 @@ max_stack(struct workspace *ws, struct swm_geometry *g) return; TAILQ_FOREACH(win, &ws->winlist, entry) { - if (win->transient != 0) { + if (win->transient) { wintrans = win; - } else { + continue; + } + + /* only reconfigure if necessary */ + if (win->g.x != gg.x || win->g.y != gg.y || win->g.w != gg.w || + win->g.h != gg.h) { bzero(&wc, sizeof wc); wc.border_width = 1; win->g.x = wc.x = gg.x; @@ -2053,12 +2065,12 @@ max_stack(struct workspace *ws, struct swm_geometry *g) win->g.h = wc.height = gg.h; mask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth; XConfigureWindow(display, win->id, mask, &wc); - - /* unmap only if we don't have multi screen */ - if (win != ws->focus) - if (!(ScreenCount(display) > 1 || outputs > 1)) - unmap_window(win); + configreq_win(win); } + /* unmap only if we don't have multi screen */ + if (win != ws->focus) + if (!(ScreenCount(display) > 1 || outputs > 1)) + unmap_window(win); } /* put the last transient on top */ @@ -2120,8 +2132,6 @@ send_to_ws(struct swm_region *r, union arg *args) if (count_win(nws, 1) == 1) nws->focus = win; - ws->restack = 1; - nws->restack = 1; stack(); if (winfocus) @@ -2180,7 +2190,7 @@ resize_window(struct ws_win *win, int center) win->id, wc.x, wc.y, wc.width, wc.height); XConfigureWindow(display, win->id, mask, &wc); - config_win(win); + configreq_win(win); } void @@ -2188,6 +2198,7 @@ resize(struct ws_win *win, union arg *args) { XEvent ev; Time time = 0; + struct swm_region *r = win->ws->r; DNPRINTF(SWM_D_MOUSE, "resize: win %lu floating %d trans %d\n", win->id, win->floating, win->transient); @@ -2209,6 +2220,14 @@ resize(struct ws_win *win, union arg *args) handler[ev.type](&ev); break; case MotionNotify: + /* do not allow resize outside of region */ + if (ev.xmotion.y_root < r->g.y || + ev.xmotion.y_root >= r->g.y + r->g.h - 1) + continue; + if (ev.xmotion.x_root < r->g.x || + ev.xmotion.x_root >= r->g.x + r->g.w - 1) + continue; + if (ev.xmotion.x <= 1) ev.xmotion.x = 1; if (ev.xmotion.y <= 1) @@ -2254,7 +2273,7 @@ move_window(struct ws_win *win) win->id, wc.x, wc.y, wc.width, wc.height); XConfigureWindow(display, win->id, mask, &wc); - config_win(win); + configreq_win(win); } void @@ -2263,6 +2282,7 @@ move(struct ws_win *win, union arg *args) XEvent ev; Time time = 0; int restack = 0; + struct swm_region *r = win->ws->r; DNPRINTF(SWM_D_MOUSE, "move: win %lu floating %d trans %d\n", win->id, win->floating, win->transient); @@ -2287,6 +2307,14 @@ move(struct ws_win *win, union arg *args) handler[ev.type](&ev); break; case MotionNotify: + /* don't allow to move window out of region */ + if (ev.xmotion.y_root < r->g.y || + ev.xmotion.y_root + win->g.h >= r->g.y + r->g.h - 1) + continue; + if (ev.xmotion.x_root < r->g.x || + ev.xmotion.x_root + win->g.w >= r->g.x + r->g.w - 1) + continue; + win->g.x = ev.xmotion.x_root; win->g.y = ev.xmotion.y_root; @@ -2381,6 +2409,7 @@ struct keyfunc { { "spawn_lock", legacyfunc, {0} }, { "spawn_initscr", legacyfunc, {0} }, { "spawn_custom", dummykeyfunc, {0} }, + { "dumpwins", dumpwins, {0} }, { "invalid key func", NULL, {0} }, }; struct key { @@ -2903,6 +2932,9 @@ setup_keys(void) setkeybinding(MODKEY|ShiftMask, XK_v, kf_version, NULL); setkeybinding(MODKEY|ShiftMask, XK_Delete, kf_spawn_custom, "lock"); setkeybinding(MODKEY|ShiftMask, XK_i, kf_spawn_custom, "initscr"); +#ifdef SWM_DEBUG + setkeybinding(MODKEY|ShiftMask, XK_d, kf_dumpwins, NULL); +#endif } void @@ -3377,7 +3409,16 @@ manage_window(Window id) XWindowChanges wc; if ((win = find_window(id)) != NULL) - return (win); /* already being managed */ + return (win); /* already being managed */ + + /* see if we are on the unmanaged list */ + if ((win = find_unmanaged_window(id)) != NULL) { + DNPRINTF(SWM_D_MISC, "manage previously unmanaged window " + "%lu\n", win->id); + TAILQ_REMOVE(&win->ws->unmanagedlist, win, entry); + TAILQ_INSERT_TAIL(&win->ws->winlist, win, entry); + return (win); + } if ((win = calloc(1, sizeof(struct ws_win))) == NULL) errx(1, "calloc: failed to allocate memory for new window"); @@ -3474,8 +3515,10 @@ manage_window(Window id) !strcmp(win->ch.res_name, quirks[i].name)) { DNPRINTF(SWM_D_CLASS, "found: %s name: %s\n", win->ch.res_class, win->ch.res_name); - if (quirks[i].quirk & SWM_Q_FLOAT) + if (quirks[i].quirk & SWM_Q_FLOAT) { win->floating = 1; + border_me = 1; + } win->quirks = quirks[i].quirk; } } @@ -3511,6 +3554,7 @@ manage_window(Window id) wc.border_width = 1; mask = CWBorderWidth; XConfigureWindow(display, win->id, mask, &wc); + configreq_win(win); } XSelectInput(display, id, EnterWindowMask | FocusChangeMask | @@ -3526,9 +3570,28 @@ manage_window(Window id) } void +free_window(struct ws_win *win) +{ + DNPRINTF(SWM_D_MISC, "free_window: %lu\n", win->id); + + if (win == NULL) + return; + + /* needed for restart wm */ + set_win_state(win, WithdrawnState); + + TAILQ_REMOVE(&win->ws->unmanagedlist, win, entry); + + if (win->ch.res_class) + XFree(win->ch.res_class); + if (win->ch.res_name) + XFree(win->ch.res_name); + free(win); +} + +void unmanage_window(struct ws_win *win) { - struct workspace *ws; struct ws_win *parent; if (win == NULL) @@ -3536,22 +3599,14 @@ 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) parent->child_trans = NULL; } - ws = win->ws; TAILQ_REMOVE(&win->ws->winlist, win, entry); - if (win->ch.res_class) - XFree(win->ch.res_class); - if (win->ch.res_name) - XFree(win->ch.res_name); - free(win); + TAILQ_INSERT_TAIL(&win->ws->unmanagedlist, win, entry); } void @@ -3652,7 +3707,8 @@ configurerequest(XEvent *e) XWindowChanges wc; if ((win = find_window(ev->window)) == NULL) - new = 1; + if ((win = find_unmanaged_window(ev->window)) == NULL) + new = 1; if (new) { DNPRINTF(SWM_D_EVENT, "configurerequest: new window: %lu\n", @@ -3678,27 +3734,8 @@ configurerequest(XEvent *e) win->g.w = ev->width; if (ev->value_mask & CWHeight) win->g.h = ev->height; - if (win->ws->r != NULL) { - /* this seems to be full screen */ - if (win->g.w >= WIDTH(win->ws->r)) { - win->g.x = 0; - win->g.w = WIDTH(win->ws->r); - ev->value_mask |= CWX | CWWidth; - } - if (win->g.h >= HEIGHT(win->ws->r)) { - /* kill border */ - win->g.y = 0; - win->g.h = HEIGHT(win->ws->r); - ev->value_mask |= CWY | CWHeight; - } - } - if ((ev->value_mask & (CWX | CWY)) && - !(ev->value_mask & (CWWidth | CWHeight))) - config_win(win); - XMoveResizeWindow(display, win->id, - win->g.x, win->g.y, win->g.w, win->g.h); - } else - config_win(win); + } + config_win(win); } } @@ -3711,12 +3748,10 @@ configurenotify(XEvent *e) DNPRINTF(SWM_D_EVENT, "configurenotify: window: %lu\n", e->xconfigure.window); - XMapWindow(display, e->xconfigure.window); win = find_window(e->xconfigure.window); if (win) { XGetWMNormalHints(display, win->id, &win->sh, &mask); adjust_font(win); - XMapWindow(display, win->id); if (font_adjusted) stack(); } @@ -3725,72 +3760,67 @@ configurenotify(XEvent *e) void destroynotify(XEvent *e) { - struct ws_win *win, *w, *winfocus = NULL; + struct ws_win *win, *w, *wn, *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); - if ((win = find_window(ev->window)) != NULL) { - /* find a window to focus */ - ws = win->ws; - wl = &ws->winlist; - - /* if we are transient give focus to parent */ - if (win->transient) - winfocus = find_window(win->transient); - else if (ws->focus == win) { - /* if in max_stack try harder */ - if (ws->cur_layout->flags & SWM_L_FOCUSPREV) { - if (win != ws->focus_prev) - winfocus = ws->focus_prev; - else if (win != ws->focus) - winfocus = ws->focus; - } - - /* fallback and normal handling */ - if (winfocus == NULL) { - if (TAILQ_FIRST(wl) == win) - winfocus = TAILQ_NEXT(win, entry); - else { - winfocus = TAILQ_PREV(ws->focus, - ws_win_list, entry); - if (winfocus == NULL) - winfocus = TAILQ_LAST(wl, - ws_win_list); - } - } - } - unmanage_window(win); + if ((win = find_window(ev->window)) == NULL) { + if ((win = find_unmanaged_window(ev->window)) == NULL) + return; + free_window(win); + return; + } - /* - * 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 */ + /* find a window to focus */ + ws = win->ws; + wl = &ws->winlist; - if (getstate(w->id) != -1) - continue; + for (w = TAILQ_FIRST(&ws->winlist); w != TAILQ_END(&ws->winlist); + w = wn) { + wn = TAILQ_NEXT(w, entry); + if (win == w) + continue; /* can't happen but oh well */ - /* 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 */ + if (getstate(w->id) != -1) + continue; + unmanage_window(w); + } + /* if we are transient give focus to parent */ + if (win->transient) + winfocus = find_window(win->transient); + else if (ws->focus == win) { + /* if in max_stack try harder */ + if (ws->cur_layout->flags & SWM_L_FOCUSPREV) { + if (win != ws->focus_prev) + winfocus = ws->focus_prev; + else if (win != ws->focus) + winfocus = ws->focus; } - ignore_enter = 1; - stack(); - if (winfocus) - focus_win(winfocus); - ignore_enter = 0; + /* fallback and normal handling */ + if (winfocus == NULL) { + if (TAILQ_FIRST(wl) == win) + winfocus = TAILQ_NEXT(win, entry); + else { + winfocus = TAILQ_PREV(ws->focus, + ws_win_list, entry); + if (winfocus == NULL) + winfocus = TAILQ_LAST(wl, + ws_win_list); + } + } } + unmanage_window(win); + free_window(win); + + ignore_enter = 1; + stack(); + if (winfocus) + focus_win(winfocus); + ignore_enter = 0; } void @@ -3839,7 +3869,7 @@ mapnotify(XEvent *e) DNPRINTF(SWM_D_EVENT, "mapnotify: window: %lu\n", ev->window); - win = find_window(ev->window); + win = manage_window(ev->window); if (win) set_win_state(win, NormalState); } @@ -4226,11 +4256,11 @@ setup_screens(void) for (j = 0; j < SWM_WS_MAX; j++) { ws = &screens[i].ws[j]; ws->idx = j; - ws->restack = 1; ws->focus = NULL; ws->r = NULL; ws->old_r = NULL; TAILQ_INIT(&ws->winlist); + TAILQ_INIT(&ws->unmanagedlist); for (k = 0; layouts[k].l_stack != NULL; k++) if (layouts[k].l_config != NULL) @@ -4257,7 +4287,7 @@ setup_screens(void) continue; state = getstate(wins[j]); - manage = state == NormalState || state == IconicState; + manage = state == IconicState; if (wa.map_state == IsViewable || manage) manage_window(wins[j]); } @@ -4268,7 +4298,7 @@ setup_screens(void) continue; state = getstate(wins[j]); - manage = state == NormalState || state == IconicState; + manage = state == IconicState; if (XGetTransientForHint(display, wins[j], &d1) && manage) manage_window(wins[j]); @@ -4329,6 +4359,7 @@ main(int argc, char *argv[]) int xfd, i; fd_set rd; +swm_debug = 0; start_argv = argv; fprintf(stderr, "Welcome to scrotwm V%s cvs tag: %s\n", SWM_VERSION, cvstag);