Allow focus changing via window cycling without necessarily raising the selected window. Method 1: press either Ctrl while holding down (typically) Alt to activate this feature and exit window cycling. Method 2: use the new "cycle windows (no raise)" shortcut, which defaults to Ctrl-Alt-Tab. Signed-off-by: Darren Salt Index: themes/default.keys/keythemerc =================================================================== --- themes/default.keys/keythemerc (revision 22214) +++ themes/default.keys/keythemerc (working copy) @@ -1,6 +1,7 @@ add_workspace_key=Alt+Insert close_window_key=Alt+F4 cycle_windows_key=Alt+Tab +cycle_windows_no_raise_key=Control+Alt+Tab del_workspace_key=Alt+Delete down_workspace_key=Control+Alt+Down fullscreen_key=Alt+F11 Index: src/settings.c =================================================================== --- src/settings.c (revision 22214) +++ src/settings.c (working copy) @@ -1138,6 +1138,7 @@ parseKeyString (dpy, &screen_info->params->keys[KEY_ADD_WORKSPACE], getValue ("add_workspace_key", rc)); parseKeyString (dpy, &screen_info->params->keys[KEY_CLOSE_WINDOW], getValue ("close_window_key", rc)); parseKeyString (dpy, &screen_info->params->keys[KEY_CYCLE_WINDOWS], getValue ("cycle_windows_key", rc)); + parseKeyString (dpy, &screen_info->params->keys[KEY_CYCLE_WINDOWS_NO_RAISE], getValue ("cycle_windows_no_raise_key", rc)); parseKeyString (dpy, &screen_info->params->keys[KEY_DEL_WORKSPACE], getValue ("del_workspace_key", rc)); parseKeyString (dpy, &screen_info->params->keys[KEY_DOWN_WORKSPACE], getValue ("down_workspace_key", rc)); parseKeyString (dpy, &screen_info->params->keys[KEY_HIDE_WINDOW], getValue ("hide_window_key", rc)); @@ -1290,6 +1291,7 @@ {"add_workspace_key", NULL, TRUE}, {"close_window_key", NULL, TRUE}, {"cycle_windows_key", NULL, TRUE}, + {"cycle_windows_no_raise_key", NULL, TRUE}, {"del_workspace_key", NULL, TRUE}, {"down_workspace_key", NULL, TRUE}, {"fullscreen_key", NULL, TRUE}, Index: src/events.c =================================================================== --- src/events.c (revision 22214) +++ src/events.c (working copy) @@ -386,8 +386,11 @@ } break; case KEY_CYCLE_WINDOWS: - clientCycle (c, (XEvent *) ev); + clientCycle (c, (XEvent *) ev, TRUE); break; + case KEY_CYCLE_WINDOWS_NO_RAISE: + clientCycle (c, (XEvent *) ev, FALSE); + break; case KEY_CLOSE_WINDOW: clientClose (c); break; @@ -479,9 +482,15 @@ case KEY_CYCLE_WINDOWS: if (screen_info->clients) { - clientCycle (screen_info->clients->prev, (XEvent *) ev); + clientCycle (screen_info->clients->prev, (XEvent *) ev, TRUE); } break; + case KEY_CYCLE_WINDOWS_NO_RAISE: + if (screen_info->clients) + { + clientCycle (screen_info->clients->prev, (XEvent *) ev, FALSE); + } + break; case KEY_CLOSE_WINDOW: if (display_info->session) { Index: src/settings.h =================================================================== --- src/settings.h (revision 22214) +++ src/settings.h (working copy) @@ -114,7 +114,8 @@ #define KEY_MOVE_LEFT_WORKSPACE 68 #define KEY_MOVE_RIGHT_WORKSPACE 69 #define KEY_MOVE_CANCEL 70 -#define KEY_COUNT 71 +#define KEY_CYCLE_WINDOWS_NO_RAISE 71 +#define KEY_COUNT 72 #define ALIGN_LEFT 0 #define ALIGN_RIGHT 1 Index: src/client.c =================================================================== --- src/client.c (revision 22214) +++ src/client.c (working copy) @@ -113,6 +113,9 @@ Tabwin *tabwin; Window wireframe; int cycle_range; + gboolean raise; + KeyCode keycode; + int modifier; }; typedef struct _ButtonPressData ButtonPressData; @@ -285,6 +288,7 @@ grabKey (clientGetXDisplay (c), &screen_info->params->keys[KEY_ADD_WORKSPACE], c->window); grabKey (clientGetXDisplay (c), &screen_info->params->keys[KEY_CLOSE_WINDOW], c->window); grabKey (clientGetXDisplay (c), &screen_info->params->keys[KEY_CYCLE_WINDOWS], c->window); + grabKey (clientGetXDisplay (c), &screen_info->params->keys[KEY_CYCLE_WINDOWS_NO_RAISE], c->window); grabKey (clientGetXDisplay (c), &screen_info->params->keys[KEY_DEL_WORKSPACE], c->window); grabKey (clientGetXDisplay (c), &screen_info->params->keys[KEY_HIDE_WINDOW], c->window); grabKey (clientGetXDisplay (c), &screen_info->params->keys[KEY_LOWER_WINDOW], c->window); @@ -4135,8 +4139,6 @@ ClientCycleData *passdata; Client *c, *removed; eventFilterStatus status; - KeyCode keycode; - int modifier; gboolean key_pressed, cycling, gone; TRACE ("entering clientCycle_event_filter"); @@ -4151,9 +4153,7 @@ c = passdata->c; screen_info = c->screen_info; display_info = screen_info->display_info; - keycode = screen_info->params->keys[KEY_CYCLE_WINDOWS].keycode; - modifier = screen_info->params->keys[KEY_CYCLE_WINDOWS].modifier; - key_pressed = ((xevent->type == KeyPress) && (xevent->xkey.keycode == keycode)); + key_pressed = ((xevent->type == KeyPress) && (xevent->xkey.keycode == passdata->keycode)); status = EVENT_FILTER_STOP; cycling = TRUE; gone = FALSE; @@ -4183,8 +4183,8 @@ if (key_pressed) { Client *c2 = NULL; - /* If KEY_CYCLE_WINDOWS has Shift, then do not reverse */ - if (!(modifier & ShiftMask) && (xevent->xkey.state & ShiftMask)) + /* If KEY_CYCLE_WINDOWS* has Shift, then do not reverse */ + if (!(passdata->modifier & ShiftMask) && (xevent->xkey.state & ShiftMask)) { TRACE ("Cycle: previous"); c2 = tabwinSelectPrev(passdata->tabwin); @@ -4218,6 +4218,9 @@ if (IsModifierKey(keysym) && (keysym != XK_Shift_L) && (keysym != XK_Shift_R)) { cycling = FALSE; + /* If KEY_CYCLE_WINDOWS* has Control, deny raise flag negation */ + if (!(passdata->modifier & ControlMask) && ((keysym == XK_Control_L) || (keysym == XK_Control_R))) + passdata->raise = !passdata->raise; } } break; @@ -4242,7 +4245,7 @@ } void -clientCycle (Client * c, XEvent * ev) +clientCycle (Client * c, XEvent * ev, gboolean raise) { ScreenInfo *screen_info; DisplayInfo *display_info; @@ -4295,6 +4298,10 @@ passdata.c = c; } + passdata.raise = raise; + passdata.keycode = ev->xkey.keycode; + passdata.modifier = ev->xkey.state; + if (passdata.c) { GdkPixbuf *icon; @@ -4338,7 +4345,8 @@ clientShow (c, TRUE); clientSetFocus (screen_info, c, myDisplayGetCurrentTime (display_info), NO_FOCUS_FLAG); - clientRaise (c, None); + if (passdata.raise) + clientRaise (c, None); } } Index: src/screen.c =================================================================== --- src/screen.c (revision 22214) +++ src/screen.c (working copy) @@ -394,6 +394,7 @@ ungrabKeys (dpy, screen_info->xroot); grabKey (dpy, &screen_info->params->keys[KEY_CYCLE_WINDOWS], screen_info->xroot); + grabKey (dpy, &screen_info->params->keys[KEY_CYCLE_WINDOWS_NO_RAISE], screen_info->xroot); grabKey (dpy, &screen_info->params->keys[KEY_NEXT_WORKSPACE], screen_info->xroot); grabKey (dpy, &screen_info->params->keys[KEY_PREV_WORKSPACE], screen_info->xroot); grabKey (dpy, &screen_info->params->keys[KEY_ADD_WORKSPACE], screen_info->xroot); Index: src/client.h =================================================================== --- src/client.h (revision 22214) +++ src/client.h (working copy) @@ -330,7 +330,7 @@ void clientScreenResize(ScreenInfo *); void clientMove (Client *, XEvent *); void clientResize (Client *, int, XEvent *); -void clientCycle (Client *, XEvent *); +void clientCycle (Client *, XEvent *, gboolean); void clientButtonPress (Client *, Window, XButtonEvent *); Client *clientGetLeader (Client *); #ifdef HAVE_LIBSTARTUP_NOTIFICATION Index: mcs-plugin/xfwm4_shortcuteditor.c =================================================================== --- mcs-plugin/xfwm4_shortcuteditor.c (revision 22214) +++ mcs-plugin/xfwm4_shortcuteditor.c (working copy) @@ -320,6 +320,7 @@ "shade_window_key", "stick_window_key", "cycle_windows_key", + "cycle_windows_no_raise_key", "move_window_up_key", "move_window_down_key", "move_window_left_key", @@ -358,6 +359,7 @@ N_("Shade window"), N_("Stick window"), N_("Cycle windows"), + N_("Cycle windows (no raising)"), N_("Move window up"), N_("Move window down"), N_("Move window left"),