X-Git-Url: https://code.delx.au/spectrwm/blobdiff_plain/edfc16af9a108c4d9193694fb8c37aa5c1afc0b0..8aa184cb8b7be42e7b5d5eb4843523c10a64be1a:/spectrwm.c diff --git a/spectrwm.c b/spectrwm.c index de42566..b894d0b 100644 --- a/spectrwm.c +++ b/spectrwm.c @@ -333,9 +333,9 @@ bool cycle_visible = false; int term_width = 0; int font_adjusted = 0; unsigned int mod_key = MODKEY; +bool warp_focus = false; bool warp_pointer = false; -unsigned int mouse_button_move = XCB_BUTTON_INDEX_1; -unsigned int mouse_button_resize = XCB_BUTTON_INDEX_3; +bool workspace_clamp = false; /* dmenu search */ struct swm_region *search_r; @@ -401,7 +401,7 @@ bool bar_at_bottom = false; bool bar_extra = false; int bar_height = 0; int bar_justify = SWM_BAR_JUSTIFY_LEFT; -char *bar_format = NULL; +char *bar_format = NULL; bool stack_enabled = true; bool clock_enabled = true; bool iconic_enabled = false; @@ -427,15 +427,14 @@ bool verbose_layout = false; time_t time_started; #endif pid_t bar_pid; -XFontSet bar_fs; +XFontSet bar_fs = NULL; XFontSetExtents *bar_fs_extents; -XftFont *bar_font; +XftFont *bar_font = NULL; bool bar_font_legacy = true; -char *bar_fonts; +char *bar_fonts = NULL; XftColor bar_font_color; XftColor search_font_color; -struct passwd *pwd; -char *startup_exception; +char *startup_exception = NULL; unsigned int nr_exceptions = 0; /* layout manager data */ @@ -674,18 +673,19 @@ struct quirk { regex_t regex_name; uint32_t quirk; int ws; /* Initial workspace. */ -#define SWM_Q_FLOAT (1<<0) /* float this window */ -#define SWM_Q_TRANSSZ (1<<1) /* transiend window size too small */ -#define SWM_Q_ANYWHERE (1<<2) /* don't position this window */ -#define SWM_Q_XTERM_FONTADJ (1<<3) /* adjust xterm fonts when resizing */ -#define SWM_Q_FULLSCREEN (1<<4) /* remove border */ -#define SWM_Q_FOCUSPREV (1<<5) /* focus on caller */ +#define SWM_Q_FLOAT (1<<0) /* Float this window. */ +#define SWM_Q_TRANSSZ (1<<1) /* Transient window size too small. */ +#define SWM_Q_ANYWHERE (1<<2) /* Don't position this window */ +#define SWM_Q_XTERM_FONTADJ (1<<3) /* Adjust xterm fonts when resizing. */ +#define SWM_Q_FULLSCREEN (1<<4) /* Remove border when fullscreen. */ +#define SWM_Q_FOCUSPREV (1<<5) /* Focus on caller. */ #define SWM_Q_NOFOCUSONMAP (1<<6) /* Don't focus on window when mapped. */ #define SWM_Q_FOCUSONMAP_SINGLE (1<<7) /* Only focus if single win of type. */ #define SWM_Q_OBEYAPPFOCUSREQ (1<<8) /* Focus when applications ask. */ #define SWM_Q_IGNOREPID (1<<9) /* Ignore PID when determining ws. */ #define SWM_Q_IGNORESPAWNWS (1<<10) /* Ignore _SWM_WS when managing win. */ #define SWM_Q_NOFOCUSCYCLE (1<<11) /* Remove from normal focus cycle. */ +#define SWM_Q_MINIMALBORDER (1<<12) /* No border when floating/unfocused. */ }; TAILQ_HEAD(quirk_list, quirk); struct quirk_list quirks = TAILQ_HEAD_INITIALIZER(quirks); @@ -889,19 +889,19 @@ enum keyfuncid { KF_RG_7, KF_RG_8, KF_RG_9, - KF_RG_NEXT, - KF_RG_PREV, KF_RG_MOVE_NEXT, KF_RG_MOVE_PREV, + KF_RG_NEXT, + KF_RG_PREV, KF_SCREEN_NEXT, KF_SCREEN_PREV, KF_SEARCH_WIN, KF_SEARCH_WORKSPACE, KF_SPAWN_CUSTOM, + KF_STACK_BALANCE, KF_STACK_INC, KF_STACK_DEC, KF_STACK_RESET, - KF_STACK_BALANCE, KF_SWAP_MAIN, KF_SWAP_NEXT, KF_SWAP_PREV, @@ -983,6 +983,8 @@ void center_pointer(struct swm_region *); void check_conn(void); void clear_keys(void); int clear_maximized(struct workspace *); +void clear_quirks(void); +void clear_spawns(void); void clientmessage(xcb_client_message_event_t *); void client_msg(struct ws_win *, xcb_atom_t, xcb_timestamp_t); int conf_load(const char *, int); @@ -1130,8 +1132,6 @@ int setautorun(const char *, const char *, int); int setconfbinding(const char *, const char *, int); int setconfcolor(const char *, const char *, int); int setconfmodkey(const char *, const char *, int); -int setconfmousebuttonmove(const char *, const char *, int); -int setconfmousebuttonresize(const char *, const char *, int); int setconfquirk(const char *, const char *, int); int setconfregion(const char *, const char *, int); int setconfspawn(const char *, const char *, int); @@ -1179,7 +1179,6 @@ void unmap_window(struct ws_win *); void updatenumlockmask(void); void update_floater(struct ws_win *); void update_modkey(unsigned int); -unsigned char update_mousebutton(unsigned char, unsigned int); void update_win_stacking(struct ws_win *); void update_window(struct ws_win *); void update_window_color(struct ws_win *); @@ -2710,13 +2709,13 @@ fontset_init(void) void xft_init(struct swm_region *r) { - char *font, *d, *search; + char *font, *str, *search; XRenderColor color; if (bar_font == NULL) { - if ((d = strdup(bar_fonts)) == NULL) + if ((search = str = strdup(bar_fonts)) == NULL) errx(1, "insufficient memory."); - search = d; + while ((font = strsep(&search, ",")) != NULL) { if (*font == '\0') continue; @@ -2740,7 +2739,7 @@ xft_init(struct swm_region *r) break; } } - free(d); + free(str); } if (bar_font == NULL) @@ -2847,7 +2846,7 @@ set_win_state(struct ws_win *win, uint8_t state) uint16_t data[2] = { state, XCB_ATOM_NONE }; DNPRINTF(SWM_D_EVENT, "set_win_state: win %#x, state: %u\n", - win->id, state); + WINID(win), state); if (win == NULL) return; @@ -3040,13 +3039,13 @@ lower_window(struct ws_win *win) struct ws_win *target = NULL; struct workspace *ws; + DNPRINTF(SWM_D_EVENT, "lower_window: win %#x\n", WINID(win)); + if (win == NULL) return; ws = win->ws; - DNPRINTF(SWM_D_EVENT, "lower_window: win %#x\n", win->id); - TAILQ_FOREACH(target, &ws->stack, stack_entry) { if (target == win || ICONIC(target)) continue; @@ -3101,11 +3100,12 @@ raise_window(struct ws_win *win) struct ws_win *target = NULL; struct workspace *ws; + DNPRINTF(SWM_D_EVENT, "raise_window: win %#x\n", WINID(win)); + if (win == NULL) return; - ws = win->ws; - DNPRINTF(SWM_D_EVENT, "raise_window: win %#x\n", win->id); + ws = win->ws; TAILQ_FOREACH(target, &ws->stack, stack_entry) { if (target == win || ICONIC(target)) @@ -3494,23 +3494,29 @@ spawn(int ws_idx, union arg *args, bool close_fd) void kill_refs(struct ws_win *win) { - int i, x, num_screens; - struct swm_region *r; struct workspace *ws; + struct ws_win *w; + int i, j, num_screens; if (win == NULL) return; num_screens = get_screen_count(); - for (i = 0; i < num_screens; i++) - TAILQ_FOREACH(r, &screens[i].rl, entry) - for (x = 0; x < workspace_limit; x++) { - ws = &r->s->ws[x]; - if (win == ws->focus) - ws->focus = NULL; - if (win == ws->focus_prev) - ws->focus_prev = NULL; - } + for (i = 0; i < num_screens; i++) { + for (j = 0; j < workspace_limit; j++) { + ws = &screens[i].ws[j]; + + if (win == ws->focus) + ws->focus = NULL; + if (win == ws->focus_prev) + ws->focus_prev = NULL; + + if (TRANS(win)) + TAILQ_FOREACH(w, &ws->winlist, entry) + if (win == w->focus_child) + w->focus_child = NULL; + } + } } int @@ -3607,6 +3613,15 @@ unfocus_win(struct ws_win *win) if (win->ws->always_raise) raise_window(win); + /* Update border width */ + if (win->bordered && (win->quirks & SWM_Q_MINIMALBORDER) && + FLOATING(win)) { + win->bordered = 0; + X(win) += border_width; + Y(win) += border_width; + update_window(win); + } + xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->s->root, ewmh[_NET_ACTIVE_WINDOW].atom, XCB_ATOM_WINDOW, 32, 1, &none); @@ -3646,6 +3661,16 @@ focus_win(struct ws_win *win) &cfw->s->c[(MAXIMIZED(cfw) ? SWM_S_COLOR_UNFOCUS_MAXIMIZED : SWM_S_COLOR_UNFOCUS)].pixel); + + /* Update border width */ + if (cfw->bordered && + (cfw->quirks & SWM_Q_MINIMALBORDER) && + FLOATING(cfw)) { + cfw->bordered = 0; + X(cfw) += border_width; + Y(cfw) += border_width; + update_window(cfw); + } } else { unfocus_win(cfw); } @@ -3659,9 +3684,8 @@ focus_win(struct ws_win *win) ws->focus = win; } - /* If this window directs focus to a child window, then clear. */ - if (win->focus_child) - win->focus_child = NULL; + /* Clear focus child redirect. */ + win->focus_child = NULL; /* If transient, adjust parent's focus child for focus_magic. */ if (TRANS(win)) { @@ -3734,10 +3758,20 @@ focus_win(struct ws_win *win) &win->id); } - if (cfw != win) + if (cfw != win) { /* Update window border even if workspace is hidden. */ update_window_color(win); + /* Update border width */ + if (!win->bordered && WS_FOCUSED(win->ws) && + (win->quirks & SWM_Q_MINIMALBORDER) && FLOATING(win)) { + win->bordered = 1; + X(win) -= border_width; + Y(win) -= border_width; + update_window(win); + } + } + out: bar_draw(); @@ -3888,6 +3922,20 @@ switchws(struct swm_region *r, union arg *args) if (new_ws == old_ws) return; + other_r = new_ws->r; + if (other_r && workspace_clamp) { + DNPRINTF(SWM_D_WS, "switchws: ws clamped.\n"); + + if (warp_focus) { + DNPRINTF(SWM_D_WS, "switchws: warping focus to region " + "with ws %d.\n", wsid); + focus_region(other_r); + center_pointer(other_r); + focus_flush(); + } + return; + } + if ((win = old_ws->focus) != NULL) { update_window_color(win); @@ -3896,17 +3944,17 @@ switchws(struct swm_region *r, union arg *args) &none); } - other_r = new_ws->r; - if (other_r == NULL) { - /* the other workspace is hidden, hide this one */ - old_ws->r = NULL; - unmap_old = true; - } else { + if (other_r) { /* the other ws is visible in another region, exchange them */ other_r->ws_prior = new_ws; other_r->ws = old_ws; old_ws->r = other_r; + } else { + /* the other workspace is hidden, hide this one */ + old_ws->r = NULL; + unmap_old = true; } + this_r->ws_prior = old_ws; this_r->ws = new_ws; new_ws->r = this_r; @@ -4652,6 +4700,8 @@ update_floater(struct ws_win *win) struct workspace *ws; struct swm_region *r; + DNPRINTF(SWM_D_MISC, "update_floater: win %#x\n", WINID(win)); + if (win == NULL) return; @@ -4660,8 +4710,6 @@ update_floater(struct ws_win *win) if ((r = ws->r) == NULL) return; - DNPRINTF(SWM_D_MISC, "update_floater: win %#x\n", win->id); - win->bordered = true; if (FULLSCREEN(win)) { @@ -4696,9 +4744,11 @@ update_floater(struct ws_win *win) if (r != ws->old_r) load_float_geom(win); - if ((win->quirks & SWM_Q_FULLSCREEN) && - WIDTH(win) >= WIDTH(r) && HEIGHT(win) >= HEIGHT(r)) { - /* Remove border for FULLSCREEN quirk. */ + if (((win->quirks & SWM_Q_FULLSCREEN) && + WIDTH(win) >= WIDTH(r) && HEIGHT(win) >= HEIGHT(r)) || + ((!WS_FOCUSED(win->ws) || win->ws->focus != win) && + (win->quirks & SWM_Q_MINIMALBORDER))) { + /* Remove border */ win->bordered = false; } else if (!MANUAL(win)) { if (TRANS(win) && (win->quirks & SWM_Q_TRANSSZ)) { @@ -4973,9 +5023,6 @@ vertical_config(struct workspace *ws, int id) ws->l_state.vertical_mwin = 1; ws->l_state.vertical_stacks = 1; break; - case SWM_ARG_ID_STACKBALANCE: - ws->l_state.vertical_msize = SWM_V_SLICE / (ws->l_state.vertical_stacks + 1); - break; case SWM_ARG_ID_MASTERSHRINK: if (ws->l_state.vertical_msize > 1) ws->l_state.vertical_msize--; @@ -4991,6 +5038,9 @@ vertical_config(struct workspace *ws, int id) if (ws->l_state.vertical_mwin > 0) ws->l_state.vertical_mwin--; break; + case SWM_ARG_ID_STACKBALANCE: + ws->l_state.vertical_msize = SWM_V_SLICE / (ws->l_state.vertical_stacks + 1); + break; case SWM_ARG_ID_STACKINC: ws->l_state.vertical_stacks++; break; @@ -5026,9 +5076,6 @@ horizontal_config(struct workspace *ws, int id) ws->l_state.horizontal_msize = SWM_H_SLICE / 2; ws->l_state.horizontal_stacks = 1; break; - case SWM_ARG_ID_STACKBALANCE: - ws->l_state.horizontal_msize = SWM_H_SLICE / (ws->l_state.horizontal_stacks + 1); - break; case SWM_ARG_ID_MASTERSHRINK: if (ws->l_state.horizontal_msize > 1) ws->l_state.horizontal_msize--; @@ -5044,6 +5091,9 @@ horizontal_config(struct workspace *ws, int id) if (ws->l_state.horizontal_mwin > 0) ws->l_state.horizontal_mwin--; break; + case SWM_ARG_ID_STACKBALANCE: + ws->l_state.horizontal_msize = SWM_H_SLICE / (ws->l_state.horizontal_stacks + 1); + break; case SWM_ARG_ID_STACKINC: ws->l_state.horizontal_stacks++; break; @@ -5847,10 +5897,13 @@ ewmh_update_current_desktop(void) int num_screens, i; num_screens = get_screen_count(); - for (i = 0; i < num_screens; ++i) - xcb_change_property(conn, XCB_PROP_MODE_REPLACE, - screens[i].root, ewmh[_NET_CURRENT_DESKTOP].atom, - XCB_ATOM_CARDINAL, 32, 1, &screens[i].r_focus->ws->idx); + for (i = 0; i < num_screens; ++i) { + if (screens[i].r_focus) + xcb_change_property(conn, XCB_PROP_MODE_REPLACE, + screens[i].root, ewmh[_NET_CURRENT_DESKTOP].atom, + XCB_ATOM_CARDINAL, 32, 1, + &screens[i].r_focus->ws->idx); + } } void @@ -6733,19 +6786,19 @@ struct keyfunc { { "rg_7", focusrg, {.id = 6} }, { "rg_8", focusrg, {.id = 7} }, { "rg_9", focusrg, {.id = 8} }, - { "rg_next", cyclerg, {.id = SWM_ARG_ID_CYCLERG_UP} }, - { "rg_prev", cyclerg, {.id = SWM_ARG_ID_CYCLERG_DOWN} }, { "rg_move_next", cyclerg, {.id = SWM_ARG_ID_CYCLERG_MOVE_UP} }, { "rg_move_prev", cyclerg, {.id = SWM_ARG_ID_CYCLERG_MOVE_DOWN} }, + { "rg_next", cyclerg, {.id = SWM_ARG_ID_CYCLERG_UP} }, + { "rg_prev", cyclerg, {.id = SWM_ARG_ID_CYCLERG_DOWN} }, { "screen_next", cyclerg, {.id = SWM_ARG_ID_CYCLERG_UP} }, { "screen_prev", cyclerg, {.id = SWM_ARG_ID_CYCLERG_DOWN} }, { "search_win", search_win, {0} }, { "search_workspace", search_workspace, {0} }, { "spawn_custom", NULL, {0} }, + { "stack_balance", stack_config, {.id = SWM_ARG_ID_STACKBALANCE} }, { "stack_inc", stack_config, {.id = SWM_ARG_ID_STACKINC} }, { "stack_dec", stack_config, {.id = SWM_ARG_ID_STACKDEC} }, { "stack_reset", stack_config, {.id = SWM_ARG_ID_STACKRESET} }, - { "stack_balance", stack_config, {.id = SWM_ARG_ID_STACKBALANCE} }, { "swap_main", swapwin, {.id = SWM_ARG_ID_SWAPMAIN} }, { "swap_next", swapwin, {.id = SWM_ARG_ID_SWAPNEXT} }, { "swap_prev", swapwin, {.id = SWM_ARG_ID_SWAPPREV} }, @@ -6841,31 +6894,6 @@ update_modkey(unsigned int mod) buttons[i].mask = mod; } -unsigned char -update_mousebutton(unsigned char type, unsigned int but) -{ - int i; - - switch (type) { - case 0: - mouse_button_move = but; - break; - case 1: - mouse_button_resize = but; - break; - } - - for (i = 0; i < LENGTH(buttons); i++) { - if (buttons[i].func == move) - buttons[i].button = mouse_button_move; - - if (buttons[i].func == resize) - buttons[i].button = mouse_button_resize; - } - - return(1); -} - int spawn_expand(struct swm_region *r, union arg *args, const char *spawn_name, char ***ret_args) @@ -7132,6 +7160,16 @@ spawn_remove(struct spawn_prog *sp) DNPRINTF(SWM_D_SPAWN, "spawn_remove: leave\n"); } +void +clear_spawns(void) +{ + struct spawn_prog *sp; + + while ((sp = TAILQ_FIRST(&spawns)) != NULL) { + spawn_remove(sp); + } +} + struct spawn_prog* spawn_find(const char *name) { @@ -7536,8 +7574,6 @@ setup_keys(void) setkeybinding(MODKEY, XK_KP_Up, KF_RG_8, NULL); setkeybinding(MODKEY, XK_KP_Prior, KF_RG_9, NULL); setkeybinding(MODKEY_SHIFT, XK_Right, KF_RG_NEXT, NULL); - setkeybinding(MODKEY, XK_c, KF_RG_MOVE_NEXT,NULL); - setkeybinding(MODKEY_SHIFT, XK_c, KF_RG_MOVE_PREV,NULL); setkeybinding(MODKEY_SHIFT, XK_Left, KF_RG_PREV, NULL); setkeybinding(MODKEY, XK_f, KF_SEARCH_WIN, NULL); setkeybinding(MODKEY, XK_slash, KF_SEARCH_WORKSPACE,NULL); @@ -7550,7 +7586,6 @@ setup_keys(void) setkeybinding(MODKEY_SHIFT, XK_comma, KF_STACK_INC, NULL); setkeybinding(MODKEY_SHIFT, XK_period, KF_STACK_DEC, NULL); setkeybinding(MODKEY_SHIFT, XK_space, KF_STACK_RESET, NULL); - setkeybinding(MODKEY_SHIFT, XK_h, KF_STACK_BALANCE, NULL); setkeybinding(MODKEY, XK_Return, KF_SWAP_MAIN, NULL); setkeybinding(MODKEY_SHIFT, XK_j, KF_SWAP_NEXT, NULL); setkeybinding(MODKEY_SHIFT, XK_k, KF_SWAP_PREV, NULL); @@ -7749,6 +7784,7 @@ const char *quirkname[] = { "IGNOREPID", "IGNORESPAWNWS", "NOFOCUSCYCLE", + "MINIMALBORDER", }; /* SWM_Q_DELIM: retain '|' for back compat for now (2009-08-11) */ @@ -7762,10 +7798,9 @@ parsequirks(const char *qstr, uint32_t *quirk, int *ws) if (quirk == NULL || qstr == NULL) return (1); - if ((str = strdup(qstr)) == NULL) + if ((cp = str = strdup(qstr)) == NULL) err(1, "parsequirks: strdup"); - cp = str; *quirk = 0; while ((name = strsep(&cp, SWM_Q_DELIM)) != NULL) { if (cp) @@ -7889,6 +7924,16 @@ quirk_free(struct quirk *qp) free(qp); } +void +clear_quirks(void) +{ + struct quirk *qp; + + while ((qp = TAILQ_FIRST(&quirks)) != NULL) { + quirk_remove(qp); + } +} + void quirk_replace(struct quirk *qp, const char *class, const char *instance, const char *name, uint32_t quirk, int ws) @@ -8076,10 +8121,12 @@ enum { SWM_S_URGENT_COLLAPSE, SWM_S_URGENT_ENABLED, SWM_S_VERBOSE_LAYOUT, + SWM_S_WARP_FOCUS, SWM_S_WARP_POINTER, SWM_S_WINDOW_CLASS_ENABLED, SWM_S_WINDOW_INSTANCE_ENABLED, SWM_S_WINDOW_NAME_ENABLED, + SWM_S_WORKSPACE_CLAMP, SWM_S_WORKSPACE_LIMIT, SWM_S_WORKSPACE_NAME, }; @@ -8089,7 +8136,7 @@ setconfvalue(const char *selector, const char *value, int flags) { struct workspace *ws; int i, ws_id, num_screens; - char *b, *str, s[1024]; + char *b, *str, *sp, s[1024]; switch (flags) { case SWM_S_BAR_ACTION: @@ -8134,11 +8181,11 @@ setconfvalue(const char *selector, const char *value, int flags) if (!bar_font_legacy) break; - if ((str = strdup(value)) == NULL) + if ((sp = str = strdup(value)) == NULL) err(1, "setconfvalue: strdup"); /* If there are any non-XLFD entries, switch to Xft mode. */ - while ((b = strsep(&str, ",")) != NULL) { + while ((b = strsep(&sp, ",")) != NULL) { if (*b == '\0') continue; if (!isxlfd(b)) { @@ -8294,6 +8341,9 @@ setconfvalue(const char *selector, const char *value, int flags) layouts[i].l_string = plain_stacker; } break; + case SWM_S_WARP_FOCUS: + warp_focus = (atoi(value) != 0); + break; case SWM_S_WARP_POINTER: warp_pointer = (atoi(value) != 0); break; @@ -8306,6 +8356,9 @@ setconfvalue(const char *selector, const char *value, int flags) case SWM_S_WINDOW_NAME_ENABLED: window_name_enabled = (atoi(value) != 0); break; + case SWM_S_WORKSPACE_CLAMP: + workspace_clamp = (atoi(value) != 0); + break; case SWM_S_WORKSPACE_LIMIT: workspace_limit = atoi(value); if (workspace_limit > SWM_WS_MAX) @@ -8369,48 +8422,6 @@ setconfmodkey(const char *selector, const char *value, int flags) return (0); } -int -setconfmousebuttonmove(const char *selector, const char *value, int flags) -{ - /* suppress unused warnings since vars are needed */ - (void)selector; - (void)flags; - - if (strncasecmp(value, "But1", strlen("But1")) == 0) { - if (!update_mousebutton(0, XCB_BUTTON_INDEX_1)) - return (1); - } else if (strncasecmp(value, "But2", strlen("But2")) == 0) { - if (!update_mousebutton(0, XCB_BUTTON_INDEX_2)) - return (1); - } else if (strncasecmp(value, "But3", strlen("But3")) == 0) { - if (!update_mousebutton(0, XCB_BUTTON_INDEX_3)) - return (1); - } else - return (1); - return (0); -} - -int -setconfmousebuttonresize(const char *selector, const char *value, int flags) -{ - /* suppress unused warnings since vars are needed */ - (void)selector; - (void)flags; - - if (strncasecmp(value, "But1", strlen("But1")) == 0) { - if (!update_mousebutton(1, XCB_BUTTON_INDEX_1)) - return (1); - } else if (strncasecmp(value, "But2", strlen("But2")) == 0) { - if (!update_mousebutton(1, XCB_BUTTON_INDEX_2)) - return (1); - } else if (strncasecmp(value, "But3", strlen("But3")) == 0) { - if (!update_mousebutton(1, XCB_BUTTON_INDEX_3)) - return (1); - } else - return (1); - return (0); -} - int setconfcolor(const char *selector, const char *value, int flags) { @@ -8469,7 +8480,7 @@ setautorun(const char *selector, const char *value, int flags) { int ws_id; char s[1024]; - char *ap, *sp; + char *ap, *sp, *str; union arg a; int argc = 0; pid_t pid; @@ -8489,7 +8500,7 @@ setautorun(const char *selector, const char *value, int flags) if (ws_id < 0 || ws_id >= workspace_limit) errx(1, "autorun: invalid workspace %d", ws_id + 1); - sp = expand_tilde((char *)&s); + sp = str = expand_tilde((char *)&s); /* * This is a little intricate @@ -8508,7 +8519,7 @@ setautorun(const char *selector, const char *value, int flags) err(1, "setautorun: realloc"); a.argv[argc - 1] = ap; } - free(sp); + free(str); if ((a.argv = realloc(a.argv, (argc + 1) * sizeof(char *))) == NULL) err(1, "setautorun: realloc"); @@ -8656,12 +8667,10 @@ struct config_option configopt[] = { { "focus_mode", setconfvalue, SWM_S_FOCUS_MODE }, { "iconic_enabled", setconfvalue, SWM_S_ICONIC_ENABLED }, { "java_workaround", setconfvalue, SWM_S_JAVA_WORKAROUND }, - { "maximize_hide_bar", setconfvalue, SWM_S_MAXIMIZE_HIDE_BAR }, { "keyboard_mapping", setkeymapping, 0 }, { "layout", setlayout, 0 }, + { "maximize_hide_bar", setconfvalue, SWM_S_MAXIMIZE_HIDE_BAR }, { "modkey", setconfmodkey, 0 }, - { "move_button", setconfmousebuttonmove, 0 }, - { "resize_button", setconfmousebuttonresize, 0 }, { "program", setconfspawn, 0 }, { "quirk", setconfquirk, 0 }, { "region", setconfregion, 0 }, @@ -8678,10 +8687,12 @@ struct config_option configopt[] = { { "urgent_collapse", setconfvalue, SWM_S_URGENT_COLLAPSE }, { "urgent_enabled", setconfvalue, SWM_S_URGENT_ENABLED }, { "verbose_layout", setconfvalue, SWM_S_VERBOSE_LAYOUT }, + { "warp_focus", setconfvalue, SWM_S_WARP_FOCUS }, { "warp_pointer", setconfvalue, SWM_S_WARP_POINTER }, { "window_class_enabled", setconfvalue, SWM_S_WINDOW_CLASS_ENABLED }, { "window_instance_enabled", setconfvalue, SWM_S_WINDOW_INSTANCE_ENABLED }, { "window_name_enabled", setconfvalue, SWM_S_WINDOW_NAME_ENABLED }, + { "workspace_clamp", setconfvalue, SWM_S_WORKSPACE_CLAMP }, { "workspace_limit", setconfvalue, SWM_S_WORKSPACE_LIMIT }, { "name", setconfvalue, SWM_S_WORKSPACE_NAME }, }; @@ -8827,12 +8838,6 @@ conf_load(const char *filename, int keymapping) if (line) free(line); fclose(config); - - if (mouse_button_move == mouse_button_resize) { - add_startup_exception("%s: move and resize mouse buttons match", - filename); - } - DNPRINTF(SWM_D_CONF, "conf_load: end\n"); return (0); @@ -9230,17 +9235,13 @@ out: void free_window(struct ws_win *win) { - DNPRINTF(SWM_D_MISC, "free_window: win %#x\n", win->id); + DNPRINTF(SWM_D_MISC, "free_window: win %#x\n", WINID(win)); if (win == NULL) return; - TAILQ_REMOVE(&win->ws->unmanagedlist, win, entry); - xcb_icccm_get_wm_class_reply_wipe(&win->ch); - kill_refs(win); - /* paint memory */ memset(win, 0xff, sizeof *win); /* XXX kill later */ @@ -9253,11 +9254,11 @@ unmanage_window(struct ws_win *win) { struct ws_win *parent; + DNPRINTF(SWM_D_MISC, "unmanage_window: win %#x\n", WINID(win)); + if (win == NULL) return; - DNPRINTF(SWM_D_MISC, "unmanage_window: win %#x\n", win->id); - if (TRANS(win)) { parent = find_window(win->transient); if (parent) @@ -9630,35 +9631,41 @@ destroynotify(xcb_destroy_notify_event_t *e) DNPRINTF(SWM_D_EVENT, "destroynotify: win %#x\n", e->window); - if ((win = find_window(e->window)) == NULL) { - if ((win = find_unmanaged_window(e->window)) == NULL) - return; - free_window(win); - return; - } - - if (focus_mode != SWM_FOCUS_FOLLOW) { - /* If we were focused, make sure we focus on something else. */ - if (win == win->ws->focus) - win->ws->focus_pending = get_focus_prev(win); - } + if ((win = find_window(e->window))) { + /* Managed window cleanup. */ + if (focus_mode != SWM_FOCUS_FOLLOW) { + /* If focused, focus on something else. */ + if (win == win->ws->focus) + win->ws->focus_pending = get_focus_prev(win); + } - unmanage_window(win); - stack(); + unmanage_window(win); + stack(); - if (focus_mode != SWM_FOCUS_FOLLOW && WS_FOCUSED(win->ws)) { - if (win->ws->focus_pending) { - focus_win(win->ws->focus_pending); - win->ws->focus_pending = NULL; - } else if (win == win->ws->focus) { - xcb_set_input_focus(conn, XCB_INPUT_FOCUS_PARENT, - win->ws->r->id, XCB_CURRENT_TIME); + if (focus_mode != SWM_FOCUS_FOLLOW && WS_FOCUSED(win->ws)) { + if (win->ws->focus_pending) { + focus_win(win->ws->focus_pending); + win->ws->focus_pending = NULL; + } else if (win == win->ws->focus) { + xcb_set_input_focus(conn, + XCB_INPUT_FOCUS_PARENT, win->ws->r->id, + XCB_CURRENT_TIME); + } } + + kill_refs(win); + focus_flush(); + } else { + win = find_unmanaged_window(e->window); } - free_window(win); + if (win) { + /* unmanage_window() puts win into unmanaged list. */ + TAILQ_REMOVE(&win->ws->unmanagedlist, win, entry); + free_window(win); + } - focus_flush(); + DNPRINTF(SWM_D_EVENT, "destroynotify: done.\n"); } #ifdef SWM_DEBUG @@ -10692,8 +10699,7 @@ setup_screens(void) xcb_randr_query_version_reply_t *r; num_screens = get_screen_count(); - if ((screens = calloc(num_screens, - sizeof(struct swm_screen))) == NULL) + if ((screens = calloc(num_screens, sizeof(struct swm_screen))) == NULL) err(1, "setup_screens: calloc: failed to allocate memory for " "screens"); @@ -10806,6 +10812,9 @@ setup_globals(void) void shutdown_cleanup(void) { + struct swm_region *r; + struct ws_win *w; + struct workspace *ws; int i, num_screens; /* disable alarm because the following code may not be interrupted */ @@ -10818,10 +10827,16 @@ shutdown_cleanup(void) cursors_cleanup(); + clear_quirks(); + clear_spawns(); + clear_keys(); + teardown_ewmh(); num_screens = get_screen_count(); for (i = 0; i < num_screens; ++i) { + int j; + xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, screens[i].root, XCB_CURRENT_TIME); @@ -10833,13 +10848,51 @@ shutdown_cleanup(void) XftColorFree(display, DefaultVisual(display, i), DefaultColormap(display, i), &search_font_color); } + + for (j = 0; j < SWM_S_COLOR_MAX; ++j) { + free(screens[i].c[j].name); + } + + /* Free window memory. */ + for (j = 0; j < SWM_WS_MAX; ++j) { + ws = &screens[i].ws[j]; + free(ws->name); + + while ((w = TAILQ_FIRST(&ws->winlist)) != NULL) { + TAILQ_REMOVE(&ws->winlist, w, entry); + free_window(w); + } + + while ((w = TAILQ_FIRST(&ws->unmanagedlist)) != NULL) { + TAILQ_REMOVE(&ws->unmanagedlist, w, entry); + free_window(w); + } + } + + /* Free region memory. */ + while ((r = TAILQ_FIRST(&screens[i].rl)) != NULL) { + TAILQ_REMOVE(&screens[i].rl, r, entry); + free(r->bar); + free(r); + } + + while ((r = TAILQ_FIRST(&screens[i].orl)) != NULL) { + TAILQ_REMOVE(&screens[i].rl, r, entry); + free(r->bar); + free(r); + } } + free(screens); - if (bar_font_legacy) + free(bar_format); + free(bar_fonts); + free(clock_format); + free(startup_exception); + + if (bar_fs) XFreeFontSet(display, bar_fs); - else { + if (bar_font) XftFontClose(display, bar_font); - } xcb_key_symbols_free(syms); xcb_flush(conn); @@ -10916,14 +10969,14 @@ event_handle(xcb_generic_event_t *evt) int main(int argc, char *argv[]) { - struct swm_region *r; - char conf[PATH_MAX], *cfile = NULL; - struct stat sb; - int xfd, i, num_screens; + struct pollfd pfd[2]; struct sigaction sact; + struct stat sb; + struct passwd *pwd; + struct swm_region *r; xcb_generic_event_t *evt; - int num_readable; - struct pollfd pfd[2]; + int xfd, i, num_screens, num_readable; + char conf[PATH_MAX], *cfile = NULL; bool stdin_ready = false, startup = true; /* suppress unused warning since var is needed */ @@ -11090,8 +11143,10 @@ noconfig: num_readable = poll(pfd, bar_extra ? 2 : 1, 1000); if (num_readable == -1) { - DNPRINTF(SWM_D_MISC, "poll failed: %s", strerror(errno)); - } else if (num_readable > 0 && bar_extra && pfd[1].revents & POLLIN) { + DNPRINTF(SWM_D_MISC, "poll failed: %s", + strerror(errno)); + } else if (num_readable > 0 && bar_extra && + pfd[1].revents & POLLIN) { stdin_ready = true; }