diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2020-12-23 01:12:51 -0800 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2020-12-23 16:58:42 -0800 |
commit | 3161db573424a554b536aaa492397341b84683ce (patch) | |
tree | 1f72d7aa908dbb484bb8907b17bf493f551e2b85 /src/window.c | |
parent | a6998186a3546f9f871e2cab3e994c782bd98a98 (diff) |
*: introduce and use direction parameter
This adds a direction parameter to vwm_desktop_next{_mru}() and
vwm_win_focus_next(), deprecating _prev() variants in favor of
a vwm_direction_t parameter.
XK_r has been wired up as a modifier for reversing the direction
of actions like Mod1+Tab (window next MRU cycle) and Mod1+Space
(desktop next MRU cycle). So now if you overshoot, simply hold
the "r" key and repeat the operation to go back, much like how
Shift is often used for reversing alt+tab in i.e. Windows.
Diffstat (limited to 'src/window.c')
-rw-r--r-- | src/window.c | 68 |
1 files changed, 48 insertions, 20 deletions
diff --git a/src/window.c b/src/window.c index 4fee538..cfcdd36 100644 --- a/src/window.c +++ b/src/window.c @@ -256,7 +256,7 @@ void vwm_win_focus(vwm_t *vwm, vwm_window_t *vwin) /* focus the next window on a virtual desktop relative to the supplied window, in the specified context, respecting screen boundaries according to fence. */ -vwm_window_t * vwm_win_focus_next(vwm_t *vwm, vwm_window_t *vwin, vwm_fence_t fence) +vwm_window_t * vwm_win_focus_next(vwm_t *vwm, vwm_window_t *vwin, vwm_direction_t direction, vwm_fence_t fence) { const vwm_screen_t *scr = vwm_screen_find(vwm, VWM_SCREEN_REL_XWIN, vwin->xwindow), *next_scr = NULL; vwm_window_t *next; @@ -264,23 +264,51 @@ vwm_window_t * vwm_win_focus_next(vwm_t *vwm, vwm_window_t *vwin, vwm_fence_t fe _retry: visited_mask = 0; - list_for_each_entry(next, &vwin->windows_mru, windows_mru) { - /* searching for the next mapped window in this context, using vwin->windows as the head */ - if (&next->windows_mru == &vwm->windows_mru) - continue; /* XXX: skip the containerless head, we're leveraging the circular list implementation */ - - if ((vwin->shelved && next->shelved) || - ((!vwin->shelved && !next->shelved && next->desktop == vwin->desktop) && - (fence == VWM_FENCE_IGNORE || - ((fence == VWM_FENCE_RESPECT || fence == VWM_FENCE_TRY_RESPECT) && vwm_screen_find(vwm, VWM_SCREEN_REL_XWIN, next->xwindow) == scr) || - (fence == VWM_FENCE_VIOLATE && vwm_screen_find(vwm, VWM_SCREEN_REL_XWIN, next->xwindow) != scr) || - (fence == VWM_FENCE_MASKED_VIOLATE && (next_scr = vwm_screen_find(vwm, VWM_SCREEN_REL_XWIN, next->xwindow)) != scr && - !((1UL << next_scr->screen_number) & vwm->fence_mask)) - ))) - break; - if (fence == VWM_FENCE_MASKED_VIOLATE && next_scr && next_scr != scr) - visited_mask |= (1UL << next_scr->screen_number); + switch (direction) { + case VWM_DIRECTION_FORWARD: + list_for_each_entry(next, &vwin->windows_mru, windows_mru) { + /* searching for the next mapped window in this context, using vwin->windows as the head */ + if (&next->windows_mru == &vwm->windows_mru) + continue; /* XXX: skip the containerless head, we're leveraging the circular list implementation */ + + if ( ((next->desktop == vwin->desktop) && + (fence == VWM_FENCE_IGNORE || + ((fence == VWM_FENCE_RESPECT || fence == VWM_FENCE_TRY_RESPECT) && vwm_screen_find(vwm, VWM_SCREEN_REL_XWIN, next->xwindow) == scr) || + (fence == VWM_FENCE_VIOLATE && vwm_screen_find(vwm, VWM_SCREEN_REL_XWIN, next->xwindow) != scr) || + (fence == VWM_FENCE_MASKED_VIOLATE && (next_scr = vwm_screen_find(vwm, VWM_SCREEN_REL_XWIN, next->xwindow)) != scr && + !((1UL << next_scr->screen_number) & vwm->fence_mask)) + ))) + break; + + if (fence == VWM_FENCE_MASKED_VIOLATE && next_scr && next_scr != scr) + visited_mask |= (1UL << next_scr->screen_number); + } + break; + + case VWM_DIRECTION_REVERSE: + list_for_each_entry_prev(next, &vwin->windows_mru, windows_mru) { + /* searching for the next mapped window in this context, using vwin->windows as the head */ + if (&next->windows_mru == &vwm->windows_mru) + continue; /* XXX: skip the containerless head, we're leveraging the circular list implementation */ + + /* TODO: move most of this into a function shared by both direction cases */ + if ( ((next->desktop == vwin->desktop) && + (fence == VWM_FENCE_IGNORE || + ((fence == VWM_FENCE_RESPECT || fence == VWM_FENCE_TRY_RESPECT) && vwm_screen_find(vwm, VWM_SCREEN_REL_XWIN, next->xwindow) == scr) || + (fence == VWM_FENCE_VIOLATE && vwm_screen_find(vwm, VWM_SCREEN_REL_XWIN, next->xwindow) != scr) || + (fence == VWM_FENCE_MASKED_VIOLATE && (next_scr = vwm_screen_find(vwm, VWM_SCREEN_REL_XWIN, next->xwindow)) != scr && + !((1UL << next_scr->screen_number) & vwm->fence_mask)) + ))) + break; + + if (fence == VWM_FENCE_MASKED_VIOLATE && next_scr && next_scr != scr) + visited_mask |= (1UL << next_scr->screen_number); + } + break; + + default: + assert(0); } if (fence == VWM_FENCE_TRY_RESPECT && next == vwin) { @@ -331,7 +359,7 @@ void vwm_win_shelve(vwm_t *vwm, vwm_window_t *vwin) /* shelving focused window, focus the next window */ if (vwin == vwin->desktop->focused_window) - vwm_win_mru(vwm, vwm_win_focus_next(vwm, vwin, VWM_FENCE_RESPECT)); + vwm_win_mru(vwm, vwm_win_focus_next(vwm, vwin, VWM_DIRECTION_FORWARD, VWM_FENCE_RESPECT)); if (vwin == vwin->desktop->focused_window) /* TODO: we can probably put this into vwm_win_focus_next() and have it always handled there... */ @@ -354,7 +382,7 @@ void vwm_win_unfocus(vwm_t *vwm, vwm_window_t *vwin) /* TODO: there's probably some icky behaviors for focused windows unmapping/destroying in unfocused contexts, we probably jump contexts suddenly. */ if (vwin == vwm->focused_shelf) { VWM_TRACE("unfocusing focused shelf"); - vwm_win_focus_next(vwm, vwin, VWM_FENCE_IGNORE); + vwm_win_focus_next(vwm, vwin, VWM_DIRECTION_FORWARD, VWM_FENCE_IGNORE); if (vwin == vwm->focused_shelf) { VWM_TRACE("shelf empty, leaving"); @@ -367,7 +395,7 @@ void vwm_win_unfocus(vwm_t *vwm, vwm_window_t *vwin) /* if we're the focused window cycle the focus to the next window on the desktop if possible */ if (vwin->desktop->focused_window == vwin) { VWM_TRACE("unfocusing focused window"); - vwm_win_focus_next(vwm, vwin, VWM_FENCE_TRY_RESPECT); + vwm_win_focus_next(vwm, vwin, VWM_DIRECTION_FORWARD, VWM_FENCE_TRY_RESPECT); } if (vwin->desktop->focused_window == vwin) { |