changed indentation to use spaces only
[wmaker-crm.git] / src / cycling.c
blob800f406809f44e2e4f7975e779739ca59ed2f88e
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,
20 * USA.
23 #include "wconfig.h"
25 #include <X11/Xlib.h>
26 #include <X11/Xutil.h>
29 #include "WindowMaker.h"
30 #include "GNUstep.h"
31 #include "screen.h"
32 #include "wcore.h"
33 #include "window.h"
34 #include "framewin.h"
35 #include "keybind.h"
36 #include "actions.h"
37 #include "stacking.h"
38 #include "funcs.h"
39 #include "xinerama.h"
41 /* Globals */
42 extern WPreferences wPreferences;
44 extern WShortKey wKeyBindings[WKBD_LAST];
51 static WWindow*
52 nextToFocusAfter(WWindow *wwin)
54 WWindow *tmp = wwin->prev;
56 while (tmp) {
57 if (wWindowCanReceiveFocus(tmp) && !WFLAGP(tmp, skip_window_list)) {
58 return tmp;
60 tmp = tmp->prev;
63 tmp = wwin;
64 /* start over from the beginning of the list */
65 while (tmp->next)
66 tmp = tmp->next;
68 while (tmp && tmp != wwin) {
69 if (wWindowCanReceiveFocus(tmp) && !WFLAGP(tmp, skip_window_list)) {
70 return tmp;
72 tmp = tmp->prev;
75 return wwin;
79 static WWindow*
80 nextToFocusBefore(WWindow *wwin)
82 WWindow *tmp = wwin->next;
84 while (tmp) {
85 if (wWindowCanReceiveFocus(tmp) && !WFLAGP(tmp, skip_window_list)) {
86 return tmp;
88 tmp = tmp->next;
91 /* start over from the beginning of the list */
92 tmp = wwin;
93 while (tmp->prev)
94 tmp = tmp->prev;
96 while (tmp && tmp != wwin) {
97 if (wWindowCanReceiveFocus(tmp) && !WFLAGP(tmp, skip_window_list)) {
99 return tmp;
101 tmp = tmp->next;
104 return wwin;
110 static WWindow*
111 nextFocusWindow(WWindow *wwin)
113 WWindow *tmp, *closest, *min;
114 Window d;
116 if (!wwin)
117 return NULL;
118 tmp = wwin->prev;
119 closest = NULL;
120 min = wwin;
121 d = 0xffffffff;
122 while (tmp) {
123 if (wWindowCanReceiveFocus(tmp)
124 && (!WFLAGP(tmp, skip_window_list)|| tmp->flags.internal_window)) {
125 if (min->client_win > tmp->client_win)
126 min = tmp;
127 if (tmp->client_win > wwin->client_win
128 && (!closest
129 || (tmp->client_win - wwin->client_win) < d)) {
130 closest = tmp;
131 d = tmp->client_win - wwin->client_win;
134 tmp = tmp->prev;
136 if (!closest||closest==wwin)
137 return min;
138 return closest;
142 static WWindow*
143 prevFocusWindow(WWindow *wwin)
145 WWindow *tmp, *closest, *max;
146 Window d;
148 if (!wwin)
149 return NULL;
150 tmp = wwin->prev;
151 closest = NULL;
152 max = wwin;
153 d = 0xffffffff;
154 while (tmp) {
155 if (wWindowCanReceiveFocus(tmp) &&
156 (!WFLAGP(tmp, skip_window_list) || tmp->flags.internal_window)) {
157 if (max->client_win < tmp->client_win)
158 max = tmp;
159 if (tmp->client_win < wwin->client_win
160 && (!closest
161 || (wwin->client_win - tmp->client_win) < d)) {
162 closest = tmp;
163 d = wwin->client_win - tmp->client_win;
166 tmp = tmp->prev;
168 if (!closest||closest==wwin)
169 return max;
170 return closest;
176 void
177 StartWindozeCycle(WWindow *wwin, XEvent *event, Bool next)
179 WScreen *scr = wScreenForRootWindow(event->xkey.root);
180 Bool done = False;
181 Bool openedSwitchMenu = False;
182 WWindow *newFocused;
183 WWindow *oldFocused;
184 int modifiers;
185 XModifierKeymap *keymap = NULL;
186 Bool hasModifier;
187 Bool somethingElse = False;
188 XEvent ev;
190 if (!wwin)
191 return;
193 if (next)
194 hasModifier = (wKeyBindings[WKBD_FOCUSNEXT].modifier != 0);
195 else
196 hasModifier = (wKeyBindings[WKBD_FOCUSPREV].modifier != 0);
198 if (hasModifier) {
199 keymap = XGetModifierMapping(dpy);
201 #ifdef DEBUG
202 printf("Grabbing keyboard\n");
203 #endif
204 XGrabKeyboard(dpy, scr->root_win, False, GrabModeAsync, GrabModeAsync,
205 CurrentTime);
208 if (next) {
209 if (wPreferences.windows_cycling)
210 newFocused = nextToFocusAfter(wwin);
211 else
212 newFocused = nextFocusWindow(wwin);
213 } else {
214 if (wPreferences.windows_cycling)
215 newFocused = nextToFocusBefore(wwin);
216 else
217 newFocused = prevFocusWindow(wwin);
220 scr->flags.doing_alt_tab = 1;
223 if (wPreferences.circ_raise)
224 XRaiseWindow(dpy, newFocused->frame->core->window);
225 wWindowFocus(newFocused, scr->focused_window);
226 oldFocused = newFocused;
228 #if 0
229 if (wPreferences.popup_switchmenu &&
230 (!scr->switch_menu || !scr->switch_menu->flags.mapped)) {
232 OpenSwitchMenu(scr, scr->scr_width/2, scr->scr_height/2, False);
233 openedSwitchMenu = True;
235 #endif
237 while (hasModifier && !done) {
238 WMMaskEvent(dpy, KeyPressMask|KeyReleaseMask|ExposureMask, &ev);
240 if (ev.type != KeyRelease && ev.type != KeyPress) {
241 WMHandleEvent(&ev);
242 continue;
244 /* ignore CapsLock */
245 modifiers = ev.xkey.state & ValidModMask;
247 if (ev.type == KeyPress) {
248 #ifdef DEBUG
249 printf("Got key press\n");
250 #endif
251 if (wKeyBindings[WKBD_FOCUSNEXT].keycode == ev.xkey.keycode
252 && wKeyBindings[WKBD_FOCUSNEXT].modifier == modifiers) {
254 newFocused = nextToFocusAfter(newFocused);
255 wWindowFocus(newFocused, oldFocused);
256 oldFocused = newFocused;
258 if (wPreferences.circ_raise) {
259 /* restore order */
260 CommitStacking(scr);
261 XRaiseWindow(dpy, newFocused->frame->core->window);
264 } else if (wKeyBindings[WKBD_FOCUSPREV].keycode == ev.xkey.keycode
265 && wKeyBindings[WKBD_FOCUSPREV].modifier == modifiers) {
267 newFocused = nextToFocusBefore(newFocused);
268 wWindowFocus(newFocused, oldFocused);
269 oldFocused = newFocused;
271 if (wPreferences.circ_raise) {
272 /* restore order */
273 CommitStacking(scr);
274 XRaiseWindow(dpy, newFocused->frame->core->window);
277 } else {
278 #ifdef DEBUG
279 printf("Got something else\n");
280 #endif
281 somethingElse = True;
282 done = True;
284 } else if (ev.type == KeyRelease) {
285 int i;
287 #ifdef DEBUG
288 printf("Got key release\n");
289 #endif
290 for (i = 0; i < 8 * keymap->max_keypermod; i++) {
291 if (keymap->modifiermap[i] == ev.xkey.keycode &&
292 wKeyBindings[WKBD_FOCUSNEXT].modifier
293 & 1<<(i/keymap->max_keypermod)) {
294 done = True;
295 break;
300 if (keymap)
301 XFreeModifiermap(keymap);
303 if (hasModifier) {
304 #ifdef DEBUG
305 printf("Ungrabbing keyboard\n");
306 #endif
307 XUngrabKeyboard(dpy, CurrentTime);
309 wSetFocusTo(scr, newFocused);
311 if (wPreferences.circ_raise) {
312 wRaiseFrame(newFocused->frame->core);
313 CommitStacking(scr);
316 scr->flags.doing_alt_tab = 0;
317 if (openedSwitchMenu) {
319 * place window in center of current head
321 WMPoint center =
322 wGetPointToCenterRectInHead(scr, wGetHeadForPointerLocation(scr),
323 0, 0);
324 OpenSwitchMenu(scr, center.x, center.y, False);
327 if (somethingElse) {
328 WMHandleEvent(&ev);