1 /* cycling.c- window cycling
3 * Window Maker window manager
5 * Copyright (c) 2000-2003 Alfredo K. Kojima
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
27 #include <X11/Xutil.h>
28 #include <X11/keysym.h>
30 #include "WindowMaker.h"
40 #include "switchpanel.h"
43 extern WPreferences wPreferences
;
45 extern WShortKey wKeyBindings
[WKBD_LAST
];
47 static void raiseWindow(WSwitchPanel
* swpanel
, WWindow
* wwin
)
49 Window swwin
= wSwitchPanelGetWindow(swpanel
);
51 if (wwin
->flags
.mapped
) {
56 win
[1] = wwin
->frame
->core
->window
;
58 XRestackWindows(dpy
, win
, 2);
60 XRaiseWindow(dpy
, wwin
->frame
->core
->window
);
64 static WWindow
*change_focus_and_raise(WWindow
*newFocused
, WWindow
*oldFocused
,
65 WSwitchPanel
*swpanel
, WScreen
*scr
, Bool esc_cancel
)
70 wWindowFocus(newFocused
, oldFocused
);
71 oldFocused
= newFocused
;
73 if (wPreferences
.circ_raise
) {
77 raiseWindow(swpanel
, newFocused
);
83 void StartWindozeCycle(WWindow
* wwin
, XEvent
* event
, Bool next
, Bool class_only
)
86 XModifierKeymap
*keymap
= NULL
;
87 WSwitchPanel
*swpanel
= NULL
;
88 WScreen
*scr
= wScreenForRootWindow(event
->xkey
.root
);
89 KeyCode leftKey
= XKeysymToKeycode(dpy
, XK_Left
);
90 KeyCode rightKey
= XKeysymToKeycode(dpy
, XK_Right
);
91 KeyCode homeKey
= XKeysymToKeycode(dpy
, XK_Home
);
92 KeyCode endKey
= XKeysymToKeycode(dpy
, XK_End
);
93 KeyCode shiftLKey
= XKeysymToKeycode(dpy
, XK_Shift_L
);
94 KeyCode shiftRKey
= XKeysymToKeycode(dpy
, XK_Shift_R
);
95 KeyCode escapeKey
= XKeysymToKeycode(dpy
, XK_Escape
);
96 Bool esc_cancel
= False
;
97 Bool somethingElse
= False
;
110 hasModifier
= (wKeyBindings
[WKBD_FOCUSNEXT
].modifier
!= 0);
112 hasModifier
= (wKeyBindings
[WKBD_FOCUSPREV
].modifier
!= 0);
115 keymap
= XGetModifierMapping(dpy
);
118 printf("Grabbing keyboard\n");
120 XGrabKeyboard(dpy
, scr
->root_win
, False
, GrabModeAsync
, GrabModeAsync
, CurrentTime
);
123 scr
->flags
.doing_alt_tab
= 1;
125 swpanel
= wInitSwitchPanel(scr
, wwin
, class_only
);
130 if (wwin
->flags
.mapped
)
131 newFocused
= wSwitchPanelSelectNext(swpanel
, !next
);
133 newFocused
= wSwitchPanelSelectFirst(swpanel
, False
);
135 oldFocused
= change_focus_and_raise(newFocused
, oldFocused
, swpanel
, scr
, False
);
137 if (wwin
->frame
->workspace
== scr
->current_workspace
)
143 while (hasModifier
&& !done
) {
146 WMMaskEvent(dpy
, KeyPressMask
| KeyReleaseMask
| ExposureMask
147 | PointerMotionMask
| ButtonReleaseMask
| EnterWindowMask
, &ev
);
149 /* ignore CapsLock */
150 modifiers
= ev
.xkey
.state
& ValidModMask
;
159 if ((wKeyBindings
[WKBD_FOCUSNEXT
].keycode
== ev
.xkey
.keycode
160 && wKeyBindings
[WKBD_FOCUSNEXT
].modifier
== modifiers
)
161 || (wKeyBindings
[WKBD_GROUPNEXT
].keycode
== ev
.xkey
.keycode
162 && wKeyBindings
[WKBD_GROUPNEXT
].modifier
== modifiers
)
163 || ev
.xkey
.keycode
== rightKey
) {
165 newFocused
= wSwitchPanelSelectNext(swpanel
, False
);
166 oldFocused
= change_focus_and_raise(newFocused
, oldFocused
, swpanel
, scr
, False
);
168 } else if ((wKeyBindings
[WKBD_FOCUSPREV
].keycode
== ev
.xkey
.keycode
169 && wKeyBindings
[WKBD_FOCUSPREV
].modifier
== modifiers
)
170 || (wKeyBindings
[WKBD_GROUPPREV
].keycode
== ev
.xkey
.keycode
171 && wKeyBindings
[WKBD_GROUPPREV
].modifier
== modifiers
)
172 || ev
.xkey
.keycode
== leftKey
) {
174 newFocused
= wSwitchPanelSelectNext(swpanel
, True
);
175 oldFocused
= change_focus_and_raise(newFocused
, oldFocused
, swpanel
, scr
, False
);
177 } else if (ev
.xkey
.keycode
== homeKey
|| ev
.xkey
.keycode
== endKey
) {
179 newFocused
= wSwitchPanelSelectFirst(swpanel
, ev
.xkey
.keycode
!= homeKey
);
180 oldFocused
= change_focus_and_raise(newFocused
, oldFocused
, swpanel
, scr
, False
);
182 } else if (ev
.xkey
.keycode
== escapeKey
) {
184 /* Focus the first window of the swpanel, despite the 'False' */
185 newFocused
= wSwitchPanelSelectFirst(swpanel
, False
);
186 oldFocused
= change_focus_and_raise(newFocused
, oldFocused
, swpanel
, scr
, True
);
190 } else if (ev
.xkey
.keycode
!= shiftLKey
&& ev
.xkey
.keycode
!= shiftRKey
) {
192 somethingElse
= True
;
199 for (i
= 0; i
< 8 * keymap
->max_keypermod
; i
++) {
201 int mask
= 1 << (i
/ keymap
->max_keypermod
);
203 if (keymap
->modifiermap
[i
] == ev
.xkey
.keycode
&&
204 ((wKeyBindings
[WKBD_FOCUSNEXT
].modifier
& mask
)
205 || (wKeyBindings
[WKBD_FOCUSPREV
].modifier
& mask
)
206 || (wKeyBindings
[WKBD_GROUPNEXT
].modifier
& mask
)
207 || (wKeyBindings
[WKBD_GROUPPREV
].modifier
& mask
))) {
216 /* ignore unwanted EnterNotify's */
225 tmp
= wSwitchPanelHandleEvent(swpanel
, &ev
);
228 oldFocused
= change_focus_and_raise(newFocused
, oldFocused
, swpanel
, scr
, False
);
230 if (ev
.type
== ButtonRelease
)
242 XFreeModifiermap(keymap
);
246 XUngrabKeyboard(dpy
, CurrentTime
);
250 wSwitchPanelDestroy(swpanel
);
252 if (newFocused
&& !esc_cancel
) {
253 wRaiseFrame(newFocused
->frame
->core
);
255 if (!newFocused
->flags
.mapped
)
256 wMakeWindowVisible(newFocused
);
257 wSetFocusTo(scr
, newFocused
);
260 scr
->flags
.doing_alt_tab
= 0;