diff options
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) { |