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