]> Dogcows Code - chaz/openbox/blob - src/blackbox.cc
make iconified windows uniconify on an XMapRequestEvent.
[chaz/openbox] / src / blackbox.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // blackbox.cc for Blackbox - an X11 Window manager
3 // Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
4 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a
7 // copy of this software and associated documentation files (the "Software"),
8 // to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 // and/or sell copies of the Software, and to permit persons to whom the
11 // Software is furnished to do so, subject to the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 // DEALINGS IN THE SOFTWARE.
23
24 #ifdef HAVE_CONFIG_H
25 # include "../config.h"
26 #endif // HAVE_CONFIG_H
27
28 extern "C" {
29 #include <X11/Xlib.h>
30 #include <X11/Xutil.h>
31 #include <X11/Xatom.h>
32 #include <X11/cursorfont.h>
33 #include <X11/keysym.h>
34
35 #ifdef SHAPE
36 #include <X11/extensions/shape.h>
37 #endif // SHAPE
38
39 #ifdef HAVE_STDIO_H
40 # include <stdio.h>
41 #endif // HAVE_STDIO_H
42
43 #ifdef HAVE_STDLIB_H
44 # include <stdlib.h>
45 #endif // HAVE_STDLIB_H
46
47 #ifdef HAVE_STRING_H
48 # include <string.h>
49 #endif // HAVE_STRING_H
50
51 #ifdef HAVE_UNISTD_H
52 # include <sys/types.h>
53 # include <unistd.h>
54 #endif // HAVE_UNISTD_H
55
56 #ifdef HAVE_SYS_PARAM_H
57 # include <sys/param.h>
58 #endif // HAVE_SYS_PARAM_H
59
60 #ifdef HAVE_SYS_SELECT_H
61 # include <sys/select.h>
62 #endif // HAVE_SYS_SELECT_H
63
64 #ifdef HAVE_SIGNAL_H
65 # include <signal.h>
66 #endif // HAVE_SIGNAL_H
67
68 #ifdef HAVE_SYS_SIGNAL_H
69 # include <sys/signal.h>
70 #endif // HAVE_SYS_SIGNAL_H
71
72 #ifdef HAVE_SYS_STAT_H
73 # include <sys/types.h>
74 # include <sys/stat.h>
75 #endif // HAVE_SYS_STAT_H
76
77 #ifdef TIME_WITH_SYS_TIME
78 # include <sys/time.h>
79 # include <time.h>
80 #else // !TIME_WITH_SYS_TIME
81 # ifdef HAVE_SYS_TIME_H
82 # include <sys/time.h>
83 # else // !HAVE_SYS_TIME_H
84 # include <time.h>
85 # endif // HAVE_SYS_TIME_H
86 #endif // TIME_WITH_SYS_TIME
87
88 #ifdef HAVE_LIBGEN_H
89 # include <libgen.h>
90 #endif // HAVE_LIBGEN_H
91 }
92
93 #include <assert.h>
94
95 #include <algorithm>
96 #include <string>
97 using std::string;
98
99 #include "i18n.hh"
100 #include "blackbox.hh"
101 #include "Basemenu.hh"
102 #include "Clientmenu.hh"
103 #include "GCCache.hh"
104 #include "Image.hh"
105 #include "Rootmenu.hh"
106 #include "Screen.hh"
107 #include "Slit.hh"
108 #include "Toolbar.hh"
109 #include "Util.hh"
110 #include "Window.hh"
111 #include "Workspace.hh"
112 #include "Workspacemenu.hh"
113 #include "XAtom.hh"
114
115 // X event scanner for enter/leave notifies - adapted from twm
116 struct scanargs {
117 Window w;
118 bool leave, inferior, enter;
119 };
120
121 static Bool queueScanner(Display *, XEvent *e, char *args) {
122 scanargs *scan = (scanargs *) args;
123 if ((e->type == LeaveNotify) &&
124 (e->xcrossing.window == scan->w) &&
125 (e->xcrossing.mode == NotifyNormal)) {
126 scan->leave = True;
127 scan->inferior = (e->xcrossing.detail == NotifyInferior);
128 } else if ((e->type == EnterNotify) && (e->xcrossing.mode == NotifyUngrab)) {
129 scan->enter = True;
130 }
131
132 return False;
133 }
134
135 Blackbox *blackbox;
136
137
138 Blackbox::Blackbox(char **m_argv, char *dpy_name, char *rc, char *menu)
139 : BaseDisplay(m_argv[0], dpy_name) {
140 if (! XSupportsLocale())
141 fprintf(stderr, "X server does not support locale\n");
142
143 if (XSetLocaleModifiers("") == NULL)
144 fprintf(stderr, "cannot set locale modifiers\n");
145
146 ::blackbox = this;
147 argv = m_argv;
148 if (! rc) rc = "~/.openbox/rc";
149 rc_file = expandTilde(rc);
150 config.setFile(rc_file);
151 if (! menu) menu = "~/.openbox/menu";
152 menu_file = expandTilde(menu);
153
154 no_focus = False;
155
156 resource.auto_raise_delay.tv_sec = resource.auto_raise_delay.tv_usec = 0;
157
158 active_screen = 0;
159 focused_window = changing_window = (BlackboxWindow *) 0;
160
161 XrmInitialize();
162 load_rc();
163
164 xatom = new XAtom(getXDisplay());
165
166 cursor.session = XCreateFontCursor(getXDisplay(), XC_left_ptr);
167 cursor.move = XCreateFontCursor(getXDisplay(), XC_fleur);
168 cursor.ll_angle = XCreateFontCursor(getXDisplay(), XC_ll_angle);
169 cursor.lr_angle = XCreateFontCursor(getXDisplay(), XC_lr_angle);
170 cursor.ul_angle = XCreateFontCursor(getXDisplay(), XC_ul_angle);
171 cursor.ur_angle = XCreateFontCursor(getXDisplay(), XC_ur_angle);
172
173 for (unsigned int i = 0; i < getNumberOfScreens(); i++) {
174 BScreen *screen = new BScreen(this, i);
175
176 if (! screen->isScreenManaged()) {
177 delete screen;
178 continue;
179 }
180
181 screenList.push_back(screen);
182 }
183
184 if (screenList.empty()) {
185 fprintf(stderr,
186 i18n(blackboxSet, blackboxNoManagableScreens,
187 "Blackbox::Blackbox: no managable screens found, aborting.\n"));
188 ::exit(3);
189 }
190
191 // save current settings and default values
192 save_rc();
193
194 // set the screen with mouse to the first managed screen
195 active_screen = screenList.front();
196 setFocusedWindow(0);
197
198 XSynchronize(getXDisplay(), False);
199 XSync(getXDisplay(), False);
200
201 reconfigure_wait = reread_menu_wait = False;
202
203 timer = new BTimer(this, this);
204 timer->setTimeout(0l);
205 }
206
207
208 Blackbox::~Blackbox(void) {
209 std::for_each(screenList.begin(), screenList.end(), PointerAssassin());
210
211 std::for_each(menuTimestamps.begin(), menuTimestamps.end(),
212 PointerAssassin());
213
214 delete xatom;
215
216 delete timer;
217 }
218
219
220 void Blackbox::process_event(XEvent *e) {
221 switch (e->type) {
222 case ButtonPress: {
223 // strip the lock key modifiers
224 e->xbutton.state &= ~(NumLockMask | ScrollLockMask | LockMask);
225
226 last_time = e->xbutton.time;
227
228 BlackboxWindow *win = (BlackboxWindow *) 0;
229 Basemenu *menu = (Basemenu *) 0;
230 Slit *slit = (Slit *) 0;
231 Toolbar *tbar = (Toolbar *) 0;
232 BScreen *scrn = (BScreen *) 0;
233
234 if ((win = searchWindow(e->xbutton.window))) {
235 win->buttonPressEvent(&e->xbutton);
236
237 /* XXX: is this sane on low colour desktops? */
238 if (e->xbutton.button == 1)
239 win->installColormap(True);
240 } else if ((menu = searchMenu(e->xbutton.window))) {
241 menu->buttonPressEvent(&e->xbutton);
242 } else if ((slit = searchSlit(e->xbutton.window))) {
243 slit->buttonPressEvent(&e->xbutton);
244 } else if ((tbar = searchToolbar(e->xbutton.window))) {
245 tbar->buttonPressEvent(&e->xbutton);
246 } else if ((scrn = searchScreen(e->xbutton.window))) {
247 scrn->buttonPressEvent(&e->xbutton);
248 if (active_screen != scrn) {
249 active_screen = scrn;
250 // first, set no focus window on the old screen
251 setFocusedWindow(0);
252 // and move focus to this screen
253 setFocusedWindow(0);
254 }
255 }
256 break;
257 }
258
259 case ButtonRelease: {
260 // strip the lock key modifiers
261 e->xbutton.state &= ~(NumLockMask | ScrollLockMask | LockMask);
262
263 last_time = e->xbutton.time;
264
265 BlackboxWindow *win = (BlackboxWindow *) 0;
266 Basemenu *menu = (Basemenu *) 0;
267 Toolbar *tbar = (Toolbar *) 0;
268
269 if ((win = searchWindow(e->xbutton.window)))
270 win->buttonReleaseEvent(&e->xbutton);
271 else if ((menu = searchMenu(e->xbutton.window)))
272 menu->buttonReleaseEvent(&e->xbutton);
273 else if ((tbar = searchToolbar(e->xbutton.window)))
274 tbar->buttonReleaseEvent(&e->xbutton);
275
276 break;
277 }
278
279 case ConfigureRequest: {
280 // compress configure requests...
281 XEvent realevent;
282 unsigned int i = 0;
283 while(XCheckTypedWindowEvent(getXDisplay(), e->xconfigurerequest.window,
284 ConfigureRequest, &realevent)) {
285 i++;
286 }
287 if ( i > 0 )
288 e = &realevent;
289
290 BlackboxWindow *win = (BlackboxWindow *) 0;
291 Slit *slit = (Slit *) 0;
292
293 if ((win = searchWindow(e->xconfigurerequest.window))) {
294 win->configureRequestEvent(&e->xconfigurerequest);
295 } else if ((slit = searchSlit(e->xconfigurerequest.window))) {
296 slit->configureRequestEvent(&e->xconfigurerequest);
297 } else {
298 if (validateWindow(e->xconfigurerequest.window)) {
299 XWindowChanges xwc;
300
301 xwc.x = e->xconfigurerequest.x;
302 xwc.y = e->xconfigurerequest.y;
303 xwc.width = e->xconfigurerequest.width;
304 xwc.height = e->xconfigurerequest.height;
305 xwc.border_width = e->xconfigurerequest.border_width;
306 xwc.sibling = e->xconfigurerequest.above;
307 xwc.stack_mode = e->xconfigurerequest.detail;
308
309 XConfigureWindow(getXDisplay(), e->xconfigurerequest.window,
310 e->xconfigurerequest.value_mask, &xwc);
311 }
312 }
313
314 break;
315 }
316
317 case MapRequest: {
318 #ifdef DEBUG
319 fprintf(stderr, "Blackbox::process_event(): MapRequest for 0x%lx\n",
320 e->xmaprequest.window);
321 #endif // DEBUG
322
323 BlackboxWindow *win = searchWindow(e->xmaprequest.window);
324
325 if (win) {
326 if (win->isIconic()) {
327 win->deiconify();
328 win->setInputFocus();
329 }
330 } else {
331 BScreen *screen = searchScreen(e->xmaprequest.parent);
332
333 if (! screen) {
334 /*
335 we got a map request for a window who's parent isn't root. this
336 can happen in only one circumstance:
337
338 a client window unmapped a managed window, and then remapped it
339 somewhere between unmapping the client window and reparenting it
340 to root.
341
342 regardless of how it happens, we need to find the screen that
343 the window is on
344 */
345 XWindowAttributes wattrib;
346 if (! XGetWindowAttributes(getXDisplay(), e->xmaprequest.window,
347 &wattrib)) {
348 // failed to get the window attributes, perhaps the window has
349 // now been destroyed?
350 break;
351 }
352
353 screen = searchScreen(wattrib.root);
354 assert(screen != 0); // this should never happen
355 }
356
357 screen->manageWindow(e->xmaprequest.window);
358 }
359
360 break;
361 }
362
363 case UnmapNotify: {
364 BlackboxWindow *win = (BlackboxWindow *) 0;
365 Slit *slit = (Slit *) 0;
366 BScreen *screen = (BScreen *) 0;
367
368 if ((win = searchWindow(e->xunmap.window))) {
369 win->unmapNotifyEvent(&e->xunmap);
370 } else if ((slit = searchSlit(e->xunmap.window))) {
371 slit->unmapNotifyEvent(&e->xunmap);
372 } else if ((screen = searchSystrayWindow(e->xunmap.window))) {
373 screen->removeSystrayWindow(e->xunmap.window);
374 } else if ((screen = searchDesktopWindow(e->xunmap.window))) {
375 screen->removeDesktopWindow(e->xunmap.window);
376 }
377
378 break;
379 }
380
381 case DestroyNotify: {
382 BlackboxWindow *win = (BlackboxWindow *) 0;
383 Slit *slit = (Slit *) 0;
384 BScreen *screen = (BScreen *) 0;
385 BWindowGroup *group = (BWindowGroup *) 0;
386
387 if ((win = searchWindow(e->xdestroywindow.window))) {
388 win->destroyNotifyEvent(&e->xdestroywindow);
389 } else if ((slit = searchSlit(e->xdestroywindow.window))) {
390 slit->removeClient(e->xdestroywindow.window, False);
391 } else if ((group = searchGroup(e->xdestroywindow.window))) {
392 delete group;
393 } else if ((screen = searchSystrayWindow(e->xunmap.window))) {
394 screen->removeSystrayWindow(e->xunmap.window);
395 } else if ((screen = searchDesktopWindow(e->xunmap.window))) {
396 screen->removeDesktopWindow(e->xunmap.window);
397 }
398
399 break;
400 }
401
402 case ReparentNotify: {
403 /*
404 this event is quite rare and is usually handled in unmapNotify
405 however, if the window is unmapped when the reparent event occurs
406 the window manager never sees it because an unmap event is not sent
407 to an already unmapped window.
408 */
409 BlackboxWindow *win = searchWindow(e->xreparent.window);
410 if (win) {
411 win->reparentNotifyEvent(&e->xreparent);
412 } else {
413 Slit *slit = searchSlit(e->xreparent.window);
414 if (slit && slit->getWindowID() != e->xreparent.parent)
415 slit->removeClient(e->xreparent.window, True);
416 }
417 break;
418 }
419
420 case MotionNotify: {
421 // motion notify compression...
422 XEvent realevent;
423 unsigned int i = 0;
424 while (XCheckTypedWindowEvent(getXDisplay(), e->xmotion.window,
425 MotionNotify, &realevent)) {
426 i++;
427 }
428
429 // if we have compressed some motion events, use the last one
430 if ( i > 0 )
431 e = &realevent;
432
433 // strip the lock key modifiers
434 e->xbutton.state &= ~(NumLockMask | ScrollLockMask | LockMask);
435
436 last_time = e->xmotion.time;
437
438 BlackboxWindow *win = (BlackboxWindow *) 0;
439 Basemenu *menu = (Basemenu *) 0;
440
441 if ((win = searchWindow(e->xmotion.window)))
442 win->motionNotifyEvent(&e->xmotion);
443 else if ((menu = searchMenu(e->xmotion.window)))
444 menu->motionNotifyEvent(&e->xmotion);
445
446 break;
447 }
448
449 case PropertyNotify: {
450 last_time = e->xproperty.time;
451
452 BlackboxWindow *win = searchWindow(e->xproperty.window);
453 if (win)
454 win->propertyNotifyEvent(&e->xproperty);
455 break;
456 }
457
458 case EnterNotify: {
459 last_time = e->xcrossing.time;
460
461 BScreen *screen = (BScreen *) 0;
462 BlackboxWindow *win = (BlackboxWindow *) 0;
463 Basemenu *menu = (Basemenu *) 0;
464 Toolbar *tbar = (Toolbar *) 0;
465 Slit *slit = (Slit *) 0;
466
467 if (e->xcrossing.mode == NotifyGrab) break;
468
469 XEvent dummy;
470 scanargs sa;
471 sa.w = e->xcrossing.window;
472 sa.enter = sa.leave = False;
473 XCheckIfEvent(getXDisplay(), &dummy, queueScanner, (char *) &sa);
474
475 if ((e->xcrossing.window == e->xcrossing.root) &&
476 (screen = searchScreen(e->xcrossing.window))) {
477 screen->getImageControl()->installRootColormap();
478 } else if ((win = searchWindow(e->xcrossing.window))) {
479 if (win->getScreen()->isSloppyFocus() &&
480 (! win->isFocused()) && (! no_focus)) {
481 if (((! sa.leave) || sa.inferior) && win->isVisible()) {
482 if (win->setInputFocus())
483 win->installColormap(True); // XXX: shouldnt we honour no install?
484 }
485 }
486 } else if ((menu = searchMenu(e->xcrossing.window))) {
487 menu->enterNotifyEvent(&e->xcrossing);
488 } else if ((tbar = searchToolbar(e->xcrossing.window))) {
489 tbar->enterNotifyEvent(&e->xcrossing);
490 } else if ((slit = searchSlit(e->xcrossing.window))) {
491 slit->enterNotifyEvent(&e->xcrossing);
492 }
493 break;
494 }
495
496 case LeaveNotify: {
497 last_time = e->xcrossing.time;
498
499 BlackboxWindow *win = (BlackboxWindow *) 0;
500 Basemenu *menu = (Basemenu *) 0;
501 Toolbar *tbar = (Toolbar *) 0;
502 Slit *slit = (Slit *) 0;
503
504 if ((menu = searchMenu(e->xcrossing.window)))
505 menu->leaveNotifyEvent(&e->xcrossing);
506 else if ((win = searchWindow(e->xcrossing.window)))
507 win->installColormap(False);
508 else if ((tbar = searchToolbar(e->xcrossing.window)))
509 tbar->leaveNotifyEvent(&e->xcrossing);
510 else if ((slit = searchSlit(e->xcrossing.window)))
511 slit->leaveNotifyEvent(&e->xcrossing);
512 break;
513 }
514
515 case Expose: {
516 // compress expose events
517 XEvent realevent;
518 unsigned int i = 0;
519 int ex1, ey1, ex2, ey2;
520 ex1 = e->xexpose.x;
521 ey1 = e->xexpose.y;
522 ex2 = ex1 + e->xexpose.width - 1;
523 ey2 = ey1 + e->xexpose.height - 1;
524 while (XCheckTypedWindowEvent(getXDisplay(), e->xexpose.window,
525 Expose, &realevent)) {
526 i++;
527
528 // merge expose area
529 ex1 = std::min(realevent.xexpose.x, ex1);
530 ey1 = std::min(realevent.xexpose.y, ey1);
531 ex2 = std::max(realevent.xexpose.x + realevent.xexpose.width - 1, ex2);
532 ey2 = std::max(realevent.xexpose.y + realevent.xexpose.height - 1, ey2);
533 }
534 if ( i > 0 )
535 e = &realevent;
536
537 // use the merged area
538 e->xexpose.x = ex1;
539 e->xexpose.y = ey1;
540 e->xexpose.width = ex2 - ex1 + 1;
541 e->xexpose.height = ey2 - ey1 + 1;
542
543 BlackboxWindow *win = (BlackboxWindow *) 0;
544 Basemenu *menu = (Basemenu *) 0;
545 Toolbar *tbar = (Toolbar *) 0;
546
547 if ((win = searchWindow(e->xexpose.window)))
548 win->exposeEvent(&e->xexpose);
549 else if ((menu = searchMenu(e->xexpose.window)))
550 menu->exposeEvent(&e->xexpose);
551 else if ((tbar = searchToolbar(e->xexpose.window)))
552 tbar->exposeEvent(&e->xexpose);
553
554 break;
555 }
556
557 case KeyPress: {
558 Toolbar *tbar = searchToolbar(e->xkey.window);
559
560 if (tbar && tbar->isEditing())
561 tbar->keyPressEvent(&e->xkey);
562
563 break;
564 }
565
566 case ColormapNotify: {
567 BScreen *screen = searchScreen(e->xcolormap.window);
568
569 if (screen)
570 screen->setRootColormapInstalled((e->xcolormap.state ==
571 ColormapInstalled) ? True : False);
572
573 break;
574 }
575
576 case FocusIn: {
577 if (e->xfocus.detail != NotifyNonlinear &&
578 e->xfocus.detail != NotifyAncestor) {
579 /*
580 don't process FocusIns when:
581 1. the new focus window isn't an ancestor or inferior of the old
582 focus window (NotifyNonlinear)
583 make sure to allow the FocusIn when the old focus window was an
584 ancestor but didn't have a parent, such as root (NotifyAncestor)
585 */
586 break;
587 }
588
589 BlackboxWindow *win = searchWindow(e->xfocus.window);
590 if (win) {
591 if (! win->isFocused())
592 win->setFocusFlag(True);
593
594 /*
595 set the event window to None. when the FocusOut event handler calls
596 this function recursively, it uses this as an indication that focus
597 has moved to a known window.
598 */
599 e->xfocus.window = None;
600 }
601
602 break;
603 }
604
605 case FocusOut: {
606 if (e->xfocus.detail != NotifyNonlinear) {
607 /*
608 don't process FocusOuts when:
609 2. the new focus window isn't an ancestor or inferior of the old
610 focus window (NotifyNonlinear)
611 */
612 break;
613 }
614
615 BlackboxWindow *win = searchWindow(e->xfocus.window);
616 if (win && win->isFocused()) {
617 /*
618 before we mark "win" as unfocused, we need to verify that focus is
619 going to a known location, is in a known location, or set focus
620 to a known location.
621 */
622
623 XEvent event;
624 // don't check the current focus if FocusOut was generated during a grab
625 bool check_focus = (e->xfocus.mode == NotifyNormal);
626
627 /*
628 First, check if there is a pending FocusIn event waiting. if there
629 is, process it and determine if focus has moved to another window
630 (the FocusIn event handler sets the window in the event
631 structure to None to indicate this).
632 */
633 if (XCheckTypedEvent(getXDisplay(), FocusIn, &event)) {
634
635 process_event(&event);
636 if (event.xfocus.window == None) {
637 // focus has moved
638 check_focus = False;
639 }
640 }
641
642 if (check_focus) {
643 /*
644 Second, we query the X server for the current input focus.
645 to make sure that we keep a consistent state.
646 */
647 BlackboxWindow *focus;
648 Window w;
649 int revert;
650 XGetInputFocus(getXDisplay(), &w, &revert);
651 focus = searchWindow(w);
652 if (focus) {
653 /*
654 focus got from "win" to "focus" under some very strange
655 circumstances, and we need to make sure that the focus indication
656 is correct.
657 */
658 setFocusedWindow(focus);
659 } else {
660 // we have no idea where focus went... so we set it to somewhere
661 setFocusedWindow(0);
662 }
663 }
664 }
665
666 break;
667 }
668
669 case ClientMessage: {
670 if (e->xclient.format == 32) {
671 if (e->xclient.message_type == xatom->getAtom(XAtom::wm_change_state)) {
672 // WM_CHANGE_STATE message
673 BlackboxWindow *win = searchWindow(e->xclient.window);
674 if (! win || ! win->validateClient()) return;
675
676 if (e->xclient.data.l[0] == IconicState)
677 win->iconify();
678 if (e->xclient.data.l[0] == NormalState)
679 win->deiconify();
680 } else if (e->xclient.message_type ==
681 xatom->getAtom(XAtom::blackbox_change_workspace) ||
682 e->xclient.message_type ==
683 xatom->getAtom(XAtom::net_current_desktop)) {
684 // NET_CURRENT_DESKTOP message
685 BScreen *screen = searchScreen(e->xclient.window);
686
687 unsigned int workspace = e->xclient.data.l[0];
688 if (screen && workspace < screen->getWorkspaceCount())
689 screen->changeWorkspaceID(workspace);
690 } else if (e->xclient.message_type ==
691 xatom->getAtom(XAtom::blackbox_change_window_focus) ||
692 e->xclient.message_type ==
693 xatom->getAtom(XAtom::net_active_window)) {
694 // NET_ACTIVE_WINDOW
695 BlackboxWindow *win = searchWindow(e->xclient.window);
696
697 if (win) {
698 if (win->isIconic())
699 win->deiconify(False, True);
700 if (win->isVisible() && win->setInputFocus()) {
701 //win->getScreen()->getWorkspace(win->getWorkspaceNumber())->
702 // raiseWindow(win);
703 win->installColormap(True);
704 }
705 }
706 } else if (e->xclient.message_type ==
707 xatom->getAtom(XAtom::blackbox_cycle_window_focus)) {
708 // BLACKBOX_CYCLE_WINDOW_FOCUS
709 BScreen *screen = searchScreen(e->xclient.window);
710
711 if (screen) {
712 if (! e->xclient.data.l[0])
713 screen->prevFocus();
714 else
715 screen->nextFocus();
716 }
717 } else if (e->xclient.message_type ==
718 xatom->getAtom(XAtom::net_wm_desktop)) {
719 // NET_WM_DESKTOP
720 BlackboxWindow *win = searchWindow(e->xclient.window);
721
722 if (win) {
723 BScreen *screen = win->getScreen();
724 unsigned long wksp = (unsigned) e->xclient.data.l[0];
725 if (wksp < screen->getWorkspaceCount()) {
726 if (win->isIconic()) win->deiconify(False, True);
727 if (win->isStuck()) win->stick();
728 if (wksp != screen->getCurrentWorkspaceID())
729 win->withdraw();
730 else
731 win->show();
732 screen->reassociateWindow(win, wksp, True);
733 } else if (wksp == 0xfffffffe) { // XXX: BUG, BUT DOING THIS SO KDE WORKS FOR NOW!!
734 if (win->isIconic()) win->deiconify(False, True);
735 if (! win->isStuck()) win->stick();
736 if (! win->isVisible()) win->show();
737 }
738 }
739 } else if (e->xclient.message_type ==
740 xatom->getAtom(XAtom::blackbox_change_attributes)) {
741 // BLACKBOX_CHANGE_ATTRIBUTES
742 BlackboxWindow *win = searchWindow(e->xclient.window);
743
744 if (win && win->validateClient()) {
745 BlackboxHints net;
746 net.flags = e->xclient.data.l[0];
747 net.attrib = e->xclient.data.l[1];
748 net.workspace = e->xclient.data.l[2];
749 net.stack = e->xclient.data.l[3];
750 net.decoration = e->xclient.data.l[4];
751
752 win->changeBlackboxHints(&net);
753 }
754 } else if (e->xclient.message_type ==
755 xatom->getAtom(XAtom::net_number_of_desktops)) {
756 // NET_NUMBER_OF_DESKTOPS
757 BScreen *screen = searchScreen(e->xclient.window);
758
759 if (e->xclient.data.l[0] > 0) {
760 if ((unsigned) e->xclient.data.l[0] < screen->getWorkspaceCount()) {
761 // shrink
762 for (int i = screen->getWorkspaceCount();
763 i > e->xclient.data.l[0]; --i)
764 screen->removeLastWorkspace();
765 // removeLast already sets the current workspace to the
766 // last available one.
767 } else if ((unsigned) e->xclient.data.l[0] >
768 screen->getWorkspaceCount()) {
769 // grow
770 for(int i = screen->getWorkspaceCount();
771 i < e->xclient.data.l[0]; ++i)
772 screen->addWorkspace();
773 }
774 }
775 } else if (e->xclient.message_type ==
776 xatom->getAtom(XAtom::net_close_window)) {
777 // NET_CLOSE_WINDOW
778 BlackboxWindow *win = searchWindow(e->xclient.window);
779 if (win && win->validateClient())
780 win->close(); // could this be smarter?
781 } else if (e->xclient.message_type ==
782 xatom->getAtom(XAtom::net_wm_moveresize)) {
783 // NET_WM_MOVERESIZE
784 BlackboxWindow *win = searchWindow(e->xclient.window);
785 if (win && win->validateClient()) {
786 int x_root = e->xclient.data.l[0],
787 y_root = e->xclient.data.l[1];
788 if ((Atom) e->xclient.data.l[2] ==
789 xatom->getAtom(XAtom::net_wm_moveresize_move)) {
790 win->beginMove(x_root, y_root);
791 } else {
792 if ((Atom) e->xclient.data.l[2] ==
793 xatom->getAtom(XAtom::net_wm_moveresize_size_topleft))
794 win->beginResize(x_root, y_root, BlackboxWindow::TopLeft);
795 else if ((Atom) e->xclient.data.l[2] ==
796 xatom->getAtom(XAtom::net_wm_moveresize_size_topright))
797 win->beginResize(x_root, y_root, BlackboxWindow::TopRight);
798 else if ((Atom) e->xclient.data.l[2] ==
799 xatom->getAtom(XAtom::net_wm_moveresize_size_bottomleft))
800 win->beginResize(x_root, y_root, BlackboxWindow::BottomLeft);
801 else if ((Atom) e->xclient.data.l[2] ==
802 xatom->getAtom(XAtom::net_wm_moveresize_size_bottomright))
803 win->beginResize(x_root, y_root, BlackboxWindow::BottomRight);
804 }
805 }
806 } else if (e->xclient.message_type ==
807 xatom->getAtom(XAtom::net_wm_state)) {
808 // NET_WM_STATE
809 BlackboxWindow *win = searchWindow(e->xclient.window);
810 if (win && win->validateClient()) {
811 const Atom action = (Atom) e->xclient.data.l[0];
812 const Atom state[] = { (Atom) e->xclient.data.l[1],
813 (Atom) e->xclient.data.l[2] };
814
815 for (int i = 0; i < 2; ++i) {
816 if (! state[i])
817 continue;
818
819 if ((Atom) e->xclient.data.l[0] == 1) {
820 // ADD
821 if (state[i] == xatom->getAtom(XAtom::net_wm_state_modal)) {
822 win->setModal(True);
823 } else if (state[i] ==
824 xatom->getAtom(XAtom::net_wm_state_maximized_vert)) {
825 if (win->isMaximizedHoriz()) {
826 win->maximize(0); // unmaximize
827 win->maximize(1); // full
828 } else if (! win->isMaximized()) {
829 win->maximize(2); // vert
830 }
831 } else if (state[i] ==
832 xatom->getAtom(XAtom::net_wm_state_maximized_horz)) {
833 if (win->isMaximizedVert()) {
834 win->maximize(0); // unmaximize
835 win->maximize(1); // full
836 } else if (! win->isMaximized()) {
837 win->maximize(3); // horiz
838 }
839 } else if (state[i] ==
840 xatom->getAtom(XAtom::net_wm_state_shaded)) {
841 if (! win->isShaded())
842 win->shade();
843 } else if (state[i] ==
844 xatom->getAtom(XAtom::net_wm_state_skip_taskbar)) {
845 win->setSkipTaskbar(True);
846 } else if (state[i] ==
847 xatom->getAtom(XAtom::net_wm_state_skip_pager)) {
848 win->setSkipPager(True);
849 } else if (state[i] ==
850 xatom->getAtom(XAtom::net_wm_state_fullscreen)) {
851 win->setFullscreen(True);
852 }
853 } else if (action == 0) {
854 // REMOVE
855 if (state[i] == xatom->getAtom(XAtom::net_wm_state_modal)) {
856 win->setModal(False);
857 } else if (state[i] ==
858 xatom->getAtom(XAtom::net_wm_state_maximized_vert)) {
859 if (win->isMaximizedFull()) {
860 win->maximize(0); // unmaximize
861 win->maximize(3); // horiz
862 } else if (win->isMaximizedVert()) {
863 win->maximize(0); // unmaximize
864 }
865 } else if (state[i] ==
866 xatom->getAtom(XAtom::net_wm_state_maximized_horz)) {
867 if (win->isMaximizedFull()) {
868 win->maximize(0); // unmaximize
869 win->maximize(2); // vert
870 } else if (win->isMaximizedHoriz()) {
871 win->maximize(0); // unmaximize
872 }
873 } else if (state[i] ==
874 xatom->getAtom(XAtom::net_wm_state_shaded)) {
875 if (win->isShaded())
876 win->shade();
877 } else if (state[i] ==
878 xatom->getAtom(XAtom::net_wm_state_skip_taskbar)) {
879 win->setSkipTaskbar(False);
880 } else if (state[i] ==
881 xatom->getAtom(XAtom::net_wm_state_skip_pager)) {
882 win->setSkipPager(False);
883 } else if (state[i] ==
884 xatom->getAtom(XAtom::net_wm_state_fullscreen)) {
885 win->setFullscreen(False);
886 }
887 } else if (action == 2) {
888 // TOGGLE
889 if (state[i] == xatom->getAtom(XAtom::net_wm_state_modal)) {
890 win->setModal(! win->isModal());
891 } else if (state[i] ==
892 xatom->getAtom(XAtom::net_wm_state_maximized_vert)) {
893 if (win->isMaximizedFull()) {
894 win->maximize(0); // unmaximize
895 win->maximize(3); // horiz
896 } else if (win->isMaximizedVert()) {
897 win->maximize(0); // unmaximize
898 } else if (win->isMaximizedHoriz()) {
899 win->maximize(0); // unmaximize
900 win->maximize(1); // full
901 } else {
902 win->maximize(2); // vert
903 }
904 } else if (state[i] ==
905 xatom->getAtom(XAtom::net_wm_state_maximized_horz)) {
906 if (win->isMaximizedFull()) {
907 win->maximize(0); // unmaximize
908 win->maximize(2); // vert
909 } else if (win->isMaximizedHoriz()) {
910 win->maximize(0); // unmaximize
911 } else if (win->isMaximizedVert()) {
912 win->maximize(0); // unmaximize
913 win->maximize(1); // full
914 } else {
915 win->maximize(3); // horiz
916 }
917 } else if (state[i] ==
918 xatom->getAtom(XAtom::net_wm_state_shaded)) {
919 win->shade();
920 } else if (state[i] ==
921 xatom->getAtom(XAtom::net_wm_state_skip_taskbar)) {
922 win->setSkipTaskbar(! win->skipTaskbar());
923 } else if (state[i] ==
924 xatom->getAtom(XAtom::net_wm_state_skip_pager)) {
925 win->setSkipPager(! win->skipPager());
926 } else if (state[i] ==
927 xatom->getAtom(XAtom::net_wm_state_fullscreen)) {
928 win->setFullscreen(! win->isFullscreen());
929 }
930 }
931 }
932 }
933 }
934 }
935
936 break;
937 }
938
939 case NoExpose:
940 case ConfigureNotify:
941 case MapNotify:
942 break; // not handled, just ignore
943
944 default: {
945 #ifdef SHAPE
946 if (e->type == getShapeEventBase()) {
947 XShapeEvent *shape_event = (XShapeEvent *) e;
948 BlackboxWindow *win = searchWindow(e->xany.window);
949
950 if (win)
951 win->shapeEvent(shape_event);
952 }
953 #endif // SHAPE
954 }
955 } // switch
956 }
957
958
959 bool Blackbox::handleSignal(int sig) {
960 switch (sig) {
961 case SIGHUP:
962 case SIGUSR1:
963 reconfigure();
964 break;
965
966 case SIGUSR2:
967 rereadMenu();
968 break;
969
970 case SIGPIPE:
971 case SIGSEGV:
972 case SIGFPE:
973 case SIGINT:
974 case SIGTERM:
975 shutdown();
976
977 default:
978 return False;
979 }
980
981 return True;
982 }
983
984
985 bool Blackbox::validateWindow(Window window) {
986 XEvent event;
987 if (XCheckTypedWindowEvent(getXDisplay(), window, DestroyNotify, &event)) {
988 XPutBackEvent(getXDisplay(), &event);
989
990 return False;
991 }
992
993 return True;
994 }
995
996
997 BScreen *Blackbox::searchScreen(Window window) {
998 ScreenList::iterator it = screenList.begin();
999
1000 for (; it != screenList.end(); ++it) {
1001 BScreen *s = *it;
1002 if (s->getRootWindow() == window)
1003 return s;
1004 }
1005
1006 return (BScreen *) 0;
1007 }
1008
1009
1010 BScreen *Blackbox::searchDesktopWindow(Window window) {
1011 WindowScreenLookup::iterator it = desktopSearchList.find(window);
1012 if (it != desktopSearchList.end())
1013 return it->second;
1014
1015 return (BScreen*) 0;
1016 }
1017
1018
1019 BScreen *Blackbox::searchSystrayWindow(Window window) {
1020 WindowScreenLookup::iterator it = systraySearchList.find(window);
1021 if (it != systraySearchList.end())
1022 return it->second;
1023
1024 return (BScreen*) 0;
1025 }
1026
1027
1028 BlackboxWindow *Blackbox::searchWindow(Window window) {
1029 WindowLookup::iterator it = windowSearchList.find(window);
1030 if (it != windowSearchList.end())
1031 return it->second;
1032
1033 return (BlackboxWindow*) 0;
1034 }
1035
1036
1037 BWindowGroup *Blackbox::searchGroup(Window window) {
1038 GroupLookup::iterator it = groupSearchList.find(window);
1039 if (it != groupSearchList.end())
1040 return it->second;
1041
1042 return (BWindowGroup *) 0;
1043 }
1044
1045
1046 Basemenu *Blackbox::searchMenu(Window window) {
1047 MenuLookup::iterator it = menuSearchList.find(window);
1048 if (it != menuSearchList.end())
1049 return it->second;
1050
1051 return (Basemenu*) 0;
1052 }
1053
1054
1055 Toolbar *Blackbox::searchToolbar(Window window) {
1056 ToolbarLookup::iterator it = toolbarSearchList.find(window);
1057 if (it != toolbarSearchList.end())
1058 return it->second;
1059
1060 return (Toolbar*) 0;
1061 }
1062
1063
1064 Slit *Blackbox::searchSlit(Window window) {
1065 SlitLookup::iterator it = slitSearchList.find(window);
1066 if (it != slitSearchList.end())
1067 return it->second;
1068
1069 return (Slit*) 0;
1070 }
1071
1072
1073 void Blackbox::saveDesktopWindowSearch(Window window, BScreen *screen) {
1074 desktopSearchList.insert(WindowScreenLookupPair(window, screen));
1075 }
1076
1077
1078 void Blackbox::saveSystrayWindowSearch(Window window, BScreen *screen) {
1079 systraySearchList.insert(WindowScreenLookupPair(window, screen));
1080 }
1081
1082
1083 void Blackbox::saveWindowSearch(Window window, BlackboxWindow *data) {
1084 windowSearchList.insert(WindowLookupPair(window, data));
1085 }
1086
1087
1088 void Blackbox::saveGroupSearch(Window window, BWindowGroup *data) {
1089 groupSearchList.insert(GroupLookupPair(window, data));
1090 }
1091
1092
1093 void Blackbox::saveMenuSearch(Window window, Basemenu *data) {
1094 menuSearchList.insert(MenuLookupPair(window, data));
1095 }
1096
1097
1098 void Blackbox::saveToolbarSearch(Window window, Toolbar *data) {
1099 toolbarSearchList.insert(ToolbarLookupPair(window, data));
1100 }
1101
1102
1103 void Blackbox::saveSlitSearch(Window window, Slit *data) {
1104 slitSearchList.insert(SlitLookupPair(window, data));
1105 }
1106
1107
1108 void Blackbox::removeDesktopWindowSearch(Window window) {
1109 desktopSearchList.erase(window);
1110 }
1111
1112
1113 void Blackbox::removeSystrayWindowSearch(Window window) {
1114 systraySearchList.erase(window);
1115 }
1116
1117
1118 void Blackbox::removeWindowSearch(Window window) {
1119 windowSearchList.erase(window);
1120 }
1121
1122
1123 void Blackbox::removeGroupSearch(Window window) {
1124 groupSearchList.erase(window);
1125 }
1126
1127
1128 void Blackbox::removeMenuSearch(Window window) {
1129 menuSearchList.erase(window);
1130 }
1131
1132
1133 void Blackbox::removeToolbarSearch(Window window) {
1134 toolbarSearchList.erase(window);
1135 }
1136
1137
1138 void Blackbox::removeSlitSearch(Window window) {
1139 slitSearchList.erase(window);
1140 }
1141
1142
1143 void Blackbox::restart(const char *prog) {
1144 shutdown();
1145
1146 if (prog) {
1147 putenv(const_cast<char *>(screenList.front()->displayString().c_str()));
1148 execlp(prog, prog, NULL);
1149 perror(prog);
1150 }
1151
1152 // fall back in case the above execlp doesn't work
1153 execvp(argv[0], argv);
1154 string name = basename(argv[0]);
1155 execvp(name.c_str(), argv);
1156 }
1157
1158
1159 void Blackbox::shutdown(void) {
1160 BaseDisplay::shutdown();
1161
1162 XSetInputFocus(getXDisplay(), PointerRoot, None, CurrentTime);
1163
1164 std::for_each(screenList.begin(), screenList.end(),
1165 std::mem_fun(&BScreen::shutdown));
1166
1167 XSync(getXDisplay(), False);
1168 }
1169
1170
1171 /*
1172 * Save all values as they are so that the defaults will be written to the rc
1173 * file
1174 */
1175 void Blackbox::save_rc(void) {
1176 config.setAutoSave(false);
1177
1178 config.setValue("session.colorsPerChannel", resource.colors_per_channel);
1179 config.setValue("session.doubleClickInterval",
1180 resource.double_click_interval);
1181 config.setValue("session.autoRaiseDelay",
1182 ((resource.auto_raise_delay.tv_sec * 1000) +
1183 (resource.auto_raise_delay.tv_usec / 1000)));
1184 config.setValue("session.cacheLife", resource.cache_life / 60000);
1185 config.setValue("session.cacheMax", resource.cache_max);
1186 config.setValue("session.styleFile", resource.style_file);
1187 config.setValue("session.titlebarLayout", resource.titlebar_layout);
1188
1189 std::for_each(screenList.begin(), screenList.end(),
1190 std::mem_fun(&BScreen::save_rc));
1191
1192 config.setAutoSave(true);
1193 config.save();
1194 }
1195
1196
1197 void Blackbox::load_rc(void) {
1198 if (! config.load())
1199 config.create();
1200
1201 string s;
1202
1203 if (! config.getValue("session.colorsPerChannel",
1204 resource.colors_per_channel))
1205 resource.colors_per_channel = 4;
1206 if (resource.colors_per_channel < 2) resource.colors_per_channel = 2;
1207 else if (resource.colors_per_channel > 6) resource.colors_per_channel = 6;
1208
1209 if (config.getValue("session.styleFile", s))
1210 resource.style_file = expandTilde(s);
1211 else
1212 resource.style_file = DEFAULTSTYLE;
1213
1214 if (! config.getValue("session.doubleClickInterval",
1215 resource.double_click_interval));
1216 resource.double_click_interval = 250;
1217
1218 if (! config.getValue("session.autoRaiseDelay",
1219 resource.auto_raise_delay.tv_usec))
1220 resource.auto_raise_delay.tv_usec = 400;
1221 resource.auto_raise_delay.tv_sec = resource.auto_raise_delay.tv_usec / 1000;
1222 resource.auto_raise_delay.tv_usec -=
1223 (resource.auto_raise_delay.tv_sec * 1000);
1224 resource.auto_raise_delay.tv_usec *= 1000;
1225
1226 if (! config.getValue("session.cacheLife", resource.cache_life))
1227 resource.cache_life = 5;
1228 resource.cache_life *= 60000;
1229
1230 if (! config.getValue("session.cacheMax", resource.cache_max))
1231 resource.cache_max = 200;
1232
1233 if (! config.getValue("session.titlebarLayout", resource.titlebar_layout))
1234 resource.titlebar_layout = "ILMC";
1235 }
1236
1237
1238 void Blackbox::reconfigure(void) {
1239 reconfigure_wait = True;
1240
1241 if (! timer->isTiming()) timer->start();
1242 }
1243
1244
1245 void Blackbox::real_reconfigure(void) {
1246 load_rc();
1247
1248 std::for_each(menuTimestamps.begin(), menuTimestamps.end(),
1249 PointerAssassin());
1250 menuTimestamps.clear();
1251
1252 gcCache()->purge();
1253
1254 std::for_each(screenList.begin(), screenList.end(),
1255 std::mem_fun(&BScreen::reconfigure));
1256 }
1257
1258
1259 void Blackbox::checkMenu(void) {
1260 bool reread = False;
1261 MenuTimestampList::iterator it = menuTimestamps.begin();
1262 for(; it != menuTimestamps.end(); ++it) {
1263 MenuTimestamp *tmp = *it;
1264 struct stat buf;
1265
1266 if (! stat(tmp->filename.c_str(), &buf)) {
1267 if (tmp->timestamp != buf.st_ctime)
1268 reread = True;
1269 } else {
1270 reread = True;
1271 }
1272 }
1273
1274 if (reread) rereadMenu();
1275 }
1276
1277
1278 void Blackbox::rereadMenu(void) {
1279 reread_menu_wait = True;
1280
1281 if (! timer->isTiming()) timer->start();
1282 }
1283
1284
1285 void Blackbox::real_rereadMenu(void) {
1286 std::for_each(menuTimestamps.begin(), menuTimestamps.end(),
1287 PointerAssassin());
1288 menuTimestamps.clear();
1289
1290 std::for_each(screenList.begin(), screenList.end(),
1291 std::mem_fun(&BScreen::rereadMenu));
1292 }
1293
1294
1295 void Blackbox::saveStyleFilename(const string& filename) {
1296 assert(! filename.empty());
1297 resource.style_file = filename;
1298 config.setValue("session.styleFile", resource.style_file);
1299 }
1300
1301
1302 void Blackbox::addMenuTimestamp(const string& filename) {
1303 assert(! filename.empty());
1304 bool found = False;
1305
1306 MenuTimestampList::iterator it = menuTimestamps.begin();
1307 for (; it != menuTimestamps.end() && ! found; ++it) {
1308 if ((*it)->filename == filename) found = True;
1309 }
1310 if (! found) {
1311 struct stat buf;
1312
1313 if (! stat(filename.c_str(), &buf)) {
1314 MenuTimestamp *ts = new MenuTimestamp;
1315
1316 ts->filename = filename;
1317 ts->timestamp = buf.st_ctime;
1318
1319 menuTimestamps.push_back(ts);
1320 }
1321 }
1322 }
1323
1324
1325 void Blackbox::timeout(void) {
1326 if (reconfigure_wait)
1327 real_reconfigure();
1328
1329 if (reread_menu_wait)
1330 real_rereadMenu();
1331
1332 reconfigure_wait = reread_menu_wait = False;
1333 }
1334
1335
1336 void Blackbox::setChangingWindow(BlackboxWindow *win) {
1337 // make sure one of the two is null and the other isn't
1338 assert((! changing_window && win) || (! win && changing_window));
1339 changing_window = win;
1340 }
1341
1342
1343 void Blackbox::setFocusedWindow(BlackboxWindow *win) {
1344 if (focused_window && focused_window == win) // nothing to do
1345 return;
1346
1347 BScreen *old_screen = 0;
1348
1349 if (focused_window) {
1350 focused_window->setFocusFlag(False);
1351 old_screen = focused_window->getScreen();
1352 }
1353
1354 if (win && ! win->isIconic()) {
1355 // the active screen is the one with the last focused window...
1356 // this will keep focus on this screen no matter where the mouse goes,
1357 // so multihead keybindings will continue to work on that screen until the
1358 // user focuses a window on a different screen.
1359 active_screen = win->getScreen();
1360 focused_window = win;
1361 } else {
1362 focused_window = 0;
1363 if (! old_screen) {
1364 if (active_screen) {
1365 // set input focus to the toolbar of the screen with mouse
1366 XSetInputFocus(getXDisplay(),
1367 active_screen->getRootWindow(),
1368 RevertToPointerRoot, CurrentTime);
1369 } else {
1370 // set input focus to the toolbar of the first managed screen
1371 XSetInputFocus(getXDisplay(),
1372 screenList.front()->getRootWindow(),
1373 RevertToPointerRoot, CurrentTime);
1374 }
1375 } else {
1376 // set input focus to the toolbar of the last screen
1377 XSetInputFocus(getXDisplay(), old_screen->getRootWindow(),
1378 RevertToPointerRoot, CurrentTime);
1379 }
1380 }
1381
1382 if (active_screen && active_screen->isScreenManaged()) {
1383 active_screen->getToolbar()->redrawWindowLabel(True);
1384 active_screen->updateNetizenWindowFocus();
1385 }
1386
1387 if (old_screen && old_screen != active_screen) {
1388 old_screen->getToolbar()->redrawWindowLabel(True);
1389 old_screen->updateNetizenWindowFocus();
1390 }
1391 }
This page took 0.107836 seconds and 5 git commands to generate.