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