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
, char *menu
)
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
= "~/.openbox/rc";
148 rc_file
= expandTilde(rc
);
149 if (! menu
) menu
= "~/.openbox/menu";
150 menu_file
= expandTilde(menu
);
154 resource
.auto_raise_delay
.tv_sec
= resource
.auto_raise_delay
.tv_usec
= 0;
157 focused_window
= (BlackboxWindow
*) 0;
164 cursor
.session
= XCreateFontCursor(getXDisplay(), XC_left_ptr
);
165 cursor
.move
= XCreateFontCursor(getXDisplay(), XC_fleur
);
166 cursor
.ll_angle
= XCreateFontCursor(getXDisplay(), XC_ll_angle
);
167 cursor
.lr_angle
= XCreateFontCursor(getXDisplay(), XC_lr_angle
);
169 for (unsigned int i
= 0; i
< getNumberOfScreens(); i
++) {
170 BScreen
*screen
= new BScreen(this, i
);
172 if (! screen
->isScreenManaged()) {
177 screenList
.push_back(screen
);
180 if (screenList
.empty()) {
182 i18n(blackboxSet
, blackboxNoManagableScreens
,
183 "Blackbox::Blackbox: no managable screens found, aborting.\n"));
187 // set the screen with mouse to the first managed screen
188 active_screen
= screenList
.front();
191 XSynchronize(getXDisplay(), False
);
192 XSync(getXDisplay(), False
);
194 reconfigure_wait
= reread_menu_wait
= False
;
196 timer
= new BTimer(this, this);
197 timer
->setTimeout(0l);
201 Blackbox::~Blackbox(void) {
202 std::for_each(screenList
.begin(), screenList
.end(), PointerAssassin());
204 std::for_each(menuTimestamps
.begin(), menuTimestamps
.end(),
211 void Blackbox::process_event(XEvent
*e
) {
214 // strip the lock key modifiers
215 e
->xbutton
.state
&= ~(NumLockMask
| ScrollLockMask
| LockMask
);
217 last_time
= e
->xbutton
.time
;
219 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
220 Basemenu
*menu
= (Basemenu
*) 0;
221 Slit
*slit
= (Slit
*) 0;
222 Toolbar
*tbar
= (Toolbar
*) 0;
223 BScreen
*scrn
= (BScreen
*) 0;
225 if ((win
= searchWindow(e
->xbutton
.window
))) {
226 win
->buttonPressEvent(&e
->xbutton
);
228 /* XXX: is this sane on low colour desktops? */
229 if (e
->xbutton
.button
== 1)
230 win
->installColormap(True
);
231 } else if ((menu
= searchMenu(e
->xbutton
.window
))) {
232 menu
->buttonPressEvent(&e
->xbutton
);
233 } else if ((slit
= searchSlit(e
->xbutton
.window
))) {
234 slit
->buttonPressEvent(&e
->xbutton
);
235 } else if ((tbar
= searchToolbar(e
->xbutton
.window
))) {
236 tbar
->buttonPressEvent(&e
->xbutton
);
237 } else if ((scrn
= searchScreen(e
->xbutton
.window
))) {
238 scrn
->buttonPressEvent(&e
->xbutton
);
239 if (active_screen
!= scrn
) {
240 active_screen
= scrn
;
241 // first, set no focus window on the old screen
243 // and move focus to this screen
250 case ButtonRelease
: {
251 // strip the lock key modifiers
252 e
->xbutton
.state
&= ~(NumLockMask
| ScrollLockMask
| LockMask
);
254 last_time
= e
->xbutton
.time
;
256 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
257 Basemenu
*menu
= (Basemenu
*) 0;
258 Toolbar
*tbar
= (Toolbar
*) 0;
260 if ((win
= searchWindow(e
->xbutton
.window
)))
261 win
->buttonReleaseEvent(&e
->xbutton
);
262 else if ((menu
= searchMenu(e
->xbutton
.window
)))
263 menu
->buttonReleaseEvent(&e
->xbutton
);
264 else if ((tbar
= searchToolbar(e
->xbutton
.window
)))
265 tbar
->buttonReleaseEvent(&e
->xbutton
);
270 case ConfigureRequest
: {
271 // compress configure requests...
274 while(XCheckTypedWindowEvent(getXDisplay(), e
->xconfigurerequest
.window
,
275 ConfigureRequest
, &realevent
)) {
281 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
282 Slit
*slit
= (Slit
*) 0;
284 if ((win
= searchWindow(e
->xconfigurerequest
.window
))) {
285 win
->configureRequestEvent(&e
->xconfigurerequest
);
286 } else if ((slit
= searchSlit(e
->xconfigurerequest
.window
))) {
287 slit
->configureRequestEvent(&e
->xconfigurerequest
);
289 if (validateWindow(e
->xconfigurerequest
.window
)) {
292 xwc
.x
= e
->xconfigurerequest
.x
;
293 xwc
.y
= e
->xconfigurerequest
.y
;
294 xwc
.width
= e
->xconfigurerequest
.width
;
295 xwc
.height
= e
->xconfigurerequest
.height
;
296 xwc
.border_width
= e
->xconfigurerequest
.border_width
;
297 xwc
.sibling
= e
->xconfigurerequest
.above
;
298 xwc
.stack_mode
= e
->xconfigurerequest
.detail
;
300 XConfigureWindow(getXDisplay(), e
->xconfigurerequest
.window
,
301 e
->xconfigurerequest
.value_mask
, &xwc
);
310 fprintf(stderr
, "Blackbox::process_event(): MapRequest for 0x%lx\n",
311 e
->xmaprequest
.window
);
314 BlackboxWindow
*win
= searchWindow(e
->xmaprequest
.window
);
317 BScreen
*screen
= searchScreen(e
->xmaprequest
.parent
);
321 we got a map request for a window who's parent isn't root. this
322 can happen in only one circumstance:
324 a client window unmapped a managed window, and then remapped it
325 somewhere between unmapping the client window and reparenting it
328 regardless of how it happens, we need to find the screen that
331 XWindowAttributes wattrib
;
332 if (! XGetWindowAttributes(getXDisplay(), e
->xmaprequest
.window
,
334 // failed to get the window attributes, perhaps the window has
335 // now been destroyed?
339 screen
= searchScreen(wattrib
.root
);
340 assert(screen
!= 0); // this should never happen
343 screen
->manageWindow(e
->xmaprequest
.window
);
350 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
351 Slit
*slit
= (Slit
*) 0;
353 if ((win
= searchWindow(e
->xunmap
.window
))) {
354 win
->unmapNotifyEvent(&e
->xunmap
);
355 } else if ((slit
= searchSlit(e
->xunmap
.window
))) {
356 slit
->unmapNotifyEvent(&e
->xunmap
);
362 case DestroyNotify
: {
363 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
364 Slit
*slit
= (Slit
*) 0;
365 BWindowGroup
*group
= (BWindowGroup
*) 0;
367 if ((win
= searchWindow(e
->xdestroywindow
.window
))) {
368 win
->destroyNotifyEvent(&e
->xdestroywindow
);
369 } else if ((slit
= searchSlit(e
->xdestroywindow
.window
))) {
370 slit
->removeClient(e
->xdestroywindow
.window
, False
);
371 } else if ((group
= searchGroup(e
->xdestroywindow
.window
))) {
378 case ReparentNotify
: {
380 this event is quite rare and is usually handled in unmapNotify
381 however, if the window is unmapped when the reparent event occurs
382 the window manager never sees it because an unmap event is not sent
383 to an already unmapped window.
385 BlackboxWindow
*win
= searchWindow(e
->xreparent
.window
);
387 win
->reparentNotifyEvent(&e
->xreparent
);
389 Slit
*slit
= searchSlit(e
->xreparent
.window
);
390 if (slit
&& slit
->getWindowID() != e
->xreparent
.parent
)
391 slit
->removeClient(e
->xreparent
.window
, True
);
397 // motion notify compression...
400 while (XCheckTypedWindowEvent(getXDisplay(), e
->xmotion
.window
,
401 MotionNotify
, &realevent
)) {
405 // if we have compressed some motion events, use the last one
409 // strip the lock key modifiers
410 e
->xbutton
.state
&= ~(NumLockMask
| ScrollLockMask
| LockMask
);
412 last_time
= e
->xmotion
.time
;
414 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
415 Basemenu
*menu
= (Basemenu
*) 0;
417 if ((win
= searchWindow(e
->xmotion
.window
)))
418 win
->motionNotifyEvent(&e
->xmotion
);
419 else if ((menu
= searchMenu(e
->xmotion
.window
)))
420 menu
->motionNotifyEvent(&e
->xmotion
);
425 case PropertyNotify
: {
426 last_time
= e
->xproperty
.time
;
428 if (e
->xproperty
.state
!= PropertyDelete
) {
429 BlackboxWindow
*win
= searchWindow(e
->xproperty
.window
);
432 win
->propertyNotifyEvent(e
->xproperty
.atom
);
439 last_time
= e
->xcrossing
.time
;
441 BScreen
*screen
= (BScreen
*) 0;
442 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
443 Basemenu
*menu
= (Basemenu
*) 0;
444 Toolbar
*tbar
= (Toolbar
*) 0;
445 Slit
*slit
= (Slit
*) 0;
447 if (e
->xcrossing
.mode
== NotifyGrab
) break;
451 sa
.w
= e
->xcrossing
.window
;
452 sa
.enter
= sa
.leave
= False
;
453 XCheckIfEvent(getXDisplay(), &dummy
, queueScanner
, (char *) &sa
);
455 if ((e
->xcrossing
.window
== e
->xcrossing
.root
) &&
456 (screen
= searchScreen(e
->xcrossing
.window
))) {
457 screen
->getImageControl()->installRootColormap();
458 } else if ((win
= searchWindow(e
->xcrossing
.window
))) {
459 if (win
->getScreen()->isSloppyFocus() &&
460 (! win
->isFocused()) && (! no_focus
)) {
461 if (((! sa
.leave
) || sa
.inferior
) && win
->isVisible()) {
462 if (win
->setInputFocus())
463 win
->installColormap(True
); // XXX: shouldnt we honour no install?
466 } else if ((menu
= searchMenu(e
->xcrossing
.window
))) {
467 menu
->enterNotifyEvent(&e
->xcrossing
);
468 } else if ((tbar
= searchToolbar(e
->xcrossing
.window
))) {
469 tbar
->enterNotifyEvent(&e
->xcrossing
);
470 } else if ((slit
= searchSlit(e
->xcrossing
.window
))) {
471 slit
->enterNotifyEvent(&e
->xcrossing
);
477 last_time
= e
->xcrossing
.time
;
479 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
480 Basemenu
*menu
= (Basemenu
*) 0;
481 Toolbar
*tbar
= (Toolbar
*) 0;
482 Slit
*slit
= (Slit
*) 0;
484 if ((menu
= searchMenu(e
->xcrossing
.window
)))
485 menu
->leaveNotifyEvent(&e
->xcrossing
);
486 else if ((win
= searchWindow(e
->xcrossing
.window
)))
487 win
->installColormap(False
);
488 else if ((tbar
= searchToolbar(e
->xcrossing
.window
)))
489 tbar
->leaveNotifyEvent(&e
->xcrossing
);
490 else if ((slit
= searchSlit(e
->xcrossing
.window
)))
491 slit
->leaveNotifyEvent(&e
->xcrossing
);
496 // compress expose events
499 int ex1
, ey1
, ex2
, ey2
;
502 ex2
= ex1
+ e
->xexpose
.width
- 1;
503 ey2
= ey1
+ e
->xexpose
.height
- 1;
504 while (XCheckTypedWindowEvent(getXDisplay(), e
->xexpose
.window
,
505 Expose
, &realevent
)) {
509 ex1
= std::min(realevent
.xexpose
.x
, ex1
);
510 ey1
= std::min(realevent
.xexpose
.y
, ey1
);
511 ex2
= std::max(realevent
.xexpose
.x
+ realevent
.xexpose
.width
- 1, ex2
);
512 ey2
= std::max(realevent
.xexpose
.y
+ realevent
.xexpose
.height
- 1, ey2
);
517 // use the merged area
520 e
->xexpose
.width
= ex2
- ex1
+ 1;
521 e
->xexpose
.height
= ey2
- ey1
+ 1;
523 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
524 Basemenu
*menu
= (Basemenu
*) 0;
525 Toolbar
*tbar
= (Toolbar
*) 0;
527 if ((win
= searchWindow(e
->xexpose
.window
)))
528 win
->exposeEvent(&e
->xexpose
);
529 else if ((menu
= searchMenu(e
->xexpose
.window
)))
530 menu
->exposeEvent(&e
->xexpose
);
531 else if ((tbar
= searchToolbar(e
->xexpose
.window
)))
532 tbar
->exposeEvent(&e
->xexpose
);
538 Toolbar
*tbar
= searchToolbar(e
->xkey
.window
);
540 if (tbar
&& tbar
->isEditing())
541 tbar
->keyPressEvent(&e
->xkey
);
546 case ColormapNotify
: {
547 BScreen
*screen
= searchScreen(e
->xcolormap
.window
);
550 screen
->setRootColormapInstalled((e
->xcolormap
.state
==
551 ColormapInstalled
) ? True
: False
);
557 if (e
->xfocus
.detail
!= NotifyNonlinear
) {
559 don't process FocusIns when:
560 1. the new focus window isn't an ancestor or inferior of the old
561 focus window (NotifyNonlinear)
566 BlackboxWindow
*win
= searchWindow(e
->xfocus
.window
);
568 if (! win
->isFocused())
569 win
->setFocusFlag(True
);
572 set the event window to None. when the FocusOut event handler calls
573 this function recursively, it uses this as an indication that focus
574 has moved to a known window.
576 e
->xfocus
.window
= None
;
583 if (e
->xfocus
.detail
!= NotifyNonlinear
) {
585 don't process FocusOuts when:
586 2. the new focus window isn't an ancestor or inferior of the old
587 focus window (NotifyNonlinear)
592 BlackboxWindow
*win
= searchWindow(e
->xfocus
.window
);
593 if (win
&& win
->isFocused()) {
595 before we mark "win" as unfocused, we need to verify that focus is
596 going to a known location, is in a known location, or set focus
601 // don't check the current focus if FocusOut was generated during a grab
602 bool check_focus
= (e
->xfocus
.mode
== NotifyNormal
);
605 First, check if there is a pending FocusIn event waiting. if there
606 is, process it and determine if focus has moved to another window
607 (the FocusIn event handler sets the window in the event
608 structure to None to indicate this).
610 if (XCheckTypedEvent(getXDisplay(), FocusIn
, &event
)) {
612 process_event(&event
);
613 if (event
.xfocus
.window
== None
) {
621 Second, we query the X server for the current input focus.
622 to make sure that we keep a consistent state.
624 BlackboxWindow
*focus
;
627 XGetInputFocus(getXDisplay(), &w
, &revert
);
628 focus
= searchWindow(w
);
631 focus got from "win" to "focus" under some very strange
632 circumstances, and we need to make sure that the focus indication
635 setFocusedWindow(focus
);
637 // we have no idea where focus went... so we set it to somewhere
646 case ClientMessage
: {
647 if (e
->xclient
.format
== 32) {
648 if (e
->xclient
.message_type
== getWMChangeStateAtom()) {
649 BlackboxWindow
*win
= searchWindow(e
->xclient
.window
);
650 if (! win
|| ! win
->validateClient()) return;
652 if (e
->xclient
.data
.l
[0] == IconicState
)
654 if (e
->xclient
.data
.l
[0] == NormalState
)
656 } else if(e
->xclient
.message_type
== getBlackboxChangeWorkspaceAtom()) {
657 BScreen
*screen
= searchScreen(e
->xclient
.window
);
659 if (screen
&& e
->xclient
.data
.l
[0] >= 0 &&
660 e
->xclient
.data
.l
[0] <
661 static_cast<signed>(screen
->getWorkspaceCount()))
662 screen
->changeWorkspaceID(e
->xclient
.data
.l
[0]);
663 } else if (e
->xclient
.message_type
== getBlackboxChangeWindowFocusAtom()) {
664 BlackboxWindow
*win
= searchWindow(e
->xclient
.window
);
666 if (win
&& win
->isVisible() && win
->setInputFocus())
667 win
->installColormap(True
);
668 } else if (e
->xclient
.message_type
== getBlackboxCycleWindowFocusAtom()) {
669 BScreen
*screen
= searchScreen(e
->xclient
.window
);
672 if (! e
->xclient
.data
.l
[0])
677 } else if (e
->xclient
.message_type
== getBlackboxChangeAttributesAtom()) {
678 BlackboxWindow
*win
= searchWindow(e
->xclient
.window
);
680 if (win
&& win
->validateClient()) {
682 net
.flags
= e
->xclient
.data
.l
[0];
683 net
.attrib
= e
->xclient
.data
.l
[1];
684 net
.workspace
= e
->xclient
.data
.l
[2];
685 net
.stack
= e
->xclient
.data
.l
[3];
686 net
.decoration
= e
->xclient
.data
.l
[4];
688 win
->changeBlackboxHints(&net
);
697 case ConfigureNotify
:
699 break; // not handled, just ignore
703 if (e
->type
== getShapeEventBase()) {
704 XShapeEvent
*shape_event
= (XShapeEvent
*) e
;
705 BlackboxWindow
*win
= searchWindow(e
->xany
.window
);
708 win
->shapeEvent(shape_event
);
716 bool Blackbox::handleSignal(int sig
) {
745 void Blackbox::init_icccm(void) {
746 xa_wm_colormap_windows
=
747 XInternAtom(getXDisplay(), "WM_COLORMAP_WINDOWS", False
);
748 xa_wm_protocols
= XInternAtom(getXDisplay(), "WM_PROTOCOLS", False
);
749 xa_wm_state
= XInternAtom(getXDisplay(), "WM_STATE", False
);
750 xa_wm_change_state
= XInternAtom(getXDisplay(), "WM_CHANGE_STATE", False
);
751 xa_wm_delete_window
= XInternAtom(getXDisplay(), "WM_DELETE_WINDOW", False
);
752 xa_wm_take_focus
= XInternAtom(getXDisplay(), "WM_TAKE_FOCUS", False
);
753 motif_wm_hints
= XInternAtom(getXDisplay(), "_MOTIF_WM_HINTS", False
);
755 blackbox_hints
= XInternAtom(getXDisplay(), "_BLACKBOX_HINTS", False
);
756 blackbox_attributes
=
757 XInternAtom(getXDisplay(), "_BLACKBOX_ATTRIBUTES", False
);
758 blackbox_change_attributes
=
759 XInternAtom(getXDisplay(), "_BLACKBOX_CHANGE_ATTRIBUTES", False
);
760 blackbox_structure_messages
=
761 XInternAtom(getXDisplay(), "_BLACKBOX_STRUCTURE_MESSAGES", False
);
762 blackbox_notify_startup
=
763 XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_STARTUP", False
);
764 blackbox_notify_window_add
=
765 XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WINDOW_ADD", False
);
766 blackbox_notify_window_del
=
767 XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WINDOW_DEL", False
);
768 blackbox_notify_current_workspace
=
769 XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_CURRENT_WORKSPACE", False
);
770 blackbox_notify_workspace_count
=
771 XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WORKSPACE_COUNT", False
);
772 blackbox_notify_window_focus
=
773 XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WINDOW_FOCUS", False
);
774 blackbox_notify_window_raise
=
775 XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WINDOW_RAISE", False
);
776 blackbox_notify_window_lower
=
777 XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WINDOW_LOWER", False
);
778 blackbox_change_workspace
=
779 XInternAtom(getXDisplay(), "_BLACKBOX_CHANGE_WORKSPACE", False
);
780 blackbox_change_window_focus
=
781 XInternAtom(getXDisplay(), "_BLACKBOX_CHANGE_WINDOW_FOCUS", False
);
782 blackbox_cycle_window_focus
=
783 XInternAtom(getXDisplay(), "_BLACKBOX_CYCLE_WINDOW_FOCUS", False
);
786 net_supported
= XInternAtom(getXDisplay(), "_NET_SUPPORTED", False
);
787 net_client_list
= XInternAtom(getXDisplay(), "_NET_CLIENT_LIST", False
);
788 net_client_list_stacking
=
789 XInternAtom(getXDisplay(), "_NET_CLIENT_LIST_STACKING", False
);
790 net_number_of_desktops
=
791 XInternAtom(getXDisplay(), "_NET_NUMBER_OF_DESKTOPS", False
);
792 net_desktop_geometry
=
793 XInternAtom(getXDisplay(), "_NET_DESKTOP_GEOMETRY", False
);
794 net_desktop_viewport
=
795 XInternAtom(getXDisplay(), "_NET_DESKTOP_VIEWPORT", False
);
796 net_current_desktop
=
797 XInternAtom(getXDisplay(), "_NET_CURRENT_DESKTOP", False
);
798 net_desktop_names
= XInternAtom(getXDisplay(), "_NET_DESKTOP_NAMES", False
);
799 net_active_window
= XInternAtom(getXDisplay(), "_NET_ACTIVE_WINDOW", False
);
800 net_workarea
= XInternAtom(getXDisplay(), "_NET_WORKAREA", False
);
801 net_supporting_wm_check
=
802 XInternAtom(getXDisplay(), "_NET_SUPPORTING_WM_CHECK", False
);
803 net_virtual_roots
= XInternAtom(getXDisplay(), "_NET_VIRTUAL_ROOTS", False
);
804 net_close_window
= XInternAtom(getXDisplay(), "_NET_CLOSE_WINDOW", False
);
805 net_wm_moveresize
= XInternAtom(getXDisplay(), "_NET_WM_MOVERESIZE", False
);
806 net_properties
= XInternAtom(getXDisplay(), "_NET_PROPERTIES", False
);
807 net_wm_name
= XInternAtom(getXDisplay(), "_NET_WM_NAME", False
);
808 net_wm_desktop
= XInternAtom(getXDisplay(), "_NET_WM_DESKTOP", False
);
810 XInternAtom(getXDisplay(), "_NET_WM_WINDOW_TYPE", False
);
811 net_wm_state
= XInternAtom(getXDisplay(), "_NET_WM_STATE", False
);
812 net_wm_strut
= XInternAtom(getXDisplay(), "_NET_WM_STRUT", False
);
813 net_wm_icon_geometry
=
814 XInternAtom(getXDisplay(), "_NET_WM_ICON_GEOMETRY", False
);
815 net_wm_icon
= XInternAtom(getXDisplay(), "_NET_WM_ICON", False
);
816 net_wm_pid
= XInternAtom(getXDisplay(), "_NET_WM_PID", False
);
817 net_wm_handled_icons
=
818 XInternAtom(getXDisplay(), "_NET_WM_HANDLED_ICONS", False
);
819 net_wm_ping
= XInternAtom(getXDisplay(), "_NET_WM_PING", False
);
823 blackbox_pid
= XInternAtom(getXDisplay(), "_BLACKBOX_PID", False
);
824 #endif // HAVE_GETPID
828 bool Blackbox::validateWindow(Window window
) {
830 if (XCheckTypedWindowEvent(getXDisplay(), window
, DestroyNotify
, &event
)) {
831 XPutBackEvent(getXDisplay(), &event
);
840 BScreen
*Blackbox::searchScreen(Window window
) {
841 ScreenList::iterator it
= screenList
.begin();
843 for (; it
!= screenList
.end(); ++it
) {
845 if (s
->getRootWindow() == window
)
849 return (BScreen
*) 0;
853 BlackboxWindow
*Blackbox::searchWindow(Window window
) {
854 WindowLookup::iterator it
= windowSearchList
.find(window
);
855 if (it
!= windowSearchList
.end())
858 return (BlackboxWindow
*) 0;
862 BWindowGroup
*Blackbox::searchGroup(Window window
) {
863 GroupLookup::iterator it
= groupSearchList
.find(window
);
864 if (it
!= groupSearchList
.end())
867 return (BWindowGroup
*) 0;
871 Basemenu
*Blackbox::searchMenu(Window window
) {
872 MenuLookup::iterator it
= menuSearchList
.find(window
);
873 if (it
!= menuSearchList
.end())
876 return (Basemenu
*) 0;
880 Toolbar
*Blackbox::searchToolbar(Window window
) {
881 ToolbarLookup::iterator it
= toolbarSearchList
.find(window
);
882 if (it
!= toolbarSearchList
.end())
889 Slit
*Blackbox::searchSlit(Window window
) {
890 SlitLookup::iterator it
= slitSearchList
.find(window
);
891 if (it
!= slitSearchList
.end())
898 void Blackbox::saveWindowSearch(Window window
, BlackboxWindow
*data
) {
899 windowSearchList
.insert(WindowLookupPair(window
, data
));
903 void Blackbox::saveGroupSearch(Window window
, BWindowGroup
*data
) {
904 groupSearchList
.insert(GroupLookupPair(window
, data
));
908 void Blackbox::saveMenuSearch(Window window
, Basemenu
*data
) {
909 menuSearchList
.insert(MenuLookupPair(window
, data
));
913 void Blackbox::saveToolbarSearch(Window window
, Toolbar
*data
) {
914 toolbarSearchList
.insert(ToolbarLookupPair(window
, data
));
918 void Blackbox::saveSlitSearch(Window window
, Slit
*data
) {
919 slitSearchList
.insert(SlitLookupPair(window
, data
));
923 void Blackbox::removeWindowSearch(Window window
) {
924 windowSearchList
.erase(window
);
928 void Blackbox::removeGroupSearch(Window window
) {
929 groupSearchList
.erase(window
);
933 void Blackbox::removeMenuSearch(Window window
) {
934 menuSearchList
.erase(window
);
938 void Blackbox::removeToolbarSearch(Window window
) {
939 toolbarSearchList
.erase(window
);
943 void Blackbox::removeSlitSearch(Window window
) {
944 slitSearchList
.erase(window
);
948 void Blackbox::restart(const char *prog
) {
952 execlp(prog
, prog
, NULL
);
956 // fall back in case the above execlp doesn't work
957 execvp(argv
[0], argv
);
958 string name
= basename(argv
[0]);
959 execvp(name
.c_str(), argv
);
963 void Blackbox::shutdown(void) {
964 BaseDisplay::shutdown();
966 XSetInputFocus(getXDisplay(), PointerRoot
, None
, CurrentTime
);
968 std::for_each(screenList
.begin(), screenList
.end(),
969 std::mem_fun(&BScreen::shutdown
));
971 XSync(getXDisplay(), False
);
977 void Blackbox::save_rc(void) {
978 XrmDatabase new_blackboxrc
= (XrmDatabase
) 0;
979 char rc_string
[1024];
983 sprintf(rc_string
, "session.colorsPerChannel: %d",
984 resource
.colors_per_channel
);
985 XrmPutLineResource(&new_blackboxrc
, rc_string
);
987 sprintf(rc_string
, "session.doubleClickInterval: %lu",
988 resource
.double_click_interval
);
989 XrmPutLineResource(&new_blackboxrc
, rc_string
);
991 sprintf(rc_string
, "session.autoRaiseDelay: %lu",
992 ((resource
.auto_raise_delay
.tv_sec
* 1000) +
993 (resource
.auto_raise_delay
.tv_usec
/ 1000)));
994 XrmPutLineResource(&new_blackboxrc
, rc_string
);
996 sprintf(rc_string
, "session.cacheLife: %lu", resource
.cache_life
/ 60000);
997 XrmPutLineResource(&new_blackboxrc
, rc_string
);
999 sprintf(rc_string
, "session.cacheMax: %lu", resource
.cache_max
);
1000 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1002 ScreenList::iterator it
= screenList
.begin();
1003 for (; it
!= screenList
.end(); ++it
) {
1004 BScreen
*screen
= *it
;
1005 int screen_number
= screen
->getScreenNumber();
1007 char *placement
= (char *) 0;
1009 switch (screen
->getSlitPlacement()) {
1010 case Slit::TopLeft
: placement
= "TopLeft"; break;
1011 case Slit::CenterLeft
: placement
= "CenterLeft"; break;
1012 case Slit::BottomLeft
: placement
= "BottomLeft"; break;
1013 case Slit::TopCenter
: placement
= "TopCenter"; break;
1014 case Slit::BottomCenter
: placement
= "BottomCenter"; break;
1015 case Slit::TopRight
: placement
= "TopRight"; break;
1016 case Slit::BottomRight
: placement
= "BottomRight"; break;
1017 case Slit::CenterRight
: default: placement
= "CenterRight"; break;
1020 sprintf(rc_string
, "session.screen%d.slit.placement: %s", screen_number
,
1022 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1024 sprintf(rc_string
, "session.screen%d.slit.direction: %s", screen_number
,
1025 ((screen
->getSlitDirection() == Slit::Horizontal
) ? "Horizontal" :
1027 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1029 sprintf(rc_string
, "session.screen%d.slit.onTop: %s", screen_number
,
1030 ((screen
->getSlit()->isOnTop()) ? "True" : "False"));
1031 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1033 sprintf(rc_string
, "session.screen%d.slit.autoHide: %s", screen_number
,
1034 ((screen
->getSlit()->doAutoHide()) ? "True" : "False"));
1035 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1037 sprintf(rc_string
, "session.opaqueMove: %s",
1038 ((screen
->doOpaqueMove()) ? "True" : "False"));
1039 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1041 sprintf(rc_string
, "session.imageDither: %s",
1042 ((screen
->getImageControl()->doDither()) ? "True" : "False"));
1043 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1045 sprintf(rc_string
, "session.screen%d.fullMaximization: %s", screen_number
,
1046 ((screen
->doFullMax()) ? "True" : "False"));
1047 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1049 sprintf(rc_string
, "session.screen%d.focusNewWindows: %s", screen_number
,
1050 ((screen
->doFocusNew()) ? "True" : "False"));
1051 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1053 sprintf(rc_string
, "session.screen%d.focusLastWindow: %s", screen_number
,
1054 ((screen
->doFocusLast()) ? "True" : "False"));
1055 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1057 sprintf(rc_string
, "session.screen%d.rowPlacementDirection: %s",
1059 ((screen
->getRowPlacementDirection() == BScreen::LeftRight
) ?
1060 "LeftToRight" : "RightToLeft"));
1061 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1063 sprintf(rc_string
, "session.screen%d.colPlacementDirection: %s",
1065 ((screen
->getColPlacementDirection() == BScreen::TopBottom
) ?
1066 "TopToBottom" : "BottomToTop"));
1067 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1069 switch (screen
->getPlacementPolicy()) {
1070 case BScreen::CascadePlacement
:
1071 placement
= "CascadePlacement";
1073 case BScreen::ColSmartPlacement
:
1074 placement
= "ColSmartPlacement";
1077 case BScreen::RowSmartPlacement
:
1079 placement
= "RowSmartPlacement";
1082 sprintf(rc_string
, "session.screen%d.windowPlacement: %s", screen_number
,
1084 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1087 if (screen
->isSloppyFocus()) {
1088 fmodel
= "SloppyFocus";
1089 if (screen
->doAutoRaise()) fmodel
+= " AutoRaise";
1090 if (screen
->doClickRaise()) fmodel
+= " ClickRaise";
1092 fmodel
= "ClickToFocus";
1094 sprintf(rc_string
, "session.screen%d.focusModel: %s", screen_number
,
1096 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1098 sprintf(rc_string
, "session.screen%d.workspaces: %d", screen_number
,
1099 screen
->getWorkspaceCount());
1100 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1102 sprintf(rc_string
, "session.screen%d.toolbar.onTop: %s", screen_number
,
1103 ((screen
->getToolbar()->isOnTop()) ? "True" : "False"));
1104 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1106 sprintf(rc_string
, "session.screen%d.toolbar.autoHide: %s",
1108 ((screen
->getToolbar()->doAutoHide()) ? "True" : "False"));
1109 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1111 switch (screen
->getToolbarPlacement()) {
1112 case Toolbar::TopLeft
: placement
= "TopLeft"; break;
1113 case Toolbar::BottomLeft
: placement
= "BottomLeft"; break;
1114 case Toolbar::TopCenter
: placement
= "TopCenter"; break;
1115 case Toolbar::TopRight
: placement
= "TopRight"; break;
1116 case Toolbar::BottomRight
: placement
= "BottomRight"; break;
1117 case Toolbar::BottomCenter
: default: placement
= "BottomCenter"; break;
1120 sprintf(rc_string
, "session.screen%d.toolbar.placement: %s",
1121 screen_number
, placement
);
1122 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1126 // these are static, but may not be saved in the users .blackboxrc,
1127 // writing these resources will allow the user to edit them at a later
1128 // time... but loading the defaults before saving allows us to rewrite the
1131 #ifdef HAVE_STRFTIME
1132 sprintf(rc_string
, "session.screen%d.strftimeFormat: %s", screen_number
,
1133 screen
->getStrftimeFormat());
1134 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1135 #else // !HAVE_STRFTIME
1136 sprintf(rc_string
, "session.screen%d.dateFormat: %s", screen_number
,
1137 ((screen
->getDateFormat() == B_EuropeanDate
) ?
1138 "European" : "American"));
1139 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1141 sprintf(rc_string
, "session.screen%d.clockFormat: %d", screen_number
,
1142 ((screen
->isClock24Hour()) ? 24 : 12));
1143 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1144 #endif // HAVE_STRFTIME
1146 sprintf(rc_string
, "session.screen%d.edgeSnapThreshold: %d",
1147 screen_number
, screen
->getEdgeSnapThreshold());
1148 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1150 sprintf(rc_string
, "session.screen%d.toolbar.widthPercent: %d",
1151 screen_number
, screen
->getToolbarWidthPercent());
1152 XrmPutLineResource(&new_blackboxrc
, rc_string
);
1154 // write out the user's workspace names
1156 string save_string
= screen
->getWorkspace(0)->getName();
1157 for (unsigned int i
= 1; i
< screen
->getWorkspaceCount(); ++i
) {
1159 save_string
+= screen
->getWorkspace(i
)->getName();
1162 char *resource_string
= new char[save_string
.length() + 48];
1163 sprintf(resource_string
, "session.screen%d.workspaceNames: %s",
1164 screen_number
, save_string
.c_str());
1165 XrmPutLineResource(&new_blackboxrc
, resource_string
);
1167 delete [] resource_string
;
1170 XrmDatabase old_blackboxrc
= XrmGetFileDatabase(rc_file
.c_str());
1172 XrmMergeDatabases(new_blackboxrc
, &old_blackboxrc
);
1173 XrmPutFileDatabase(old_blackboxrc
, rc_file
.c_str());
1174 XrmDestroyDatabase(old_blackboxrc
);
1178 void Blackbox::load_rc(void) {
1179 XrmDatabase database
= (XrmDatabase
) 0;
1181 database
= XrmGetFileDatabase(rc_file
.c_str());
1186 unsigned long long_value
;
1188 resource
.colors_per_channel
= 4;
1189 if (XrmGetResource(database
, "session.colorsPerChannel",
1190 "Session.ColorsPerChannel", &value_type
, &value
) &&
1191 sscanf(value
.addr
, "%d", &int_value
) == 1) {
1192 resource
.colors_per_channel
= int_value
;
1193 if (resource
.colors_per_channel
< 2) resource
.colors_per_channel
= 2;
1194 if (resource
.colors_per_channel
> 6) resource
.colors_per_channel
= 6;
1197 if (XrmGetResource(database
, "session.styleFile", "Session.StyleFile",
1198 &value_type
, &value
))
1199 resource
.style_file
= expandTilde(value
.addr
);
1201 resource
.style_file
= DEFAULTSTYLE
;
1203 resource
.double_click_interval
= 250;
1204 if (XrmGetResource(database
, "session.doubleClickInterval",
1205 "Session.DoubleClickInterval", &value_type
, &value
) &&
1206 sscanf(value
.addr
, "%lu", &long_value
) == 1) {
1207 resource
.double_click_interval
= long_value
;
1210 resource
.auto_raise_delay
.tv_usec
= 400;
1211 if (XrmGetResource(database
, "session.autoRaiseDelay",
1212 "Session.AutoRaiseDelay", &value_type
, &value
) &&
1213 sscanf(value
.addr
, "%lu", &long_value
) == 1) {
1214 resource
.auto_raise_delay
.tv_usec
= long_value
;
1217 resource
.auto_raise_delay
.tv_sec
= resource
.auto_raise_delay
.tv_usec
/ 1000;
1218 resource
.auto_raise_delay
.tv_usec
-=
1219 (resource
.auto_raise_delay
.tv_sec
* 1000);
1220 resource
.auto_raise_delay
.tv_usec
*= 1000;
1222 resource
.cache_life
= 5l;
1223 if (XrmGetResource(database
, "session.cacheLife", "Session.CacheLife",
1224 &value_type
, &value
) &&
1225 sscanf(value
.addr
, "%lu", &long_value
) == 1) {
1226 resource
.cache_life
= long_value
;
1228 resource
.cache_life
*= 60000;
1230 resource
.cache_max
= 200;
1231 if (XrmGetResource(database
, "session.cacheMax", "Session.CacheMax",
1232 &value_type
, &value
) &&
1233 sscanf(value
.addr
, "%lu", &long_value
) == 1) {
1234 resource
.cache_max
= long_value
;
1239 void Blackbox::load_rc(BScreen
*screen
) {
1240 XrmDatabase database
= (XrmDatabase
) 0;
1242 database
= XrmGetFileDatabase(rc_file
.c_str());
1245 char *value_type
, name_lookup
[1024], class_lookup
[1024];
1246 int screen_number
= screen
->getScreenNumber();
1249 sprintf(name_lookup
, "session.screen%d.fullMaximization", screen_number
);
1250 sprintf(class_lookup
, "Session.Screen%d.FullMaximization", screen_number
);
1251 screen
->saveFullMax(False
);
1252 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1254 ! strncasecmp(value
.addr
, "true", value
.size
)) {
1255 screen
->saveFullMax(True
);
1258 sprintf(name_lookup
, "session.screen%d.focusNewWindows", screen_number
);
1259 sprintf(class_lookup
, "Session.Screen%d.FocusNewWindows", screen_number
);
1260 screen
->saveFocusNew(False
);
1261 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1263 ! strncasecmp(value
.addr
, "true", value
.size
)) {
1264 screen
->saveFocusNew(True
);
1267 sprintf(name_lookup
, "session.screen%d.focusLastWindow", screen_number
);
1268 sprintf(class_lookup
, "Session.Screen%d.focusLastWindow", screen_number
);
1269 screen
->saveFocusLast(False
);
1270 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1272 ! strncasecmp(value
.addr
, "true", value
.size
)) {
1273 screen
->saveFocusLast(True
);
1276 sprintf(name_lookup
, "session.screen%d.rowPlacementDirection",
1278 sprintf(class_lookup
, "Session.Screen%d.RowPlacementDirection",
1280 screen
->saveRowPlacementDirection(BScreen::LeftRight
);
1281 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1283 ! strncasecmp(value
.addr
, "righttoleft", value
.size
)) {
1284 screen
->saveRowPlacementDirection(BScreen::RightLeft
);
1287 sprintf(name_lookup
, "session.screen%d.colPlacementDirection",
1289 sprintf(class_lookup
, "Session.Screen%d.ColPlacementDirection",
1291 screen
->saveColPlacementDirection(BScreen::TopBottom
);
1292 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1294 ! strncasecmp(value
.addr
, "bottomtotop", value
.size
)) {
1295 screen
->saveColPlacementDirection(BScreen::BottomTop
);
1298 sprintf(name_lookup
, "session.screen%d.workspaces", screen_number
);
1299 sprintf(class_lookup
, "Session.Screen%d.Workspaces", screen_number
);
1300 screen
->saveWorkspaces(1);
1301 if (XrmGetResource(database
, name_lookup
, class_lookup
,
1302 &value_type
, &value
) &&
1303 sscanf(value
.addr
, "%d", &int_value
) == 1 &&
1304 int_value
> 0 && int_value
< 128) {
1305 screen
->saveWorkspaces(int_value
);
1308 sprintf(name_lookup
, "session.screen%d.toolbar.widthPercent",
1310 sprintf(class_lookup
, "Session.Screen%d.Toolbar.WidthPercent",
1312 screen
->saveToolbarWidthPercent(66);
1313 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1315 sscanf(value
.addr
, "%d", &int_value
) == 1 &&
1316 int_value
> 0 && int_value
<= 100) {
1317 screen
->saveToolbarWidthPercent(int_value
);
1320 sprintf(name_lookup
, "session.screen%d.toolbar.placement", screen_number
);
1321 sprintf(class_lookup
, "Session.Screen%d.Toolbar.Placement", screen_number
);
1322 screen
->saveToolbarPlacement(Toolbar::BottomCenter
);
1323 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1325 if (! strncasecmp(value
.addr
, "TopLeft", value
.size
))
1326 screen
->saveToolbarPlacement(Toolbar::TopLeft
);
1327 else if (! strncasecmp(value
.addr
, "BottomLeft", value
.size
))
1328 screen
->saveToolbarPlacement(Toolbar::BottomLeft
);
1329 else if (! strncasecmp(value
.addr
, "TopCenter", value
.size
))
1330 screen
->saveToolbarPlacement(Toolbar::TopCenter
);
1331 else if (! strncasecmp(value
.addr
, "TopRight", value
.size
))
1332 screen
->saveToolbarPlacement(Toolbar::TopRight
);
1333 else if (! strncasecmp(value
.addr
, "BottomRight", value
.size
))
1334 screen
->saveToolbarPlacement(Toolbar::BottomRight
);
1336 screen
->removeWorkspaceNames();
1338 sprintf(name_lookup
, "session.screen%d.workspaceNames", screen_number
);
1339 sprintf(class_lookup
, "Session.Screen%d.WorkspaceNames", screen_number
);
1340 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1342 string search
= value
.addr
;
1343 string::const_iterator it
= search
.begin(),
1346 string::const_iterator tmp
= it
; // current string.begin()
1347 it
= std::find(tmp
, end
, ','); // look for comma between tmp and end
1348 screen
->addWorkspaceName(string(tmp
, it
)); // string = search[tmp:it]
1349 if (it
== end
) break;
1354 sprintf(name_lookup
, "session.screen%d.toolbar.onTop", screen_number
);
1355 sprintf(class_lookup
, "Session.Screen%d.Toolbar.OnTop", screen_number
);
1356 screen
->saveToolbarOnTop(False
);
1357 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1359 ! strncasecmp(value
.addr
, "true", value
.size
)) {
1360 screen
->saveToolbarOnTop(True
);
1363 sprintf(name_lookup
, "session.screen%d.toolbar.autoHide", screen_number
);
1364 sprintf(class_lookup
, "Session.Screen%d.Toolbar.autoHide", screen_number
);
1365 screen
->saveToolbarAutoHide(False
);
1366 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1368 ! strncasecmp(value
.addr
, "true", value
.size
)) {
1369 screen
->saveToolbarAutoHide(True
);
1372 sprintf(name_lookup
, "session.screen%d.focusModel", screen_number
);
1373 sprintf(class_lookup
, "Session.Screen%d.FocusModel", screen_number
);
1374 screen
->saveSloppyFocus(True
);
1375 screen
->saveAutoRaise(False
);
1376 screen
->saveClickRaise(False
);
1377 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1379 string fmodel
= value
.addr
;
1381 if (fmodel
.find("ClickToFocus") != string::npos
) {
1382 screen
->saveSloppyFocus(False
);
1386 if (fmodel
.find("AutoRaise") != string::npos
)
1387 screen
->saveAutoRaise(True
);
1388 if (fmodel
.find("ClickRaise") != string::npos
)
1389 screen
->saveClickRaise(True
);
1393 sprintf(name_lookup
, "session.screen%d.windowPlacement", screen_number
);
1394 sprintf(class_lookup
, "Session.Screen%d.WindowPlacement", screen_number
);
1395 screen
->savePlacementPolicy(BScreen::RowSmartPlacement
);
1396 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1398 if (! strncasecmp(value
.addr
, "RowSmartPlacement", value
.size
))
1400 else if (! strncasecmp(value
.addr
, "ColSmartPlacement", value
.size
))
1401 screen
->savePlacementPolicy(BScreen::ColSmartPlacement
);
1402 else if (! strncasecmp(value
.addr
, "CascadePlacement", value
.size
))
1403 screen
->savePlacementPolicy(BScreen::CascadePlacement
);
1406 sprintf(name_lookup
, "session.screen%d.slit.placement", screen_number
);
1407 sprintf(class_lookup
, "Session.Screen%d.Slit.Placement", screen_number
);
1408 screen
->saveSlitPlacement(Slit::CenterRight
);
1409 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1411 if (! strncasecmp(value
.addr
, "TopLeft", value
.size
))
1412 screen
->saveSlitPlacement(Slit::TopLeft
);
1413 else if (! strncasecmp(value
.addr
, "CenterLeft", value
.size
))
1414 screen
->saveSlitPlacement(Slit::CenterLeft
);
1415 else if (! strncasecmp(value
.addr
, "BottomLeft", value
.size
))
1416 screen
->saveSlitPlacement(Slit::BottomLeft
);
1417 else if (! strncasecmp(value
.addr
, "TopCenter", value
.size
))
1418 screen
->saveSlitPlacement(Slit::TopCenter
);
1419 else if (! strncasecmp(value
.addr
, "BottomCenter", value
.size
))
1420 screen
->saveSlitPlacement(Slit::BottomCenter
);
1421 else if (! strncasecmp(value
.addr
, "TopRight", value
.size
))
1422 screen
->saveSlitPlacement(Slit::TopRight
);
1423 else if (! strncasecmp(value
.addr
, "BottomRight", value
.size
))
1424 screen
->saveSlitPlacement(Slit::BottomRight
);
1427 sprintf(name_lookup
, "session.screen%d.slit.direction", screen_number
);
1428 sprintf(class_lookup
, "Session.Screen%d.Slit.Direction", screen_number
);
1429 screen
->saveSlitDirection(Slit::Vertical
);
1430 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1432 ! strncasecmp(value
.addr
, "Horizontal", value
.size
)) {
1433 screen
->saveSlitDirection(Slit::Horizontal
);
1436 sprintf(name_lookup
, "session.screen%d.slit.onTop", screen_number
);
1437 sprintf(class_lookup
, "Session.Screen%d.Slit.OnTop", screen_number
);
1438 screen
->saveSlitOnTop(False
);
1439 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1441 ! strncasecmp(value
.addr
, "True", value
.size
)) {
1442 screen
->saveSlitOnTop(True
);
1445 sprintf(name_lookup
, "session.screen%d.slit.autoHide", screen_number
);
1446 sprintf(class_lookup
, "Session.Screen%d.Slit.AutoHide", screen_number
);
1447 screen
->saveSlitAutoHide(False
);
1448 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1450 ! strncasecmp(value
.addr
, "true", value
.size
)) {
1451 screen
->saveSlitAutoHide(True
);
1454 #ifdef HAVE_STRFTIME
1455 sprintf(name_lookup
, "session.screen%d.strftimeFormat", screen_number
);
1456 sprintf(class_lookup
, "Session.Screen%d.StrftimeFormat", screen_number
);
1457 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1459 screen
->saveStrftimeFormat(value
.addr
);
1461 screen
->saveStrftimeFormat("%I:%M %p");
1463 #else // HAVE_STRFTIME
1464 sprintf(name_lookup
, "session.screen%d.dateFormat", screen_number
);
1465 sprintf(class_lookup
, "Session.Screen%d.DateFormat", screen_number
);
1466 screen
->saveDateFormat(B_AmericanDate
);
1467 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1469 if (! strncasecmp(value
.addr
, "european", value
.size
))
1470 screen
->saveDateFormat(B_EuropeanDate
);
1473 sprintf(name_lookup
, "session.screen%d.clockFormat", screen_number
);
1474 sprintf(class_lookup
, "Session.Screen%d.ClockFormat", screen_number
);
1475 screen
->saveClock24Hour(False
);
1476 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1478 sscanf(value
.addr
, "%d", &int_value
) == 1 && int_value
== 24) {
1479 screen
->saveClock24Hour(True
);
1481 #endif // HAVE_STRFTIME
1483 sprintf(name_lookup
, "session.screen%d.edgeSnapThreshold", screen_number
);
1484 sprintf(class_lookup
, "Session.Screen%d.EdgeSnapThreshold", screen_number
);
1485 if (XrmGetResource(database
, name_lookup
, class_lookup
, &value_type
,
1487 sscanf(value
.addr
, "%d", &int_value
) == 1) {
1488 screen
->saveEdgeSnapThreshold(int_value
);
1491 screen
->saveImageDither(True
);
1492 if (XrmGetResource(database
, "session.imageDither", "Session.ImageDither",
1493 &value_type
, &value
) &&
1494 ! strncasecmp("false", value
.addr
, value
.size
)) {
1495 screen
->saveImageDither(False
);
1498 screen
->saveOpaqueMove(False
);
1499 if (XrmGetResource(database
, "session.opaqueMove", "Session.OpaqueMove",
1500 &value_type
, &value
) &&
1501 ! strncasecmp("true", value
.addr
, value
.size
)) {
1502 screen
->saveOpaqueMove(True
);
1505 XrmDestroyDatabase(database
);
1509 void Blackbox::reload_rc(void) {
1515 void Blackbox::reconfigure(void) {
1516 reconfigure_wait
= True
;
1518 if (! timer
->isTiming()) timer
->start();
1522 void Blackbox::real_reconfigure(void) {
1523 XrmDatabase new_blackboxrc
= (XrmDatabase
) 0;
1524 char *style
= new char[resource
.style_file
.length() + 20];
1526 sprintf(style
, "session.styleFile: %s", getStyleFilename());
1527 XrmPutLineResource(&new_blackboxrc
, style
);
1531 XrmDatabase old_blackboxrc
= XrmGetFileDatabase(rc_file
.c_str());
1533 XrmMergeDatabases(new_blackboxrc
, &old_blackboxrc
);
1534 XrmPutFileDatabase(old_blackboxrc
, rc_file
.c_str());
1535 if (old_blackboxrc
) XrmDestroyDatabase(old_blackboxrc
);
1537 std::for_each(menuTimestamps
.begin(), menuTimestamps
.end(),
1539 menuTimestamps
.clear();
1543 std::for_each(screenList
.begin(), screenList
.end(),
1544 std::mem_fun(&BScreen::reconfigure
));
1548 void Blackbox::checkMenu(void) {
1549 bool reread
= False
;
1550 MenuTimestampList::iterator it
= menuTimestamps
.begin();
1551 for(; it
!= menuTimestamps
.end(); ++it
) {
1552 MenuTimestamp
*tmp
= *it
;
1555 if (! stat(tmp
->filename
.c_str(), &buf
)) {
1556 if (tmp
->timestamp
!= buf
.st_ctime
)
1563 if (reread
) rereadMenu();
1567 void Blackbox::rereadMenu(void) {
1568 reread_menu_wait
= True
;
1570 if (! timer
->isTiming()) timer
->start();
1574 void Blackbox::real_rereadMenu(void) {
1575 std::for_each(menuTimestamps
.begin(), menuTimestamps
.end(),
1577 menuTimestamps
.clear();
1579 std::for_each(screenList
.begin(), screenList
.end(),
1580 std::mem_fun(&BScreen::rereadMenu
));
1584 void Blackbox::saveStyleFilename(const string
& filename
) {
1585 assert(! filename
.empty());
1586 resource
.style_file
= filename
;
1590 void Blackbox::addMenuTimestamp(const string
& filename
) {
1591 assert(! filename
.empty());
1594 MenuTimestampList::iterator it
= menuTimestamps
.begin();
1595 for (; it
!= menuTimestamps
.end() && !found
; ++it
) {
1596 if ((*it
)->filename
== filename
) found
= True
;
1601 if (! stat(filename
.c_str(), &buf
)) {
1602 MenuTimestamp
*ts
= new MenuTimestamp
;
1604 ts
->filename
= filename
;
1605 ts
->timestamp
= buf
.st_ctime
;
1607 menuTimestamps
.push_back(ts
);
1613 void Blackbox::timeout(void) {
1614 if (reconfigure_wait
)
1617 if (reread_menu_wait
)
1620 reconfigure_wait
= reread_menu_wait
= False
;
1624 void Blackbox::setFocusedWindow(BlackboxWindow
*win
) {
1625 if (focused_window
&& focused_window
== win
) // nothing to do
1628 BScreen
*old_screen
= 0;
1630 if (focused_window
) {
1631 focused_window
->setFocusFlag(False
);
1632 old_screen
= focused_window
->getScreen();
1635 if (win
&& ! win
->isIconic()) {
1636 // the active screen is the one with the last focused window...
1637 // this will keep focus on this screen no matter where the mouse goes,
1638 // so multihead keybindings will continue to work on that screen until the
1639 // user focuses a window on a different screen.
1640 active_screen
= win
->getScreen();
1641 focused_window
= win
;
1645 if (active_screen
) {
1646 // set input focus to the toolbar of the screen with mouse
1647 XSetInputFocus(getXDisplay(),
1648 active_screen
->getToolbar()->getWindowID(),
1649 RevertToPointerRoot
, CurrentTime
);
1651 // set input focus to the toolbar of the first managed screen
1652 XSetInputFocus(getXDisplay(),
1653 screenList
.front()->getToolbar()->getWindowID(),
1654 RevertToPointerRoot
, CurrentTime
);
1657 // set input focus to the toolbar of the last screen
1658 XSetInputFocus(getXDisplay(), old_screen
->getToolbar()->getWindowID(),
1659 RevertToPointerRoot
, CurrentTime
);
1663 if (active_screen
&& active_screen
->isScreenManaged()) {
1664 active_screen
->getToolbar()->redrawWindowLabel(True
);
1665 active_screen
->updateNetizenWindowFocus();
1668 if (old_screen
&& old_screen
!= active_screen
) {
1669 old_screen
->getToolbar()->redrawWindowLabel(True
);
1670 old_screen
->updateNetizenWindowFocus();