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