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