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