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 along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <X11/Xutil.h>
27 #include <X11/keysym.h>
29 #include "WindowMaker.h"
39 #include "switchpanel.h"
42 static void raiseWindow(WSwitchPanel
* swpanel
, WWindow
* wwin
)
44 Window swwin
= wSwitchPanelGetWindow(swpanel
);
46 if (wwin
->flags
.mapped
|| wwin
->flags
.shaded
) {
51 win
[1] = wwin
->frame
->core
->window
;
53 XRestackWindows(dpy
, win
, 2);
55 XRaiseWindow(dpy
, wwin
->frame
->core
->window
);
59 static WWindow
*change_focus_and_raise(WWindow
*newFocused
, WWindow
*oldFocused
,
60 WSwitchPanel
*swpanel
, WScreen
*scr
, Bool esc_cancel
)
65 /* allow the focused window to float on top of a fullscreen window */
66 if (oldFocused
->flags
.fullscreen
)
67 ChangeStackingLevel(oldFocused
->frame
->core
, WMNormalLevel
);
69 wWindowFocus(newFocused
, oldFocused
);
70 oldFocused
= newFocused
;
72 if (wPreferences
.circ_raise
) {
76 raiseWindow(swpanel
, newFocused
);
82 void StartWindozeCycle(WWindow
*wwin
, XEvent
*event
, Bool next
, Bool class_only
)
86 WSwitchPanel
*swpanel
= NULL
;
87 WScreen
*scr
= wScreenForRootWindow(event
->xkey
.root
);
88 KeyCode leftKey
= XKeysymToKeycode(dpy
, XK_Left
);
89 KeyCode rightKey
= XKeysymToKeycode(dpy
, XK_Right
);
90 KeyCode homeKey
= XKeysymToKeycode(dpy
, XK_Home
);
91 KeyCode endKey
= XKeysymToKeycode(dpy
, XK_End
);
92 KeyCode shiftLKey
= XKeysymToKeycode(dpy
, XK_Shift_L
);
93 KeyCode shiftRKey
= XKeysymToKeycode(dpy
, XK_Shift_R
);
94 KeyCode escapeKey
= XKeysymToKeycode(dpy
, XK_Escape
);
95 KeyCode returnKey
= XKeysymToKeycode(dpy
, XK_Return
);
96 Bool esc_cancel
= False
;
97 Bool somethingElse
= False
;
111 binding
= wKeyBindings
[WKBD_GROUPNEXT
];
113 binding
= wKeyBindings
[WKBD_FOCUSNEXT
];
116 binding
= wKeyBindings
[WKBD_GROUPPREV
];
118 binding
= wKeyBindings
[WKBD_FOCUSPREV
];
121 hasModifier
= (binding
.modifier
!= 0);
123 XGrabKeyboard(dpy
, scr
->root_win
, False
, GrabModeAsync
, GrabModeAsync
, CurrentTime
);
125 scr
->flags
.doing_alt_tab
= 1;
127 swpanel
= wInitSwitchPanel(scr
, wwin
, class_only
);
131 if (wwin
->flags
.mapped
&& !wPreferences
.panel_only_open
)
132 newFocused
= wSwitchPanelSelectNext(swpanel
, !next
, True
, False
);
134 newFocused
= wSwitchPanelSelectFirst(swpanel
, False
);
136 oldFocused
= change_focus_and_raise(newFocused
, oldFocused
, swpanel
, scr
, False
);
138 if (wwin
->frame
->workspace
== scr
->current_workspace
)
144 while (hasModifier
&& !done
) {
145 WMMaskEvent(dpy
, KeyPressMask
| KeyReleaseMask
| ExposureMask
146 | PointerMotionMask
| ButtonReleaseMask
| EnterWindowMask
, &ev
);
148 /* ignore CapsLock */
149 modifiers
= ev
.xkey
.state
& w_global
.shortcut
.modifiers_mask
;
156 if ((wKeyBindings
[WKBD_FOCUSNEXT
].keycode
== ev
.xkey
.keycode
157 && wKeyBindings
[WKBD_FOCUSNEXT
].modifier
== modifiers
)
158 || (wKeyBindings
[WKBD_GROUPNEXT
].keycode
== ev
.xkey
.keycode
159 && wKeyBindings
[WKBD_GROUPNEXT
].modifier
== modifiers
)
160 || ev
.xkey
.keycode
== rightKey
) {
162 newFocused
= wSwitchPanelSelectNext(swpanel
, False
, ev
.xkey
.keycode
!= rightKey
, (!class_only
&& wKeyBindings
[WKBD_GROUPNEXT
].keycode
== ev
.xkey
.keycode
&& wKeyBindings
[WKBD_GROUPNEXT
].modifier
== modifiers
));
163 oldFocused
= change_focus_and_raise(newFocused
, oldFocused
, swpanel
, scr
, False
);
165 } else if ((wKeyBindings
[WKBD_FOCUSPREV
].keycode
== ev
.xkey
.keycode
166 && wKeyBindings
[WKBD_FOCUSPREV
].modifier
== modifiers
)
167 || (wKeyBindings
[WKBD_GROUPPREV
].keycode
== ev
.xkey
.keycode
168 && wKeyBindings
[WKBD_GROUPPREV
].modifier
== modifiers
)
169 || ev
.xkey
.keycode
== leftKey
) {
171 newFocused
= wSwitchPanelSelectNext(swpanel
, True
, ev
.xkey
.keycode
!= leftKey
, (!class_only
&& wKeyBindings
[WKBD_GROUPPREV
].keycode
== ev
.xkey
.keycode
&& wKeyBindings
[WKBD_GROUPPREV
].modifier
== modifiers
));
172 oldFocused
= change_focus_and_raise(newFocused
, oldFocused
, swpanel
, scr
, False
);
174 } else if (ev
.xkey
.keycode
== homeKey
|| ev
.xkey
.keycode
== endKey
) {
176 newFocused
= wSwitchPanelSelectFirst(swpanel
, ev
.xkey
.keycode
!= homeKey
);
177 oldFocused
= change_focus_and_raise(newFocused
, oldFocused
, swpanel
, scr
, False
);
179 } else if (ev
.xkey
.keycode
== escapeKey
) {
181 /* Focus the first window of the swpanel, despite the 'False' */
182 newFocused
= wSwitchPanelSelectFirst(swpanel
, False
);
183 oldFocused
= change_focus_and_raise(newFocused
, oldFocused
, swpanel
, scr
, True
);
187 } else if (ev
.xkey
.keycode
== returnKey
) {
189 /* Close the switch panel without eating the keypress */
192 } else if (ev
.xkey
.keycode
!= shiftLKey
&& ev
.xkey
.keycode
!= shiftRKey
) {
194 somethingElse
= True
;
200 if (ev
.xkey
.keycode
== shiftLKey
|| ev
.xkey
.keycode
== shiftRKey
)
201 if (wPreferences
.strict_windoze_cycle
)
204 if (ev
.xkey
.keycode
== leftKey
|| ev
.xkey
.keycode
== rightKey
)
207 if (ev
.xkey
.keycode
== XK_Return
)
210 if (ev
.xkey
.keycode
!= binding
.keycode
)
217 /* ignore unwanted EnterNotify's */
226 tmp
= wSwitchPanelHandleEvent(swpanel
, &ev
);
229 oldFocused
= change_focus_and_raise(newFocused
, oldFocused
, swpanel
, scr
, False
);
231 if (ev
.type
== ButtonRelease
)
244 XUngrabKeyboard(dpy
, CurrentTime
);
247 wSwitchPanelDestroy(swpanel
);
249 if (newFocused
&& !esc_cancel
) {
250 wRaiseFrame(newFocused
->frame
->core
);
252 if (!newFocused
->flags
.mapped
)
253 wMakeWindowVisible(newFocused
);
254 wSetFocusTo(scr
, newFocused
);
257 scr
->flags
.doing_alt_tab
= 0;