X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=spectrwm.c;h=932f11ff7550d15e180d74ad466fa5b3b43491ad;hb=5f8042da0ee96bb4475049d901659e4ca26c625c;hp=06b73c0b9a1ef2b9f6e5a3a6d35c215a62b6a09c;hpb=4c59fde083056c15e80b6b9e9ceb89e09598293d;p=spectrwm.git diff --git a/spectrwm.c b/spectrwm.c index 06b73c0..932f11f 100644 --- a/spectrwm.c +++ b/spectrwm.c @@ -128,6 +128,7 @@ static const char *buildstr = SPECTRWM_VERSION; #define XCB_ICCCM_SIZE_HINT_P_MIN_SIZE XCB_SIZE_HINT_P_MIN_SIZE #define XCB_ICCCM_SIZE_HINT_P_MAX_SIZE XCB_SIZE_HINT_P_MAX_SIZE #define XCB_ICCCM_SIZE_HINT_P_RESIZE_INC XCB_SIZE_HINT_P_RESIZE_INC +#define XCB_ICCCM_WM_HINT_INPUT XCB_WM_HINT_INPUT #define XCB_ICCCM_WM_HINT_X_URGENCY XCB_WM_HINT_X_URGENCY #define XCB_ICCCM_WM_STATE_ICONIC XCB_WM_STATE_ICONIC #define XCB_ICCCM_WM_STATE_WITHDRAWN XCB_WM_STATE_WITHDRAWN @@ -490,6 +491,7 @@ struct workspace { struct layout *cur_layout; /* current layout handlers */ struct ws_win *focus; /* may be NULL */ struct ws_win *focus_prev; /* may be NULL */ + struct ws_win *focus_pending; /* 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 */ @@ -849,7 +851,6 @@ get_swm_iconic(struct ws_win *win) int32_t v = 0; xcb_get_property_reply_t *pr = NULL; - pr = xcb_get_property_reply(conn, xcb_get_property(conn, 0, win->id, a_swm_iconic, XCB_ATOM_INTEGER, 0, 1), NULL); @@ -2847,6 +2848,8 @@ switchws(struct swm_region *r, union arg *args) if (new_ws == old_ws) return; + unfocus_win(old_ws->focus); + other_r = new_ws->r; if (other_r == NULL) { /* the other workspace is hidden, hide this one */ @@ -2864,16 +2867,21 @@ switchws(struct swm_region *r, union arg *args) stack(); - new_ws->focus = get_region_focus(new_ws->r); - /* unmap old windows */ if (unmap_old) TAILQ_FOREACH(win, &old_ws->winlist, entry) unmap_window(win); - /* make sure bar gets updated if ws is empty */ - if (!new_ws->focus) + new_ws->focus_pending = get_region_focus(new_ws->r); + + if (new_ws->focus_pending) { + /* if workspaces were swapped, then don't wait to set focus */ + if (old_ws->r) + focus_win(new_ws->focus); + } else { + /* make sure bar gets updated if ws is empty */ bar_update(); + } focus_flush(); @@ -3020,7 +3028,6 @@ swapwin(struct swm_region *r, union arg *args) struct ws_win *cur_focus; struct ws_win_list *wl; - DNPRINTF(SWM_D_WS, "swapwin: id: %d, screen[%d]:%dx%d+%d+%d, ws: %d\n", args->id, r->s->idx, WIDTH(r), HEIGHT(r), X(r), Y(r), r->ws->idx); @@ -3514,7 +3521,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, reconfigure; + int remain, missing, v_slice, reconfigure = 0; int bordered = 1; DNPRINTF(SWM_D_STACK, "stack_master: workspace: %d, rot: %s, " @@ -4425,7 +4432,6 @@ wkill(struct swm_region *r, union arg *args) xcb_flush(conn); } - int floating_toggle_win(struct ws_win *win) { @@ -4889,7 +4895,6 @@ move_step(struct swm_region *r, union arg *args) move(win, args); } - /* user/key callable function IDs */ enum keyfuncid { KF_BAR_TOGGLE, @@ -6498,7 +6503,6 @@ struct config_option configopt[] = { { "layout", setlayout, 0 }, }; - int conf_load(char *filename, int keymapping) { @@ -6506,7 +6510,7 @@ conf_load(char *filename, int keymapping) char *line, *cp, *optsub, *optval; size_t linelen, lineno = 0; int wordlen, i, optidx; - struct config_option *opt; + struct config_option *opt = NULL; DNPRINTF(SWM_D_CONF, "conf_load: begin\n"); @@ -6555,7 +6559,7 @@ conf_load(char *filename, int keymapping) filename, lineno, wordlen, cp); goto out; } - if (keymapping && strcmp(opt->optname, "bind")) { + if (keymapping && opt && strcmp(opt->optname, "bind")) { warnx("%s: line %zd: invalid option %.*s", filename, lineno, wordlen, cp); goto out; @@ -6743,12 +6747,12 @@ manage_window(xcb_window_t id, uint16_t mapped) { xcb_window_t trans = XCB_WINDOW_NONE; struct ws_win *win, *ww; - int ws_idx, border_me = 0; + int ws_idx; char ws_idx_str[SWM_PROPLEN]; struct swm_region *r; struct pid_e *p; struct quirk *qp; - uint32_t event_mask, i; + uint32_t i, wa[2]; xcb_icccm_get_wm_protocols_reply_t wpr; if ((win = find_window(id)) != NULL) { @@ -6789,9 +6793,9 @@ manage_window(xcb_window_t id, uint16_t mapped) /* Ignore window border if there is one. */ WIDTH(win) = win->wa->width; HEIGHT(win) = win->wa->height; - X(win) = win->wa->x + win->wa->border_width; - Y(win) = win->wa->y + win->wa->border_width; - win->bordered = 0; + X(win) = win->wa->x + win->wa->border_width - border_width; + Y(win) = win->wa->y + win->wa->border_width - border_width; + win->bordered = 1; win->mapped = mapped; win->floatmaxed = 0; win->ewmh_flags = 0; @@ -6846,7 +6850,6 @@ manage_window(xcb_window_t id, uint16_t mapped) } else if (trans && (ww = find_window(trans)) != NULL) { /* Launch transients in the same ws as parent. */ win->ws = ww->ws; - border_me = 1; } else { win->ws = r->ws; } @@ -6876,7 +6879,6 @@ manage_window(xcb_window_t id, uint16_t mapped) DNPRINTF(SWM_D_CLASS, "manage_window: java window " "detected.\n"); win->java = 1; - border_me = 1; } TAILQ_FOREACH(qp, &quirks, entry) { @@ -6884,20 +6886,16 @@ manage_window(xcb_window_t id, uint16_t mapped) !strcmp(win->ch.instance_name, qp->name)) { DNPRINTF(SWM_D_CLASS, "manage_window: on quirks" "list; mask: 0x%lx\n", qp->quirk); - if (qp->quirk & SWM_Q_FLOAT) { + if (qp->quirk & SWM_Q_FLOAT) win->floating = 1; - border_me = 1; - } win->quirks = qp->quirk; } } } /* Alter window position if quirky */ - if (win->quirks & SWM_Q_ANYWHERE) { + if (win->quirks & SWM_Q_ANYWHERE) win->manual = 1; - border_me = 1; - } /* Reset font sizes (the bruteforce way; no default keybinding). */ if (win->quirks & SWM_Q_XTERM_FONTADJ) { @@ -6907,28 +6905,22 @@ manage_window(xcb_window_t id, uint16_t mapped) fake_keypress(win, XK_KP_Add, XCB_MOD_MASK_SHIFT); } - if (border_me) { - win->bordered = 1; - X(win) -= border_width; - Y(win) -= border_width; - } - /* Make sure window is positioned inside its region, if its active. */ - if (win->ws->r) + if (win->ws->r) { constrain_window(win, win->ws->r, 0); - - if (win->ws->r || border_me) update_window(win); + } - /* Select which X events to monitor. */ - event_mask = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE | - XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY; + /* Select which X events to monitor and set border pixel color. */ + wa[0] = win->s->c[SWM_S_COLOR_UNFOCUS].pixel; + wa[1] = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_PROPERTY_CHANGE | + XCB_EVENT_MASK_STRUCTURE_NOTIFY; #ifdef SWM_DEBUG - event_mask |= XCB_EVENT_MASK_LEAVE_WINDOW; + wa[1] |= XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE; #endif - xcb_change_window_attributes(conn, win->id, XCB_CW_EVENT_MASK, - &event_mask); + xcb_change_window_attributes(conn, win->id, XCB_CW_BORDER_PIXEL | + XCB_CW_EVENT_MASK, wa); out: /* Figure out where to stack the window in the workspace. */ @@ -7005,8 +6997,6 @@ unmanage_window(struct ws_win *win) parent->focus_child = NULL; } - focus_win(get_focus_prev(win)); - TAILQ_REMOVE(&win->ws->winlist, win, entry); TAILQ_INSERT_TAIL(&win->ws->unmanagedlist, win, entry); } @@ -7310,14 +7300,20 @@ destroynotify(xcb_destroy_notify_event_t *e) return; } - /* make sure we focus on something */ - win->floating = 0; + /* If we were focused, make sure we focus on something else. */ + if (win == win->ws->focus) + win->ws->focus_pending = get_focus_prev(win); unmanage_window(win); - free_window(win); - stack(); + if (win->ws->focus_pending) { + focus_win(win->ws->focus_pending); + win->ws->focus_pending = NULL; + } + + free_window(win); + focus_flush(); } @@ -7448,9 +7444,10 @@ mapnotify(xcb_map_notify_event_t *e) win->mapped = 1; set_win_state(win, XCB_ICCCM_WM_STATE_NORMAL); - /* Focus on window if it is selected. */ - if (win->ws->focus == win) + if (win->ws->focus_pending == win) { focus_win(win); + win->ws->focus_pending = NULL; + } xcb_flush(conn); } @@ -7495,7 +7492,7 @@ maprequest(xcb_map_request_event_t *e) stack(); /* The new window should get focus. */ - win->ws->focus = get_focus_magic(win); + win->ws->focus_pending = get_focus_magic(win); /* Ignore EnterNotify to handle the mapnotify without interference. */ if (focus_mode == SWM_FOCUS_DEFAULT) @@ -7560,30 +7557,30 @@ propertynotify(xcb_property_notify_event_t *e) if (e->atom == a_swm_iconic) { if (e->state == XCB_PROPERTY_DELETE) { /* The window is no longer iconic, restack ws. */ + win->ws->focus_pending = get_focus_magic(win); stack(); - /* The window should get focus. */ - win->ws->focus = get_focus_magic(win); - /* Flush EnterNotify for mapnotify, if needed. */ focus_flush(); return; } else if (e->state == XCB_PROPERTY_NEW_VALUE) { - win->ws->focus = NULL; - + win->ws->focus_pending = get_focus_prev(win); unfocus_win(win); unmap_window(win); if (win->ws->r) { - focus_win(get_focus_prev(win)); stack(); + focus_win(win->ws->focus_pending); + win->ws->focus_pending = NULL; focus_flush(); } } } else if (e->atom == a_state && e->state == XCB_PROPERTY_NEW_VALUE) { - /* Focus on window if it is selected. */ - if (win->ws->focus == win) + /* State just changed, make sure it gets focused if mapped. */ + if (win->mapped && win->ws->focus_pending == win) { + win->ws->focus_pending = NULL; focus_win(win); + } } switch (e->atom) { @@ -7611,8 +7608,18 @@ unmapnotify(xcb_unmap_notify_event_t *e) return; if (getstate(e->window) == XCB_ICCCM_WM_STATE_NORMAL) { + /* If we were focused, make sure we focus on something else. */ + if (win == win->ws->focus) + win->ws->focus_pending = get_focus_prev(win); + unmanage_window(win); stack(); + + if (win->ws->focus_pending) { + focus_win(win->ws->focus_pending); + win->ws->focus_pending = NULL; + } + focus_flush(); } } @@ -8089,6 +8096,8 @@ setup_screens(void) ws->idx = j; ws->name = NULL; ws->focus = NULL; + ws->focus_prev = NULL; + ws->focus_pending = NULL; ws->r = NULL; ws->old_r = NULL; TAILQ_INIT(&ws->winlist);