]> Dogcows Code - chaz/openbox/blob - openbox/focus.c
de346ead98ddefe1a64a9c7ba9e805a9372d97bf
[chaz/openbox] / openbox / focus.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3 focus.c for the Openbox window manager
4 Copyright (c) 2003 Ben Jansens
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 See the COPYING file for a copy of the GNU General Public License.
17 */
18
19 #include "debug.h"
20 #include "event.h"
21 #include "openbox.h"
22 #include "grab.h"
23 #include "framerender.h"
24 #include "client.h"
25 #include "config.h"
26 #include "frame.h"
27 #include "screen.h"
28 #include "group.h"
29 #include "prop.h"
30 #include "focus.h"
31 #include "stacking.h"
32 #include "popup.h"
33 #include "render/render.h"
34
35 #include <X11/Xlib.h>
36 #include <glib.h>
37 #include <assert.h>
38
39 ObClient *focus_client, *focus_hilite;
40 GList **focus_order; /* these lists are created when screen_startup
41 sets the number of desktops */
42 ObClient *focus_cycle_target;
43
44 struct {
45 InternalWindow top;
46 InternalWindow left;
47 InternalWindow right;
48 InternalWindow bottom;
49 } focus_indicator;
50
51 RrAppearance *a_focus_indicator;
52 RrColor *color_black;
53 RrColor *color_white;
54
55 static ObIconPopup *focus_cycle_popup;
56
57 static void focus_cycle_destructor(ObClient *client, gpointer data)
58 {
59 /* end cycling if the target disappears */
60 if (focus_cycle_target == client)
61 focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE);
62 }
63
64 static Window createWindow(Window parent, unsigned long mask,
65 XSetWindowAttributes *attrib)
66 {
67 return XCreateWindow(ob_display, parent, 0, 0, 1, 1, 0,
68 RrDepth(ob_rr_inst), InputOutput,
69 RrVisual(ob_rr_inst), mask, attrib);
70
71 }
72
73 void focus_startup(gboolean reconfig)
74 {
75 focus_cycle_popup = icon_popup_new(TRUE);
76
77 if (!reconfig) {
78 XSetWindowAttributes attr;
79
80 client_add_destructor(focus_cycle_destructor, NULL);
81
82 /* start with nothing focused */
83 focus_set_client(NULL);
84
85 focus_indicator.top.obwin.type = Window_Internal;
86 focus_indicator.left.obwin.type = Window_Internal;
87 focus_indicator.right.obwin.type = Window_Internal;
88 focus_indicator.bottom.obwin.type = Window_Internal;
89
90 attr.override_redirect = True;
91 attr.background_pixel = BlackPixel(ob_display, ob_screen);
92 focus_indicator.top.win =
93 createWindow(RootWindow(ob_display, ob_screen),
94 CWOverrideRedirect | CWBackPixel, &attr);
95 focus_indicator.left.win =
96 createWindow(RootWindow(ob_display, ob_screen),
97 CWOverrideRedirect | CWBackPixel, &attr);
98 focus_indicator.right.win =
99 createWindow(RootWindow(ob_display, ob_screen),
100 CWOverrideRedirect | CWBackPixel, &attr);
101 focus_indicator.bottom.win =
102 createWindow(RootWindow(ob_display, ob_screen),
103 CWOverrideRedirect | CWBackPixel, &attr);
104
105 stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.top));
106 stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.left));
107 stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.right));
108 stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.bottom));
109
110 color_black = RrColorNew(ob_rr_inst, 0, 0, 0);
111 color_white = RrColorNew(ob_rr_inst, 0xff, 0xff, 0xff);
112
113 a_focus_indicator = RrAppearanceNew(ob_rr_inst, 4);
114 a_focus_indicator->surface.grad = RR_SURFACE_SOLID;
115 a_focus_indicator->surface.relief = RR_RELIEF_FLAT;
116 a_focus_indicator->surface.primary = RrColorNew(ob_rr_inst,
117 0, 0, 0);
118 a_focus_indicator->texture[0].type = RR_TEXTURE_LINE_ART;
119 a_focus_indicator->texture[0].data.lineart.color = color_white;
120 a_focus_indicator->texture[1].type = RR_TEXTURE_LINE_ART;
121 a_focus_indicator->texture[1].data.lineart.color = color_white;
122 a_focus_indicator->texture[2].type = RR_TEXTURE_LINE_ART;
123 a_focus_indicator->texture[2].data.lineart.color = color_white;
124 a_focus_indicator->texture[3].type = RR_TEXTURE_LINE_ART;
125 a_focus_indicator->texture[3].data.lineart.color = color_white;
126 }
127 }
128
129 void focus_shutdown(gboolean reconfig)
130 {
131 guint i;
132
133 icon_popup_free(focus_cycle_popup);
134
135 if (!reconfig) {
136 client_remove_destructor(focus_cycle_destructor);
137
138 for (i = 0; i < screen_num_desktops; ++i)
139 g_list_free(focus_order[i]);
140 g_free(focus_order);
141
142 /* reset focus to root */
143 XSetInputFocus(ob_display, PointerRoot, RevertToNone, event_lasttime);
144
145 RrColorFree(color_black);
146 RrColorFree(color_white);
147
148 RrAppearanceFree(a_focus_indicator);
149
150 XDestroyWindow(ob_display, focus_indicator.top.win);
151 XDestroyWindow(ob_display, focus_indicator.left.win);
152 XDestroyWindow(ob_display, focus_indicator.right.win);
153 XDestroyWindow(ob_display, focus_indicator.bottom.win);
154 }
155 }
156
157 static void push_to_top(ObClient *client)
158 {
159 guint desktop;
160
161 desktop = client->desktop;
162 if (desktop == DESKTOP_ALL) desktop = screen_desktop;
163 focus_order[desktop] = g_list_remove(focus_order[desktop], client);
164 focus_order[desktop] = g_list_prepend(focus_order[desktop], client);
165 }
166
167 void focus_set_client(ObClient *client)
168 {
169 Window active;
170 ObClient *old;
171
172 #ifdef DEBUG_FOCUS
173 ob_debug("focus_set_client 0x%lx\n", client ? client->window : 0);
174 #endif
175
176 /* uninstall the old colormap, and install the new one */
177 screen_install_colormap(focus_client, FALSE);
178 screen_install_colormap(client, TRUE);
179
180 if (client == NULL) {
181 #ifdef DEBUG_FOCUS
182 ob_debug("actively focusing NONWINDOW\n");
183 #endif
184 /* when nothing will be focused, send focus to the backup target */
185 XSetInputFocus(ob_display, screen_support_win, RevertToNone,
186 event_lasttime);
187 XSync(ob_display, FALSE);
188 }
189
190 /* in the middle of cycling..? kill it. */
191 if (focus_cycle_target)
192 focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE);
193
194 old = focus_client;
195 focus_client = client;
196
197 /* move to the top of the list */
198 if (client != NULL)
199 push_to_top(client);
200
201 /* set the NET_ACTIVE_WINDOW hint, but preserve it on shutdown */
202 if (ob_state() != OB_STATE_EXITING) {
203 active = client ? client->window : None;
204 PROP_SET32(RootWindow(ob_display, ob_screen),
205 net_active_window, window, active);
206 }
207 }
208
209 /* finds the first transient that isn't 'skip' and ensure's that client_normal
210 is true for it */
211 static ObClient *find_transient_recursive(ObClient *c, ObClient *top, ObClient *skip)
212 {
213 GSList *it;
214 ObClient *ret;
215
216 for (it = c->transients; it; it = it->next) {
217 if (it->data == top) return NULL;
218 ret = find_transient_recursive(it->data, top, skip);
219 if (ret && ret != skip && client_normal(ret)) return ret;
220 if (it->data != skip && client_normal(it->data)) return it->data;
221 }
222 return NULL;
223 }
224
225 static ObClient* focus_fallback_transient(ObClient *top, ObClient *old)
226 {
227 ObClient *target = find_transient_recursive(top, top, old);
228 if (!target) {
229 /* make sure client_normal is true always */
230 if (!client_normal(top))
231 return NULL;
232 target = top; /* no transient, keep the top */
233 }
234 if (client_can_focus(target))
235 return target;
236 else
237 return NULL;
238 }
239
240 ObClient* focus_fallback_target(ObFocusFallbackType type)
241 {
242 GList *it;
243 ObClient *old = NULL;
244 ObClient *target = NULL;
245
246 old = focus_client;
247
248 if (type == OB_FOCUS_FALLBACK_UNFOCUSING && old) {
249 if (old->transient_for) {
250 gboolean trans = FALSE;
251
252 if (!config_focus_follow)
253 trans = TRUE;
254 else {
255 if ((target = client_under_pointer()) &&
256 client_search_transient
257 (client_search_top_transient(target), old))
258 {
259 trans = TRUE;
260 }
261 }
262
263 /* try for transient relations */
264 if (trans) {
265 if (old->transient_for == OB_TRAN_GROUP) {
266 for (it = focus_order[screen_desktop]; it; it = it->next) {
267 GSList *sit;
268
269 for (sit = old->group->members; sit; sit = sit->next)
270 if (sit->data == it->data)
271 if ((target =
272 focus_fallback_transient(sit->data, old)))
273 return target;
274 }
275 } else {
276 if ((target =
277 focus_fallback_transient(old->transient_for, old)))
278 return target;
279 }
280 }
281 }
282 }
283
284 if (config_focus_follow) {
285 if ((target = client_under_pointer()))
286 if (client_normal(target) && client_can_focus(target))
287 return target;
288 }
289
290 #if 0
291 /* try for group relations */
292 if (old->group) {
293 GSList *sit;
294
295 for (it = focus_order[screen_desktop]; it != NULL; it = it->next)
296 for (sit = old->group->members; sit; sit = sit->next)
297 if (sit->data == it->data)
298 if (sit->data != old && client_normal(sit->data))
299 if (client_can_focus(sit->data))
300 return sit->data;
301 }
302 #endif
303
304 for (it = focus_order[screen_desktop]; it != NULL; it = it->next)
305 if (type != OB_FOCUS_FALLBACK_UNFOCUSING || it->data != old)
306 if (client_normal(it->data) && client_can_focus(it->data))
307 return it->data;
308
309 return NULL;
310 }
311
312 void focus_fallback(ObFocusFallbackType type)
313 {
314 ObClient *new;
315
316 /* unfocus any focused clients.. they can be focused by Pointer events
317 and such, and then when I try focus them, I won't get a FocusIn event
318 at all for them.
319 */
320 focus_set_client(NULL);
321
322 if ((new = focus_fallback_target(type)))
323 client_focus(new);
324 }
325
326 static void popup_cycle(ObClient *c, gboolean show)
327 {
328 if (!show) {
329 icon_popup_hide(focus_cycle_popup);
330 } else {
331 Rect *a;
332 ObClient *p = c;
333 char *title;
334
335 a = screen_physical_area_monitor(0);
336 icon_popup_position(focus_cycle_popup, CenterGravity,
337 a->x + a->width / 2, a->y + a->height / 2);
338 /* icon_popup_size(focus_cycle_popup, a->height/2, a->height/16);
339 icon_popup_show(focus_cycle_popup, c->title,
340 client_icon(c, a->height/16, a->height/16));
341 */
342 /* XXX the size and the font extents need to be related on some level
343 */
344 icon_popup_size(focus_cycle_popup, POPUP_WIDTH, POPUP_HEIGHT);
345
346 /* use the transient's parent's title/icon */
347 while (p->transient_for && p->transient_for != OB_TRAN_GROUP)
348 p = p->transient_for;
349
350 if (p == c)
351 title = NULL;
352 else
353 title = g_strconcat((c->iconic ? c->icon_title : c->title),
354 " - ",
355 (p->iconic ? p->icon_title : p->title),
356 NULL);
357
358 icon_popup_show(focus_cycle_popup,
359 (title ? title :
360 (c->iconic ? c->icon_title : c->title)),
361 client_icon(p, 48, 48));
362 g_free(title);
363 }
364 }
365
366 void focus_cycle_draw_indicator()
367 {
368 if (!focus_cycle_target) {
369 XUnmapWindow(ob_display, focus_indicator.top.win);
370 XUnmapWindow(ob_display, focus_indicator.left.win);
371 XUnmapWindow(ob_display, focus_indicator.right.win);
372 XUnmapWindow(ob_display, focus_indicator.bottom.win);
373 } else {
374 /*
375 if (focus_cycle_target)
376 frame_adjust_focus(focus_cycle_target->frame, FALSE);
377 frame_adjust_focus(focus_cycle_target->frame, TRUE);
378 */
379 int x, y, w, h;
380 int wt, wl, wr, wb;
381
382 wt = wl = wr = wb = MAX(3,
383 ob_rr_theme->handle_height +
384 ob_rr_theme->bwidth * 2);
385
386 x = focus_cycle_target->frame->area.x;
387 y = focus_cycle_target->frame->area.y;
388 w = focus_cycle_target->frame->area.width;
389 h = wt;
390
391 XMoveResizeWindow(ob_display, focus_indicator.top.win,
392 x, y, w, h);
393 a_focus_indicator->texture[0].data.lineart.x1 = 0;
394 a_focus_indicator->texture[0].data.lineart.y1 = h-1;
395 a_focus_indicator->texture[0].data.lineart.x2 = 0;
396 a_focus_indicator->texture[0].data.lineart.y2 = 0;
397 a_focus_indicator->texture[1].data.lineart.x1 = 0;
398 a_focus_indicator->texture[1].data.lineart.y1 = 0;
399 a_focus_indicator->texture[1].data.lineart.x2 = w-1;
400 a_focus_indicator->texture[1].data.lineart.y2 = 0;
401 a_focus_indicator->texture[2].data.lineart.x1 = w-1;
402 a_focus_indicator->texture[2].data.lineart.y1 = 0;
403 a_focus_indicator->texture[2].data.lineart.x2 = w-1;
404 a_focus_indicator->texture[2].data.lineart.y2 = h-1;
405 a_focus_indicator->texture[3].data.lineart.x1 = (wl-1);
406 a_focus_indicator->texture[3].data.lineart.y1 = h-1;
407 a_focus_indicator->texture[3].data.lineart.x2 = w - wr;
408 a_focus_indicator->texture[3].data.lineart.y2 = h-1;
409 RrPaint(a_focus_indicator, focus_indicator.top.win,
410 w, h);
411
412 x = focus_cycle_target->frame->area.x;
413 y = focus_cycle_target->frame->area.y;
414 w = wl;
415 h = focus_cycle_target->frame->area.height;
416
417 XMoveResizeWindow(ob_display, focus_indicator.left.win,
418 x, y, w, h);
419 a_focus_indicator->texture[0].data.lineart.x1 = w-1;
420 a_focus_indicator->texture[0].data.lineart.y1 = 0;
421 a_focus_indicator->texture[0].data.lineart.x2 = 0;
422 a_focus_indicator->texture[0].data.lineart.y2 = 0;
423 a_focus_indicator->texture[1].data.lineart.x1 = 0;
424 a_focus_indicator->texture[1].data.lineart.y1 = 0;
425 a_focus_indicator->texture[1].data.lineart.x2 = 0;
426 a_focus_indicator->texture[1].data.lineart.y2 = h-1;
427 a_focus_indicator->texture[2].data.lineart.x1 = 0;
428 a_focus_indicator->texture[2].data.lineart.y1 = h-1;
429 a_focus_indicator->texture[2].data.lineart.x2 = w-1;
430 a_focus_indicator->texture[2].data.lineart.y2 = h-1;
431 a_focus_indicator->texture[3].data.lineart.x1 = w-1;
432 a_focus_indicator->texture[3].data.lineart.y1 = wt-1;
433 a_focus_indicator->texture[3].data.lineart.x2 = w-1;
434 a_focus_indicator->texture[3].data.lineart.y2 = h - wb;
435 RrPaint(a_focus_indicator, focus_indicator.left.win,
436 w, h);
437
438 x = focus_cycle_target->frame->area.x +
439 focus_cycle_target->frame->area.width - wr;
440 y = focus_cycle_target->frame->area.y;
441 w = wr;
442 h = focus_cycle_target->frame->area.height ;
443
444 XMoveResizeWindow(ob_display, focus_indicator.right.win,
445 x, y, w, h);
446 a_focus_indicator->texture[0].data.lineart.x1 = 0;
447 a_focus_indicator->texture[0].data.lineart.y1 = 0;
448 a_focus_indicator->texture[0].data.lineart.x2 = w-1;
449 a_focus_indicator->texture[0].data.lineart.y2 = 0;
450 a_focus_indicator->texture[1].data.lineart.x1 = w-1;
451 a_focus_indicator->texture[1].data.lineart.y1 = 0;
452 a_focus_indicator->texture[1].data.lineart.x2 = w-1;
453 a_focus_indicator->texture[1].data.lineart.y2 = h-1;
454 a_focus_indicator->texture[2].data.lineart.x1 = w-1;
455 a_focus_indicator->texture[2].data.lineart.y1 = h-1;
456 a_focus_indicator->texture[2].data.lineart.x2 = 0;
457 a_focus_indicator->texture[2].data.lineart.y2 = h-1;
458 a_focus_indicator->texture[3].data.lineart.x1 = 0;
459 a_focus_indicator->texture[3].data.lineart.y1 = wt-1;
460 a_focus_indicator->texture[3].data.lineart.x2 = 0;
461 a_focus_indicator->texture[3].data.lineart.y2 = h - wb;
462 RrPaint(a_focus_indicator, focus_indicator.right.win,
463 w, h);
464
465 x = focus_cycle_target->frame->area.x;
466 y = focus_cycle_target->frame->area.y +
467 focus_cycle_target->frame->area.height - wb;
468 w = focus_cycle_target->frame->area.width;
469 h = wb;
470
471 XMoveResizeWindow(ob_display, focus_indicator.bottom.win,
472 x, y, w, h);
473 a_focus_indicator->texture[0].data.lineart.x1 = 0;
474 a_focus_indicator->texture[0].data.lineart.y1 = 0;
475 a_focus_indicator->texture[0].data.lineart.x2 = 0;
476 a_focus_indicator->texture[0].data.lineart.y2 = h-1;
477 a_focus_indicator->texture[1].data.lineart.x1 = 0;
478 a_focus_indicator->texture[1].data.lineart.y1 = h-1;
479 a_focus_indicator->texture[1].data.lineart.x2 = w-1;
480 a_focus_indicator->texture[1].data.lineart.y2 = h-1;
481 a_focus_indicator->texture[2].data.lineart.x1 = w-1;
482 a_focus_indicator->texture[2].data.lineart.y1 = h-1;
483 a_focus_indicator->texture[2].data.lineart.x2 = w-1;
484 a_focus_indicator->texture[2].data.lineart.y2 = 0;
485 a_focus_indicator->texture[3].data.lineart.x1 = wl-1;
486 a_focus_indicator->texture[3].data.lineart.y1 = 0;
487 a_focus_indicator->texture[3].data.lineart.x2 = w - wr;
488 a_focus_indicator->texture[3].data.lineart.y2 = 0;
489 RrPaint(a_focus_indicator, focus_indicator.bottom.win,
490 w, h);
491
492 XMapWindow(ob_display, focus_indicator.top.win);
493 XMapWindow(ob_display, focus_indicator.left.win);
494 XMapWindow(ob_display, focus_indicator.right.win);
495 XMapWindow(ob_display, focus_indicator.bottom.win);
496 }
497 }
498
499 static gboolean valid_focus_target(ObClient *ft)
500 {
501 /* we don't use client_can_focus here, because that doesn't let you
502 focus an iconic window, but we want to be able to, so we just check
503 if the focus flags on the window allow it, and its on the current
504 desktop */
505 return ((ft->type == OB_CLIENT_TYPE_NORMAL ||
506 ft->type == OB_CLIENT_TYPE_DIALOG ||
507 (!client_has_group_siblings(ft) &&
508 (ft->type == OB_CLIENT_TYPE_TOOLBAR ||
509 ft->type == OB_CLIENT_TYPE_MENU ||
510 ft->type == OB_CLIENT_TYPE_UTILITY))) &&
511 !ft->transients &&
512 ((ft->can_focus || ft->focus_notify) &&
513 !ft->skip_taskbar &&
514 (ft->desktop == screen_desktop || ft->desktop == DESKTOP_ALL)));
515 }
516
517 void focus_cycle(gboolean forward, gboolean linear,
518 gboolean dialog, gboolean done, gboolean cancel)
519 {
520 static ObClient *first = NULL;
521 static ObClient *t = NULL;
522 static GList *order = NULL;
523 GList *it, *start, *list;
524 ObClient *ft = NULL;
525
526 if (cancel) {
527 focus_cycle_target = NULL;
528 goto done_cycle;
529 } else if (done)
530 goto done_cycle;
531
532 if (!focus_order[screen_desktop])
533 goto done_cycle;
534
535 if (!first) first = focus_client;
536 if (!focus_cycle_target) focus_cycle_target = focus_client;
537
538 if (linear) list = client_list;
539 else list = focus_order[screen_desktop];
540
541 start = it = g_list_find(list, focus_cycle_target);
542 if (!start) /* switched desktops or something? */
543 start = it = forward ? g_list_last(list) : g_list_first(list);
544 if (!start) goto done_cycle;
545
546 do {
547 if (forward) {
548 it = it->next;
549 if (it == NULL) it = g_list_first(list);
550 } else {
551 it = it->prev;
552 if (it == NULL) it = g_list_last(list);
553 }
554 ft = it->data;
555 if (valid_focus_target(ft)) {
556 if (ft != focus_cycle_target) { /* prevents flicker */
557 focus_cycle_target = ft;
558 focus_cycle_draw_indicator();
559 }
560 popup_cycle(ft, dialog);
561 return;
562 }
563 } while (it != start);
564
565 done_cycle:
566 if (done && focus_cycle_target)
567 client_activate(focus_cycle_target, FALSE);
568
569 t = NULL;
570 first = NULL;
571 focus_cycle_target = NULL;
572 g_list_free(order);
573 order = NULL;
574
575 focus_cycle_draw_indicator();
576 popup_cycle(ft, FALSE);
577
578 return;
579 }
580
581 void focus_directional_cycle(ObDirection dir,
582 gboolean dialog, gboolean done, gboolean cancel)
583 {
584 static ObClient *first = NULL;
585 ObClient *ft = NULL;
586
587 if (cancel) {
588 focus_cycle_target = NULL;
589 goto done_cycle;
590 } else if (done)
591 goto done_cycle;
592
593 if (!focus_order[screen_desktop])
594 goto done_cycle;
595
596 if (!first) first = focus_client;
597 if (!focus_cycle_target) focus_cycle_target = focus_client;
598
599 if (focus_cycle_target)
600 ft = client_find_directional(focus_cycle_target, dir);
601 else {
602 GList *it;
603
604 for (it = focus_order[screen_desktop]; it; it = g_list_next(it))
605 if (valid_focus_target(it->data))
606 ft = it->data;
607 }
608
609 if (ft) {
610 if (ft != focus_cycle_target) {/* prevents flicker */
611 focus_cycle_target = ft;
612 focus_cycle_draw_indicator();
613 }
614 }
615 if (focus_cycle_target) {
616 popup_cycle(focus_cycle_target, dialog);
617 if (dialog)
618 return;
619 }
620
621
622 done_cycle:
623 if (done && focus_cycle_target)
624 client_activate(focus_cycle_target, FALSE);
625
626 first = NULL;
627 focus_cycle_target = NULL;
628
629 focus_cycle_draw_indicator();
630 popup_cycle(ft, FALSE);
631
632 return;
633 }
634
635 void focus_order_add_new(ObClient *c)
636 {
637 guint d, i;
638
639 if (c->iconic)
640 focus_order_to_top(c);
641 else {
642 d = c->desktop;
643 if (d == DESKTOP_ALL) {
644 for (i = 0; i < screen_num_desktops; ++i) {
645 if (focus_order[i] && ((ObClient*)focus_order[i]->data)->iconic)
646 focus_order[i] = g_list_insert(focus_order[i], c, 0);
647 else
648 focus_order[i] = g_list_insert(focus_order[i], c, 1);
649 }
650 } else
651 if (focus_order[d] && ((ObClient*)focus_order[d]->data)->iconic)
652 focus_order[d] = g_list_insert(focus_order[d], c, 0);
653 else
654 focus_order[d] = g_list_insert(focus_order[d], c, 1);
655 }
656 }
657
658 void focus_order_remove(ObClient *c)
659 {
660 guint d, i;
661
662 d = c->desktop;
663 if (d == DESKTOP_ALL) {
664 for (i = 0; i < screen_num_desktops; ++i)
665 focus_order[i] = g_list_remove(focus_order[i], c);
666 } else
667 focus_order[d] = g_list_remove(focus_order[d], c);
668 }
669
670 static void to_top(ObClient *c, guint d)
671 {
672 focus_order[d] = g_list_remove(focus_order[d], c);
673 if (!c->iconic) {
674 focus_order[d] = g_list_prepend(focus_order[d], c);
675 } else {
676 GList *it;
677
678 /* insert before first iconic window */
679 for (it = focus_order[d];
680 it && !((ObClient*)it->data)->iconic; it = it->next);
681 focus_order[d] = g_list_insert_before(focus_order[d], it, c);
682 }
683 }
684
685 void focus_order_to_top(ObClient *c)
686 {
687 guint d, i;
688
689 d = c->desktop;
690 if (d == DESKTOP_ALL) {
691 for (i = 0; i < screen_num_desktops; ++i)
692 to_top(c, i);
693 } else
694 to_top(c, d);
695 }
696
697 static void to_bottom(ObClient *c, guint d)
698 {
699 focus_order[d] = g_list_remove(focus_order[d], c);
700 if (c->iconic) {
701 focus_order[d] = g_list_append(focus_order[d], c);
702 } else {
703 GList *it;
704
705 /* insert before first iconic window */
706 for (it = focus_order[d];
707 it && !((ObClient*)it->data)->iconic; it = it->next);
708 g_list_insert_before(focus_order[d], it, c);
709 }
710 }
711
712 void focus_order_to_bottom(ObClient *c)
713 {
714 guint d, i;
715
716 d = c->desktop;
717 if (d == DESKTOP_ALL) {
718 for (i = 0; i < screen_num_desktops; ++i)
719 to_bottom(c, i);
720 } else
721 to_bottom(c, d);
722 }
This page took 0.062206 seconds and 3 git commands to generate.