]> Dogcows Code - chaz/openbox/blob - openbox/focus.c
same shit different pile
[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 && dialog) {
530 goto done_cycle;
531 }
532
533 if (!focus_order[screen_desktop])
534 goto done_cycle;
535
536 if (!first) first = focus_client;
537 if (!focus_cycle_target) focus_cycle_target = focus_client;
538
539 if (linear) list = client_list;
540 else list = focus_order[screen_desktop];
541
542 start = it = g_list_find(list, focus_cycle_target);
543 if (!start) /* switched desktops or something? */
544 start = it = forward ? g_list_last(list) : g_list_first(list);
545 if (!start) goto done_cycle;
546
547 do {
548 if (forward) {
549 it = it->next;
550 if (it == NULL) it = g_list_first(list);
551 } else {
552 it = it->prev;
553 if (it == NULL) it = g_list_last(list);
554 }
555 ft = it->data;
556 if (valid_focus_target(ft)) {
557 if (ft != focus_cycle_target) { /* prevents flicker */
558 focus_cycle_target = ft;
559 focus_cycle_draw_indicator();
560 }
561 popup_cycle(ft, dialog);
562 return;
563 }
564 } while (it != start);
565
566 done_cycle:
567 if (done && focus_cycle_target)
568 client_activate(focus_cycle_target, FALSE);
569
570 t = NULL;
571 first = NULL;
572 focus_cycle_target = NULL;
573 g_list_free(order);
574 order = NULL;
575
576 focus_cycle_draw_indicator();
577 popup_cycle(ft, FALSE);
578
579 return;
580 }
581
582 void focus_directional_cycle(ObDirection dir,
583 gboolean dialog, gboolean done, gboolean cancel)
584 {
585 static ObClient *first = NULL;
586 ObClient *ft = NULL;
587
588 if (cancel) {
589 focus_cycle_target = NULL;
590 goto done_cycle;
591 } else if (done && dialog) {
592 goto done_cycle;
593 }
594
595 if (!focus_order[screen_desktop])
596 goto done_cycle;
597
598 if (!first) first = focus_client;
599 if (!focus_cycle_target) focus_cycle_target = focus_client;
600
601 if (focus_cycle_target)
602 ft = client_find_directional(focus_cycle_target, dir);
603 else {
604 GList *it;
605
606 for (it = focus_order[screen_desktop]; it; it = g_list_next(it))
607 if (valid_focus_target(it->data))
608 ft = it->data;
609 }
610
611 if (ft) {
612 if (ft != focus_cycle_target) {/* prevents flicker */
613 focus_cycle_target = ft;
614 focus_cycle_draw_indicator();
615 }
616 }
617 if (focus_cycle_target) {
618 popup_cycle(focus_cycle_target, dialog);
619 if (dialog)
620 return;
621 }
622
623
624 done_cycle:
625 if (done && focus_cycle_target)
626 client_activate(focus_cycle_target, FALSE);
627
628 first = NULL;
629 focus_cycle_target = NULL;
630
631 focus_cycle_draw_indicator();
632 popup_cycle(ft, FALSE);
633
634 return;
635 }
636
637 void focus_order_add_new(ObClient *c)
638 {
639 guint d, i;
640
641 if (c->iconic)
642 focus_order_to_top(c);
643 else {
644 d = c->desktop;
645 if (d == DESKTOP_ALL) {
646 for (i = 0; i < screen_num_desktops; ++i) {
647 if (focus_order[i] && ((ObClient*)focus_order[i]->data)->iconic)
648 focus_order[i] = g_list_insert(focus_order[i], c, 0);
649 else
650 focus_order[i] = g_list_insert(focus_order[i], c, 1);
651 }
652 } else
653 if (focus_order[d] && ((ObClient*)focus_order[d]->data)->iconic)
654 focus_order[d] = g_list_insert(focus_order[d], c, 0);
655 else
656 focus_order[d] = g_list_insert(focus_order[d], c, 1);
657 }
658 }
659
660 void focus_order_remove(ObClient *c)
661 {
662 guint d, i;
663
664 d = c->desktop;
665 if (d == DESKTOP_ALL) {
666 for (i = 0; i < screen_num_desktops; ++i)
667 focus_order[i] = g_list_remove(focus_order[i], c);
668 } else
669 focus_order[d] = g_list_remove(focus_order[d], c);
670 }
671
672 static void to_top(ObClient *c, guint d)
673 {
674 focus_order[d] = g_list_remove(focus_order[d], c);
675 if (!c->iconic) {
676 focus_order[d] = g_list_prepend(focus_order[d], c);
677 } else {
678 GList *it;
679
680 /* insert before first iconic window */
681 for (it = focus_order[d];
682 it && !((ObClient*)it->data)->iconic; it = it->next);
683 focus_order[d] = g_list_insert_before(focus_order[d], it, c);
684 }
685 }
686
687 void focus_order_to_top(ObClient *c)
688 {
689 guint d, i;
690
691 d = c->desktop;
692 if (d == DESKTOP_ALL) {
693 for (i = 0; i < screen_num_desktops; ++i)
694 to_top(c, i);
695 } else
696 to_top(c, d);
697 }
698
699 static void to_bottom(ObClient *c, guint d)
700 {
701 focus_order[d] = g_list_remove(focus_order[d], c);
702 if (c->iconic) {
703 focus_order[d] = g_list_append(focus_order[d], c);
704 } else {
705 GList *it;
706
707 /* insert before first iconic window */
708 for (it = focus_order[d];
709 it && !((ObClient*)it->data)->iconic; it = it->next);
710 g_list_insert_before(focus_order[d], it, c);
711 }
712 }
713
714 void focus_order_to_bottom(ObClient *c)
715 {
716 guint d, i;
717
718 d = c->desktop;
719 if (d == DESKTOP_ALL) {
720 for (i = 0; i < screen_num_desktops; ++i)
721 to_bottom(c, i);
722 } else
723 to_bottom(c, d);
724 }
This page took 0.068617 seconds and 4 git commands to generate.