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