summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/desktop.c60
-rw-r--r--src/desktop.h6
-rw-r--r--src/key.c29
-rw-r--r--src/window.c68
-rw-r--r--src/window.h3
5 files changed, 114 insertions, 52 deletions
diff --git a/src/desktop.c b/src/desktop.c
index 1fcce8c..e6130e0 100644
--- a/src/desktop.c
+++ b/src/desktop.c
@@ -17,6 +17,7 @@
*/
/* virtual desktops */
+#include <assert.h>
#include <X11/Xlib.h>
#include <stdlib.h>
#include <string.h>
@@ -80,39 +81,58 @@ int vwm_desktop_focus(vwm_t *vwm, vwm_desktop_t *desktop)
return 1;
}
-/* return next MRU desktop relative to the supplied desktop */
-vwm_desktop_t * vwm_desktop_next_mru(vwm_t *vwm, vwm_desktop_t *desktop)
+
+/* return next MRU desktop relative to the supplied desktop, wraps-around */
+vwm_desktop_t * vwm_desktop_next_mru(vwm_t *vwm, vwm_desktop_t *desktop, vwm_direction_t direction)
{
- list_head_t *next;
+ vwm_desktop_t *next = desktop;
/* this dance is necessary because the list head @ vwm->desktops_mru has no vwm_desktop_t container,
* and we're exploiting the circular nature of the doubly linked lists, so we need to take care to skip
* past the container-less head.
*/
- if (desktop->desktops_mru.next == &vwm->desktops_mru) {
- next = desktop->desktops_mru.next->next;
- } else {
- next = desktop->desktops_mru.next;
- }
+ switch (direction) {
+ case VWM_DIRECTION_FORWARD:
+ if (next->desktops_mru.next == &vwm->desktops_mru) {
+ next = list_entry(next->desktops_mru.next->next, vwm_desktop_t, desktops_mru);
+ } else {
+ next = list_entry(next->desktops_mru.next, vwm_desktop_t, desktops_mru);
+ }
+ break;
- return list_entry(next, vwm_desktop_t, desktops_mru);
-}
+ case VWM_DIRECTION_REVERSE:
+ if (next->desktops_mru.prev == &vwm->desktops_mru) {
+ next = list_entry(next->desktops_mru.prev->prev, vwm_desktop_t, desktops_mru);
+ } else {
+ next = list_entry(next->desktops_mru.prev, vwm_desktop_t, desktops_mru);
+ }
+ break;
-/* return next desktop spatially relative to the supplied desktop, no wrap-around */
-vwm_desktop_t * vwm_desktop_next(vwm_t *vwm, vwm_desktop_t *desktop)
-{
- if (desktop->desktops.next != &vwm->desktops)
- desktop = list_entry(desktop->desktops.next, vwm_desktop_t, desktops);
+ default:
+ assert(0);
+ }
- return desktop;
+ return next;
}
-/* return previous desktop spatially relative to the supplied desktop, no wrap-around */
-vwm_desktop_t * vwm_desktop_prev(vwm_t *vwm, vwm_desktop_t *desktop)
+/* return next desktop spatially relative to the supplied desktop, no wrap-around */
+vwm_desktop_t * vwm_desktop_next(vwm_t *vwm, vwm_desktop_t *desktop, vwm_direction_t direction)
{
- if (desktop->desktops.prev != &vwm->desktops)
- desktop = list_entry(desktop->desktops.prev, vwm_desktop_t, desktops);
+ switch (direction) {
+ case VWM_DIRECTION_FORWARD:
+ if (desktop->desktops.next != &vwm->desktops)
+ return list_entry(desktop->desktops.next, vwm_desktop_t, desktops);
+ break;
+
+ case VWM_DIRECTION_REVERSE:
+ if (desktop->desktops.prev != &vwm->desktops)
+ return list_entry(desktop->desktops.prev, vwm_desktop_t, desktops);
+ break;
+
+ default:
+ assert(0);
+ }
return desktop;
}
diff --git a/src/desktop.h b/src/desktop.h
index cc6df38..c231ca5 100644
--- a/src/desktop.h
+++ b/src/desktop.h
@@ -1,6 +1,7 @@
#ifndef _DESKTOP_H
#define _DESKTOP_H
+#include "direction.h"
#include "list.h"
#include "window.h"
@@ -18,8 +19,7 @@ void vwm_desktop_mru(vwm_t *vwm, vwm_desktop_t *desktop);
int vwm_desktop_focus(vwm_t *vwm, vwm_desktop_t *desktop);
vwm_desktop_t * vwm_desktop_create(vwm_t *vwm, char *name);
void vwm_desktop_destroy(vwm_t *vwm, vwm_desktop_t *desktop);
-vwm_desktop_t * vwm_desktop_next_mru(vwm_t *vwm, vwm_desktop_t *desktop);
-vwm_desktop_t * vwm_desktop_next(vwm_t *vwm, vwm_desktop_t *desktop);
-vwm_desktop_t * vwm_desktop_prev(vwm_t *vwm, vwm_desktop_t *desktop);
+vwm_desktop_t * vwm_desktop_next_mru(vwm_t *vwm, vwm_desktop_t *desktop, vwm_direction_t direction);
+vwm_desktop_t * vwm_desktop_next(vwm_t *vwm, vwm_desktop_t *desktop, vwm_direction_t direction);
#endif
diff --git a/src/key.c b/src/key.c
index dcd8a16..6456695 100644
--- a/src/key.c
+++ b/src/key.c
@@ -29,7 +29,8 @@
#include "window.h"
#include "xwindow.h"
-static int key_is_grabbed; /* flag for tracking keyboard grab state */
+static int key_is_grabbed; /* flag for tracking keyboard grab state */
+static vwm_direction_t direction = VWM_DIRECTION_FORWARD; /* flag for reversing directional actions */
/* Poll the keyboard state to see if _any_ keys are pressed */
static int keys_pressed(vwm_t *vwm)
@@ -79,6 +80,11 @@ void vwm_key_released(vwm_t *vwm, Window win, XKeyReleasedEvent *keyrelease)
break;
+ case XK_r:
+ VWM_TRACE("XK_r released with direction=%i", direction);
+ direction = VWM_DIRECTION_FORWARD;
+ break;
+
default:
VWM_TRACE("Unhandled keycode: %x", (unsigned int)sym);
break;
@@ -133,6 +139,11 @@ void vwm_key_pressed(vwm_t *vwm, Window win, XKeyPressedEvent *keypress)
VWM_TRACE("aborting with origin %p", vwm->focused_origin);
break;
+ case XK_r: /* reverse directional actions */
+ VWM_TRACE("XK_r pressed with direction=%i", direction);
+ direction = VWM_DIRECTION_REVERSE;
+ break;
+
case XK_grave: /* toggle shelf visibility */
vwm_context_focus(vwm, VWM_CONTEXT_OTHER);
break;
@@ -143,15 +154,17 @@ void vwm_key_pressed(vwm_t *vwm, Window win, XKeyPressedEvent *keypress)
/* focus the next window, note this doesn't affect MRU yet, that happens on Mod1 release */
if (vwin) {
if (keypress->state & ShiftMask) {
- vwm_win_focus_next(vwm, vwin, VWM_FENCE_MASKED_VIOLATE);
+ vwm_win_focus_next(vwm, vwin, direction, VWM_FENCE_MASKED_VIOLATE);
} else {
- vwm_win_focus_next(vwm, vwin, VWM_FENCE_RESPECT);
+ vwm_win_focus_next(vwm, vwin, direction, VWM_FENCE_RESPECT);
}
}
break;
case XK_space: { /* cycle focused desktop utilizing MRU */
- vwm_desktop_t *next_desktop = vwm_desktop_next_mru(vwm, vwm->focused_desktop);
+ vwm_desktop_t *next_desktop;
+
+ next_desktop = vwm_desktop_next_mru(vwm, vwm->focused_desktop, direction);
do_grab = 1; /* update MRU desktop on commit (Mod1 release) */
@@ -205,7 +218,7 @@ void vwm_key_pressed(vwm_t *vwm, Window win, XKeyPressedEvent *keypress)
if (keypress->state & ShiftMask) {
if (vwin) {
/* migrate the focused window with the desktop focus to the previous desktop */
- vwm_win_migrate(vwm, vwin, vwm_desktop_prev(vwm, vwin->desktop));
+ vwm_win_migrate(vwm, vwin, vwm_desktop_next(vwm, vwin->desktop, VWM_DIRECTION_REVERSE));
}
} else {
if (vwm->focused_context == VWM_CONTEXT_SHELF) {
@@ -213,7 +226,7 @@ void vwm_key_pressed(vwm_t *vwm, Window win, XKeyPressedEvent *keypress)
vwm_context_focus(vwm, VWM_CONTEXT_DESKTOP);
} else {
/* focus the previous desktop */
- vwm_desktop_focus(vwm, vwm_desktop_prev(vwm, vwm->focused_desktop));
+ vwm_desktop_focus(vwm, vwm_desktop_next(vwm, vwm->focused_desktop, VWM_DIRECTION_REVERSE));
}
}
break;
@@ -224,7 +237,7 @@ void vwm_key_pressed(vwm_t *vwm, Window win, XKeyPressedEvent *keypress)
if (keypress->state & ShiftMask) {
if (vwin) {
/* migrate the focused window with the desktop focus to the next desktop */
- vwm_win_migrate(vwm, vwin, vwm_desktop_next(vwm, vwin->desktop));
+ vwm_win_migrate(vwm, vwin, vwm_desktop_next(vwm, vwin->desktop, VWM_DIRECTION_FORWARD));
}
} else {
if (vwm->focused_context == VWM_CONTEXT_SHELF) {
@@ -232,7 +245,7 @@ void vwm_key_pressed(vwm_t *vwm, Window win, XKeyPressedEvent *keypress)
vwm_context_focus(vwm, VWM_CONTEXT_DESKTOP);
} else {
/* focus the next desktop */
- vwm_desktop_focus(vwm, vwm_desktop_next(vwm, vwm->focused_desktop));
+ vwm_desktop_focus(vwm, vwm_desktop_next(vwm, vwm->focused_desktop, VWM_DIRECTION_FORWARD));
}
}
break;
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) {
diff --git a/src/window.h b/src/window.h
index c142d89..00ebc72 100644
--- a/src/window.h
+++ b/src/window.h
@@ -4,6 +4,7 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
+#include "direction.h"
#include "list.h"
#include "screen.h"
@@ -71,7 +72,7 @@ typedef enum _vwm_fence_t {
VWM_FENCE_MASKED_VIOLATE /* leave the screen for any other not masked */
} vwm_fence_t;
-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);
void vwm_win_shelve(vwm_t *vwm, vwm_window_t *vwin);
void vwm_win_unfocus(vwm_t *vwm, vwm_window_t *vwin);
vwm_xwindow_t * vwm_win_unmanage(vwm_t *vwm, vwm_window_t *vwin);
© All Rights Reserved