X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=spectrwm.c;h=93b42444d8c7607ead1ca7a118ff7e9d1696d2d3;hb=519aa00149f17f00cc7067c2b957e3639b8411f5;hp=a47f3b0e496e4c2cb29ae72cc674dd048bfbc709;hpb=66f742ca4870a1458a21732913518c87ac7c9f27;p=spectrwm.git diff --git a/spectrwm.c b/spectrwm.c index a47f3b0..93b4244 100644 --- a/spectrwm.c +++ b/spectrwm.c @@ -5,10 +5,10 @@ * Copyright (c) 2009 Pierre-Yves Ritschard * Copyright (c) 2010 Tuukka Kataja * Copyright (c) 2011 Jason L. Wright - * Copyright (c) 2011-2012 Reginald Kennedy + * Copyright (c) 2011-2013 Reginald Kennedy * Copyright (c) 2011-2012 Lawrence Teo * Copyright (c) 2011-2012 Tiago Cunha - * Copyright (c) 2012 David Hill + * Copyright (c) 2012-2013 David Hill * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -577,6 +577,8 @@ union arg { #define SWM_ARG_ID_CYCLERG_DOWN (43) #define SWM_ARG_ID_CYCLEWS_UP_ALL (44) #define SWM_ARG_ID_CYCLEWS_DOWN_ALL (45) +#define SWM_ARG_ID_CYCLEWS_MOVE_UP (46) +#define SWM_ARG_ID_CYCLEWS_MOVE_DOWN (47) #define SWM_ARG_ID_STACKINC (50) #define SWM_ARG_ID_STACKDEC (51) #define SWM_ARG_ID_SS_ALL (60) @@ -831,8 +833,10 @@ enum keyfuncid { KF_WS_22, KF_WS_NEXT, KF_WS_NEXT_ALL, + KF_WS_NEXT_MOVE, KF_WS_PREV, KF_WS_PREV_ALL, + KF_WS_PREV_MOVE, KF_WS_PRIOR, KF_DUMPWINS, /* MUST BE LAST */ KF_INVALID @@ -991,10 +995,10 @@ struct swm_region *root_to_region(xcb_window_t, int); void screenchange(xcb_randr_screen_change_notify_event_t *); void scan_xrandr(int); void search_do_resp(void); -void search_resp_name_workspace(const char *, unsigned long); +void search_resp_name_workspace(const char *, size_t); void search_resp_search_window(const char *); void search_resp_search_workspace(const char *); -void search_resp_uniconify(const char *, unsigned long); +void search_resp_uniconify(const char *, size_t); void search_win(struct swm_region *, union arg *); void search_win_cleanup(void); void search_workspace(struct swm_region *, union arg *); @@ -1985,12 +1989,12 @@ bar_window_name(char *s, size_t sz, struct swm_region *r) free(title); } -int urgent[SWM_WS_MAX]; void bar_urgent(char *s, size_t sz) { struct ws_win *win; int i, j, num_screens; + int urgent[SWM_WS_MAX]; char b[8]; xcb_get_property_cookie_t c; xcb_icccm_wm_hints_t hints; @@ -2975,6 +2979,8 @@ root_to_region(xcb_window_t root, int check) if (r == NULL && check & SWM_CK_FALLBACK) r = TAILQ_FIRST(&screens[i].rl); + DNPRINTF(SWM_D_MISC, "root_to_region: idx: %d\n", get_region_index(r)); + return (r); } @@ -3408,7 +3414,7 @@ focus_region(struct swm_region *r) if (old_r) unfocus_win(old_r->ws->focus); - xcb_set_input_focus(conn, XCB_INPUT_FOCUS_PARENT, r->s->root, + xcb_set_input_focus(conn, XCB_INPUT_FOCUS_PARENT, r->id, XCB_CURRENT_TIME); /* Clear bar since empty. */ @@ -3459,8 +3465,9 @@ switchws(struct swm_region *r, union arg *args) this_r->ws = new_ws; new_ws->r = this_r; - /* Set focus_pending before stacking. */ - if (focus_mode != SWM_FOCUS_FOLLOW) + /* Set focus_pending before stacking, if needed. */ + if (focus_mode != SWM_FOCUS_FOLLOW && (!new_ws->focus_pending || + validate_win(new_ws->focus_pending))) new_ws->focus_pending = get_region_focus(new_ws->r); stack(); @@ -3474,17 +3481,16 @@ switchws(struct swm_region *r, union arg *args) if (old_ws->r && focus_mode != SWM_FOCUS_FOLLOW) { if (new_ws->focus_pending) { focus_win(new_ws->focus_pending); - } else { - /* Empty region, focus on root. */ - xcb_set_input_focus(conn, XCB_INPUT_FOCUS_PARENT, - new_ws->r->s[new_ws->r->s->idx].root, - XCB_CURRENT_TIME); + new_ws->focus_pending = NULL; } } - /* Clear bar if new ws is empty. */ - if (new_ws->focus_pending == NULL) + /* Clear bar and set focus on region input win if new ws is empty. */ + if (new_ws->focus_pending == NULL && new_ws->focus == NULL) { + xcb_set_input_focus(conn, XCB_INPUT_FOCUS_PARENT, r->id, + XCB_CURRENT_TIME); bar_draw(); + } focus_flush(); @@ -3497,30 +3503,32 @@ cyclews(struct swm_region *r, union arg *args) union arg a; struct swm_screen *s = r->s; int cycle_all = 0; + int move = 0; DNPRINTF(SWM_D_WS, "cyclews: 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); a.id = r->ws->idx; + do { switch (args->id) { + case SWM_ARG_ID_CYCLEWS_MOVE_UP: + move = 1; + /* FALLTHROUGH */ case SWM_ARG_ID_CYCLEWS_UP_ALL: cycle_all = 1; /* FALLTHROUGH */ case SWM_ARG_ID_CYCLEWS_UP: - if (a.id < workspace_limit - 1) - a.id++; - else - a.id = 0; + a.id = (a.id < workspace_limit - 1) ? a.id + 1 : 0; break; + case SWM_ARG_ID_CYCLEWS_MOVE_DOWN: + move = 1; + /* FALLTHROUGH */ case SWM_ARG_ID_CYCLEWS_DOWN_ALL: cycle_all = 1; /* FALLTHROUGH */ case SWM_ARG_ID_CYCLEWS_DOWN: - if (a.id > 0) - a.id--; - else - a.id = workspace_limit - 1; + a.id = (a.id > 0) ? a.id - 1 : workspace_limit - 1; break; default: return; @@ -3532,6 +3540,9 @@ cyclews(struct swm_region *r, union arg *args) if (!cycle_visible && s->ws[a.id].r != NULL) continue; + if (move) + send_to_ws(r, &a); + switchws(r, &a); } while (a.id != r->ws->idx); } @@ -4248,20 +4259,24 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip) colno = (winno - mwin) / stacks; if (s <= (winno - mwin) % stacks) colno++; - split = split + colno; - hrh = (r_g.h / colno); + split += colno; + hrh = r_g.h / colno; extra = r_g.h - (colno * hrh); - if (flip) - win_g.x = r_g.x; - else + + if (!flip) win_g.x += win_g.w + 2 * border_width + tile_gap; + win_g.w = (r_g.w - msize - (stacks * (2 * border_width + tile_gap))) / stacks; if (s == 1) win_g.w += (r_g.w - msize - (stacks * (2 * border_width + tile_gap))) % stacks; + + if (flip) + win_g.x -= win_g.w + 2 * border_width + + tile_gap; s--; j = 0; } @@ -4489,6 +4504,8 @@ max_stack(struct workspace *ws, struct swm_geometry *g) win = ws->focus_pending; else if (ws->focus) win = ws->focus; + else if (ws->focus_prev) + win = ws->focus_prev; else win = TAILQ_FIRST(&ws->winlist); @@ -4623,11 +4640,10 @@ send_to_ws(struct swm_region *r, union arg *args) unfocus_win(parent); - if (focus_mode != SWM_FOCUS_FOLLOW) + if (focus_mode != SWM_FOCUS_FOLLOW) { pws->focus = pws->focus_pending; - - if (focus_mode != SWM_FOCUS_FOLLOW) pws->focus_pending = NULL; + } } /* Don't unmap parent if new ws is visible */ @@ -4672,8 +4688,14 @@ send_to_ws(struct swm_region *r, union arg *args) stack(); if (focus_mode != SWM_FOCUS_FOLLOW) { - focus_win(ws->focus_pending); - ws->focus_pending = NULL; + if (ws->focus_pending) { + focus_win(ws->focus_pending); + ws->focus_pending = NULL; + } else { + xcb_set_input_focus(conn, + XCB_INPUT_FOCUS_PARENT, r->id, + XCB_CURRENT_TIME); + } } focus_flush(); @@ -4985,7 +5007,7 @@ search_win(struct swm_region *r, union arg *args) } void -search_resp_uniconify(const char *resp, unsigned long len) +search_resp_uniconify(const char *resp, size_t len) { char *name; struct ws_win *win; @@ -5015,7 +5037,7 @@ search_resp_uniconify(const char *resp, unsigned long len) } void -search_resp_name_workspace(const char *resp, unsigned long len) +search_resp_name_workspace(const char *resp, size_t len) { struct workspace *ws; @@ -5111,7 +5133,7 @@ search_do_resp(void) { ssize_t rbytes; char *resp; - unsigned long len; + size_t len; DNPRINTF(SWM_D_MISC, "search_do_resp:\n"); @@ -5311,7 +5333,7 @@ resize(struct ws_win *win, union arg *args) int top = 0, left = 0, resizing; int dx, dy; xcb_cursor_t cursor; - xcb_query_pointer_reply_t *xpr; + xcb_query_pointer_reply_t *xpr = NULL; xcb_generic_event_t *evt; xcb_motion_notify_event_t *mne; @@ -5509,7 +5531,7 @@ move(struct ws_win *win, union arg *args) xcb_timestamp_t timestamp = 0; int move_stp = 0, moving; struct swm_region *r = NULL; - xcb_query_pointer_reply_t *qpr; + xcb_query_pointer_reply_t *qpr = NULL; xcb_generic_event_t *evt; xcb_motion_notify_event_t *mne; @@ -5762,8 +5784,10 @@ struct keyfunc { { "ws_22", switchws, {.id = 21} }, { "ws_next", cyclews, {.id = SWM_ARG_ID_CYCLEWS_UP} }, { "ws_next_all", cyclews, {.id = SWM_ARG_ID_CYCLEWS_UP_ALL} }, + { "ws_next_move", cyclews, {.id = SWM_ARG_ID_CYCLEWS_MOVE_UP} }, { "ws_prev", cyclews, {.id = SWM_ARG_ID_CYCLEWS_DOWN} }, { "ws_prev_all", cyclews, {.id = SWM_ARG_ID_CYCLEWS_DOWN_ALL} }, + { "ws_prev_move", cyclews, {.id = SWM_ARG_ID_CYCLEWS_MOVE_DOWN} }, { "ws_prior", priorws, {0} }, { "dumpwins", dumpwins, {0} }, /* MUST BE LAST */ { "invalid key func", NULL, {0} }, @@ -6452,6 +6476,8 @@ setup_keys(void) setkeybinding(MODKEY, XK_Left, KF_WS_PREV, NULL); setkeybinding(MODKEY, XK_Up, KF_WS_NEXT_ALL, NULL); setkeybinding(MODKEY, XK_Down, KF_WS_PREV_ALL, NULL); + setkeybinding(MODKEY_SHIFT, XK_Up, KF_WS_NEXT_MOVE,NULL); + setkeybinding(MODKEY_SHIFT, XK_Down, KF_WS_PREV_MOVE,NULL); setkeybinding(MODKEY, XK_a, KF_WS_PRIOR, NULL); #ifdef SWM_DEBUG setkeybinding(MODKEY_SHIFT, XK_d, KF_DUMPWINS, NULL); @@ -6549,6 +6575,16 @@ grabkeys(void) xcb_ungrab_key(conn, XCB_GRAB_ANY, screens[k].root, XCB_MOD_MASK_ANY); RB_FOREACH(kp, key_tree, &keys) { + /* Skip unused ws binds. */ + if ((int)kp->funcid > KF_WS_1 + workspace_limit - 1 && + kp->funcid <= KF_WS_22) + continue; + + /* Skip unused mvws binds. */ + if ((int)kp->funcid > KF_MVWS_1 + workspace_limit - 1 && + kp->funcid <= KF_MVWS_22) + continue; + if ((code = xcb_key_symbols_get_keycode(syms, kp->keysym))) { for (j = 0; j < LENGTH(modifiers); j++) @@ -8174,6 +8210,9 @@ destroynotify(xcb_destroy_notify_event_t *e) if (win->ws->focus_pending) { focus_win(win->ws->focus_pending); win->ws->focus_pending = NULL; + } else if (win == win->ws->focus && win->ws->r) { + xcb_set_input_focus(conn, XCB_INPUT_FOCUS_PARENT, + win->ws->r->id, XCB_CURRENT_TIME); } } @@ -8415,6 +8454,9 @@ motionnotify(xcb_motion_notify_event_t *e) last_event_time = e->time; + if (focus_mode == SWM_FOCUS_MANUAL) + return; + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) if (screens[i].root == e->root) @@ -8466,6 +8508,7 @@ void propertynotify(xcb_property_notify_event_t *e) { struct ws_win *win; + struct workspace *ws; #ifdef SWM_DEBUG char *name; @@ -8479,28 +8522,39 @@ propertynotify(xcb_property_notify_event_t *e) if (win == NULL) return; + ws = win->ws; + last_event_time = e->time; if (e->atom == a_swm_iconic) { if (e->state == XCB_PROPERTY_NEW_VALUE) { if (focus_mode != SWM_FOCUS_FOLLOW) - win->ws->focus_pending = get_focus_prev(win); + ws->focus_pending = get_focus_prev(win); unfocus_win(win); unmap_window(win); - if (win->ws->r) { + if (ws->r) { stack(); + if (focus_mode != SWM_FOCUS_FOLLOW) { - focus_win(win->ws->focus_pending); - win->ws->focus_pending = NULL; + if (ws->focus_pending) { + focus_win(ws->focus_pending); + ws->focus_pending = NULL; + } else { + xcb_set_input_focus(conn, + XCB_INPUT_FOCUS_PARENT, + ws->r->id, + XCB_CURRENT_TIME); + } } + focus_flush(); } } else if (e->state == XCB_PROPERTY_DELETE) { /* The window is no longer iconic, restack ws. */ if (focus_mode != SWM_FOCUS_FOLLOW) - win->ws->focus_pending = get_focus_magic(win); + ws->focus_pending = get_focus_magic(win); stack(); @@ -8512,9 +8566,9 @@ propertynotify(xcb_property_notify_event_t *e) if (e->state == XCB_PROPERTY_NEW_VALUE) { if (focus_mode != SWM_FOCUS_FOLLOW) { if (win->mapped && - win->ws->focus_pending == win) { - focus_win(win->ws->focus_pending); - win->ws->focus_pending = NULL; + ws->focus_pending == win) { + focus_win(ws->focus_pending); + ws->focus_pending = NULL; } } } @@ -8569,11 +8623,12 @@ unmapnotify(xcb_unmap_notify_event_t *e) if (focus_mode == SWM_FOCUS_FOLLOW) { if (ws->r) focus_win(get_pointer_win(ws->r->s->root)); - } else { - if (ws->focus_pending) { - focus_win(ws->focus_pending); - ws->focus_pending = NULL; - } + } else if (ws->focus_pending) { + focus_win(ws->focus_pending); + ws->focus_pending = NULL; + } else if (ws->focus == NULL && ws->r) { + xcb_set_input_focus(conn, XCB_INPUT_FOCUS_PARENT, + ws->r->id, XCB_CURRENT_TIME); } }