summaryrefslogtreecommitdiff
path: root/src/window.c
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2020-12-23 01:12:51 -0800
committerVito Caputo <vcaputo@pengaru.com>2020-12-23 16:58:42 -0800
commit3161db573424a554b536aaa492397341b84683ce (patch)
tree1f72d7aa908dbb484bb8907b17bf493f551e2b85 /src/window.c
parenta6998186a3546f9f871e2cab3e994c782bd98a98 (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.c68
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) {
© All Rights Reserved