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