X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=scrotwm.c;h=cbba2491a1cdc4bca26528ac67b83bac07e2424d;hb=cd77f27d662a8e9311d4227334c23a0fd4c3f2bc;hp=6964df7b77f0aacff724cececdad918f7e424e6f;hpb=7976b49314c1fb669fcc5668c4932ec9d55e9192;p=spectrwm.git diff --git a/scrotwm.c b/scrotwm.c index 6964df7..cbba249 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -96,8 +96,8 @@ static const char *cvstag = "$scrotwm$"; /* #define SWM_DEBUG */ #ifdef SWM_DEBUG -#define DPRINTF(x...) do { if (swm_debug) fprintf(stderr, x); } while(0) -#define DNPRINTF(n,x...) do { if (swm_debug & n) fprintf(stderr, x); } while(0) +#define DPRINTF(x...) do { if (swm_debug) fprintf(stderr, x); } while (0) +#define DNPRINTF(n,x...) do { if (swm_debug & n) fprintf(stderr, x); } while (0) #define SWM_D_MISC 0x0001 #define SWM_D_EVENT 0x0002 #define SWM_D_WS 0x0004 @@ -148,6 +148,8 @@ u_int32_t swm_debug = 0 #define WIDTH(r) (r)->g.w #define HEIGHT(r) (r)->g.h #define SWM_MAX_FONT_STEPS (3) +#define SWM_EV_PROLOGUE(x) do { XGrabServer(x); } while (0) +#define SWM_EV_EPILOGUE(x) do { XUngrabServer(x); XFlush(x); } while (0) #ifndef SWM_LIB #define SWM_LIB "/usr/local/lib/libswmhack.so" @@ -190,6 +192,7 @@ int bar_extra = 1; int bar_extra_running = 0; int bar_verbose = 1; int bar_height = 0; +int stack_enabled = 1; int clock_enabled = 1; int title_name_enabled = 0; int title_class_enabled = 0; @@ -319,12 +322,17 @@ void new_region(struct swm_screen *, int, int, int, int); struct layout { void (*l_stack)(struct workspace *, struct swm_geometry *); void (*l_config)(struct workspace *, int); + u_int32_t flags; +#define SWM_L_FOCUSPREV (1<<0) +#define SWM_L_MAPONFOCUS (1<<1) + char *name; } layouts[] = { /* stack, configure */ - { vertical_stack, vertical_config}, - { horizontal_stack, horizontal_config}, - { max_stack, NULL}, - { NULL, NULL}, + { vertical_stack, vertical_config, 0, "[|]" }, + { horizontal_stack, horizontal_config, 0, "[-]" }, + { max_stack, NULL, + SWM_L_FOCUSPREV | SWM_L_MAPONFOCUS, "[ ]"}, + { NULL, NULL, 0}, }; #define SWM_H_SLICE (32) @@ -753,6 +761,7 @@ bar_update(void) char s[SWM_BAR_MAX]; char loc[SWM_BAR_MAX]; char *b; + char *stack = ""; if (bar_enabled == 0) return; @@ -785,12 +794,15 @@ bar_update(void) if (r && r->ws) bar_class_name(s, sizeof s, r->ws->focus); - snprintf(loc, sizeof loc, "%d:%d %s %s %s", - x++, r->ws->idx + 1, s, bar_ext, bar_vertext); + if (stack_enabled) + stack = r->ws->cur_layout->name; + + snprintf(loc, sizeof loc, "%d:%d %s %s %s %s", + x++, r->ws->idx + 1, stack, s, bar_ext, + bar_vertext); bar_print(r, loc); } } - XSync(display, False); alarm(bar_delay); } @@ -1222,6 +1234,8 @@ focus_win(struct ws_win *win) 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); XSetInputFocus(display, win->id, RevertToPointerRoot, CurrentTime); XSync(display, False); @@ -1330,6 +1344,10 @@ cyclescr(struct swm_region *r, union arg *args) struct swm_region *rr; int i; + /* do nothing if we don't have more than one screen */ + if (!(ScreenCount(display) > 1 || outputs > 1)) + return; + i = r->s->idx; switch (args->id) { case SWM_ARG_ID_CYCLESC_UP: @@ -1347,8 +1365,8 @@ cyclescr(struct swm_region *r, union arg *args) }; unfocus_all(); XSetInputFocus(display, PointerRoot, RevertToPointerRoot, CurrentTime); - XWarpPointer(display, None, rr->s[i].root, 0, 0, 0, 0, rr->g.x, - rr->g.y + bar_enabled ? bar_height : 0); + XWarpPointer(display, None, rr->s[i].root, 0, 0, 0, 0, rr->g.x + 1, + rr->g.y + bar_enabled + 1 ? bar_height : 0); } void @@ -1457,9 +1475,7 @@ focus(struct swm_region *r, union arg *args) if (winfocus == winlostfocus || winfocus == NULL) return; - XMapRaised(display, winfocus->id); focus_win(winfocus); - XSync(display, False); } void @@ -1479,6 +1495,7 @@ cycle_layout(struct swm_region *r, union arg *args) ignore_enter = 1; stack(); focus_win(winfocus); + ignore_enter = 0; } void @@ -1871,6 +1888,9 @@ max_stack(struct workspace *ws, struct swm_geometry *g) DNPRINTF(SWM_D_STACK, "max_stack: workspace: %d\n", ws->idx); + if (ws == NULL) + return; + winno = count_win(ws, 0); if (winno == 0 && count_win(ws, 1) == 0) return; @@ -1887,15 +1907,17 @@ 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) - unmap_window(win); + if (!(ScreenCount(display) > 1 || outputs > 1)) + unmap_window(win); } } /* put the last transient on top */ if (wintrans) { stack_floater(wintrans, ws->r); - XMapRaised(display, wintrans->id); focus_win(wintrans); /* override */ } } @@ -1904,11 +1926,15 @@ void send_to_ws(struct swm_region *r, union arg *args) { int wsid = args->id; - struct ws_win *win = r->ws->focus, *winfocus = NULL; + struct ws_win *win = win, *winfocus = NULL; struct workspace *ws, *nws; Atom ws_idx_atom = 0; unsigned char ws_idx_str[SWM_PROPLEN]; + if (r && r->ws) + win = r->ws->focus; + else + return; if (win == NULL) return; @@ -1922,18 +1948,18 @@ send_to_ws(struct swm_region *r, union arg *args) if (TAILQ_FIRST(&ws->winlist) == win) winfocus = TAILQ_NEXT(win, entry); else { - winfocus = TAILQ_PREV(ws->focus, ws_win_list, entry); + winfocus = TAILQ_PREV(win, ws_win_list, entry); if (winfocus == NULL) winfocus = TAILQ_LAST(&ws->winlist, ws_win_list); } - /* out of windows in ws so focus on nws instead */ + /* out of windows in ws so focus on nws instead if we multi screen */ if (winfocus == NULL) - winfocus = win; + if (ScreenCount(display) > 1 || outputs > 1) + winfocus = win; - unmap_window(win); + unmap_window(win); TAILQ_REMOVE(&ws->winlist, win, entry); - TAILQ_INSERT_TAIL(&nws->winlist, win, entry); win->ws = nws; @@ -1953,7 +1979,8 @@ send_to_ws(struct swm_region *r, union arg *args) nws->restack = 1; stack(); - focus_win(winfocus); + if (winfocus) + focus_win(winfocus); } void @@ -2141,8 +2168,15 @@ move(struct ws_win *win, union arg *args) } /* key definitions */ -void dummykeyfunc(struct swm_region *r, union arg *args) {}; -void legacyfunc(struct swm_region *r, union arg *args) {}; +void +dummykeyfunc(struct swm_region *r, union arg *args) +{ +}; + +void +legacyfunc(struct swm_region *r, union arg *args) +{ +}; struct keyfunc { char name[SWM_FUNCNAME_LEN]; @@ -2788,65 +2822,6 @@ grabbuttons(struct ws_win *win, int focused) BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); } -void -expose(XEvent *e) -{ - DNPRINTF(SWM_D_EVENT, "expose: window: %lu\n", e->xexpose.window); -} - -void -keypress(XEvent *e) -{ - unsigned int i; - KeySym keysym; - XKeyEvent *ev = &e->xkey; - - DNPRINTF(SWM_D_EVENT, "keypress: window: %lu\n", ev->window); - - keysym = XKeycodeToKeysym(display, (KeyCode)ev->keycode, 0); - for (i = 0; i < keys_length; i++) - if (keysym == keys[i].keysym - && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) - && keyfuncs[keys[i].funcid].func) { - if (keys[i].funcid == kf_spawn_custom) - spawn_custom( - root_to_region(ev->root), - &(keyfuncs[keys[i].funcid].args), - keys[i].spawn_name - ); - else - keyfuncs[keys[i].funcid].func( - root_to_region(ev->root), - &(keyfuncs[keys[i].funcid].args) - ); - } -} - -void -buttonpress(XEvent *e) -{ - XButtonPressedEvent *ev = &e->xbutton; - - struct ws_win *win; - int i, action; - - DNPRINTF(SWM_D_EVENT, "buttonpress: window: %lu\n", ev->window); - - action = root_click; - if ((win = find_window(ev->window)) == NULL) - return; - else { - focus_win(win); - action = client_click; - } - - for (i = 0; i < LENGTH(buttons); i++) - if (action == buttons[i].action && buttons[i].func && - buttons[i].button == ev->button && - CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) - buttons[i].func(win, &buttons[i].args); -} - const char *quirkname[] = { "NONE", /* config string for "no value" */ "FLOAT", @@ -2863,8 +2838,10 @@ parsequirks(char *qstr, unsigned long *quirk) { char *cp, *name; int i; + if (quirk == NULL) return (1); + cp = qstr; *quirk = 0; while ((name = strsep(&cp, SWM_Q_WS)) != NULL) { @@ -2893,6 +2870,7 @@ void setquirk(const char *class, const char *name, const int quirk) { int i, j; + /* find existing */ for (i = 0; i < quirks_length; i++) { if (!strcmp(quirks[i].class, class) && @@ -3001,11 +2979,11 @@ setup_quirks(void) /* conf file stuff */ #define SWM_CONF_FILE "scrotwm.conf" -enum { SWM_S_BAR_DELAY, SWM_S_BAR_ENABLED, SWM_S_CLOCK_ENABLED, - SWM_S_CYCLE_EMPTY, SWM_S_CYCLE_VISIBLE, SWM_S_SS_ENABLED, - SWM_S_TERM_WIDTH, SWM_S_TITLE_CLASS_ENABLED, SWM_S_TITLE_NAME_ENABLED, - SWM_S_BAR_FONT, SWM_S_BAR_ACTION, SWM_S_SPAWN_TERM, SWM_S_SS_APP, - SWM_S_DIALOG_RATIO }; +enum { SWM_S_BAR_DELAY, SWM_S_BAR_ENABLED, SWM_S_STACK_ENABLED, + SWM_S_CLOCK_ENABLED, SWM_S_CYCLE_EMPTY, SWM_S_CYCLE_VISIBLE, + SWM_S_SS_ENABLED, SWM_S_TERM_WIDTH, SWM_S_TITLE_CLASS_ENABLED, + SWM_S_TITLE_NAME_ENABLED, SWM_S_BAR_FONT, SWM_S_BAR_ACTION, + SWM_S_SPAWN_TERM, SWM_S_SS_APP, SWM_S_DIALOG_RATIO }; int setconfvalue(char *selector, char *value, int flags) @@ -3017,6 +2995,9 @@ setconfvalue(char *selector, char *value, int flags) case SWM_S_BAR_ENABLED: bar_enabled = atoi(value); break; + case SWM_S_STACK_ENABLED: + stack_enabled = atoi(value); + break; case SWM_S_CLOCK_ENABLED: clock_enabled = atoi(value); break; @@ -3111,6 +3092,7 @@ struct config_option configopt[] = { { "bar_action", setconfvalue, SWM_S_BAR_ACTION }, { "bar_delay", setconfvalue, SWM_S_BAR_DELAY }, { "bind", setconfbinding, 0 }, + { "stack_enabled", setconfvalue, SWM_S_STACK_ENABLED }, { "clock_enabled", setconfvalue, SWM_S_CLOCK_ENABLED }, { "color_focus", setconfcolor, SWM_S_COLOR_FOCUS }, { "color_unfocus", setconfcolor, SWM_S_COLOR_UNFOCUS }, @@ -3401,6 +3383,65 @@ unmanage_window(struct ws_win *win) } void +expose(XEvent *e) +{ + DNPRINTF(SWM_D_EVENT, "expose: window: %lu\n", e->xexpose.window); +} + +void +keypress(XEvent *e) +{ + unsigned int i; + KeySym keysym; + XKeyEvent *ev = &e->xkey; + + DNPRINTF(SWM_D_EVENT, "keypress: window: %lu\n", ev->window); + + keysym = XKeycodeToKeysym(display, (KeyCode)ev->keycode, 0); + for (i = 0; i < keys_length; i++) + if (keysym == keys[i].keysym + && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) + && keyfuncs[keys[i].funcid].func) { + if (keys[i].funcid == kf_spawn_custom) + spawn_custom( + root_to_region(ev->root), + &(keyfuncs[keys[i].funcid].args), + keys[i].spawn_name + ); + else + keyfuncs[keys[i].funcid].func( + root_to_region(ev->root), + &(keyfuncs[keys[i].funcid].args) + ); + } +} + +void +buttonpress(XEvent *e) +{ + XButtonPressedEvent *ev = &e->xbutton; + + struct ws_win *win; + int i, action; + + DNPRINTF(SWM_D_EVENT, "buttonpress: window: %lu\n", ev->window); + + action = root_click; + if ((win = find_window(ev->window)) == NULL) + return; + else { + focus_win(win); + action = client_click; + } + + for (i = 0; i < LENGTH(buttons); i++) + if (action == buttons[i].action && buttons[i].func && + buttons[i].button == ev->button && + CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) + buttons[i].func(win, &buttons[i].args); +} + +void configurerequest(XEvent *e) { XConfigureRequestEvent *ev = &e->xconfigurerequest; @@ -3490,17 +3531,33 @@ destroynotify(XEvent *e) DNPRINTF(SWM_D_EVENT, "destroynotify: window %lu\n", ev->window); + SWM_EV_PROLOGUE(display); + 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); + + /* 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 && win != ws->focus_prev) + winfocus = ws->focus_prev; + + /* 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); + } } } @@ -3509,6 +3566,8 @@ destroynotify(XEvent *e) if (winfocus) focus_win(winfocus); } + + SWM_EV_EPILOGUE(display); } void @@ -3555,6 +3614,8 @@ mapnotify(XEvent *e) DNPRINTF(SWM_D_EVENT, "mapnotify: window: %lu\n", ev->window); + SWM_EV_PROLOGUE(display); + win = find_window(ev->window); if (win) set_win_state(win, NormalState); @@ -3562,6 +3623,8 @@ mapnotify(XEvent *e) XRefreshKeyboardMapping(ev); if (ev->request == MappingKeyboard) grabkeys(); + + SWM_EV_EPILOGUE(display); } void @@ -3576,10 +3639,12 @@ maprequest(XEvent *e) DNPRINTF(SWM_D_EVENT, "maprequest: window: %lu\n", e->xmaprequest.window); + SWM_EV_PROLOGUE(display); + if (!XGetWindowAttributes(display, ev->window, &wa)) - return; + goto done; if (wa.override_redirect) - return; + goto done; manage_window(e->xmaprequest.window); @@ -3591,6 +3656,9 @@ maprequest(XEvent *e) if (win->ws == r->ws) focus_win(win); + +done: + SWM_EV_EPILOGUE(display); } void @@ -3631,17 +3699,19 @@ propertynotify(XEvent *e) void unmapnotify(XEvent *e) { - struct ws_win *win, *winfocus; + struct ws_win *win, *winfocus = NULL; struct workspace *ws; DNPRINTF(SWM_D_EVENT, "unmapnotify: window: %lu\n", e->xunmap.window); + SWM_EV_PROLOGUE(display); + /* determine if we need to help unmanage this window */ win = find_window(e->xunmap.window); if (win == NULL) - return; + goto done; if (win->transient) - return; + goto done; if (getstate(e->xunmap.window) == NormalState) { /* @@ -3649,15 +3719,24 @@ unmapnotify(XEvent *e) * longer visible due to the app unmapping it so unmanage it */ - /* find something to focus */ ws = win->ws; - winfocus = TAILQ_PREV(win, ws_win_list, entry); - if (TAILQ_FIRST(&ws->winlist) == win) - winfocus = TAILQ_NEXT(win, entry); - else { - winfocus = TAILQ_PREV(ws->focus, ws_win_list, entry); - if (winfocus == NULL) - winfocus = TAILQ_LAST(&ws->winlist, ws_win_list); + /* if we are max_stack try harder to focus on something */ + if (ws->cur_layout->flags & SWM_L_FOCUSPREV) + if (win != ws->focus && win != ws->focus_prev) + winfocus = ws->focus_prev; + + /* normal and fallback if haven't found anything to focus on */ + if (winfocus == NULL) { + winfocus = TAILQ_PREV(win, ws_win_list, entry); + if (TAILQ_FIRST(&ws->winlist) == win) + winfocus = TAILQ_NEXT(win, entry); + else { + winfocus = TAILQ_PREV(ws->focus, ws_win_list, + entry); + if (winfocus == NULL) + winfocus = TAILQ_LAST(&ws->winlist, + ws_win_list); + } } /* trash window and refocus */ @@ -3665,6 +3744,9 @@ unmapnotify(XEvent *e) stack(); focus_win(winfocus); } + +done: + SWM_EV_EPILOGUE(display); } void @@ -3847,7 +3929,6 @@ void screenchange(XEvent *e) { XRRScreenChangeNotifyEvent *xe = (XRRScreenChangeNotifyEvent *)e; struct swm_region *r; - struct ws_win *win; int i; DNPRINTF(SWM_D_EVENT, "screenchange: %lu\n", xe->root); @@ -3865,11 +3946,6 @@ screenchange(XEvent *e) { /* brute force for now, just re-enumerate the regions */ scan_xrandr(i); - /* hide any windows that went away */ - TAILQ_FOREACH(r, &screens[i].rl, entry) - TAILQ_FOREACH(win, &r->ws->winlist, entry) - unmap_window(win); - /* add bars to all regions */ for (i = 0; i < ScreenCount(display); i++) TAILQ_FOREACH(r, &screens[i].rl, entry)