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)
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:
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
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.
25 # include "../config.h"
26 #endif // HAVE_CONFIG_H
30 #include <X11/Xutil.h>
31 #include <X11/Xresource.h>
32 #include <X11/Xatom.h>
33 #include <X11/cursorfont.h>
34 #include <X11/keysym.h>
37 #include <X11/extensions/shape.h>
42 #endif // HAVE_STDIO_H
46 #endif // HAVE_STDLIB_H
50 #endif // HAVE_STRING_H
53 # include <sys/types.h>
55 #endif // HAVE_UNISTD_H
57 #ifdef HAVE_SYS_PARAM_H
58 # include <sys/param.h>
59 #endif // HAVE_SYS_PARAM_H
61 #ifdef HAVE_SYS_SELECT_H
62 # include <sys/select.h>
63 #endif // HAVE_SYS_SELECT_H
67 #endif // HAVE_SIGNAL_H
69 #ifdef HAVE_SYS_SIGNAL_H
70 # include <sys/signal.h>
71 #endif // HAVE_SYS_SIGNAL_H
73 #ifdef HAVE_SYS_STAT_H
74 # include <sys/types.h>
75 # include <sys/stat.h>
76 #endif // HAVE_SYS_STAT_H
78 #ifdef TIME_WITH_SYS_TIME
79 # include <sys/time.h>
81 #else // !TIME_WITH_SYS_TIME
82 # ifdef HAVE_SYS_TIME_H
83 # include <sys/time.h>
84 # else // !HAVE_SYS_TIME_H
86 # endif // HAVE_SYS_TIME_H
87 #endif // TIME_WITH_SYS_TIME
91 #endif // HAVE_LIBGEN_H
99 #include "blackbox.hh"
100 #include "Basemenu.hh"
101 #include "Clientmenu.hh"
102 #include "GCCache.hh"
104 #include "Rootmenu.hh"
107 #include "Toolbar.hh"
110 #include "Workspace.hh"
111 #include "Workspacemenu.hh"
114 // X event scanner for enter/leave notifies - adapted from twm
117 bool leave
, inferior
, enter
;
120 static Bool
queueScanner(Display
*, XEvent
*e
, char *args
) {
121 scanargs
*scan
= (scanargs
*) args
;
122 if ((e
->type
== LeaveNotify
) &&
123 (e
->xcrossing
.window
== scan
->w
) &&
124 (e
->xcrossing
.mode
== NotifyNormal
)) {
126 scan
->inferior
= (e
->xcrossing
.detail
== NotifyInferior
);
127 } else if ((e
->type
== EnterNotify
) && (e
->xcrossing
.mode
== NotifyUngrab
)) {
137 Blackbox::Blackbox(char **m_argv
, char *dpy_name
, char *rc
)
138 : BaseDisplay(m_argv
[0], dpy_name
) {
139 if (! XSupportsLocale())
140 fprintf(stderr
, "X server does not support locale\n");
142 if (XSetLocaleModifiers("") == NULL
)
143 fprintf(stderr
, "cannot set locale modifiers\n");
147 if (! rc
) rc
= "~/.blackboxrc";
148 rc_file
= expandTilde(rc
);
152 resource
.auto_raise_delay
.tv_sec
= resource
.auto_raise_delay
.tv_usec
= 0;
155 focused_window
= (BlackboxWindow
*) 0;
162 cursor
.session
= XCreateFontCursor(getXDisplay(), XC_left_ptr
);
163 cursor
.move
= XCreateFontCursor(getXDisplay(), XC_fleur
);
164 cursor
.ll_angle
= XCreateFontCursor(getXDisplay(), XC_ll_angle
);
165 cursor
.lr_angle
= XCreateFontCursor(getXDisplay(), XC_lr_angle
);
167 for (unsigned int i
= 0; i
< getNumberOfScreens(); i
++) {
168 BScreen
*screen
= new BScreen(this, i
);
170 if (! screen
->isScreenManaged()) {
175 screenList
.push_back(screen
);
178 if (screenList
.empty()) {
180 i18n(blackboxSet
, blackboxNoManagableScreens
,
181 "Blackbox::Blackbox: no managable screens found, aborting.\n"));
185 // set the screen with mouse to the first managed screen
186 active_screen
= screenList
.front();
189 XSynchronize(getXDisplay(), False
);
190 XSync(getXDisplay(), False
);
192 reconfigure_wait
= reread_menu_wait
= False
;
194 timer
= new BTimer(this, this);
195 timer
->setTimeout(0l);
199 Blackbox::~Blackbox(void) {
200 std::for_each(screenList
.begin(), screenList
.end(), PointerAssassin());
202 std::for_each(menuTimestamps
.begin(), menuTimestamps
.end(),
209 void Blackbox::process_event(XEvent
*e
) {
212 // strip the lock key modifiers
213 e
->xbutton
.state
&= ~(NumLockMask
| ScrollLockMask
| LockMask
);
215 last_time
= e
->xbutton
.time
;
217 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
218 Basemenu
*menu
= (Basemenu
*) 0;
219 Slit
*slit
= (Slit
*) 0;
220 Toolbar
*tbar
= (Toolbar
*) 0;
221 BScreen
*scrn
= (BScreen
*) 0;
223 if ((win
= searchWindow(e
->xbutton
.window
))) {
224 win
->buttonPressEvent(&e
->xbutton
);
226 /* XXX: is this sane on low colour desktops? */
227 if (e
->xbutton
.button
== 1)
228 win
->installColormap(True
);
229 } else if ((menu
= searchMenu(e
->xbutton
.window
))) {
230 menu
->buttonPressEvent(&e
->xbutton
);
231 } else if ((slit
= searchSlit(e
->xbutton
.window
))) {
232 slit
->buttonPressEvent(&e
->xbutton
);
233 } else if ((tbar
= searchToolbar(e
->xbutton
.window
))) {
234 tbar
->buttonPressEvent(&e
->xbutton
);
235 } else if ((scrn
= searchScreen(e
->xbutton
.window
))) {
236 scrn
->buttonPressEvent(&e
->xbutton
);
237 if (active_screen
!= scrn
) {
238 active_screen
= scrn
;
239 // first, set no focus window on the old screen
241 // and move focus to this screen
248 case ButtonRelease
: {
249 // strip the lock key modifiers
250 e
->xbutton
.state
&= ~(NumLockMask
| ScrollLockMask
| LockMask
);
252 last_time
= e
->xbutton
.time
;
254 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
255 Basemenu
*menu
= (Basemenu
*) 0;
256 Toolbar
*tbar
= (Toolbar
*) 0;
258 if ((win
= searchWindow(e
->xbutton
.window
)))
259 win
->buttonReleaseEvent(&e
->xbutton
);
260 else if ((menu
= searchMenu(e
->xbutton
.window
)))
261 menu
->buttonReleaseEvent(&e
->xbutton
);
262 else if ((tbar
= searchToolbar(e
->xbutton
.window
)))
263 tbar
->buttonReleaseEvent(&e
->xbutton
);
268 case ConfigureRequest
: {
269 // compress configure requests...
272 while(XCheckTypedWindowEvent(getXDisplay(), e
->xconfigurerequest
.window
,
273 ConfigureRequest
, &realevent
)) {
279 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
280 Slit
*slit
= (Slit
*) 0;
282 if ((win
= searchWindow(e
->xconfigurerequest
.window
))) {
283 win
->configureRequestEvent(&e
->xconfigurerequest
);
284 } else if ((slit
= searchSlit(e
->xconfigurerequest
.window
))) {
285 slit
->configureRequestEvent(&e
->xconfigurerequest
);
287 if (validateWindow(e
->xconfigurerequest
.window
)) {
290 xwc
.x
= e
->xconfigurerequest
.x
;
291 xwc
.y
= e
->xconfigurerequest
.y
;
292 xwc
.width
= e
->xconfigurerequest
.width
;
293 xwc
.height
= e
->xconfigurerequest
.height
;
294 xwc
.border_width
= e
->xconfigurerequest
.border_width
;
295 xwc
.sibling
= e
->xconfigurerequest
.above
;
296 xwc
.stack_mode
= e
->xconfigurerequest
.detail
;
298 XConfigureWindow(getXDisplay(), e
->xconfigurerequest
.window
,
299 e
->xconfigurerequest
.value_mask
, &xwc
);
308 fprintf(stderr
, "Blackbox::process_event(): MapRequest for 0x%lx\n",
309 e
->xmaprequest
.window
);
312 BlackboxWindow
*win
= searchWindow(e
->xmaprequest
.window
);
315 BScreen
*screen
= searchScreen(e
->xmaprequest
.parent
);
319 we got a map request for a window who's parent isn't root. this
320 can happen in only one circumstance:
322 a client window unmapped a managed window, and then remapped it
323 somewhere between unmapping the client window and reparenting it
326 regardless of how it happens, we need to find the screen that
329 XWindowAttributes wattrib
;
330 if (! XGetWindowAttributes(getXDisplay(), e
->xmaprequest
.window
,
332 // failed to get the window attributes, perhaps the window has
333 // now been destroyed?
337 screen
= searchScreen(wattrib
.root
);
338 assert(screen
!= 0); // this should never happen
341 screen
->manageWindow(e
->xmaprequest
.window
);
348 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
349 Slit
*slit
= (Slit
*) 0;
351 if ((win
= searchWindow(e
->xunmap
.window
))) {
352 win
->unmapNotifyEvent(&e
->xunmap
);
353 } else if ((slit
= searchSlit(e
->xunmap
.window
))) {
354 slit
->unmapNotifyEvent(&e
->xunmap
);
360 case DestroyNotify
: {
361 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
362 Slit
*slit
= (Slit
*) 0;
363 BWindowGroup
*group
= (BWindowGroup
*) 0;
365 if ((win
= searchWindow(e
->xdestroywindow
.window
))) {
366 win
->destroyNotifyEvent(&e
->xdestroywindow
);
367 } else if ((slit
= searchSlit(e
->xdestroywindow
.window
))) {
368 slit
->removeClient(e
->xdestroywindow
.window
, False
);
369 } else if ((group
= searchGroup(e
->xdestroywindow
.window
))) {
376 case ReparentNotify
: {
378 this event is quite rare and is usually handled in unmapNotify
379 however, if the window is unmapped when the reparent event occurs
380 the window manager never sees it because an unmap event is not sent
381 to an already unmapped window.
383 BlackboxWindow
*win
= searchWindow(e
->xreparent
.window
);
385 win
->reparentNotifyEvent(&e
->xreparent
);
387 Slit
*slit
= searchSlit(e
->xreparent
.window
);
388 if (slit
&& slit
->getWindowID() != e
->xreparent
.parent
)
389 slit
->removeClient(e
->xreparent
.window
, True
);
395 // motion notify compression...
398 while (XCheckTypedWindowEvent(getXDisplay(), e
->xmotion
.window
,
399 MotionNotify
, &realevent
)) {
403 // if we have compressed some motion events, use the last one
407 // strip the lock key modifiers
408 e
->xbutton
.state
&= ~(NumLockMask
| ScrollLockMask
| LockMask
);
410 last_time
= e
->xmotion
.time
;
412 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
413 Basemenu
*menu
= (Basemenu
*) 0;
415 if ((win
= searchWindow(e
->xmotion
.window
)))
416 win
->motionNotifyEvent(&e
->xmotion
);
417 else if ((menu
= searchMenu(e
->xmotion
.window
)))
418 menu
->motionNotifyEvent(&e
->xmotion
);
423 case PropertyNotify
: {
424 last_time
= e
->xproperty
.time
;
426 if (e
->xproperty
.state
!= PropertyDelete
) {
427 BlackboxWindow
*win
= searchWindow(e
->xproperty
.window
);
430 win
->propertyNotifyEvent(e
->xproperty
.atom
);
437 last_time
= e
->xcrossing
.time
;
439 BScreen
*screen
= (BScreen
*) 0;
440 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
441 Basemenu
*menu
= (Basemenu
*) 0;
442 Toolbar
*tbar
= (Toolbar
*) 0;
443 Slit
*slit
= (Slit
*) 0;
445 if (e
->xcrossing
.mode
== NotifyGrab
) break;
449 sa
.w
= e
->xcrossing
.window
;
450 sa
.enter
= sa
.leave
= False
;
451 XCheckIfEvent(getXDisplay(), &dummy
, queueScanner
, (char *) &sa
);
453 if ((e
->xcrossing
.window
== e
->xcrossing
.root
) &&
454 (screen
= searchScreen(e
->xcrossing
.window
))) {
455 screen
->getImageControl()->installRootColormap();
456 } else if ((win
= searchWindow(e
->xcrossing
.window
))) {
457 if (win
->getScreen()->isSloppyFocus() &&
458 (! win
->isFocused()) && (! no_focus
)) {
459 if (((! sa
.leave
) || sa
.inferior
) && win
->isVisible()) {
460 if (win
->setInputFocus())
461 win
->installColormap(True
); // XXX: shouldnt we honour no install?
464 } else if ((menu
= searchMenu(e
->xcrossing
.window
))) {
465 menu
->enterNotifyEvent(&e
->xcrossing
);
466 } else if ((tbar
= searchToolbar(e
->xcrossing
.window
))) {
467 tbar
->enterNotifyEvent(&e
->xcrossing
);
468 } else if ((slit
= searchSlit(e
->xcrossing
.window
))) {
469 slit
->enterNotifyEvent(&e
->xcrossing
);
475 last_time
= e
->xcrossing
.time
;
477 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
478 Basemenu
*menu
= (Basemenu
*) 0;
479 Toolbar
*tbar
= (Toolbar
*) 0;
480 Slit
*slit
= (Slit
*) 0;
482 if ((menu
= searchMenu(e
->xcrossing
.window
)))
483 menu
->leaveNotifyEvent(&e
->xcrossing
);
484 else if ((win
= searchWindow(e
->xcrossing
.window
)))
485 win
->installColormap(False
);
486 else if ((tbar
= searchToolbar(e
->xcrossing
.window
)))
487 tbar
->leaveNotifyEvent(&e
->xcrossing
);
488 else if ((slit
= searchSlit(e
->xcrossing
.window
)))
489 slit
->leaveNotifyEvent(&e
->xcrossing
);
494 // compress expose events
497 int ex1
, ey1
, ex2
, ey2
;
500 ex2
= ex1
+ e
->xexpose
.width
- 1;
501 ey2
= ey1
+ e
->xexpose
.height
- 1;
502 while (XCheckTypedWindowEvent(getXDisplay(), e
->xexpose
.window
,
503 Expose
, &realevent
)) {
507 ex1
= std::min(realevent
.xexpose
.x
, ex1
);
508 ey1
= std::min(realevent
.xexpose
.y
, ey1
);
509 ex2
= std::max(realevent
.xexpose
.x
+ realevent
.xexpose
.width
- 1, ex2
);
510 ey2
= std::max(realevent
.xexpose
.y
+ realevent
.xexpose
.height
- 1, ey2
);
515 // use the merged area
518 e
->xexpose
.width
= ex2
- ex1
+ 1;
519 e
->xexpose
.height
= ey2
- ey1
+ 1;
521 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
522 Basemenu
*menu
= (Basemenu
*) 0;
523 Toolbar
*tbar
= (Toolbar
*) 0;
525 if ((win
= searchWindow(e
->xexpose
.window
)))
526 win
->exposeEvent(&e
->xexpose
);
527 else if ((menu
= searchMenu(e
->xexpose
.window
)))
528 menu
->exposeEvent(&e
->xexpose
);
529 else if ((tbar
= searchToolbar(e
->xexpose
.window
)))
530 tbar
->exposeEvent(&e
->xexpose
);
536 Toolbar
*tbar
= searchToolbar(e
->xkey
.window
);
538 if (tbar
&& tbar
->isEditing())
539 tbar
->keyPressEvent(&e
->xkey
);
544 case ColormapNotify
: {
545 BScreen
*screen
= searchScreen(e
->xcolormap
.window
);
548 screen
->setRootColormapInstalled((e
->xcolormap
.state
==
549 ColormapInstalled
) ? True
: False
);
555 if (e
->xfocus
.detail
!= NotifyNonlinear
) {
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)
564 BlackboxWindow
*win
= searchWindow(e
->xfocus
.window
);
566 if (! win
->isFocused())
567 win
->setFocusFlag(True
);
570 set the event window to None. when the FocusOut event handler calls
571 this function recursively, it uses this as an indication that focus
572 has moved to a known window.
574 e
->xfocus
.window
= None
;
581 if (e
->xfocus
.detail
!= NotifyNonlinear
) {
583 don't process FocusOuts when:
584 2. the new focus window isn't an ancestor or inferior of the old
585 focus window (NotifyNonlinear)
590 BlackboxWindow
*win
= searchWindow(e
->xfocus
.window
);
591 if (win
&& win
->isFocused()) {
593 before we mark "win" as unfocused, we need to verify that focus is
594 going to a known location, is in a known location, or set focus
599 // don't check the current focus if FocusOut was generated during a grab
600 bool check_focus
= (e
->xfocus
.mode
== NotifyNormal
);
603 First, check if there is a pending FocusIn event waiting. if there
604 is, process it and determine if focus has moved to another window
605 (the FocusIn event handler sets the window in the event
606 structure to None to indicate this).
608 if (XCheckTypedEvent(getXDisplay(), FocusIn
, &event
)) {
610 process_event(&event
);
611 if (event
.xfocus
.window
== None
) {
619 Second, we query the X server for the current input focus.
620 to make sure that we keep a consistent state.
622 BlackboxWindow
*focus
;
625 XGetInputFocus(getXDisplay(), &w
, &revert
);
626 focus
= searchWindow(w
);
629 focus got from "win" to "focus" under some very strange
630 circumstances, and we need to make sure that the focus indication
633 setFocusedWindow(focus
);
635 // we have no idea where focus went... so we set it to somewhere
644 case ClientMessage
: {
645 if (e
->xclient
.format
== 32) {
646 if (e
->xclient
.message_type
== getWMChangeStateAtom()) {
647 BlackboxWindow
*win
= searchWindow(e
->xclient
.window
);
648 if (! win
|| ! win
->validateClient()) return;
650 if (e
->xclient
.data
.l
[0] == IconicState
)
652 if (e
->xclient
.data
.l
[0] == NormalState
)
654 } else if(e
->xclient
.message_type
== getBlackboxChangeWorkspaceAtom()) {
655 BScreen
*screen
= searchScreen(e
->xclient
.window
);
657 if (screen
&& e
->xclient
.data
.l
[0] >= 0 &&
658 e
->xclient
.data
.l
[0] <
659 static_cast<signed>(screen
->getWorkspaceCount()))
660 screen
->changeWorkspaceID(e
->xclient
.data
.l
[0]);
661 } else if (e
->xclient
.message_type
== getBlackboxChangeWindowFocusAtom()) {
662 BlackboxWindow
*win
= searchWindow(e
->xclient
.window
);
664 if (win
&& win
->isVisible() && win
->setInputFocus())
665 win
->installColormap(True
);
666 } else if (e
->xclient
.message_type
== getBlackboxCycleWindowFocusAtom()) {
667 BScreen
*screen
= searchScreen(e
->xclient
.window
);
670 if (! e
->xclient
.data
.l
[0])
675 } else if (e
->xclient
.message_type
== getBlackboxChangeAttributesAtom()) {
676 BlackboxWindow
*win
= searchWindow(e
->xclient
.window
);
678 if (win
&& win
->validateClient()) {
680 net
.flags
= e
->xclient
.data
.l
[0];
681 net
.attrib
= e
->xclient
.data
.l
[1];
682 net
.workspace
= e
->xclient
.data
.l
[2];
683 net
.stack
= e
->xclient
.data
.l
[3];
684 net
.decoration
= e
->xclient
.data
.l
[4];
686 win
->changeBlackboxHints(&net
);
695 case ConfigureNotify
:
697 break; // not handled, just ignore
701 if (e
->type
== getShapeEventBase()) {
702 XShapeEvent
*shape_event
= (XShapeEvent
*) e
;
703 BlackboxWindow
*win
= searchWindow(e
->xany
.window
);
706 win
->shapeEvent(shape_event
);
714 bool Blackbox::handleSignal(int sig
) {
743 void Blackbox::init_icccm(void) {
744 xa_wm_colormap_windows
=
745 XInternAtom(getXDisplay(), "WM_COLORMAP_WINDOWS", False
);
746 xa_wm_protocols
= XInternAtom(getXDisplay(), "WM_PROTOCOLS", False
);
747 xa_wm_state
= XInternAtom(getXDisplay(), "WM_STATE", False
);
748 xa_wm_change_state
= XInternAtom(getXDisplay(), "WM_CHANGE_STATE", False
);
749 xa_wm_delete_window
= XInternAtom(getXDisplay(), "WM_DELETE_WINDOW", False
);
750 xa_wm_take_focus
= XInternAtom(getXDisplay(), "WM_TAKE_FOCUS", False
);
751 motif_wm_hints
= XInternAtom(getXDisplay(), "_MOTIF_WM_HINTS", False
);
753 blackbox_hints
= XInternAtom(getXDisplay(), "_BLACKBOX_HINTS", False
);
754 blackbox_attributes
=
755 XInternAtom(getXDisplay(), "_BLACKBOX_ATTRIBUTES", False
);
756 blackbox_change_attributes
=
757 XInternAtom(getXDisplay(), "_BLACKBOX_CHANGE_ATTRIBUTES", False
);
758 blackbox_structure_messages
=
759 XInternAtom(getXDisplay(), "_BLACKBOX_STRUCTURE_MESSAGES", False
);
760 blackbox_notify_startup
=
761 XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_STARTUP", False
);
762 blackbox_notify_window_add
=
763 XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WINDOW_ADD", False
);
764 blackbox_notify_window_del
=
765 XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WINDOW_DEL", False
);
766 blackbox_notify_current_workspace
=
767 XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_CURRENT_WORKSPACE", False
);
768 blackbox_notify_workspace_count
=
769 XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WORKSPACE_COUNT", False
);
770 blackbox_notify_window_focus
=
771 XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WINDOW_FOCUS", False
);
772 blackbox_notify_window_raise
=
773 XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WINDOW_RAISE", False
);
774 blackbox_notify_window_lower
=
775 XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WINDOW_LOWER", False
);
776 blackbox_change_workspace
=
777 XInternAtom(getXDisplay(), "_BLACKBOX_CHANGE_WORKSPACE", False
);
778 blackbox_change_window_focus
=
779 XInternAtom(getXDisplay(), "_BLACKBOX_CHANGE_WINDOW_FOCUS", False
);
780 blackbox_cycle_window_focus
=
781 XInternAtom(getXDisplay(), "_BLACKBOX_CYCLE_WINDOW_FOCUS", False
);
784 net_supported
= XInternAtom(getXDisplay(), "_NET_SUPPORTED", False
);
785 net_client_list
= XInternAtom(getXDisplay(), "_NET_CLIENT_LIST", False
);
786 net_client_list_stacking
=
787 XInternAtom(getXDisplay(), "_NET_CLIENT_LIST_STACKING", False
);
788 net_number_of_desktops
=
789 XInternAtom(getXDisplay(), "_NET_NUMBER_OF_DESKTOPS", False
);
790 net_desktop_geometry
=
791 XInternAtom(getXDisplay(), "_NET_DESKTOP_GEOMETRY", False
);
792 net_desktop_viewport
=
793 XInternAtom(getXDisplay(), "_NET_DESKTOP_VIEWPORT", False
);
794 net_current_desktop
=
795 XInternAtom(getXDisplay(), "_NET_CURRENT_DESKTOP", False
);
796 net_desktop_names
= XInternAtom(getXDisplay(), "_NET_DESKTOP_NAMES", False
);
797 net_active_window
= XInternAtom(getXDisplay(), "_NET_ACTIVE_WINDOW", False
);
798 net_workarea
= XInternAtom(getXDisplay(), "_NET_WORKAREA", False
);
799 net_supporting_wm_check
=
800 XInternAtom(getXDisplay(), "_NET_SUPPORTING_WM_CHECK", False
);
801 net_virtual_roots
= XInternAtom(getXDisplay(), "_NET_VIRTUAL_ROOTS", False
);
802 net_close_window
= XInternAtom(getXDisplay(), "_NET_CLOSE_WINDOW", False
);
803 net_wm_moveresize
= XInternAtom(getXDisplay(), "_NET_WM_MOVERESIZE", False
);
804 net_properties
= XInternAtom(getXDisplay(), "_NET_PROPERTIES", False
);
805 net_wm_name
= XInternAtom(getXDisplay(), "_NET_WM_NAME", False
);
806 net_wm_desktop
= XInternAtom(getXDisplay(), "_NET_WM_DESKTOP", False
);
808 XInternAtom(getXDisplay(), "_NET_WM_WINDOW_TYPE", False
);
809 net_wm_state
= XInternAtom(getXDisplay(), "_NET_WM_STATE", False
);
810 net_wm_strut
= XInternAtom(getXDisplay(), "_NET_WM_STRUT", False
);
811 net_wm_icon_geometry
=
812 XInternAtom(getXDisplay(), "_NET_WM_ICON_GEOMETRY", False
);
813 net_wm_icon
= XInternAtom(getXDisplay(), "_NET_WM_ICON", False
);
814 net_wm_pid
= XInternAtom(getXDisplay(), "_NET_WM_PID", False
);
815 net_wm_handled_icons
=
816 XInternAtom(getXDisplay(), "_NET_WM_HANDLED_ICONS", False
);
817 net_wm_ping
= XInternAtom(getXDisplay(), "_NET_WM_PING", False
);
821 blackbox_pid
= XInternAtom(getXDisplay(), "_BLACKBOX_PID", False
);
822 #endif // HAVE_GETPID
826 bool Blackbox::validateWindow(Window window
) {
828 if (XCheckTypedWindowEvent(getXDisplay(), window
, DestroyNotify
, &event
)) {
829 XPutBackEvent(getXDisplay(), &event
);
838 BScreen
*Blackbox::searchScreen(Window window
) {
839 ScreenList::iterator it
= screenList
.begin();
841 for (; it
!= screenList
.end(); ++it
) {
843 if (s
->getRootWindow() == window
)
847 return (BScreen
*) 0;
851 BlackboxWindow
*Blackbox::searchWindow(Window window
) {
852 WindowLookup::iterator it
= windowSearchList
.find(window
);
853 if (it
!= windowSearchList
.end())
856 return (BlackboxWindow
*) 0;
860 BWindowGroup
*Blackbox::searchGroup(Window window
) {
861 GroupLookup::iterator it
= groupSearchList
.find(window
);
862 if (it
!= groupSearchList
.end())
865 return (BWindowGroup
*) 0;
869 Basemenu
*Blackbox::searchMenu(Window window
) {
870 MenuLookup::iterator it
= menuSearchList
.find(window
);
871 if (it
!= menuSearchList
.end())
874 return (Basemenu
*) 0;
878 Toolbar
*Blackbox::searchToolbar(Window window
) {
879 ToolbarLookup::iterator it
= toolbarSearchList
.find(window
);
880 if (it
!= toolbarSearchList
.end())
887 Slit
*Blackbox::searchSlit(Window window
) {
888 SlitLookup::iterator it
= slitSearchList
.find(window
);
889 if (it
!= slitSearchList
.end())
896 void Blackbox::saveWindowSearch(Window window
, BlackboxWindow
*data
) {
897 windowSearchList
.insert(WindowLookupPair(window
, data
));
901 void Blackbox::saveGroupSearch(Window window
, BWindowGroup
*data
) {
902 groupSearchList
.insert(GroupLookupPair(window
, data
));
906 void Blackbox::saveMenuSearch(Window window
, Basemenu
*data
) {
907 menuSearchList
.insert(MenuLookupPair(window
, data
));
911 void Blackbox::saveToolbarSearch(Window window
, Toolbar
*data
) {
912 toolbarSearchList
.insert(ToolbarLookupPair(window
, data
));
916 void Blackbox::saveSlitSearch(Window window
, Slit
*data
) {
917 slitSearchList
.insert(SlitLookupPair(window
, data
));
921 void Blackbox::removeWindowSearch(Window window
) {
922 windowSearchList
.erase(window
);
926 void Blackbox::removeGroupSearch(Window window
) {
927 groupSearchList
.erase(window
);
931 void Blackbox::removeMenuSearch(Window window
) {
932 menuSearchList
.erase(window
);
936 void Blackbox::removeToolbarSearch(Window window
) {
937 toolbarSearchList
.erase(window
);
941 void Blackbox::removeSlitSearch(Window window
) {
942 slitSearchList
.erase(window
);
946 void Blackbox::restart(const char *prog
) {
950 execlp(prog
, prog
, NULL
);
954 // fall back in case the above execlp doesn't work
955 execvp(argv
[0], argv
);
956 string name
= basename(argv
[0]);
957 execvp(name
.c_str(), argv
);
961 void Blackbox::shutdown(void) {
962 BaseDisplay::shutdown();
964 XSetInputFocus(getXDisplay(), PointerRoot
, None
, CurrentTime
);
966 std::for_each(screenList
.begin(), screenList
.end(),
967 std::mem_fun(&BScreen::shutdown
));
969 XSync(getXDisplay(), False
);
975 void Blackbox::save_rc(void) {
976 XrmDatabase new_blackboxrc
= (XrmDatabase
) 0;
977 char rc_string
[1024];
981 sprintf(rc_string
, "session.menuFile: %s", getMenuFilename());
982 XrmPutLineResource(&new_blackboxrc
, rc_string
);
984 sprintf(rc_string
, "session.colorsPerChannel: %d",
985 resource
.colors_per_channel
);
986 XrmPutLineResource(&new_blackboxrc
, rc_string
);
988 sprintf(rc_string
, "session.doubleClickInterval: %lu",
989 resource
.double_click_interval
);
990 XrmPutLineResource(&new_blackboxrc
, rc_string
);
992 sprintf(rc_string
, "session.autoRaiseDelay: %lu",
993 ((resource
.auto_raise_delay
.tv_sec
* 1000) +
994 (resource
.auto_raise_delay
.tv_usec
/ 1000)));
995 XrmPutLineResource(&new_blackboxrc
, rc_string
);
997 sprintf(rc_string
, "session.cacheLife: %lu", resource
.cache_life
/ 60000);
998 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1000 sprintf(rc_string
, "session.cacheMax: %lu", resource
.cache_max
);
1001 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1003 ScreenList::iterator it
= screenList
.begin();
1004 for (; it
!= screenList
.end(); ++it
) {
1005 BScreen
*screen
= *it
;
1006 int screen_number
= screen
->getScreenNumber();
1008 char *placement
= (char *) 0;
1010 switch (screen
->getSlitPlacement()) {
1011 case Slit::TopLeft
: placement
= "TopLeft"; break;
1012 case Slit::CenterLeft
: placement
= "CenterLeft"; break;
1013 case Slit::BottomLeft
: placement
= "BottomLeft"; break;
1014 case Slit::TopCenter
: placement
= "TopCenter"; break;
1015 case Slit::BottomCenter
: placement
= "BottomCenter"; break;
1016 case Slit::TopRight
: placement
= "TopRight"; break;
1017 case Slit::BottomRight
: placement
= "BottomRight"; break;
1018 case Slit::CenterRight
: default: placement
= "CenterRight"; break;
1021 sprintf(rc_string
, "session.screen%d.slit.placement: %s", screen_number
,
1023 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1025 sprintf(rc_string
, "session.screen%d.slit.direction: %s", screen_number
,
1026 ((screen
->getSlitDirection() == Slit::Horizontal
) ? "Horizontal" :
1028 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1030 sprintf(rc_string
, "session.screen%d.slit.onTop: %s", screen_number
,
1031 ((screen
->getSlit()->isOnTop()) ? "True" : "False"));
1032 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1034 sprintf(rc_string
, "session.screen%d.slit.autoHide: %s", screen_number
,
1035 ((screen
->getSlit()->doAutoHide()) ? "True" : "False"));
1036 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1038 sprintf(rc_string
, "session.opaqueMove: %s",
1039 ((screen
->doOpaqueMove()) ? "True" : "False"));
1040 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1042 sprintf(rc_string
, "session.imageDither: %s",
1043 ((screen
->getImageControl()->doDither()) ? "True" : "False"));
1044 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1046 sprintf(rc_string
, "session.screen%d.fullMaximization: %s", screen_number
,
1047 ((screen
->doFullMax()) ? "True" : "False"));
1048 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1050 sprintf(rc_string
, "session.screen%d.focusNewWindows: %s", screen_number
,
1051 ((screen
->doFocusNew()) ? "True" : "False"));
1052 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1054 sprintf(rc_string
, "session.screen%d.focusLastWindow: %s", screen_number
,
1055 ((screen
->doFocusLast()) ? "True" : "False"));
1056 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1058 sprintf(rc_string
, "session.screen%d.rowPlacementDirection: %s",
1060 ((screen
->getRowPlacementDirection() == BScreen::LeftRight
) ?
1061 "LeftToRight" : "RightToLeft"));
1062 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1064 sprintf(rc_string
, "session.screen%d.colPlacementDirection: %s",
1066 ((screen
->getColPlacementDirection() == BScreen::TopBottom
) ?
1067 "TopToBottom" : "BottomToTop"));
1068 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1070 switch (screen
->getPlacementPolicy()) {
1071 case BScreen::CascadePlacement
:
1072 placement
= "CascadePlacement";
1074 case BScreen::ColSmartPlacement
:
1075 placement
= "ColSmartPlacement";
1078 case BScreen::RowSmartPlacement
:
1080 placement
= "RowSmartPlacement";
1083 sprintf(rc_string
, "session.screen%d.windowPlacement: %s", screen_number
,
1085 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1088 if (screen
->isSloppyFocus()) {
1089 fmodel
= "SloppyFocus";
1090 if (screen
->doAutoRaise()) fmodel
+= " AutoRaise";
1091 if (screen
->doClickRaise()) fmodel
+= " ClickRaise";
1093 fmodel
= "ClickToFocus";
1095 sprintf(rc_string
, "session.screen%d.focusModel: %s", screen_number
,
1097 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1099 sprintf(rc_string
, "session.screen%d.workspaces: %d", screen_number
,
1100 screen
->getWorkspaceCount());
1101 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1103 sprintf(rc_string
, "session.screen%d.toolbar.onTop: %s", screen_number
,
1104 ((screen
->getToolbar()->isOnTop()) ? "True" : "False"));
1105 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1107 sprintf(rc_string
, "session.screen%d.toolbar.autoHide: %s",
1109 ((screen
->getToolbar()->doAutoHide()) ? "True" : "False"));
1110 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1112 switch (screen
->getToolbarPlacement()) {
1113 case Toolbar::TopLeft
: placement
= "TopLeft"; break;
1114 case Toolbar::BottomLeft
: placement
= "BottomLeft"; break;
1115 case Toolbar::TopCenter
: placement
= "TopCenter"; break;
1116 case Toolbar::TopRight
: placement
= "TopRight"; break;
1117 case Toolbar::BottomRight
: placement
= "BottomRight"; break;
1118 case Toolbar::BottomCenter
: default: placement
= "BottomCenter"; break;
1121 sprintf(rc_string
, "session.screen%d.toolbar.placement: %s",
1122 screen_number
, placement
);
1123 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1127 // these are static, but may not be saved in the users .blackboxrc,
1128 // writing these resources will allow the user to edit them at a later
1129 // time... but loading the defaults before saving allows us to rewrite the
1132 #ifdef HAVE_STRFTIME
1133 sprintf(rc_string
, "session.screen%d.strftimeFormat: %s", screen_number
,
1134 screen
->getStrftimeFormat());
1135 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1136 #else // !HAVE_STRFTIME
1137 sprintf(rc_string
, "session.screen%d.dateFormat: %s", screen_number
,
1138 ((screen
->getDateFormat() == B_EuropeanDate
) ?
1139 "European" : "American"));
1140 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1142 sprintf(rc_string
, "session.screen%d.clockFormat: %d", screen_number
,
1143 ((screen
->isClock24Hour()) ? 24 : 12));
1144 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1145 #endif // HAVE_STRFTIME
1147 sprintf(rc_string
, "session.screen%d.edgeSnapThreshold: %d",
1148 screen_number
, screen
->getEdgeSnapThreshold());
1149 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1151 sprintf(rc_string
, "session.screen%d.toolbar.widthPercent: %d",
1152 screen_number
, screen
->getToolbarWidthPercent());
1153 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1155 // write out the user's workspace names
1157 string save_string
= screen
->getWorkspace(0)->getName();
1158 for (unsigned int i
= 1; i
< screen
->getWorkspaceCount(); ++i
) {
1160 save_string
+= screen
->getWorkspace(i
)->getName();
1163 char *resource_string
= new char[save_string
.length() + 48];
1164 sprintf(resource_string
, "session.screen%d.workspaceNames: %s",
1165 screen_number
, save_string
.c_str());
1166 XrmPutLineResource(&new_blackboxrc
, resource_string
);
1168 delete [] resource_string
;
1171 XrmDatabase old_blackboxrc
= XrmGetFileDatabase(rc_file
.c_str());
1173 XrmMergeDatabases(new_blackboxrc
, &old_blackboxrc
);
1174 XrmPutFileDatabase(old_blackboxrc
, rc_file
.c_str());
1175 XrmDestroyDatabase(old_blackboxrc
);
1179 void Blackbox::load_rc(void) {
1180 XrmDatabase database
= (XrmDatabase
) 0;
1182 database
= XrmGetFileDatabase(rc_file
.c_str());
1187 unsigned long long_value
;
1189 if (XrmGetResource(database
, "session.menuFile", "Session.MenuFile",
1190 &value_type
, &value
)) {
1191 resource
.menu_file
= expandTilde(value
.addr
);
1193 resource
.menu_file
= DEFAULTMENU
;
1196 resource
.colors_per_channel
= 4;
1197 if (XrmGetResource(database
, "session.colorsPerChannel",
1198 "Session.ColorsPerChannel", &value_type
, &value
) &&
1199 sscanf(value
.addr
, "%d", &int_value
) == 1) {
1200 resource
.colors_per_channel
= int_value
;
1201 if (resource
.colors_per_channel
< 2) resource
.colors_per_channel
= 2;
1202 if (resource
.colors_per_channel
> 6) resource
.colors_per_channel
= 6;
1205 if (XrmGetResource(database
, "session.styleFile", "Session.StyleFile",
1206 &value_type
, &value
))
1207 resource
.style_file
= expandTilde(value
.addr
);
1209 resource
.style_file
= DEFAULTSTYLE
;
1211 resource
.double_click_interval
= 250;
1212 if (XrmGetResource(database
, "session.doubleClickInterval",
1213 "Session.DoubleClickInterval", &value_type
, &value
) &&
1214 sscanf(value
.addr
, "%lu", &long_value
) == 1) {
1215 resource
.double_click_interval
= long_value
;
1218 resource
.auto_raise_delay
.tv_usec
= 400;
1219 if (XrmGetResource(database
, "session.autoRaiseDelay",
1220 "Session.AutoRaiseDelay", &value_type
, &value
) &&
1221 sscanf(value
.addr
, "%lu", &long_value
) == 1) {
1222 resource
.auto_raise_delay
.tv_usec
= long_value
;
1225 resource
.auto_raise_delay
.tv_sec
= resource
.auto_raise_delay
.tv_usec
/ 1000;
1226 resource
.auto_raise_delay
.tv_usec
-=
1227 (resource
.auto_raise_delay
.tv_sec
* 1000);
1228 resource
.auto_raise_delay
.tv_usec
*= 1000;
1230 resource
.cache_life
= 5l;
1231 if (XrmGetResource(database
, "session.cacheLife", "Session.CacheLife",
1232 &value_type
, &value
) &&
1233 sscanf(value
.addr
, "%lu", &long_value
) == 1) {
1234 resource
.cache_life
= long_value
;
1236 resource
.cache_life
*= 60000;
1238 resource
.cache_max
= 200;
1239 if (XrmGetResource(database
, "session.cacheMax", "Session.CacheMax",
1240 &value_type
, &value
) &&
1241 sscanf(value
.addr
, "%lu", &long_value
) == 1) {
1242 resource
.cache_max
= long_value
;
1247 void Blackbox::load_rc(BScreen
*screen
) {
1248 XrmDatabase database
= (XrmDatabase
) 0;
1250 database
= XrmGetFileDatabase(rc_file
.c_str());
1253 char *value_type
, name_lookup
[1024], class_lookup
[1024];
1254 int screen_number
= screen
->getScreenNumber();
1257 sprintf(name_lookup
, "session.screen%d.fullMaximization", screen_number
);
1258 sprintf(class_lookup
, "Session.Screen%d.FullMaximization", screen_number
);
1259 screen
->saveFullMax(False
);
1260 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1262 ! strncasecmp(value
.addr
, "true", value
.size
)) {
1263 screen
->saveFullMax(True
);
1266 sprintf(name_lookup
, "session.screen%d.focusNewWindows", screen_number
);
1267 sprintf(class_lookup
, "Session.Screen%d.FocusNewWindows", screen_number
);
1268 screen
->saveFocusNew(False
);
1269 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1271 ! strncasecmp(value
.addr
, "true", value
.size
)) {
1272 screen
->saveFocusNew(True
);
1275 sprintf(name_lookup
, "session.screen%d.focusLastWindow", screen_number
);
1276 sprintf(class_lookup
, "Session.Screen%d.focusLastWindow", screen_number
);
1277 screen
->saveFocusLast(False
);
1278 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1280 ! strncasecmp(value
.addr
, "true", value
.size
)) {
1281 screen
->saveFocusLast(True
);
1284 sprintf(name_lookup
, "session.screen%d.rowPlacementDirection",
1286 sprintf(class_lookup
, "Session.Screen%d.RowPlacementDirection",
1288 screen
->saveRowPlacementDirection(BScreen::LeftRight
);
1289 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1291 ! strncasecmp(value
.addr
, "righttoleft", value
.size
)) {
1292 screen
->saveRowPlacementDirection(BScreen::RightLeft
);
1295 sprintf(name_lookup
, "session.screen%d.colPlacementDirection",
1297 sprintf(class_lookup
, "Session.Screen%d.ColPlacementDirection",
1299 screen
->saveColPlacementDirection(BScreen::TopBottom
);
1300 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1302 ! strncasecmp(value
.addr
, "bottomtotop", value
.size
)) {
1303 screen
->saveColPlacementDirection(BScreen::BottomTop
);
1306 sprintf(name_lookup
, "session.screen%d.workspaces", screen_number
);
1307 sprintf(class_lookup
, "Session.Screen%d.Workspaces", screen_number
);
1308 screen
->saveWorkspaces(1);
1309 if (XrmGetResource(database
, name_lookup
, class_lookup
,
1310 &value_type
, &value
) &&
1311 sscanf(value
.addr
, "%d", &int_value
) == 1 &&
1312 int_value
> 0 && int_value
< 128) {
1313 screen
->saveWorkspaces(int_value
);
1316 sprintf(name_lookup
, "session.screen%d.toolbar.widthPercent",
1318 sprintf(class_lookup
, "Session.Screen%d.Toolbar.WidthPercent",
1320 screen
->saveToolbarWidthPercent(66);
1321 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1323 sscanf(value
.addr
, "%d", &int_value
) == 1 &&
1324 int_value
> 0 && int_value
<= 100) {
1325 screen
->saveToolbarWidthPercent(int_value
);
1328 sprintf(name_lookup
, "session.screen%d.toolbar.placement", screen_number
);
1329 sprintf(class_lookup
, "Session.Screen%d.Toolbar.Placement", screen_number
);
1330 screen
->saveToolbarPlacement(Toolbar::BottomCenter
);
1331 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1333 if (! strncasecmp(value
.addr
, "TopLeft", value
.size
))
1334 screen
->saveToolbarPlacement(Toolbar::TopLeft
);
1335 else if (! strncasecmp(value
.addr
, "BottomLeft", value
.size
))
1336 screen
->saveToolbarPlacement(Toolbar::BottomLeft
);
1337 else if (! strncasecmp(value
.addr
, "TopCenter", value
.size
))
1338 screen
->saveToolbarPlacement(Toolbar::TopCenter
);
1339 else if (! strncasecmp(value
.addr
, "TopRight", value
.size
))
1340 screen
->saveToolbarPlacement(Toolbar::TopRight
);
1341 else if (! strncasecmp(value
.addr
, "BottomRight", value
.size
))
1342 screen
->saveToolbarPlacement(Toolbar::BottomRight
);
1344 screen
->removeWorkspaceNames();
1346 sprintf(name_lookup
, "session.screen%d.workspaceNames", screen_number
);
1347 sprintf(class_lookup
, "Session.Screen%d.WorkspaceNames", screen_number
);
1348 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1350 string search
= value
.addr
;
1351 string::const_iterator it
= search
.begin(),
1354 string::const_iterator tmp
= it
; // current string.begin()
1355 it
= std::find(tmp
, end
, ','); // look for comma between tmp and end
1356 screen
->addWorkspaceName(string(tmp
, it
)); // string = search[tmp:it]
1357 if (it
== end
) break;
1362 sprintf(name_lookup
, "session.screen%d.toolbar.onTop", screen_number
);
1363 sprintf(class_lookup
, "Session.Screen%d.Toolbar.OnTop", screen_number
);
1364 screen
->saveToolbarOnTop(False
);
1365 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1367 ! strncasecmp(value
.addr
, "true", value
.size
)) {
1368 screen
->saveToolbarOnTop(True
);
1371 sprintf(name_lookup
, "session.screen%d.toolbar.autoHide", screen_number
);
1372 sprintf(class_lookup
, "Session.Screen%d.Toolbar.autoHide", screen_number
);
1373 screen
->saveToolbarAutoHide(False
);
1374 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1376 ! strncasecmp(value
.addr
, "true", value
.size
)) {
1377 screen
->saveToolbarAutoHide(True
);
1380 sprintf(name_lookup
, "session.screen%d.focusModel", screen_number
);
1381 sprintf(class_lookup
, "Session.Screen%d.FocusModel", screen_number
);
1382 screen
->saveSloppyFocus(True
);
1383 screen
->saveAutoRaise(False
);
1384 screen
->saveClickRaise(False
);
1385 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1387 string fmodel
= value
.addr
;
1389 if (fmodel
.find("ClickToFocus") != string::npos
) {
1390 screen
->saveSloppyFocus(False
);
1394 if (fmodel
.find("AutoRaise") != string::npos
)
1395 screen
->saveAutoRaise(True
);
1396 if (fmodel
.find("ClickRaise") != string::npos
)
1397 screen
->saveClickRaise(True
);
1401 sprintf(name_lookup
, "session.screen%d.windowPlacement", screen_number
);
1402 sprintf(class_lookup
, "Session.Screen%d.WindowPlacement", screen_number
);
1403 screen
->savePlacementPolicy(BScreen::RowSmartPlacement
);
1404 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1406 if (! strncasecmp(value
.addr
, "RowSmartPlacement", value
.size
))
1408 else if (! strncasecmp(value
.addr
, "ColSmartPlacement", value
.size
))
1409 screen
->savePlacementPolicy(BScreen::ColSmartPlacement
);
1410 else if (! strncasecmp(value
.addr
, "CascadePlacement", value
.size
))
1411 screen
->savePlacementPolicy(BScreen::CascadePlacement
);
1414 sprintf(name_lookup
, "session.screen%d.slit.placement", screen_number
);
1415 sprintf(class_lookup
, "Session.Screen%d.Slit.Placement", screen_number
);
1416 screen
->saveSlitPlacement(Slit::CenterRight
);
1417 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1419 if (! strncasecmp(value
.addr
, "TopLeft", value
.size
))
1420 screen
->saveSlitPlacement(Slit::TopLeft
);
1421 else if (! strncasecmp(value
.addr
, "CenterLeft", value
.size
))
1422 screen
->saveSlitPlacement(Slit::CenterLeft
);
1423 else if (! strncasecmp(value
.addr
, "BottomLeft", value
.size
))
1424 screen
->saveSlitPlacement(Slit::BottomLeft
);
1425 else if (! strncasecmp(value
.addr
, "TopCenter", value
.size
))
1426 screen
->saveSlitPlacement(Slit::TopCenter
);
1427 else if (! strncasecmp(value
.addr
, "BottomCenter", value
.size
))
1428 screen
->saveSlitPlacement(Slit::BottomCenter
);
1429 else if (! strncasecmp(value
.addr
, "TopRight", value
.size
))
1430 screen
->saveSlitPlacement(Slit::TopRight
);
1431 else if (! strncasecmp(value
.addr
, "BottomRight", value
.size
))
1432 screen
->saveSlitPlacement(Slit::BottomRight
);
1435 sprintf(name_lookup
, "session.screen%d.slit.direction", screen_number
);
1436 sprintf(class_lookup
, "Session.Screen%d.Slit.Direction", screen_number
);
1437 screen
->saveSlitDirection(Slit::Vertical
);
1438 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1440 ! strncasecmp(value
.addr
, "Horizontal", value
.size
)) {
1441 screen
->saveSlitDirection(Slit::Horizontal
);
1444 sprintf(name_lookup
, "session.screen%d.slit.onTop", screen_number
);
1445 sprintf(class_lookup
, "Session.Screen%d.Slit.OnTop", screen_number
);
1446 screen
->saveSlitOnTop(False
);
1447 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1449 ! strncasecmp(value
.addr
, "True", value
.size
)) {
1450 screen
->saveSlitOnTop(True
);
1453 sprintf(name_lookup
, "session.screen%d.slit.autoHide", screen_number
);
1454 sprintf(class_lookup
, "Session.Screen%d.Slit.AutoHide", screen_number
);
1455 screen
->saveSlitAutoHide(False
);
1456 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1458 ! strncasecmp(value
.addr
, "true", value
.size
)) {
1459 screen
->saveSlitAutoHide(True
);
1462 #ifdef HAVE_STRFTIME
1463 sprintf(name_lookup
, "session.screen%d.strftimeFormat", screen_number
);
1464 sprintf(class_lookup
, "Session.Screen%d.StrftimeFormat", screen_number
);
1465 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1467 screen
->saveStrftimeFormat(value
.addr
);
1469 screen
->saveStrftimeFormat("%I:%M %p");
1471 #else // HAVE_STRFTIME
1472 sprintf(name_lookup
, "session.screen%d.dateFormat", screen_number
);
1473 sprintf(class_lookup
, "Session.Screen%d.DateFormat", screen_number
);
1474 screen
->saveDateFormat(B_AmericanDate
);
1475 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1477 if (! strncasecmp(value
.addr
, "european", value
.size
))
1478 screen
->saveDateFormat(B_EuropeanDate
);
1481 sprintf(name_lookup
, "session.screen%d.clockFormat", screen_number
);
1482 sprintf(class_lookup
, "Session.Screen%d.ClockFormat", screen_number
);
1483 screen
->saveClock24Hour(False
);
1484 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1486 sscanf(value
.addr
, "%d", &int_value
) == 1 && int_value
== 24) {
1487 screen
->saveClock24Hour(True
);
1489 #endif // HAVE_STRFTIME
1491 sprintf(name_lookup
, "session.screen%d.edgeSnapThreshold", screen_number
);
1492 sprintf(class_lookup
, "Session.Screen%d.EdgeSnapThreshold", screen_number
);
1493 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1495 sscanf(value
.addr
, "%d", &int_value
) == 1) {
1496 screen
->saveEdgeSnapThreshold(int_value
);
1499 screen
->saveImageDither(True
);
1500 if (XrmGetResource(database
, "session.imageDither", "Session.ImageDither",
1501 &value_type
, &value
) &&
1502 ! strncasecmp("false", value
.addr
, value
.size
)) {
1503 screen
->saveImageDither(False
);
1506 screen
->saveOpaqueMove(False
);
1507 if (XrmGetResource(database
, "session.opaqueMove", "Session.OpaqueMove",
1508 &value_type
, &value
) &&
1509 ! strncasecmp("true", value
.addr
, value
.size
)) {
1510 screen
->saveOpaqueMove(True
);
1513 XrmDestroyDatabase(database
);
1517 void Blackbox::reload_rc(void) {
1523 void Blackbox::reconfigure(void) {
1524 reconfigure_wait
= True
;
1526 if (! timer
->isTiming()) timer
->start();
1530 void Blackbox::real_reconfigure(void) {
1531 XrmDatabase new_blackboxrc
= (XrmDatabase
) 0;
1532 char *style
= new char[resource
.style_file
.length() + 20];
1534 sprintf(style
, "session.styleFile: %s", getStyleFilename());
1535 XrmPutLineResource(&new_blackboxrc
, style
);
1539 XrmDatabase old_blackboxrc
= XrmGetFileDatabase(rc_file
.c_str());
1541 XrmMergeDatabases(new_blackboxrc
, &old_blackboxrc
);
1542 XrmPutFileDatabase(old_blackboxrc
, rc_file
.c_str());
1543 if (old_blackboxrc
) XrmDestroyDatabase(old_blackboxrc
);
1545 std::for_each(menuTimestamps
.begin(), menuTimestamps
.end(),
1547 menuTimestamps
.clear();
1551 std::for_each(screenList
.begin(), screenList
.end(),
1552 std::mem_fun(&BScreen::reconfigure
));
1556 void Blackbox::checkMenu(void) {
1557 bool reread
= False
;
1558 MenuTimestampList::iterator it
= menuTimestamps
.begin();
1559 for(; it
!= menuTimestamps
.end(); ++it
) {
1560 MenuTimestamp
*tmp
= *it
;
1563 if (! stat(tmp
->filename
.c_str(), &buf
)) {
1564 if (tmp
->timestamp
!= buf
.st_ctime
)
1571 if (reread
) rereadMenu();
1575 void Blackbox::rereadMenu(void) {
1576 reread_menu_wait
= True
;
1578 if (! timer
->isTiming()) timer
->start();
1582 void Blackbox::real_rereadMenu(void) {
1583 std::for_each(menuTimestamps
.begin(), menuTimestamps
.end(),
1585 menuTimestamps
.clear();
1587 std::for_each(screenList
.begin(), screenList
.end(),
1588 std::mem_fun(&BScreen::rereadMenu
));
1592 void Blackbox::saveStyleFilename(const string
& filename
) {
1593 assert(! filename
.empty());
1594 resource
.style_file
= filename
;
1598 void Blackbox::saveMenuFilename(const string
& filename
) {
1599 assert(! filename
.empty());
1602 MenuTimestampList::iterator it
= menuTimestamps
.begin();
1603 for (; it
!= menuTimestamps
.end() && !found
; ++it
) {
1604 if ((*it
)->filename
== filename
) found
= True
;
1609 if (! stat(filename
.c_str(), &buf
)) {
1610 MenuTimestamp
*ts
= new MenuTimestamp
;
1612 ts
->filename
= filename
;
1613 ts
->timestamp
= buf
.st_ctime
;
1615 menuTimestamps
.push_back(ts
);
1621 void Blackbox::timeout(void) {
1622 if (reconfigure_wait
)
1625 if (reread_menu_wait
)
1628 reconfigure_wait
= reread_menu_wait
= False
;
1632 void Blackbox::setFocusedWindow(BlackboxWindow
*win
) {
1633 if (focused_window
&& focused_window
== win
) // nothing to do
1636 BScreen
*old_screen
= 0;
1638 if (focused_window
) {
1639 focused_window
->setFocusFlag(False
);
1640 old_screen
= focused_window
->getScreen();
1643 if (win
&& ! win
->isIconic()) {
1644 // the active screen is the one with the last focused window...
1645 // this will keep focus on this screen no matter where the mouse goes,
1646 // so multihead keybindings will continue to work on that screen until the
1647 // user focuses a window on a different screen.
1648 active_screen
= win
->getScreen();
1649 focused_window
= win
;
1653 if (active_screen
) {
1654 // set input focus to the toolbar of the screen with mouse
1655 XSetInputFocus(getXDisplay(),
1656 active_screen
->getToolbar()->getWindowID(),
1657 RevertToPointerRoot
, CurrentTime
);
1659 // set input focus to the toolbar of the first managed screen
1660 XSetInputFocus(getXDisplay(),
1661 screenList
.front()->getToolbar()->getWindowID(),
1662 RevertToPointerRoot
, CurrentTime
);
1665 // set input focus to the toolbar of the last screen
1666 XSetInputFocus(getXDisplay(), old_screen
->getToolbar()->getWindowID(),
1667 RevertToPointerRoot
, CurrentTime
);
1671 if (active_screen
&& active_screen
->isScreenManaged()) {
1672 active_screen
->getToolbar()->redrawWindowLabel(True
);
1673 active_screen
->updateNetizenWindowFocus();
1676 if (old_screen
&& old_screen
!= active_screen
) {
1677 old_screen
->getToolbar()->redrawWindowLabel(True
);
1678 old_screen
->updateNetizenWindowFocus();