X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=scrotwm.c;h=0dda0108009746c316c72fb0aff97cb208047a8a;hb=597613109eb2103c3a196742ec04953b0996d6ae;hp=6beea517433d361670fe353b762877abaad01a6f;hpb=3a97b91dd148f453fae03469724018dc5aeefca5;p=spectrwm.git diff --git a/scrotwm.c b/scrotwm.c index 6beea51..0dda010 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -158,6 +158,7 @@ Atom astate; Atom aprot; Atom adelete; volatile sig_atomic_t running = 1; +int outputs = 0; int (*xerrorxlib)(Display *, XErrorEvent *); int other_wm; int ss_enabled = 0; @@ -231,7 +232,6 @@ struct ws_win { TAILQ_ENTRY(ws_win) entry; Window id; struct swm_geometry g; - int got_focus; int floating; int transient; int manual; @@ -1137,19 +1137,17 @@ unfocus_win(struct ws_win *win) if (win == NULL) return; - if (win->ws->focus != win && win->ws->focus != NULL) - win->ws->focus_prev = win->ws->focus; - if (win->ws->r == NULL) return; grabbuttons(win, 0); XSetWindowBorder(display, win->id, win->ws->r->s->c[SWM_S_COLOR_UNFOCUS].color); - win->got_focus = 0; - if (win->ws->focus == win) + if (win->ws->focus == win) { win->ws->focus = NULL; + win->ws->focus_prev = win; + } } void @@ -1164,6 +1162,7 @@ unfocus_all(void) for (j = 0; j < SWM_WS_MAX; j++) TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry) unfocus_win(win); + XSync(display, False); } void @@ -1174,24 +1173,17 @@ focus_win(struct ws_win *win) if (win == NULL) return; - if (win->ws->focus) - unfocus_win(win->ws->focus); - if (win->ws->focus) { - /* probably shouldn't happen due to the previous unfocus_win */ - DNPRINTF(SWM_D_FOCUS, "unfocusing win->ws->focus: %lu\n", - win->ws->focus->id); - unfocus_win(win->ws->focus); - } + /* use big hammer to make sure it works under all use cases */ + unfocus_all(); win->ws->focus = win; + if (win->ws->r != NULL) { - if (win->got_focus == 0) { - XSetWindowBorder(display, win->id, - win->ws->r->s->c[SWM_S_COLOR_FOCUS].color); - grabbuttons(win, 1); - } - win->got_focus = 1; + XSetWindowBorder(display, win->id, + win->ws->r->s->c[SWM_S_COLOR_FOCUS].color); + grabbuttons(win, 1); XSetInputFocus(display, win->id, RevertToPointerRoot, CurrentTime); + XSync(display, False); } } @@ -1200,7 +1192,7 @@ switchws(struct swm_region *r, union arg *args) { int wsid = args->id; struct swm_region *this_r, *other_r; - struct ws_win *win, *winfocus; + struct ws_win *win, *winfocus = NULL; struct workspace *new_ws, *old_ws; this_r = r; @@ -1211,6 +1203,17 @@ 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); + /* get focus window */ + if (new_ws->focus) + winfocus = new_ws->focus; + else if (new_ws->focus_prev) + winfocus = new_ws->focus_prev; + + if (new_ws->focus) + winfocus = new_ws->focus; + else if (new_ws->focus_prev) + winfocus = new_ws->focus_prev; + if (new_ws == old_ws) return; @@ -1233,15 +1236,8 @@ switchws(struct swm_region *r, union arg *args) this_r->ws = new_ws; new_ws->r = this_r; - /* get focus window */ - if (new_ws->focus == NULL) - winfocus = TAILQ_FIRST(&new_ws->winlist); - else - winfocus = new_ws->focus; - ignore_enter = 1; stack(); - unfocus_all(); /* we need this after a M-q */ focus_win(winfocus); bar_update(); } @@ -3195,7 +3191,7 @@ manage_window(Window id) { Window trans; struct workspace *ws; - struct ws_win *win; + struct ws_win *win, *ww; int format, i, ws_idx, n; unsigned long nitems, bytes; Atom ws_idx_atom = 0, type; @@ -3248,8 +3244,17 @@ manage_window(Window id) errstr, prop); } ws = &r->s->ws[ws_idx]; - } else + } else { ws = r->ws; + /* this should launch transients in the same ws as parent */ + /* XXX doesn't work for intel xrandr */ + if (id && trans) { + if ((ww = find_window(trans)) != NULL) { + ws = ww->ws; + r = ws->r; + } + } + } /* set up the window layout */ win->id = id; @@ -3322,9 +3327,6 @@ manage_window(Window id) if (win->floating && (ws->idx == r->ws->idx)) XMapRaised(display, win->id); - /* make new win focused */ - focus_win(win); - return (win); } @@ -3339,20 +3341,6 @@ unmanage_window(struct ws_win *win) DNPRINTF(SWM_D_MISC, "unmanage_window: %lu\n", win->id); ws = win->ws; - - /* find a window to focus */ - if (ws->focus == win) - ws->focus = TAILQ_PREV(win, ws_win_list, entry); - if (ws->focus == NULL) - ws->focus = TAILQ_FIRST(&ws->winlist); - if (ws->focus == NULL || ws->focus == win) { - ws->focus = NULL; - unfocus_win(win); - } else - focus_win(ws->focus); - if (ws->focus_prev == win) - ws->focus_prev = NULL; - TAILQ_REMOVE(&win->ws->winlist, win, entry); set_win_state(win, WithdrawnState); if (win->ch.res_class) @@ -3444,14 +3432,32 @@ configurenotify(XEvent *e) void destroynotify(XEvent *e) { - struct ws_win *win; + struct ws_win *win, *winfocus = NULL; + struct workspace *ws; + struct ws_win_list *wl; + XDestroyWindowEvent *ev = &e->xdestroywindow; 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 (ws->focus == win) { + 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); stack(); + if (winfocus) + focus_win(winfocus); } } @@ -3468,6 +3474,12 @@ enternotify(XEvent *e) ignore_enter--; return; } + /* + * happens when a window is created or destroyed and the border + * crosses the mouse pointer + */ + if (QLength(display)) + return; if ((win = find_window(ev->window)) != NULL) focus_win(win); @@ -3482,28 +3494,7 @@ focusin(XEvent *e) void focusout(XEvent *e) { - struct swm_screen *s; - struct ws_win *win, *cur_focus; - Window rr, cr; - int x, y, wx, wy; - unsigned int mask; - DNPRINTF(SWM_D_EVENT, "focusout: window: %lu\n", e->xfocus.window); - - win = find_window(e->xany.window); - if (win) - cur_focus = win->ws->focus; - - if (cur_focus && cur_focus->ws->r && - cur_focus->id == e->xfocus.window) { - s = cur_focus->ws->r->s; - if (XQueryPointer(display, cur_focus->id, - &rr, &cr, &x, &y, &wx, &wy, &mask) != False && - cr == 0 && !mask && - x == DisplayWidth(display, s->idx) / 2 && - y == DisplayHeight(display, s->idx) / 2) - unfocus_win(cur_focus); - } } void @@ -3531,9 +3522,15 @@ maprequest(XEvent *e) return; if (wa.override_redirect) return; + manage_window(e->xmaprequest.window); stack(); + + /* make new win focused */ + struct ws_win *win; + win = find_window(ev->window); + focus_win(win); } void @@ -3737,6 +3734,7 @@ scan_xrandr(int i) /* map virtual screens onto physical screens */ #ifdef SWM_XRR_HAS_CRTC + outputs = 0; if (xrandr_support) { sr = XRRGetScreenResources(display, screens[i].root); if (sr == NULL) @@ -3750,6 +3748,7 @@ scan_xrandr(int i) ci = XRRGetCrtcInfo(display, sr, sr->crtcs[c]); if (ci->noutput == 0) continue; + outputs++; if (ci != NULL && ci->mode == None) new_region(&screens[i], 0, 0, @@ -3936,8 +3935,8 @@ int main(int argc, char *argv[]) { struct passwd *pwd; - struct swm_region *r; - struct swm_win *winfocus = NULL; + struct swm_region *r, *rr; + struct ws_win *winfocus = NULL; char conf[PATH_MAX], *cfile = NULL; struct stat sb; XEvent e; @@ -4034,6 +4033,13 @@ main(int argc, char *argv[]) /* if we are being restarted go focus on first window */ if (winfocus) { + rr = TAILQ_FIRST(&screens[0].rl); + /* move pointer to first screen */ + if (ScreenCount(display) > 1 || outputs > 1) + XWarpPointer(display, None, rr->s[0].root, + 0, 0, 0, 0, rr->g.x, + rr->g.y + bar_enabled ? bar_height : 0); + focus_win(winfocus); winfocus = NULL; continue;