]> icculus.org git repositories - dana/openbox.git/blob - openbox/action.c
linear focus cycling of the gods
[dana/openbox.git] / openbox / action.c
1 #include "client.h"
2 #include "focus.h"
3 #include "stacking.h"
4 #include "frame.h"
5 #include "screen.h"
6 #include "action.h"
7 #include "dispatch.h"
8 #include "openbox.h"
9
10 #include <glib.h>
11
12 Action *action_new(void (*func)(union ActionData *data))
13 {
14     Action *a = g_new0(Action, 1);
15     a->func = func;
16
17     /* deal with pointers */
18     if (func == action_execute)
19         a->data.execute.path = NULL;
20
21     return a;
22 }
23
24 void action_free(Action *a)
25 {
26     if (a == NULL) return;
27
28     /* deal with pointers */
29     if (a->func == action_execute || a->func == action_restart)
30         g_free(a->data.execute.path);
31
32     g_free(a);
33 }
34
35 Action *action_from_string(char *name)
36 {
37     Action *a = NULL;
38     if (!g_ascii_strcasecmp(name, "execute")) {
39         a = action_new(action_execute);
40     } else if (!g_ascii_strcasecmp(name, "focus")) {
41         a = action_new(action_focus);
42     } else if (!g_ascii_strcasecmp(name, "unfocus")) {
43         a = action_new(action_unfocus);
44     } else if (!g_ascii_strcasecmp(name, "iconify")) {
45         a = action_new(action_iconify);
46     } else if (!g_ascii_strcasecmp(name, "raise")) {
47         a = action_new(action_raise);
48     } else if (!g_ascii_strcasecmp(name, "lower")) {
49         a = action_new(action_lower);
50     } else if (!g_ascii_strcasecmp(name, "focusraise")) {
51         a = action_new(action_focusraise);
52     } else if (!g_ascii_strcasecmp(name, "close")) {
53         a = action_new(action_close);
54     } else if (!g_ascii_strcasecmp(name, "kill")) {
55         a = action_new(action_kill);
56     } else if (!g_ascii_strcasecmp(name, "shadelower")) {
57         a = action_new(action_shadelower);
58     } else if (!g_ascii_strcasecmp(name, "unshaderaise")) {
59         a = action_new(action_unshaderaise);
60     } else if (!g_ascii_strcasecmp(name, "shade")) {
61         a = action_new(action_shade);
62     } else if (!g_ascii_strcasecmp(name, "unshade")) {
63         a = action_new(action_unshade);
64     } else if (!g_ascii_strcasecmp(name, "toggleshade")) {
65         a = action_new(action_toggle_shade);
66     } else if (!g_ascii_strcasecmp(name, "toggleomnipresent")) {
67         a = action_new(action_toggle_omnipresent);
68     } else if (!g_ascii_strcasecmp(name, "moverelativehorz")) {
69         a = action_new(action_move_relative_horz);
70     } else if (!g_ascii_strcasecmp(name, "moverelativevert")) {
71         a = action_new(action_move_relative_vert);
72     } else if (!g_ascii_strcasecmp(name, "resizerelativehorz")) {
73         a = action_new(action_resize_relative_horz);
74     } else if (!g_ascii_strcasecmp(name, "resizerelativevert")) {
75         a = action_new(action_resize_relative_vert);
76     } else if (!g_ascii_strcasecmp(name, "maximizefull")) {
77         a = action_new(action_maximize_full);
78     } else if (!g_ascii_strcasecmp(name, "unmaximizefull")) {
79         a = action_new(action_unmaximize_full);
80     } else if (!g_ascii_strcasecmp(name, "togglemaximizefull")) {
81         a = action_new(action_toggle_maximize_full);
82     } else if (!g_ascii_strcasecmp(name, "maximizehorz")) {
83         a = action_new(action_maximize_horz);
84     } else if (!g_ascii_strcasecmp(name, "unmaximizehorz")) {
85         a = action_new(action_unmaximize_horz);
86     } else if (!g_ascii_strcasecmp(name, "togglemaximizehorz")) {
87         a = action_new(action_toggle_maximize_horz);
88     } else if (!g_ascii_strcasecmp(name, "maximizevert")) {
89         a = action_new(action_maximize_vert);
90     } else if (!g_ascii_strcasecmp(name, "unmaximizevert")) {
91         a = action_new(action_unmaximize_vert);
92     } else if (!g_ascii_strcasecmp(name, "togglemaximizevert")) {
93         a = action_new(action_toggle_maximize_vert);
94     } else if (!g_ascii_strcasecmp(name, "sendtodesktop")) {
95         a = action_new(action_send_to_desktop);
96         a->data.sendto.follow = TRUE;
97     } else if (!g_ascii_strcasecmp(name, "sendtonextdesktop")) {
98         a = action_new(action_send_to_next_desktop);
99         a->data.sendtonextprev.wrap = FALSE;
100         a->data.sendtonextprev.follow = TRUE;
101     } else if (!g_ascii_strcasecmp(name, "sendtonextdesktopwrap")) {
102         a = action_new(action_send_to_next_desktop);
103         a->data.sendtonextprev.wrap = TRUE;
104         a->data.sendtonextprev.follow = TRUE;
105     } else if (!g_ascii_strcasecmp(name, "sendtopreviousdesktop")) {
106         a = action_new(action_send_to_previous_desktop);
107         a->data.sendtonextprev.wrap = FALSE;
108         a->data.sendtonextprev.follow = TRUE;
109     } else if (!g_ascii_strcasecmp(name, "sendtopreviousdesktopwrap")) {
110         a = action_new(action_send_to_previous_desktop);
111         a->data.sendtonextprev.wrap = TRUE;
112         a->data.sendtonextprev.follow = TRUE;
113     } else if (!g_ascii_strcasecmp(name, "desktop")) {
114         a = action_new(action_desktop);
115     } else if (!g_ascii_strcasecmp(name, "nextdesktop")) {
116         a = action_new(action_next_desktop);
117         a->data.nextprevdesktop.wrap = FALSE;
118     } else if (!g_ascii_strcasecmp(name, "nextdesktopwrap")) {
119         a = action_new(action_next_desktop);
120         a->data.nextprevdesktop.wrap = TRUE;
121     } else if (!g_ascii_strcasecmp(name, "previousdesktop")) {
122         a = action_new(action_previous_desktop);
123         a->data.nextprevdesktop.wrap = FALSE;
124     } else if (!g_ascii_strcasecmp(name, "previousdesktopwrap")) {
125         a = action_new(action_previous_desktop);
126         a->data.nextprevdesktop.wrap = TRUE;
127     } else if (!g_ascii_strcasecmp(name, "nextdesktopcolumn")) {
128         a = action_new(action_next_desktop_column);
129         a->data.nextprevdesktop.wrap = FALSE;
130     } else if (!g_ascii_strcasecmp(name, "nextdesktopcolumnwrap")) {
131         a = action_new(action_next_desktop_column);
132         a->data.nextprevdesktop.wrap = TRUE;
133     } else if (!g_ascii_strcasecmp(name, "previousdesktopcolumn")) {
134         a = action_new(action_previous_desktop_column);
135         a->data.nextprevdesktop.wrap = FALSE;
136     } else if (!g_ascii_strcasecmp(name, "previousdesktopcolumnwrap")) {
137         a = action_new(action_previous_desktop_column);
138         a->data.nextprevdesktop.wrap = TRUE;
139     } else if (!g_ascii_strcasecmp(name, "nextdesktoprow")) {
140         a = action_new(action_next_desktop_row);
141         a->data.nextprevdesktop.wrap = FALSE;
142     } else if (!g_ascii_strcasecmp(name, "nextdesktoprowwrap")) {
143         a = action_new(action_next_desktop_row);
144         a->data.nextprevdesktop.wrap = TRUE;
145     } else if (!g_ascii_strcasecmp(name, "previousdesktoprow")) {
146         a = action_new(action_previous_desktop_row);
147         a->data.nextprevdesktop.wrap = FALSE;
148     } else if (!g_ascii_strcasecmp(name, "previousdesktoprowwrap")) {
149         a = action_new(action_previous_desktop_row);
150         a->data.nextprevdesktop.wrap = TRUE;
151     } else if (!g_ascii_strcasecmp(name, "toggledecorations")) {
152         a = action_new(action_toggle_decorations);
153     } else if (!g_ascii_strcasecmp(name, "move")) {
154         a = action_new(action_move);
155     } else if (!g_ascii_strcasecmp(name, "resize")) {
156         a = action_new(action_resize);
157     } else if (!g_ascii_strcasecmp(name, "restart")) {
158         a = action_new(action_restart);
159     } else if (!g_ascii_strcasecmp(name, "exit")) {
160         a = action_new(action_exit);
161     } else if (!g_ascii_strcasecmp(name, "showmenu")) {
162         a = action_new(action_showmenu);
163     } else if (!g_ascii_strcasecmp(name, "nextwindowlinear")) {
164         a = action_new(action_cycle_windows);
165         a->data.cycle.linear = TRUE;
166         a->data.cycle.forward = TRUE;
167     } else if (!g_ascii_strcasecmp(name, "previouswindowlinear")) {
168         a = action_new(action_cycle_windows);
169         a->data.cycle.linear = TRUE;
170         a->data.cycle.forward = FALSE;
171     }
172     
173     return a;
174 }
175
176 void action_execute(union ActionData *data)
177 {
178     GError *e = NULL;
179     if (data->execute.path)
180         if (!g_spawn_command_line_async(data->execute.path, &e)) {
181             g_warning("failed to execute '%s': %s",
182                       data->execute.path, e->message);
183         }
184 }
185
186 void action_focus(union ActionData *data)
187 {
188     if (data->client.c)
189         client_focus(data->client.c);
190 }
191
192 void action_unfocus (union ActionData *data)
193 {
194     if (data->client.c)
195         client_unfocus(data->client.c);
196 }
197
198 void action_iconify(union ActionData *data)
199 {
200     if (data->client.c)
201         client_iconify(data->client.c, TRUE, TRUE);
202 }
203
204 void action_focusraise(union ActionData *data)
205 {
206     if (data->client.c) {
207         client_focus(data->client.c);
208         stacking_raise(data->client.c);
209     }
210 }
211
212 void action_raise(union ActionData *data)
213 {
214     if (data->client.c)
215         stacking_raise(data->client.c);
216 }
217
218 void action_unshaderaise(union ActionData *data)
219 {
220     if (data->client.c) {
221         if (data->client.c->shaded)
222             client_shade(data->client.c, FALSE);
223         else
224             stacking_raise(data->client.c);
225     }
226 }
227
228 void action_shadelower(union ActionData *data)
229 {
230     if (data->client.c) {
231         if (data->client.c->shaded)
232             stacking_lower(data->client.c);
233         else
234             client_shade(data->client.c, TRUE);
235     }
236 }
237
238 void action_lower(union ActionData *data)
239 {
240     if (data->client.c)
241         stacking_lower(data->client.c);
242 }
243
244 void action_close(union ActionData *data)
245 {
246     if (data->client.c)
247         client_close(data->client.c);
248 }
249
250 void action_kill(union ActionData *data)
251 {
252     if (data->client.c)
253         client_kill(data->client.c);
254 }
255
256 void action_shade(union ActionData *data)
257 {
258     if (data->client.c)
259         client_shade(data->client.c, TRUE);
260 }
261
262 void action_unshade(union ActionData *data)
263 {
264     if (data->client.c)
265         client_shade(data->client.c, FALSE);
266 }
267
268 void action_toggle_shade(union ActionData *data)
269 {
270     if (data->client.c)
271         client_shade(data->client.c, !data->client.c->shaded);
272 }
273
274 void action_toggle_omnipresent(union ActionData *data)
275
276     if (data->client.c)
277         client_set_desktop(data->client.c,
278                            data->client.c->desktop == DESKTOP_ALL ?
279                            screen_desktop : DESKTOP_ALL, FALSE);
280 }
281
282 void action_move_relative_horz(union ActionData *data)
283 {
284     Client *c = data->relative.c;
285     if (c)
286         client_configure(c, Corner_TopLeft,
287                          c->area.x + data->relative.delta, c->area.y,
288                          c->area.width, c->area.height, TRUE, TRUE);
289 }
290
291 void action_move_relative_vert(union ActionData *data)
292 {
293     Client *c = data->relative.c;
294     if (c)
295         client_configure(c, Corner_TopLeft,
296                          c->area.x, c->area.y + data->relative.delta,
297                          c->area.width, c->area.height, TRUE, TRUE);
298 }
299
300 void action_resize_relative_horz(union ActionData *data)
301 {
302     Client *c = data->relative.c;
303     if (c)
304         client_configure(c, Corner_TopLeft, c->area.x, c->area.y,
305                          c->area.width + data->relative.delta,
306                          c->area.height, TRUE, TRUE);
307 }
308
309 void action_resize_relative_vert(union ActionData *data)
310 {
311     Client *c = data->relative.c;
312     if (c && !c->shaded)
313         client_configure(c, Corner_TopLeft, c->area.x, c->area.y,
314                          c->area.width, c->area.height + data->relative.delta,
315                          TRUE, TRUE);
316 }
317
318 void action_maximize_full(union ActionData *data)
319 {
320     if (data->client.c)
321         client_maximize(data->client.c, TRUE, 0, TRUE);
322 }
323
324 void action_unmaximize_full(union ActionData *data)
325 {
326     if (data->client.c)
327         client_maximize(data->client.c, FALSE, 0, TRUE);
328 }
329
330 void action_toggle_maximize_full(union ActionData *data)
331 {
332     if (data->client.c)
333         client_maximize(data->client.c,
334                         !(data->client.c->max_horz ||
335                           data->client.c->max_vert),
336                         0, TRUE);
337 }
338
339 void action_maximize_horz(union ActionData *data)
340 {
341     if (data->client.c)
342         client_maximize(data->client.c, TRUE, 1, TRUE);
343 }
344
345 void action_unmaximize_horz(union ActionData *data)
346 {
347     if (data->client.c)
348         client_maximize(data->client.c, FALSE, 1, TRUE);
349 }
350
351 void action_toggle_maximize_horz(union ActionData *data)
352 {
353     if (data->client.c)
354         client_maximize(data->client.c, !data->client.c->max_horz, 1, TRUE);
355 }
356
357 void action_maximize_vert(union ActionData *data)
358 {
359     if (data->client.c)
360         client_maximize(data->client.c, TRUE, 2, TRUE);
361 }
362
363 void action_unmaximize_vert(union ActionData *data)
364 {
365     if (data->client.c)
366         client_maximize(data->client.c, FALSE, 2, TRUE);
367 }
368
369 void action_toggle_maximize_vert(union ActionData *data)
370 {
371     if (data->client.c)
372         client_maximize(data->client.c, !data->client.c->max_vert, 2, TRUE);
373 }
374
375 void action_send_to_desktop(union ActionData *data)
376 {
377     if (data->sendto.c) {
378         if (data->sendto.desk < screen_num_desktops ||
379             data->sendto.desk == DESKTOP_ALL) {
380             client_set_desktop(data->desktop.c,
381                                data->sendto.desk, data->sendto.follow);
382             if (data->sendto.follow) screen_set_desktop(data->sendto.desk);
383         }
384     }
385 }
386
387 void action_send_to_next_desktop(union ActionData *data)
388 {
389     guint d;
390
391     if (!data->sendtonextprev.c) return;
392
393     d = screen_desktop + 1;
394     if (d >= screen_num_desktops) {
395         if (!data->sendtonextprev.wrap) return;
396         d = 0;
397     }
398     client_set_desktop(data->sendtonextprev.c, d, data->sendtonextprev.follow);
399     if (data->sendtonextprev.follow) screen_set_desktop(d);
400 }
401
402 void action_send_to_previous_desktop(union ActionData *data)
403 {
404     guint d;
405
406     if (!data->sendtonextprev.c) return;
407
408     d = screen_desktop - 1;
409     if (d >= screen_num_desktops) {
410         if (!data->sendtonextprev.wrap) return;
411         d = screen_num_desktops - 1;
412     }
413     client_set_desktop(data->sendtonextprev.c, d, data->sendtonextprev.follow);
414     if (data->sendtonextprev.follow) screen_set_desktop(d);
415 }
416
417 void action_desktop(union ActionData *data)
418 {
419     if (data->desktop.desk < screen_num_desktops ||
420         data->desktop.desk == DESKTOP_ALL)
421         screen_set_desktop(data->desktop.desk);
422 }
423
424 void action_next_desktop(union ActionData *data)
425 {
426     guint d;
427
428     d = screen_desktop + 1;
429     if (d >= screen_num_desktops) {
430         if (!data->nextprevdesktop.wrap) return;
431         d = 0;
432     }
433     screen_set_desktop(d);
434 }
435
436 void action_previous_desktop(union ActionData *data)
437 {
438     guint d;
439
440     d = screen_desktop - 1;
441     if (d >= screen_num_desktops) {
442         if (!data->nextprevdesktop.wrap) return;
443         d = screen_num_desktops - 1;
444     }
445     screen_set_desktop(d);
446 }
447
448 static void cur_row_col(guint *r, guint *c)
449 {
450     switch (screen_desktop_layout.orientation) {
451     case Orientation_Horz:
452         switch (screen_desktop_layout.start_corner) {
453         case Corner_TopLeft:
454             *r = screen_desktop / screen_desktop_layout.columns;
455             *c = screen_desktop % screen_desktop_layout.columns;
456             break;
457         case Corner_BottomLeft:
458             *r = screen_desktop_layout.rows - 1 -
459                 screen_desktop / screen_desktop_layout.columns;
460             *c = screen_desktop % screen_desktop_layout.columns;
461             break;
462         case Corner_TopRight:
463             *r = screen_desktop / screen_desktop_layout.columns;
464             *c = screen_desktop_layout.columns - 1 -
465                 screen_desktop % screen_desktop_layout.columns;
466             break;
467         case Corner_BottomRight:
468             *r = screen_desktop_layout.rows - 1 -
469                 screen_desktop / screen_desktop_layout.columns;
470             *c = screen_desktop_layout.columns - 1 -
471                 screen_desktop % screen_desktop_layout.columns;
472             break;
473         }
474         break;
475     case Orientation_Vert:
476         switch (screen_desktop_layout.start_corner) {
477         case Corner_TopLeft:
478             *r = screen_desktop % screen_desktop_layout.rows;
479             *c = screen_desktop / screen_desktop_layout.rows;
480             break;
481         case Corner_BottomLeft:
482             *r = screen_desktop_layout.rows - 1 -
483                 screen_desktop % screen_desktop_layout.rows;
484             *c = screen_desktop / screen_desktop_layout.rows;
485             break;
486         case Corner_TopRight:
487             *r = screen_desktop % screen_desktop_layout.rows;
488             *c = screen_desktop_layout.columns - 1 -
489                 screen_desktop / screen_desktop_layout.rows;
490             break;
491         case Corner_BottomRight:
492             *r = screen_desktop_layout.rows - 1 -
493                 screen_desktop % screen_desktop_layout.rows;
494             *c = screen_desktop_layout.columns - 1 -
495                 screen_desktop / screen_desktop_layout.rows;
496             break;
497         }
498         break;
499     }
500 }
501
502 static guint translate_row_col(guint r, guint c)
503 {
504     switch (screen_desktop_layout.orientation) {
505     case Orientation_Horz:
506         switch (screen_desktop_layout.start_corner) {
507         case Corner_TopLeft:
508             return r * screen_desktop_layout.columns + c;
509         case Corner_BottomLeft:
510             return (screen_desktop_layout.rows - 1 - r) *
511                 screen_desktop_layout.columns + c;
512         case Corner_TopRight:
513             return r * screen_desktop_layout.columns +
514                 (screen_desktop_layout.columns - 1 - c);
515         case Corner_BottomRight:
516             return (screen_desktop_layout.rows - 1 - r) *
517                 screen_desktop_layout.columns +
518                 (screen_desktop_layout.columns - 1 - c);
519         }
520     case Orientation_Vert:
521         switch (screen_desktop_layout.start_corner) {
522         case Corner_TopLeft:
523             return c * screen_desktop_layout.rows + r;
524         case Corner_BottomLeft:
525             return c * screen_desktop_layout.rows +
526                 (screen_desktop_layout.rows - 1 - r);
527         case Corner_TopRight:
528             return (screen_desktop_layout.columns - 1 - c) *
529                 screen_desktop_layout.rows + r;
530         case Corner_BottomRight:
531             return (screen_desktop_layout.columns - 1 - c) *
532                 screen_desktop_layout.rows +
533                 (screen_desktop_layout.rows - 1 - r);
534         }
535     }
536     g_assert_not_reached();
537     return 0;
538 }
539
540 void action_next_desktop_column(union ActionData *data)
541 {
542     guint r, c, d;
543
544     cur_row_col(&r, &c);
545     ++c;
546     d = translate_row_col(r, c);
547     if (d >= screen_num_desktops) {
548         if (!data->nextprevdesktop.wrap) return;
549         c = 0;
550     }
551     if (d >= screen_num_desktops)
552         ++c;
553     d = translate_row_col(r, c);
554     if (d < screen_num_desktops)
555         screen_set_desktop(d);
556 }
557
558 void action_previous_desktop_column(union ActionData *data)
559 {
560     guint r, c, d;
561
562     cur_row_col(&r, &c);
563     --c;
564     d = translate_row_col(r, c);
565     if (d >= screen_num_desktops) {
566         if (!data->nextprevdesktop.wrap) return;
567         c = screen_desktop_layout.columns - 1;
568     }
569     if (d >= screen_num_desktops)
570         --c;
571     d = translate_row_col(r, c);
572     if (d < screen_num_desktops)
573         screen_set_desktop(d);
574 }
575
576 void action_next_desktop_row(union ActionData *data)
577 {
578     guint r, c, d;
579
580     cur_row_col(&r, &c);
581     ++r;
582     d = translate_row_col(r, c);
583     if (d >= screen_num_desktops) {
584         if (!data->nextprevdesktop.wrap) return;
585         r = 0;
586     }
587     if (d >= screen_num_desktops)
588         ++r;
589     d = translate_row_col(r, c);
590     if (d < screen_num_desktops)
591         screen_set_desktop(d);
592 }
593
594 void action_previous_desktop_row(union ActionData *data)
595 {
596     guint r, c, d;
597
598     cur_row_col(&r, &c);
599     --r;
600     d = translate_row_col(r, c);
601     if (d >= screen_num_desktops) {
602         if (!data->nextprevdesktop.wrap) return;
603         c = screen_desktop_layout.rows - 1;
604     }
605     if (d >= screen_num_desktops)
606         --r;
607     d = translate_row_col(r, c);
608     if (d < screen_num_desktops)
609         screen_set_desktop(d);
610 }
611
612 void action_toggle_decorations(union ActionData *data)
613 {
614     Client *c = data->client.c;
615     c->disabled_decorations = c->disabled_decorations ? 0 : ~0;
616     client_setup_decor_and_functions(c);
617 }
618
619 void action_move(union ActionData *data)
620 {
621     Client *c = data->move.c;
622     int x = data->move.x;
623     int y = data->move.y;
624
625     if (!c || !client_normal(c)) return;
626
627     dispatch_move(c, &x, &y);
628
629     frame_frame_gravity(c->frame, &x, &y); /* get where the client should be */
630     client_configure(c, Corner_TopLeft, x, y, c->area.width, c->area.height,
631                      TRUE, data->move.final);
632 }
633
634 void action_resize(union ActionData *data)
635 {
636     Client *c = data->resize.c;
637     int w = data->resize.x;
638     int h = data->resize.y;
639  
640     if (!c || c->shaded || !client_normal(c)) return;
641
642     dispatch_resize(c, &w, &h, data->resize.corner);
643     
644     w -= c->frame->size.left + c->frame->size.right;
645     h -= c->frame->size.top + c->frame->size.bottom;
646     
647     client_configure(c, data->resize.corner, c->area.x, c->area.y, w, h,
648                      TRUE, data->resize.final);
649 }
650
651 void action_restart(union ActionData *data)
652 {
653     ob_restart_path = data->execute.path;
654     ob_shutdown = ob_restart = TRUE;
655 }
656
657 void action_exit(union ActionData *data)
658 {
659     ob_shutdown = TRUE;
660 }
661
662 void action_showmenu(union ActionData *data)
663 {
664     g_message(__FUNCTION__);
665 }
666
667 void action_cycle_windows(union ActionData *data)
668 {
669     if (data->cycle.linear) {
670         static Client *first = NULL;
671         static Client *t = NULL;
672
673         if (data->cycle.cancel) {
674             if (first) client_focus(first);
675         } else if (!data->cycle.final) {
676             GList *it, *start;
677
678             t = NULL;
679             first = focus_client;
680             start = it = g_list_find(client_list, data->cycle.c);
681             do {
682                 if (data->cycle.forward) {
683                     it = it->next;
684                     if (it == NULL) it = client_list;
685                 } else {
686                     it = it->prev;
687                     if (it == NULL) it = g_list_last(client_list);
688                 }
689                 if (client_focus(it->data)) {
690                     t = it->data;
691                     break;
692                 }
693             } while (it != start);
694         } else {
695             if (t) stacking_raise(t);
696         }
697     } else {
698     }
699 }
700