1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // Screen.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
29 #include <X11/Xatom.h>
30 #include <X11/keysym.h>
33 # include <X11/Xlib.h>
34 # include <X11/extensions/Xinerama.h>
39 #endif // HAVE_STDLIB_H
43 #endif // HAVE_STRING_H
47 #endif // HAVE_CTYPE_H
50 # include <sys/types.h>
52 #endif // HAVE_UNISTD_H
56 #endif // HAVE_DIRENT_H
60 #endif // HAVE_LOCALE_H
62 #ifdef HAVE_SYS_STAT_H
63 # include <sys/stat.h>
64 #endif // HAVE_SYS_STAT_H
68 #endif // HAVE_STDARG_H
79 #include "blackbox.hh"
80 #include "Clientmenu.hh"
83 #include "Iconmenu.hh"
87 #include "Rootmenu.hh"
91 #include "Workspace.hh"
92 #include "Workspacemenu.hh"
96 #ifndef FONT_ELEMENT_SIZE
97 #define FONT_ELEMENT_SIZE 50
98 #endif // FONT_ELEMENT_SIZE
101 static bool running
= True
;
103 static int anotherWMRunning(Display
*display
, XErrorEvent
*) {
104 fprintf(stderr
, i18n(ScreenSet
, ScreenAnotherWMRunning
,
105 "BScreen::BScreen: an error occured while querying the X server.\n"
106 " another window manager already running on display %s.\n"),
107 DisplayString(display
));
115 BScreen::BScreen(Blackbox
*bb
, unsigned int scrn
) : ScreenInfo(bb
, scrn
) {
117 screenstr
= "session.screen" + itostring(scrn
) + '.';
118 config
= blackbox
->getConfig();
119 xatom
= blackbox
->getXAtom();
121 event_mask
= ColormapChangeMask
| EnterWindowMask
| PropertyChangeMask
|
122 SubstructureRedirectMask
| ButtonPressMask
| ButtonReleaseMask
;
124 XErrorHandler old
= XSetErrorHandler((XErrorHandler
) anotherWMRunning
);
125 XSelectInput(getBaseDisplay()->getXDisplay(), getRootWindow(), event_mask
);
126 XSync(getBaseDisplay()->getXDisplay(), False
);
127 XSetErrorHandler((XErrorHandler
) old
);
130 if (! managed
) return;
132 fprintf(stderr
, i18n(ScreenSet
, ScreenManagingScreen
,
133 "BScreen::BScreen: managing screen %d "
134 "using visual 0x%lx, depth %d\n"),
135 getScreenNumber(), XVisualIDFromVisual(getVisual()),
140 resource
.mstyle
.t_font
= resource
.mstyle
.f_font
= resource
.tstyle
.font
=
141 resource
.wstyle
.font
= (BFont
*) 0;
145 xatom
->setSupported(this); // set-up netwm support
147 xatom
->setValue(getRootWindow(), XAtom::blackbox_pid
, XAtom::cardinal
,
148 (unsigned long) getpid());
149 #endif // HAVE_GETPID
150 unsigned long geometry
[] = { getWidth(),
152 xatom
->setValue(getRootWindow(), XAtom::net_desktop_geometry
,
153 XAtom::cardinal
, geometry
, 2);
154 unsigned long viewport
[] = {0,0};
155 xatom
->setValue(getRootWindow(), XAtom::net_desktop_viewport
,
156 XAtom::cardinal
, viewport
, 2);
159 XDefineCursor(blackbox
->getXDisplay(), getRootWindow(),
160 blackbox
->getSessionCursor());
162 updateAvailableArea();
165 new BImageControl(blackbox
, this, True
, blackbox
->getColorsPerChannel(),
166 blackbox
->getCacheLife(), blackbox
->getCacheMax());
167 image_control
->installRootColormap();
168 root_colormap_installed
= True
;
174 gcv
.foreground
= WhitePixel(blackbox
->getXDisplay(), getScreenNumber())
175 ^ BlackPixel(blackbox
->getXDisplay(), getScreenNumber());
176 gcv
.function
= GXxor
;
177 gcv
.subwindow_mode
= IncludeInferiors
;
178 opGC
= XCreateGC(blackbox
->getXDisplay(), getRootWindow(),
179 GCForeground
| GCFunction
| GCSubwindowMode
, &gcv
);
181 const char *s
= i18n(ScreenSet
, ScreenPositionLength
,
182 "0: 0000 x 0: 0000");
183 geom_w
= resource
.wstyle
.font
->measureString(s
) + resource
.bevel_width
* 2;
184 geom_h
= resource
.wstyle
.font
->height() + resource
.bevel_width
* 2;
186 XSetWindowAttributes attrib
;
187 unsigned long mask
= CWBorderPixel
| CWColormap
| CWSaveUnder
;
188 attrib
.border_pixel
= getBorderColor()->pixel();
189 attrib
.colormap
= getColormap();
190 attrib
.save_under
= True
;
192 geom_window
= XCreateWindow(blackbox
->getXDisplay(), getRootWindow(),
193 0, 0, geom_w
, geom_h
, resource
.border_width
,
194 getDepth(), InputOutput
, getVisual(),
196 geom_visible
= False
;
198 BTexture
* texture
= &(resource
.wstyle
.l_focus
);
199 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
200 if (geom_pixmap
== ParentRelative
) {
201 texture
= &(resource
.wstyle
.t_focus
);
202 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
205 XSetWindowBackground(blackbox
->getXDisplay(), geom_window
,
206 texture
->color().pixel());
208 XSetWindowBackgroundPixmap(blackbox
->getXDisplay(),
209 geom_window
, geom_pixmap
);
211 workspacemenu
= new Workspacemenu(this);
212 iconmenu
= new Iconmenu(this);
213 configmenu
= new Configmenu(this);
215 if (resource
.workspaces
> 0) {
216 for (unsigned int i
= 0; i
< resource
.workspaces
; ++i
) {
217 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
218 workspacesList
.push_back(wkspc
);
219 workspacemenu
->insertWorkspace(wkspc
);
220 workspacemenu
->update();
224 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
225 workspacesList
.push_back(wkspc
);
226 workspacemenu
->insertWorkspace(wkspc
);
227 workspacemenu
->update();
229 saveWorkspaceNames();
231 updateNetizenWorkspaceCount();
233 workspacemenu
->insert(i18n(IconSet
, IconIcons
, "Icons"), iconmenu
);
234 workspacemenu
->update();
236 current_workspace
= workspacesList
.front();
238 xatom
->setValue(getRootWindow(), XAtom::net_current_desktop
,
239 XAtom::cardinal
, 0); //first workspace
241 workspacemenu
->setItemSelected(2, True
);
243 toolbar
= new Toolbar(this);
245 slit
= new Slit(this);
249 raiseWindows(0, 0); // this also initializes the empty stacking list
252 updateClientList(); // initialize the client lists, which will be empty
253 updateAvailableArea();
255 changeWorkspaceID(0);
257 unsigned int i
, j
, nchild
;
258 Window r
, p
, *children
;
259 XQueryTree(blackbox
->getXDisplay(), getRootWindow(), &r
, &p
,
262 // preen the window list of all icon windows... for better dockapp support
263 for (i
= 0; i
< nchild
; i
++) {
264 if (children
[i
] == None
) continue;
266 XWMHints
*wmhints
= XGetWMHints(blackbox
->getXDisplay(),
270 if ((wmhints
->flags
& IconWindowHint
) &&
271 (wmhints
->icon_window
!= children
[i
])) {
272 for (j
= 0; j
< nchild
; j
++) {
273 if (children
[j
] == wmhints
->icon_window
) {
284 // manage shown windows
285 for (i
= 0; i
< nchild
; ++i
) {
286 if (children
[i
] == None
|| ! blackbox
->validateWindow(children
[i
]))
289 XWindowAttributes attrib
;
290 if (XGetWindowAttributes(blackbox
->getXDisplay(), children
[i
], &attrib
)) {
291 if (attrib
.override_redirect
) continue;
293 if (attrib
.map_state
!= IsUnmapped
) {
294 manageWindow(children
[i
]);
301 // call this again just in case a window we found updates the Strut list
302 updateAvailableArea();
306 BScreen::~BScreen(void) {
307 if (! managed
) return;
309 if (geom_pixmap
!= None
)
310 image_control
->removeImage(geom_pixmap
);
312 if (geom_window
!= None
)
313 XDestroyWindow(blackbox
->getXDisplay(), geom_window
);
315 std::for_each(workspacesList
.begin(), workspacesList
.end(),
318 std::for_each(iconList
.begin(), iconList
.end(), PointerAssassin());
320 std::for_each(netizenList
.begin(), netizenList
.end(), PointerAssassin());
322 while (! systrayWindowList
.empty())
323 removeSystrayWindow(systrayWindowList
[0]);
326 delete workspacemenu
;
331 delete image_control
;
333 if (resource
.wstyle
.font
)
334 delete resource
.wstyle
.font
;
335 if (resource
.mstyle
.t_font
)
336 delete resource
.mstyle
.t_font
;
337 if (resource
.mstyle
.f_font
)
338 delete resource
.mstyle
.f_font
;
339 if (resource
.tstyle
.font
)
340 delete resource
.tstyle
.font
;
342 XFreeGC(blackbox
->getXDisplay(), opGC
);
346 void BScreen::saveSloppyFocus(bool s
) {
347 resource
.sloppy_focus
= s
;
350 if (resource
.sloppy_focus
) {
351 fmodel
= "SloppyFocus";
352 if (resource
.auto_raise
) fmodel
+= " AutoRaise";
353 if (resource
.click_raise
) fmodel
+= " ClickRaise";
355 fmodel
= "ClickToFocus";
357 config
->setValue(screenstr
+ "focusModel", fmodel
);
361 void BScreen::saveAutoRaise(bool a
) {
362 resource
.auto_raise
= a
;
363 saveSloppyFocus(resource
.sloppy_focus
);
367 void BScreen::saveClickRaise(bool c
) {
368 resource
.click_raise
= c
;
369 saveSloppyFocus(resource
.sloppy_focus
);
373 void BScreen::saveImageDither(bool d
) {
374 image_control
->setDither(d
);
375 config
->setValue(screenstr
+ "imageDither", doImageDither());
379 void BScreen::saveOpaqueMove(bool o
) {
380 resource
.opaque_move
= o
;
381 config
->setValue(screenstr
+ "opaqueMove", resource
.opaque_move
);
385 void BScreen::saveFullMax(bool f
) {
386 resource
.full_max
= f
;
387 config
->setValue(screenstr
+ "fullMaximization", resource
.full_max
);
391 void BScreen::saveFocusNew(bool f
) {
392 resource
.focus_new
= f
;
393 config
->setValue(screenstr
+ "focusNewWindows", resource
.focus_new
);
397 void BScreen::saveFocusLast(bool f
) {
398 resource
.focus_last
= f
;
399 config
->setValue(screenstr
+ "focusLastWindow", resource
.focus_last
);
403 void BScreen::saveAAFonts(bool f
) {
404 resource
.aa_fonts
= f
;
406 config
->setValue(screenstr
+ "antialiasFonts", resource
.aa_fonts
);
410 void BScreen::saveShadowFonts(bool f
) {
411 resource
.shadow_fonts
= f
;
413 config
->setValue(screenstr
+ "dropShadowFonts", resource
.shadow_fonts
);
417 void BScreen::saveHideToolbar(bool h
) {
418 resource
.hide_toolbar
= h
;
419 if (resource
.hide_toolbar
)
420 toolbar
->unmapToolbar();
422 toolbar
->mapToolbar();
423 config
->setValue(screenstr
+ "hideToolbar", resource
.hide_toolbar
);
427 void BScreen::saveWindowToEdgeSnap(int s
) {
428 resource
.snap_to_edges
= s
;
431 switch (resource
.snap_to_edges
) {
432 case WindowNoSnap
: snap
= "NoSnap"; break;
433 case WindowResistance
: snap
= "Resistance"; break;
434 case WindowSnap
: default: snap
= "Snap"; break;
436 config
->setValue(screenstr
+ "windowToEdgeSnap", snap
);
440 void BScreen::saveWindowToWindowSnap(int s
) {
441 resource
.snap_to_windows
= s
;
444 switch (resource
.snap_to_windows
) {
445 case WindowNoSnap
: snap
= "NoSnap"; break;
446 case WindowResistance
: snap
= "Resistance"; break;
447 case WindowSnap
: default: snap
= "Snap"; break;
449 config
->setValue(screenstr
+ "windowToWindowSnap", snap
);
453 void BScreen::saveResizeZones(unsigned int z
) {
454 resource
.resize_zones
= z
;
455 config
->setValue(screenstr
+ "resizeZones", resource
.resize_zones
);
459 void BScreen::saveWindowCornerSnap(bool s
) {
460 resource
.window_corner_snap
= s
;
461 config
->setValue(screenstr
+ "windowCornerSnap",
462 resource
.window_corner_snap
);
466 void BScreen::saveWorkspaces(unsigned int w
) {
467 resource
.workspaces
= w
;
468 config
->setValue(screenstr
+ "workspaces", resource
.workspaces
);
472 void BScreen::savePlacementPolicy(int p
) {
473 resource
.placement_policy
= p
;
474 const char *placement
;
475 switch (resource
.placement_policy
) {
476 case CascadePlacement
: placement
= "CascadePlacement"; break;
477 case UnderMousePlacement
: placement
= "UnderMousePlacement"; break;
478 case ClickMousePlacement
: placement
= "ClickMousePlacement"; break;
479 case ColSmartPlacement
: placement
= "ColSmartPlacement"; break;
480 case RowSmartPlacement
: default: placement
= "RowSmartPlacement"; break;
482 config
->setValue(screenstr
+ "windowPlacement", placement
);
486 void BScreen::saveResistanceSize(int s
) {
487 resource
.resistance_size
= s
;
488 config
->setValue(screenstr
+ "resistanceSize",
489 resource
.resistance_size
);
493 void BScreen::saveSnapThreshold(int t
) {
494 resource
.snap_threshold
= t
;
495 config
->setValue(screenstr
+ "edgeSnapThreshold",
496 resource
.snap_threshold
);
500 void BScreen::saveSnapOffset(int t
) {
501 resource
.snap_offset
= t
;
502 config
->setValue(screenstr
+ "edgeSnapOffset",
503 resource
.snap_offset
);
507 void BScreen::saveRowPlacementDirection(int d
) {
508 resource
.row_direction
= d
;
509 config
->setValue(screenstr
+ "rowPlacementDirection",
510 resource
.row_direction
== LeftRight
?
511 "LeftToRight" : "RightToLeft");
515 void BScreen::saveColPlacementDirection(int d
) {
516 resource
.col_direction
= d
;
517 config
->setValue(screenstr
+ "colPlacementDirection",
518 resource
.col_direction
== TopBottom
?
519 "TopToBottom" : "BottomToTop");
524 void BScreen::saveStrftimeFormat(const std::string
& format
) {
525 resource
.strftime_format
= format
;
526 config
->setValue(screenstr
+ "strftimeFormat", resource
.strftime_format
);
529 #else // !HAVE_STRFTIME
531 void BScreen::saveDateFormat(int f
) {
532 resource
.date_format
= f
;
533 config
->setValue(screenstr
+ "dateFormat",
534 resource
.date_format
== B_EuropeanDate
?
535 "European" : "American");
539 void BScreen::saveClock24Hour(bool c
) {
540 resource
.clock24hour
= c
;
541 config
->setValue(screenstr
+ "clockFormat", resource
.clock24hour
? 24 : 12);
543 #endif // HAVE_STRFTIME
546 void BScreen::saveWorkspaceNames() {
549 for (unsigned int i
= 0; i
< workspacesList
.size(); ++i
) {
550 names
+= workspacesList
[i
]->getName();
551 if (i
< workspacesList
.size() - 1)
555 config
->setValue(screenstr
+ "workspaceNames", names
);
559 void BScreen::savePlaceIgnoreShaded(bool i
) {
560 resource
.ignore_shaded
= i
;
561 config
->setValue(screenstr
+ "placementIgnoreShaded",
562 resource
.ignore_shaded
);
566 void BScreen::savePlaceIgnoreMaximized(bool i
) {
567 resource
.ignore_maximized
= i
;
568 config
->setValue(screenstr
+ "placementIgnoreMaximized",
569 resource
.ignore_maximized
);
573 void BScreen::saveAllowScrollLock(bool a
) {
574 resource
.allow_scroll_lock
= a
;
575 config
->setValue(screenstr
+ "disableBindingsWithScrollLock",
576 resource
.allow_scroll_lock
);
580 void BScreen::saveWorkspaceWarping(bool w
) {
581 resource
.workspace_warping
= w
;
582 config
->setValue(screenstr
+ "workspaceWarping",
583 resource
.workspace_warping
);
587 void BScreen::saveRootScrollDirection(int d
) {
588 resource
.root_scroll
= d
;
590 switch (resource
.root_scroll
) {
591 case NoScroll
: dir
= "None"; break;
592 case ReverseScroll
: dir
= "Reverse"; break;
593 case NormalScroll
: default: dir
= "Normal"; break;
595 config
->setValue(screenstr
+ "rootScrollDirection", dir
);
599 void BScreen::save_rc(void) {
600 saveSloppyFocus(resource
.sloppy_focus
);
601 saveAutoRaise(resource
.auto_raise
);
602 saveImageDither(doImageDither());
603 saveShadowFonts(resource
.shadow_fonts
);
604 saveAAFonts(resource
.aa_fonts
);
605 saveResizeZones(resource
.resize_zones
);
606 saveOpaqueMove(resource
.opaque_move
);
607 saveFullMax(resource
.full_max
);
608 saveFocusNew(resource
.focus_new
);
609 saveFocusLast(resource
.focus_last
);
610 saveHideToolbar(resource
.hide_toolbar
);
611 saveWindowToWindowSnap(resource
.snap_to_windows
);
612 saveWindowToEdgeSnap(resource
.snap_to_edges
);
613 saveWindowCornerSnap(resource
.window_corner_snap
);
614 saveWorkspaces(resource
.workspaces
);
615 savePlacementPolicy(resource
.placement_policy
);
616 saveSnapThreshold(resource
.snap_threshold
);
617 saveSnapOffset(resource
.snap_offset
);
618 saveResistanceSize(resource
.resistance_size
);
619 saveRowPlacementDirection(resource
.row_direction
);
620 saveColPlacementDirection(resource
.col_direction
);
622 saveStrftimeFormat(resource
.strftime_format
);
623 #else // !HAVE_STRFTIME
624 saveDateFormat(resource
.date_format
);
625 savwClock24Hour(resource
.clock24hour
);
626 #endif // HAVE_STRFTIME
627 savePlaceIgnoreShaded(resource
.ignore_shaded
);
628 savePlaceIgnoreMaximized(resource
.ignore_maximized
);
629 saveAllowScrollLock(resource
.allow_scroll_lock
);
630 saveWorkspaceWarping(resource
.workspace_warping
);
631 saveRootScrollDirection(resource
.root_scroll
);
638 void BScreen::load_rc(void) {
642 if (! config
->getValue(screenstr
+ "fullMaximization", resource
.full_max
))
643 resource
.full_max
= false;
645 if (! config
->getValue(screenstr
+ "focusNewWindows", resource
.focus_new
))
646 resource
.focus_new
= false;
648 if (! config
->getValue(screenstr
+ "focusLastWindow", resource
.focus_last
))
649 resource
.focus_last
= false;
651 if (! config
->getValue(screenstr
+ "workspaces", resource
.workspaces
))
652 resource
.workspaces
= 1;
654 if (! config
->getValue(screenstr
+ "opaqueMove", resource
.opaque_move
))
655 resource
.opaque_move
= false;
657 if (! config
->getValue(screenstr
+ "dropShadowFonts", resource
.shadow_fonts
))
658 resource
.shadow_fonts
= true;
660 if (! config
->getValue(screenstr
+ "antialiasFonts", resource
.aa_fonts
))
661 resource
.aa_fonts
= true;
663 if (! config
->getValue(screenstr
+ "resizeZones", resource
.resize_zones
) ||
664 (resource
.resize_zones
!= 1 && resource
.resize_zones
!= 2 &&
665 resource
.resize_zones
!= 4))
666 resource
.resize_zones
= 4;
668 if (! config
->getValue(screenstr
+ "hideToolbar", resource
.hide_toolbar
))
669 resource
.hide_toolbar
= false;
671 resource
.snap_to_windows
= WindowResistance
;
672 if (config
->getValue(screenstr
+ "windowToWindowSnap", s
)) {
674 resource
.snap_to_windows
= WindowNoSnap
;
675 else if (s
== "Snap")
676 resource
.snap_to_windows
= WindowSnap
;
679 resource
.snap_to_edges
= WindowResistance
;
680 if (config
->getValue(screenstr
+ "windowToEdgeSnap", s
)) {
682 resource
.snap_to_edges
= WindowNoSnap
;
683 else if (s
== "Snap")
684 resource
.snap_to_edges
= WindowSnap
;
687 if (! config
->getValue(screenstr
+ "windowCornerSnap",
688 resource
.window_corner_snap
))
689 resource
.window_corner_snap
= true;
691 if (! config
->getValue(screenstr
+ "imageDither", b
))
693 image_control
->setDither(b
);
695 if (! config
->getValue(screenstr
+ "edgeSnapOffset",
696 resource
.snap_offset
))
697 resource
.snap_offset
= 0;
698 if (resource
.snap_offset
> 50) // sanity check, setting this huge would
699 resource
.snap_offset
= 50; // seriously suck.
701 if (! config
->getValue(screenstr
+ "edgeSnapThreshold",
702 resource
.snap_threshold
))
703 resource
.snap_threshold
= 4;
705 if (! config
->getValue(screenstr
+ "resistanceSize",
706 resource
.resistance_size
))
707 resource
.resistance_size
= 18;
709 if (config
->getValue(screenstr
+ "rowPlacementDirection", s
) &&
711 resource
.row_direction
= RightLeft
;
713 resource
.row_direction
= LeftRight
;
715 if (config
->getValue(screenstr
+ "colPlacementDirection", s
) &&
717 resource
.col_direction
= BottomTop
;
719 resource
.col_direction
= TopBottom
;
721 if (config
->getValue(screenstr
+ "workspaceNames", s
)) {
722 XAtom::StringVect workspaceNames
;
724 string::const_iterator it
= s
.begin(), end
= s
.end();
726 string::const_iterator tmp
= it
; // current string.begin()
727 it
= std::find(tmp
, end
, ','); // look for comma between tmp and end
728 workspaceNames
.push_back(string(tmp
, it
)); // s[tmp:it]
734 xatom
->setValue(getRootWindow(), XAtom::net_desktop_names
, XAtom::utf8
,
738 resource
.sloppy_focus
= true;
739 resource
.auto_raise
= false;
740 resource
.click_raise
= false;
741 if (config
->getValue(screenstr
+ "focusModel", s
)) {
742 if (s
.find("ClickToFocus") != string::npos
) {
743 resource
.sloppy_focus
= false;
746 if (s
.find("AutoRaise") != string::npos
)
747 resource
.auto_raise
= true;
748 if (s
.find("ClickRaise") != string::npos
)
749 resource
.click_raise
= true;
753 if (config
->getValue(screenstr
+ "windowPlacement", s
)) {
754 if (s
== "CascadePlacement")
755 resource
.placement_policy
= CascadePlacement
;
756 else if (s
== "UnderMousePlacement")
757 resource
.placement_policy
= UnderMousePlacement
;
758 else if (s
== "ClickMousePlacement")
759 resource
.placement_policy
= ClickMousePlacement
;
760 else if (s
== "ColSmartPlacement")
761 resource
.placement_policy
= ColSmartPlacement
;
762 else //if (s == "RowSmartPlacement")
763 resource
.placement_policy
= RowSmartPlacement
;
765 resource
.placement_policy
= RowSmartPlacement
;
768 if (! config
->getValue(screenstr
+ "strftimeFormat",
769 resource
.strftime_format
))
770 resource
.strftime_format
= "%I:%M %p";
771 #else // !HAVE_STRFTIME
774 if (config
->getValue(screenstr
+ "dateFormat", s
) && s
== "European")
775 resource
.date_format
= B_EuropeanDate
;
777 resource
.date_format
= B_AmericanDate
;
779 if (! config
->getValue(screenstr
+ "clockFormat", l
))
781 resource
.clock24hour
= l
== 24;
782 #endif // HAVE_STRFTIME
784 if (! config
->getValue(screenstr
+ "placementIgnoreShaded",
785 resource
.ignore_shaded
))
786 resource
.ignore_shaded
= true;
788 if (! config
->getValue(screenstr
+ "placementIgnoreMaximized",
789 resource
.ignore_maximized
))
790 resource
.ignore_maximized
= true;
792 if (! config
->getValue(screenstr
+ "disableBindingsWithScrollLock",
793 resource
.allow_scroll_lock
))
794 resource
.allow_scroll_lock
= false;
796 if (! config
->getValue(screenstr
+ "workspaceWarping",
797 resource
.workspace_warping
))
798 resource
.workspace_warping
= false;
800 resource
.root_scroll
= NormalScroll
;
801 if (config
->getValue(screenstr
+ "rootScrollDirection", s
)) {
803 resource
.root_scroll
= NoScroll
;
804 else if (s
== "Reverse")
805 resource
.root_scroll
= ReverseScroll
;
810 void BScreen::changeWorkspaceCount(unsigned int new_count
) {
811 assert(new_count
> 0);
813 if (new_count
< workspacesList
.size()) {
815 for (unsigned int i
= workspacesList
.size(); i
> new_count
; --i
)
816 removeLastWorkspace();
817 // removeLast already sets the current workspace to the
818 // last available one.
819 } else if (new_count
> workspacesList
.size()) {
821 for(unsigned int i
= workspacesList
.size(); i
< new_count
; ++i
)
827 void BScreen::reconfigure(void) {
828 // don't reconfigure while saving the initial rc file, it's a waste and it
829 // breaks somethings (workspace names)
830 if (blackbox
->isStartup()) return;
837 // we need to do this explicitly, because just loading this value from the rc
839 changeWorkspaceCount(resource
.workspaces
);
842 gcv
.foreground
= WhitePixel(blackbox
->getXDisplay(),
844 gcv
.function
= GXinvert
;
845 gcv
.subwindow_mode
= IncludeInferiors
;
846 XChangeGC(blackbox
->getXDisplay(), opGC
,
847 GCForeground
| GCFunction
| GCSubwindowMode
, &gcv
);
849 const char *s
= i18n(ScreenSet
, ScreenPositionLength
,
850 "0: 0000 x 0: 0000");
852 geom_w
= resource
.wstyle
.font
->measureString(s
) + resource
.bevel_width
* 2;
853 geom_h
= resource
.wstyle
.font
->height() + resource
.bevel_width
* 2;
855 BTexture
* texture
= &(resource
.wstyle
.l_focus
);
856 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
857 if (geom_pixmap
== ParentRelative
) {
858 texture
= &(resource
.wstyle
.t_focus
);
859 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
862 XSetWindowBackground(blackbox
->getXDisplay(), geom_window
,
863 texture
->color().pixel());
865 XSetWindowBackgroundPixmap(blackbox
->getXDisplay(),
866 geom_window
, geom_pixmap
);
868 XSetWindowBorderWidth(blackbox
->getXDisplay(), geom_window
,
869 resource
.border_width
);
870 XSetWindowBorder(blackbox
->getXDisplay(), geom_window
,
871 resource
.border_color
.pixel());
873 workspacemenu
->reconfigure();
874 iconmenu
->reconfigure();
876 typedef std::vector
<int> SubList
;
877 SubList remember_subs
;
879 // save the current open menus
880 Basemenu
*menu
= rootmenu
;
882 while ((submenu
= menu
->getCurrentSubmenu()) >= 0) {
883 remember_subs
.push_back(submenu
);
884 menu
= menu
->find(submenu
)->submenu();
890 rootmenu
->reconfigure();
892 // reopen the saved menus
894 const SubList::iterator subs_end
= remember_subs
.end();
895 for (SubList::iterator it
= remember_subs
.begin(); it
!= subs_end
; ++it
) {
896 menu
->drawSubmenu(*it
);
897 menu
= menu
->find(*it
)->submenu();
902 configmenu
->reconfigure();
904 toolbar
->reconfigure();
908 std::for_each(workspacesList
.begin(), workspacesList
.end(),
909 std::mem_fun(&Workspace::reconfigure
));
911 BlackboxWindowList::iterator iit
= iconList
.begin();
912 for (; iit
!= iconList
.end(); ++iit
) {
913 BlackboxWindow
*bw
= *iit
;
914 if (bw
->validateClient())
918 image_control
->timeout();
922 void BScreen::rereadMenu(void) {
926 rootmenu
->reconfigure();
930 void BScreen::LoadStyle(void) {
931 Configuration
style(False
);
933 const char *sfile
= blackbox
->getStyleFilename();
935 style
.setFile(sfile
);
936 if (! style
.load()) {
937 style
.setFile(DEFAULTSTYLE
);
939 style
.create(); // hardcoded default values will be used.
943 // merge in the rc file
944 style
.merge(config
->file(), True
);
948 // load fonts/fontsets
949 if (resource
.wstyle
.font
)
950 delete resource
.wstyle
.font
;
951 if (resource
.tstyle
.font
)
952 delete resource
.tstyle
.font
;
953 if (resource
.mstyle
.f_font
)
954 delete resource
.mstyle
.f_font
;
955 if (resource
.mstyle
.t_font
)
956 delete resource
.mstyle
.t_font
;
957 resource
.wstyle
.font
= resource
.tstyle
.font
= resource
.mstyle
.f_font
=
958 resource
.mstyle
.t_font
= (BFont
*) 0;
960 resource
.wstyle
.font
= readDatabaseFont("window.", style
);
961 resource
.tstyle
.font
= readDatabaseFont("toolbar.", style
);
962 resource
.mstyle
.t_font
= readDatabaseFont("menu.title.", style
);
963 resource
.mstyle
.f_font
= readDatabaseFont("menu.frame.", style
);
965 // load window config
966 resource
.wstyle
.t_focus
=
967 readDatabaseTexture("window.title.focus", "white", style
);
968 resource
.wstyle
.t_unfocus
=
969 readDatabaseTexture("window.title.unfocus", "black", style
);
970 resource
.wstyle
.l_focus
=
971 readDatabaseTexture("window.label.focus", "white", style
);
972 resource
.wstyle
.l_unfocus
=
973 readDatabaseTexture("window.label.unfocus", "black", style
);
974 resource
.wstyle
.h_focus
=
975 readDatabaseTexture("window.handle.focus", "white", style
);
976 resource
.wstyle
.h_unfocus
=
977 readDatabaseTexture("window.handle.unfocus", "black", style
);
978 resource
.wstyle
.g_focus
=
979 readDatabaseTexture("window.grip.focus", "white", style
);
980 resource
.wstyle
.g_unfocus
=
981 readDatabaseTexture("window.grip.unfocus", "black", style
);
982 resource
.wstyle
.b_focus
=
983 readDatabaseTexture("window.button.focus", "white", style
);
984 resource
.wstyle
.b_unfocus
=
985 readDatabaseTexture("window.button.unfocus", "black", style
);
986 resource
.wstyle
.b_pressed
=
987 readDatabaseTexture("window.button.pressed", "black", style
);
989 // we create the window.frame texture by hand because it exists only to
990 // make the code cleaner and is not actually used for display
991 BColor color
= readDatabaseColor("window.frame.focusColor", "white", style
);
992 resource
.wstyle
.f_focus
= BTexture("solid flat", getBaseDisplay(),
993 getScreenNumber(), image_control
);
994 resource
.wstyle
.f_focus
.setColor(color
);
996 color
= readDatabaseColor("window.frame.unfocusColor", "white", style
);
997 resource
.wstyle
.f_unfocus
= BTexture("solid flat", getBaseDisplay(),
998 getScreenNumber(), image_control
);
999 resource
.wstyle
.f_unfocus
.setColor(color
);
1001 resource
.wstyle
.l_text_focus
=
1002 readDatabaseColor("window.label.focus.textColor", "black", style
);
1003 resource
.wstyle
.l_text_unfocus
=
1004 readDatabaseColor("window.label.unfocus.textColor", "white", style
);
1005 resource
.wstyle
.b_pic_focus
=
1006 readDatabaseColor("window.button.focus.picColor", "black", style
);
1007 resource
.wstyle
.b_pic_unfocus
=
1008 readDatabaseColor("window.button.unfocus.picColor", "white", style
);
1010 resource
.wstyle
.justify
= LeftJustify
;
1011 if (style
.getValue("window.justify", s
)) {
1012 if (s
== "right" || s
== "Right")
1013 resource
.wstyle
.justify
= RightJustify
;
1014 else if (s
== "center" || s
== "Center")
1015 resource
.wstyle
.justify
= CenterJustify
;
1019 if (resource
.wstyle
.t_focus
.texture() == BTexture::Parent_Relative
)
1020 resource
.wstyle
.t_focus
= resource
.wstyle
.f_focus
;
1021 if (resource
.wstyle
.t_unfocus
.texture() == BTexture::Parent_Relative
)
1022 resource
.wstyle
.t_unfocus
= resource
.wstyle
.f_unfocus
;
1023 if (resource
.wstyle
.h_focus
.texture() == BTexture::Parent_Relative
)
1024 resource
.wstyle
.h_focus
= resource
.wstyle
.f_focus
;
1025 if (resource
.wstyle
.h_unfocus
.texture() == BTexture::Parent_Relative
)
1026 resource
.wstyle
.h_unfocus
= resource
.wstyle
.f_unfocus
;
1028 // load toolbar config
1029 resource
.tstyle
.toolbar
=
1030 readDatabaseTexture("toolbar", "black", style
);
1031 resource
.tstyle
.label
=
1032 readDatabaseTexture("toolbar.label", "black", style
);
1033 resource
.tstyle
.window
=
1034 readDatabaseTexture("toolbar.windowLabel", "black", style
);
1035 resource
.tstyle
.button
=
1036 readDatabaseTexture("toolbar.button", "white", style
);
1037 resource
.tstyle
.pressed
=
1038 readDatabaseTexture("toolbar.button.pressed", "black", style
);
1039 resource
.tstyle
.clock
=
1040 readDatabaseTexture("toolbar.clock", "black", style
);
1041 resource
.tstyle
.l_text
=
1042 readDatabaseColor("toolbar.label.textColor", "white", style
);
1043 resource
.tstyle
.w_text
=
1044 readDatabaseColor("toolbar.windowLabel.textColor", "white", style
);
1045 resource
.tstyle
.c_text
=
1046 readDatabaseColor("toolbar.clock.textColor", "white", style
);
1047 resource
.tstyle
.b_pic
=
1048 readDatabaseColor("toolbar.button.picColor", "black", style
);
1050 resource
.tstyle
.justify
= LeftJustify
;
1051 if (style
.getValue("toolbar.justify", s
)) {
1052 if (s
== "right" || s
== "Right")
1053 resource
.tstyle
.justify
= RightJustify
;
1054 else if (s
== "center" || s
== "Center")
1055 resource
.tstyle
.justify
= CenterJustify
;
1059 if (resource
.tstyle
.toolbar
.texture() == BTexture::Parent_Relative
) {
1060 resource
.tstyle
.toolbar
= BTexture("solid flat", getBaseDisplay(),
1061 getScreenNumber(), image_control
);
1062 resource
.tstyle
.toolbar
.setColor(BColor("black", getBaseDisplay(),
1063 getScreenNumber()));
1067 resource
.mstyle
.title
=
1068 readDatabaseTexture("menu.title", "white", style
);
1069 resource
.mstyle
.frame
=
1070 readDatabaseTexture("menu.frame", "black", style
);
1071 resource
.mstyle
.hilite
=
1072 readDatabaseTexture("menu.hilite", "white", style
);
1073 resource
.mstyle
.t_text
=
1074 readDatabaseColor("menu.title.textColor", "black", style
);
1075 resource
.mstyle
.f_text
=
1076 readDatabaseColor("menu.frame.textColor", "white", style
);
1077 resource
.mstyle
.d_text
=
1078 readDatabaseColor("menu.frame.disableColor", "black", style
);
1079 resource
.mstyle
.h_text
=
1080 readDatabaseColor("menu.hilite.textColor", "black", style
);
1082 resource
.mstyle
.t_justify
= LeftJustify
;
1083 if (style
.getValue("menu.title.justify", s
)) {
1084 if (s
== "right" || s
== "Right")
1085 resource
.mstyle
.t_justify
= RightJustify
;
1086 else if (s
== "center" || s
== "Center")
1087 resource
.mstyle
.t_justify
= CenterJustify
;
1090 resource
.mstyle
.f_justify
= LeftJustify
;
1091 if (style
.getValue("menu.frame.justify", s
)) {
1092 if (s
== "right" || s
== "Right")
1093 resource
.mstyle
.f_justify
= RightJustify
;
1094 else if (s
== "center" || s
== "Center")
1095 resource
.mstyle
.f_justify
= CenterJustify
;
1098 resource
.mstyle
.bullet
= Basemenu::Triangle
;
1099 if (style
.getValue("menu.bullet", s
)) {
1100 if (s
== "empty" || s
== "Empty")
1101 resource
.mstyle
.bullet
= Basemenu::Empty
;
1102 else if (s
== "square" || s
== "Square")
1103 resource
.mstyle
.bullet
= Basemenu::Square
;
1104 else if (s
== "diamond" || s
== "Diamond")
1105 resource
.mstyle
.bullet
= Basemenu::Diamond
;
1108 resource
.mstyle
.bullet_pos
= Basemenu::Left
;
1109 if (style
.getValue("menu.bullet.position", s
)) {
1110 if (s
== "right" || s
== "Right")
1111 resource
.mstyle
.bullet_pos
= Basemenu::Right
;
1115 if (resource
.mstyle
.frame
.texture() == BTexture::Parent_Relative
) {
1116 resource
.mstyle
.frame
= BTexture("solid flat", getBaseDisplay(),
1117 getScreenNumber(), image_control
);
1118 resource
.mstyle
.frame
.setColor(BColor("black", getBaseDisplay(),
1119 getScreenNumber()));
1122 resource
.border_color
=
1123 readDatabaseColor("borderColor", "black", style
);
1125 // load bevel, border and handle widths
1126 if (! style
.getValue("handleWidth", resource
.handle_width
) ||
1127 resource
.handle_width
> (getWidth() / 2) || resource
.handle_width
== 0)
1128 resource
.handle_width
= 6;
1130 if (! style
.getValue("borderWidth", resource
.border_width
))
1131 resource
.border_width
= 1;
1133 if (! style
.getValue("bevelWidth", resource
.bevel_width
) ||
1134 resource
.bevel_width
> (getWidth() / 2) || resource
.bevel_width
== 0)
1135 resource
.bevel_width
= 3;
1137 if (! style
.getValue("frameWidth", resource
.frame_width
) ||
1138 resource
.frame_width
> (getWidth() / 2))
1139 resource
.frame_width
= resource
.bevel_width
;
1141 if (style
.getValue("rootCommand", s
))
1142 bexec(s
, displayString());
1146 void BScreen::addIcon(BlackboxWindow
*w
) {
1149 w
->setWorkspace(BSENTINEL
);
1150 w
->setWindowNumber(iconList
.size());
1152 iconList
.push_back(w
);
1154 const char* title
= w
->getIconTitle();
1155 iconmenu
->insert(title
);
1160 void BScreen::removeIcon(BlackboxWindow
*w
) {
1165 iconmenu
->remove(w
->getWindowNumber());
1168 BlackboxWindowList::iterator it
= iconList
.begin(),
1169 end
= iconList
.end();
1170 for (int i
= 0; it
!= end
; ++it
)
1171 (*it
)->setWindowNumber(i
++);
1175 BlackboxWindow
*BScreen::getIcon(unsigned int index
) {
1176 if (index
< iconList
.size()) {
1177 BlackboxWindowList::iterator it
= iconList
.begin();
1178 while (index
-- > 0) // increment to index
1183 return (BlackboxWindow
*) 0;
1187 unsigned int BScreen::addWorkspace(void) {
1188 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
1189 workspacesList
.push_back(wkspc
);
1190 saveWorkspaces(getWorkspaceCount());
1191 saveWorkspaceNames();
1193 workspacemenu
->insertWorkspace(wkspc
);
1194 workspacemenu
->update();
1196 toolbar
->reconfigure();
1198 updateNetizenWorkspaceCount();
1200 return workspacesList
.size();
1204 unsigned int BScreen::removeLastWorkspace(void) {
1205 if (workspacesList
.size() == 1)
1208 Workspace
*wkspc
= workspacesList
.back();
1210 if (current_workspace
->getID() == wkspc
->getID())
1211 changeWorkspaceID(current_workspace
->getID() - 1);
1215 workspacemenu
->removeWorkspace(wkspc
);
1216 workspacemenu
->update();
1218 workspacesList
.pop_back();
1221 saveWorkspaces(getWorkspaceCount());
1222 saveWorkspaceNames();
1224 toolbar
->reconfigure();
1226 updateNetizenWorkspaceCount();
1228 return workspacesList
.size();
1232 void BScreen::changeWorkspaceID(unsigned int id
) {
1233 if (! current_workspace
|| id
== current_workspace
->getID()) return;
1235 BlackboxWindow
*focused
= blackbox
->getFocusedWindow();
1236 if (focused
&& focused
->getScreen() == this) {
1237 assert(focused
->isStuck() ||
1238 focused
->getWorkspaceNumber() == current_workspace
->getID());
1240 current_workspace
->setLastFocusedWindow(focused
);
1242 // if no window had focus, no need to store a last focus
1243 current_workspace
->setLastFocusedWindow((BlackboxWindow
*) 0);
1246 // when we switch workspaces, unfocus whatever was focused if it is going
1248 if (focused
&& ! focused
->isStuck())
1249 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1251 current_workspace
->hideAll();
1252 workspacemenu
->setItemSelected(current_workspace
->getID() + 2, False
);
1254 current_workspace
= getWorkspace(id
);
1256 xatom
->setValue(getRootWindow(), XAtom::net_current_desktop
,
1257 XAtom::cardinal
, id
);
1259 workspacemenu
->setItemSelected(current_workspace
->getID() + 2, True
);
1260 toolbar
->redrawWorkspaceLabel(True
);
1262 current_workspace
->showAll();
1267 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
1270 XSync(blackbox
->getXDisplay(), False
);
1272 // If sloppy focus and we can find the client window under the pointer,
1274 if (resource
.sloppy_focus
&&
1275 XQueryPointer(blackbox
->getXDisplay(), getRootWindow(), &r
, &c
,
1276 &rx
, &ry
, &x
, &y
, &m
) &&
1278 if ( (win
= blackbox
->searchWindow(c
)) )
1279 f
= win
->setInputFocus();
1282 // If that fails, and we're doing focus_last, try to focus the last window.
1283 if (! f
&& resource
.focus_last
&&
1284 (win
= current_workspace
->getLastFocusedWindow()))
1285 f
= win
->setInputFocus();
1288 if we found a focus target, then we set the focused window explicitly
1289 because it is possible to switch off this workspace before the x server
1290 generates the FocusIn event for the window. if that happens, openbox would
1291 lose track of what window was the 'LastFocused' window on the workspace.
1293 if we did not find a focus target, then set the current focused window to
1297 blackbox
->setFocusedWindow(win
);
1299 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1301 updateNetizenCurrentWorkspace();
1306 * Set the _NET_CLIENT_LIST root window property.
1308 void BScreen::updateClientList(void) {
1309 if (windowList
.size() > 0) {
1310 Window
*windows
= new Window
[windowList
.size()];
1311 Window
*win_it
= windows
;
1312 BlackboxWindowList::iterator it
= windowList
.begin();
1313 const BlackboxWindowList::iterator end
= windowList
.end();
1314 for (; it
!= end
; ++it
, ++win_it
)
1315 *win_it
= (*it
)->getClientWindow();
1316 xatom
->setValue(getRootWindow(), XAtom::net_client_list
, XAtom::window
,
1317 windows
, windowList
.size());
1320 xatom
->setValue(getRootWindow(), XAtom::net_client_list
, XAtom::window
,
1323 updateStackingList();
1328 * Set the _NET_CLIENT_LIST_STACKING root window property.
1330 void BScreen::updateStackingList(void) {
1332 BlackboxWindowList stack_order
;
1335 * Get the stacking order from all of the workspaces.
1336 * We start with the current workspace so that the sticky windows will be
1337 * in the right order on the current workspace.
1338 * XXX: Do we need to have sticky windows in the list once for each workspace?
1340 getCurrentWorkspace()->appendStackOrder(stack_order
);
1341 for (unsigned int i
= 0; i
< getWorkspaceCount(); ++i
)
1342 if (i
!= getCurrentWorkspaceID())
1343 getWorkspace(i
)->appendStackOrder(stack_order
);
1345 if (stack_order
.size() > 0) {
1346 // set the client list atoms
1347 Window
*windows
= new Window
[stack_order
.size()];
1348 Window
*win_it
= windows
;
1349 BlackboxWindowList::iterator it
= stack_order
.begin(),
1350 end
= stack_order
.end();
1351 for (; it
!= end
; ++it
, ++win_it
)
1352 *win_it
= (*it
)->getClientWindow();
1353 xatom
->setValue(getRootWindow(), XAtom::net_client_list_stacking
,
1354 XAtom::window
, windows
, stack_order
.size());
1357 xatom
->setValue(getRootWindow(), XAtom::net_client_list_stacking
,
1358 XAtom::window
, 0, 0);
1362 void BScreen::addSystrayWindow(Window window
) {
1363 XGrabServer(blackbox
->getXDisplay());
1365 XSelectInput(blackbox
->getXDisplay(), window
, StructureNotifyMask
);
1366 systrayWindowList
.push_back(window
);
1367 xatom
->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows
,
1369 &systrayWindowList
[0], systrayWindowList
.size());
1370 blackbox
->saveSystrayWindowSearch(window
, this);
1372 XUngrabServer(blackbox
->getXDisplay());
1376 void BScreen::removeSystrayWindow(Window window
) {
1377 XGrabServer(blackbox
->getXDisplay());
1379 WindowList::iterator it
= systrayWindowList
.begin();
1380 const WindowList::iterator end
= systrayWindowList
.end();
1381 for (; it
!= end
; ++it
)
1382 if (*it
== window
) {
1383 systrayWindowList
.erase(it
);
1384 xatom
->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows
,
1386 &systrayWindowList
[0], systrayWindowList
.size());
1387 blackbox
->removeSystrayWindowSearch(window
);
1388 XSelectInput(blackbox
->getXDisplay(), window
, NoEventMask
);
1392 assert(it
!= end
); // not a systray window
1394 XUngrabServer(blackbox
->getXDisplay());
1398 void BScreen::manageWindow(Window w
) {
1399 // is the window a KDE systray window?
1401 if (xatom
->getValue(w
, XAtom::kde_net_wm_system_tray_window_for
,
1402 XAtom::window
, systray
) && systray
!= None
) {
1403 addSystrayWindow(w
);
1407 // is the window a docking app
1408 XWMHints
*wmhint
= XGetWMHints(blackbox
->getXDisplay(), w
);
1409 if (wmhint
&& (wmhint
->flags
& StateHint
) &&
1410 wmhint
->initial_state
== WithdrawnState
) {
1415 new BlackboxWindow(blackbox
, w
, this);
1417 BlackboxWindow
*win
= blackbox
->searchWindow(w
);
1421 if (win
->isDesktop()) {
1422 desktopWindowList
.push_back(win
->getFrameWindow());
1423 } else { // if (win->isNormal()) {
1424 // don't list desktop windows as managed windows
1425 windowList
.push_back(win
);
1428 if (win
->isTopmost())
1429 specialWindowList
.push_back(win
->getFrameWindow());
1432 XMapRequestEvent mre
;
1434 if (blackbox
->isStartup() && win
->isNormal()) win
->restoreAttributes();
1435 win
->mapRequestEvent(&mre
);
1439 void BScreen::unmanageWindow(BlackboxWindow
*w
, bool remap
) {
1440 // is the window a KDE systray window?
1442 if (xatom
->getValue(w
->getClientWindow(),
1443 XAtom::kde_net_wm_system_tray_window_for
,
1444 XAtom::window
, systray
) && systray
!= None
) {
1445 removeSystrayWindow(w
->getClientWindow());
1451 // Remove the modality so that its parent won't try to re-focus the window
1452 if (w
->isModal()) w
->setModal(False
);
1454 if (w
->getWorkspaceNumber() != BSENTINEL
&&
1455 w
->getWindowNumber() != BSENTINEL
) {
1456 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1458 for (unsigned int i
= 0; i
< getNumberOfWorkspaces(); ++i
)
1459 if (i
!= w
->getWorkspaceNumber())
1460 getWorkspace(i
)->removeWindow(w
, True
);
1462 } else if (w
->isIconic())
1465 if (w
->isDesktop()) {
1466 WindowList::iterator it
= desktopWindowList
.begin();
1467 const WindowList::iterator end
= desktopWindowList
.end();
1468 for (; it
!= end
; ++it
)
1469 if (*it
== w
->getFrameWindow()) {
1470 desktopWindowList
.erase(it
);
1473 assert(it
!= end
); // the window wasnt a desktop window?
1474 } else { // if (w->isNormal()) {
1475 // we don't list desktop windows as managed windows
1476 windowList
.remove(w
);
1479 if (w
->isTopmost()) {
1480 WindowList::iterator it
= specialWindowList
.begin();
1481 const WindowList::iterator end
= specialWindowList
.end();
1482 for (; it
!= end
; ++it
)
1483 if (*it
== w
->getFrameWindow()) {
1484 specialWindowList
.erase(it
);
1487 assert(it
!= end
); // the window wasnt a special window?
1491 if (blackbox
->getFocusedWindow() == w
)
1492 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1494 removeNetizen(w
->getClientWindow());
1497 some managed windows can also be window group controllers. when
1498 unmanaging such windows, we should also delete the window group.
1500 BWindowGroup
*group
= blackbox
->searchGroup(w
->getClientWindow());
1507 void BScreen::addNetizen(Netizen
*n
) {
1508 netizenList
.push_back(n
);
1510 n
->sendWorkspaceCount();
1511 n
->sendCurrentWorkspace();
1513 WorkspaceList::iterator it
= workspacesList
.begin();
1514 const WorkspaceList::iterator end
= workspacesList
.end();
1515 for (; it
!= end
; ++it
)
1516 (*it
)->sendWindowList(*n
);
1518 Window f
= ((blackbox
->getFocusedWindow()) ?
1519 blackbox
->getFocusedWindow()->getClientWindow() : None
);
1520 n
->sendWindowFocus(f
);
1524 void BScreen::removeNetizen(Window w
) {
1525 NetizenList::iterator it
= netizenList
.begin();
1526 for (; it
!= netizenList
.end(); ++it
) {
1527 if ((*it
)->getWindowID() == w
) {
1529 netizenList
.erase(it
);
1536 void BScreen::updateWorkArea(void) {
1537 if (workspacesList
.size() > 0) {
1538 unsigned long *dims
= new unsigned long[4 * workspacesList
.size()];
1539 for (unsigned int i
= 0, m
= workspacesList
.size(); i
< m
; ++i
) {
1540 // XXX: this could be different for each workspace
1541 const Rect
&area
= availableArea();
1542 dims
[(i
* 4) + 0] = area
.x();
1543 dims
[(i
* 4) + 1] = area
.y();
1544 dims
[(i
* 4) + 2] = area
.width();
1545 dims
[(i
* 4) + 3] = area
.height();
1547 xatom
->setValue(getRootWindow(), XAtom::net_workarea
, XAtom::cardinal
,
1548 dims
, 4 * workspacesList
.size());
1551 xatom
->setValue(getRootWindow(), XAtom::net_workarea
, XAtom::cardinal
,
1556 void BScreen::updateNetizenCurrentWorkspace(void) {
1557 std::for_each(netizenList
.begin(), netizenList
.end(),
1558 std::mem_fun(&Netizen::sendCurrentWorkspace
));
1562 void BScreen::updateNetizenWorkspaceCount(void) {
1563 xatom
->setValue(getRootWindow(), XAtom::net_number_of_desktops
,
1564 XAtom::cardinal
, workspacesList
.size());
1568 std::for_each(netizenList
.begin(), netizenList
.end(),
1569 std::mem_fun(&Netizen::sendWorkspaceCount
));
1573 void BScreen::updateNetizenWindowFocus(void) {
1574 Window f
= ((blackbox
->getFocusedWindow()) ?
1575 blackbox
->getFocusedWindow()->getClientWindow() : None
);
1577 xatom
->setValue(getRootWindow(), XAtom::net_active_window
,
1580 NetizenList::iterator it
= netizenList
.begin();
1581 for (; it
!= netizenList
.end(); ++it
)
1582 (*it
)->sendWindowFocus(f
);
1586 void BScreen::updateNetizenWindowAdd(Window w
, unsigned long p
) {
1587 NetizenList::iterator it
= netizenList
.begin();
1588 for (; it
!= netizenList
.end(); ++it
) {
1589 (*it
)->sendWindowAdd(w
, p
);
1594 void BScreen::updateNetizenWindowDel(Window w
) {
1595 NetizenList::iterator it
= netizenList
.begin();
1596 for (; it
!= netizenList
.end(); ++it
)
1597 (*it
)->sendWindowDel(w
);
1601 void BScreen::updateNetizenWindowRaise(Window w
) {
1602 NetizenList::iterator it
= netizenList
.begin();
1603 for (; it
!= netizenList
.end(); ++it
)
1604 (*it
)->sendWindowRaise(w
);
1608 void BScreen::updateNetizenWindowLower(Window w
) {
1609 NetizenList::iterator it
= netizenList
.begin();
1610 for (; it
!= netizenList
.end(); ++it
)
1611 (*it
)->sendWindowLower(w
);
1615 void BScreen::updateNetizenConfigNotify(XEvent
*e
) {
1616 NetizenList::iterator it
= netizenList
.begin();
1617 for (; it
!= netizenList
.end(); ++it
)
1618 (*it
)->sendConfigNotify(e
);
1622 void BScreen::raiseWindows(Window
*workspace_stack
, unsigned int num
) {
1623 // the 13 represents the number of blackbox windows such as menus
1629 Window
*session_stack
= new
1630 Window
[(num
+ workspacesList
.size() + rootmenuList
.size() +
1631 specialWindowList
.size() + bbwins
)];
1632 unsigned int i
= 0, k
= num
;
1634 XRaiseWindow(blackbox
->getXDisplay(), iconmenu
->getWindowID());
1635 *(session_stack
+ i
++) = iconmenu
->getWindowID();
1637 WorkspaceList::iterator wit
= workspacesList
.begin();
1638 const WorkspaceList::iterator w_end
= workspacesList
.end();
1639 for (; wit
!= w_end
; ++wit
)
1640 *(session_stack
+ i
++) = (*wit
)->getMenu()->getWindowID();
1642 *(session_stack
+ i
++) = workspacemenu
->getWindowID();
1644 *(session_stack
+ i
++) = configmenu
->getFocusmenu()->getWindowID();
1645 *(session_stack
+ i
++) = configmenu
->getPlacementmenu()->getWindowID();
1646 *(session_stack
+ i
++) = configmenu
->getWindowSnapmenu()->getWindowID();
1647 *(session_stack
+ i
++) = configmenu
->getEdgeSnapmenu()->getWindowID();
1649 *(session_stack
+ i
++) = configmenu
->getXineramamenu()->getWindowID();
1651 *(session_stack
+ i
++) = configmenu
->getWindowID();
1653 *(session_stack
+ i
++) = slit
->getMenu()->getDirectionmenu()->getWindowID();
1654 *(session_stack
+ i
++) = slit
->getMenu()->getPlacementmenu()->getWindowID();
1655 *(session_stack
+ i
++) = slit
->getMenu()->getWindowID();
1657 *(session_stack
+ i
++) =
1658 toolbar
->getMenu()->getPlacementmenu()->getWindowID();
1659 *(session_stack
+ i
++) = toolbar
->getMenu()->getWindowID();
1661 RootmenuList::iterator rit
= rootmenuList
.begin();
1662 for (; rit
!= rootmenuList
.end(); ++rit
)
1663 *(session_stack
+ i
++) = (*rit
)->getWindowID();
1664 *(session_stack
+ i
++) = rootmenu
->getWindowID();
1666 if (toolbar
->isOnTop())
1667 *(session_stack
+ i
++) = toolbar
->getWindowID();
1669 if (slit
->isOnTop())
1670 *(session_stack
+ i
++) = slit
->getWindowID();
1672 WindowList::iterator sit
, send
= specialWindowList
.end();
1673 for (sit
= specialWindowList
.begin(); sit
!= send
; ++sit
)
1674 *(session_stack
+ i
++) = *sit
;
1677 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
1679 XRestackWindows(blackbox
->getXDisplay(), session_stack
, i
);
1681 delete [] session_stack
;
1683 updateStackingList();
1687 void BScreen::lowerWindows(Window
*workspace_stack
, unsigned int num
) {
1688 assert(num
> 0); // this would cause trouble in the XRaiseWindow call
1690 Window
*session_stack
= new Window
[(num
+ desktopWindowList
.size())];
1691 unsigned int i
= 0, k
= num
;
1693 XLowerWindow(blackbox
->getXDisplay(), workspace_stack
[0]);
1696 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
1698 WindowList::iterator dit
= desktopWindowList
.begin();
1699 const WindowList::iterator d_end
= desktopWindowList
.end();
1700 for (; dit
!= d_end
; ++dit
)
1701 *(session_stack
+ i
++) = *dit
;
1703 XRestackWindows(blackbox
->getXDisplay(), session_stack
, i
);
1705 delete [] session_stack
;
1707 updateStackingList();
1711 void BScreen::reassociateWindow(BlackboxWindow
*w
, unsigned int wkspc_id
,
1712 bool ignore_sticky
) {
1715 if (wkspc_id
== BSENTINEL
)
1716 wkspc_id
= current_workspace
->getID();
1718 if (w
->getWorkspaceNumber() == wkspc_id
)
1721 if (w
->isIconic()) {
1723 getWorkspace(wkspc_id
)->addWindow(w
);
1725 for (unsigned int i
= 0; i
< getNumberOfWorkspaces(); ++i
)
1726 if (i
!= w
->getWorkspaceNumber())
1727 getWorkspace(i
)->addWindow(w
, True
);
1728 } else if (ignore_sticky
|| ! w
->isStuck()) {
1731 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1732 getWorkspace(wkspc_id
)->addWindow(w
);
1734 updateStackingList();
1738 void BScreen::propagateWindowName(const BlackboxWindow
*bw
) {
1739 if (bw
->isIconic()) {
1740 iconmenu
->changeItemLabel(bw
->getWindowNumber(), bw
->getIconTitle());
1744 Clientmenu
*clientmenu
= getWorkspace(bw
->getWorkspaceNumber())->getMenu();
1745 clientmenu
->changeItemLabel(bw
->getWindowNumber(), bw
->getTitle());
1746 clientmenu
->update();
1748 if (blackbox
->getFocusedWindow() == bw
)
1749 toolbar
->redrawWindowLabel(True
);
1754 void BScreen::nextFocus(void) {
1755 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1759 // if window is not on this screen, ignore it
1760 if (focused
->getScreen()->getScreenNumber() != getScreenNumber())
1761 focused
= (BlackboxWindow
*) 0;
1764 if (focused
&& current_workspace
->getCount() > 1) {
1765 // next is the next window to recieve focus, current is a place holder
1766 BlackboxWindow
*current
;
1769 next
= current_workspace
->getNextWindowInList(current
);
1770 } while(! next
->setInputFocus() && next
!= focused
);
1772 if (next
!= focused
)
1773 current_workspace
->raiseWindow(next
);
1774 } else if (current_workspace
->getCount() >= 1) {
1775 next
= current_workspace
->getTopWindowOnStack();
1777 current_workspace
->raiseWindow(next
);
1778 next
->setInputFocus();
1783 void BScreen::prevFocus(void) {
1784 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1788 // if window is not on this screen, ignore it
1789 if (focused
->getScreen()->getScreenNumber() != getScreenNumber())
1790 focused
= (BlackboxWindow
*) 0;
1793 if (focused
&& current_workspace
->getCount() > 1) {
1794 // next is the next window to recieve focus, current is a place holder
1795 BlackboxWindow
*current
;
1798 next
= current_workspace
->getPrevWindowInList(current
);
1799 } while(! next
->setInputFocus() && next
!= focused
);
1801 if (next
!= focused
)
1802 current_workspace
->raiseWindow(next
);
1803 } else if (current_workspace
->getCount() >= 1) {
1804 next
= current_workspace
->getTopWindowOnStack();
1806 current_workspace
->raiseWindow(next
);
1807 next
->setInputFocus();
1812 void BScreen::raiseFocus(void) {
1813 BlackboxWindow
*focused
= blackbox
->getFocusedWindow();
1817 // if on this Screen, raise it
1818 if (focused
->getScreen()->getScreenNumber() == getScreenNumber()) {
1819 Workspace
*workspace
= getWorkspace(focused
->getWorkspaceNumber());
1820 workspace
->raiseWindow(focused
);
1825 void BScreen::InitMenu(void) {
1827 rootmenuList
.clear();
1829 while (rootmenu
->getCount())
1830 rootmenu
->remove(0);
1832 rootmenu
= new Rootmenu(this);
1834 bool defaultMenu
= True
;
1836 FILE *menu_file
= (FILE *) 0;
1837 const char *menu_filename
= blackbox
->getMenuFilename();
1840 if (! (menu_file
= fopen(menu_filename
, "r")))
1841 perror(menu_filename
);
1842 if (! menu_file
) { // opening the menu file failed, try the default menu
1843 menu_filename
= DEFAULTMENU
;
1844 if (! (menu_file
= fopen(menu_filename
, "r")))
1845 perror(menu_filename
);
1849 if (feof(menu_file
)) {
1850 fprintf(stderr
, i18n(ScreenSet
, ScreenEmptyMenuFile
,
1851 "%s: Empty menu file"),
1854 char line
[1024], label
[1024];
1855 memset(line
, 0, 1024);
1856 memset(label
, 0, 1024);
1858 while (fgets(line
, 1024, menu_file
) && ! feof(menu_file
)) {
1862 int i
, key
= 0, index
= -1, len
= strlen(line
);
1864 for (i
= 0; i
< len
; i
++) {
1865 if (line
[i
] == '[') index
= 0;
1866 else if (line
[i
] == ']') break;
1867 else if (line
[i
] != ' ')
1869 key
+= tolower(line
[i
]);
1872 if (key
== 517) { // [begin]
1874 for (i
= index
; i
< len
; i
++) {
1875 if (line
[i
] == '(') index
= 0;
1876 else if (line
[i
] == ')') break;
1877 else if (index
++ >= 0) {
1878 if (line
[i
] == '\\' && i
< len
- 1) i
++;
1879 label
[index
- 1] = line
[i
];
1883 if (index
== -1) index
= 0;
1884 label
[index
] = '\0';
1886 rootmenu
->setLabel(label
);
1887 defaultMenu
= parseMenuFile(menu_file
, rootmenu
);
1889 blackbox
->addMenuTimestamp(menu_filename
);
1898 rootmenu
->setInternalMenu();
1899 rootmenu
->insert(i18n(ScreenSet
, Screenxterm
, "xterm"),
1901 i18n(ScreenSet
, Screenxterm
, "xterm"));
1902 rootmenu
->insert(i18n(ScreenSet
, ScreenRestart
, "Restart"),
1904 rootmenu
->insert(i18n(ScreenSet
, ScreenExit
, "Exit"),
1906 rootmenu
->setLabel(i18n(BasemenuSet
, BasemenuBlackboxMenu
,
1913 size_t string_within(char begin
, char end
,
1914 const char *input
, size_t start_at
, size_t length
,
1918 size_t i
= start_at
;
1919 for (; i
< length
; ++i
) {
1920 if (input
[i
] == begin
) {
1922 } else if (input
[i
] == end
) {
1925 if (input
[i
] == '\\' && i
< length
- 1) i
++;
1926 output
[index
++] = input
[i
];
1931 output
[index
] = '\0';
1939 bool BScreen::parseMenuFile(FILE *file
, Rootmenu
*menu
) {
1940 char line
[1024], keyword
[1024], label
[1024], command
[1024];
1943 while (! (done
|| feof(file
))) {
1944 memset(line
, 0, 1024);
1945 memset(label
, 0, 1024);
1946 memset(command
, 0, 1024);
1948 if (! fgets(line
, 1024, file
))
1951 if (line
[0] == '#') // comment, skip it
1954 size_t line_length
= strlen(line
);
1955 unsigned int key
= 0;
1957 // get the keyword enclosed in []'s
1958 size_t pos
= string_within('[', ']', line
, 0, line_length
, keyword
);
1960 if (keyword
[0] == '\0') { // no keyword, no menu entry
1963 size_t len
= strlen(keyword
);
1964 for (size_t i
= 0; i
< len
; ++i
) {
1965 if (keyword
[i
] != ' ')
1966 key
+= tolower(keyword
[i
]);
1970 // get the label enclosed in ()'s
1971 pos
= string_within('(', ')', line
, pos
, line_length
, label
);
1973 // get the command enclosed in {}'s
1974 pos
= string_within('{', '}', line
, pos
, line_length
, command
);
1985 menu
->insert(label
);
1990 if (! (*label
&& *command
)) {
1991 fprintf(stderr
, i18n(ScreenSet
, ScreenEXECError
,
1992 "BScreen::parseMenuFile: [exec] error, "
1993 "no menu label and/or command defined\n"));
1997 menu
->insert(label
, BScreen::Execute
, command
);
2003 fprintf(stderr
, i18n(ScreenSet
, ScreenEXITError
,
2004 "BScreen::parseMenuFile: [exit] error, "
2005 "no menu label defined\n"));
2009 menu
->insert(label
, BScreen::Exit
);
2013 case 561: { // style
2014 if (! (*label
&& *command
)) {
2016 i18n(ScreenSet
, ScreenSTYLEError
,
2017 "BScreen::parseMenuFile: [style] error, "
2018 "no menu label and/or filename defined\n"));
2022 string style
= expandTilde(command
);
2024 menu
->insert(label
, BScreen::SetStyle
, style
.c_str());
2030 fprintf(stderr
, i18n(ScreenSet
, ScreenCONFIGError
,
2031 "BScreen::parseMenufile: [config] error, "
2032 "no label defined"));
2036 menu
->insert(label
, configmenu
);
2040 case 740: { // include
2042 fprintf(stderr
, i18n(ScreenSet
, ScreenINCLUDEError
,
2043 "BScreen::parseMenuFile: [include] error, "
2044 "no filename defined\n"));
2048 string newfile
= expandTilde(label
);
2049 FILE *submenufile
= fopen(newfile
.c_str(), "r");
2051 if (! submenufile
) {
2052 perror(newfile
.c_str());
2057 if (fstat(fileno(submenufile
), &buf
) ||
2058 ! S_ISREG(buf
.st_mode
)) {
2060 i18n(ScreenSet
, ScreenINCLUDEErrorReg
,
2061 "BScreen::parseMenuFile: [include] error: "
2062 "'%s' is not a regular file\n"), newfile
.c_str());
2066 if (! feof(submenufile
)) {
2067 if (! parseMenuFile(submenufile
, menu
))
2068 blackbox
->addMenuTimestamp(newfile
);
2070 fclose(submenufile
);
2076 case 767: { // submenu
2078 fprintf(stderr
, i18n(ScreenSet
, ScreenSUBMENUError
,
2079 "BScreen::parseMenuFile: [submenu] error, "
2080 "no menu label defined\n"));
2084 Rootmenu
*submenu
= new Rootmenu(this);
2087 submenu
->setLabel(command
);
2089 submenu
->setLabel(label
);
2091 parseMenuFile(file
, submenu
);
2093 menu
->insert(label
, submenu
);
2094 rootmenuList
.push_back(submenu
);
2099 case 773: { // restart
2101 fprintf(stderr
, i18n(ScreenSet
, ScreenRESTARTError
,
2102 "BScreen::parseMenuFile: [restart] error, "
2103 "no menu label defined\n"));
2108 menu
->insert(label
, BScreen::RestartOther
, command
);
2110 menu
->insert(label
, BScreen::Restart
);
2115 case 845: { // reconfig
2118 i18n(ScreenSet
, ScreenRECONFIGError
,
2119 "BScreen::parseMenuFile: [reconfig] error, "
2120 "no menu label defined\n"));
2124 menu
->insert(label
, BScreen::Reconfigure
);
2129 case 995: // stylesdir
2130 case 1113: { // stylesmenu
2131 bool newmenu
= ((key
== 1113) ? True
: False
);
2133 if (! *label
|| (! *command
&& newmenu
)) {
2135 i18n(ScreenSet
, ScreenSTYLESDIRError
,
2136 "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
2137 " error, no directory defined\n"));
2141 char *directory
= ((newmenu
) ? command
: label
);
2143 string stylesdir
= expandTilde(directory
);
2145 struct stat statbuf
;
2147 if (stat(stylesdir
.c_str(), &statbuf
) == -1) {
2149 i18n(ScreenSet
, ScreenSTYLESDIRErrorNoExist
,
2150 "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
2151 " error, %s does not exist\n"), stylesdir
.c_str());
2154 if (! S_ISDIR(statbuf
.st_mode
)) {
2156 i18n(ScreenSet
, ScreenSTYLESDIRErrorNotDir
,
2157 "BScreen::parseMenuFile:"
2158 " [stylesdir/stylesmenu] error, %s is not a"
2159 " directory\n"), stylesdir
.c_str());
2163 Rootmenu
*stylesmenu
;
2166 stylesmenu
= new Rootmenu(this);
2170 DIR *d
= opendir(stylesdir
.c_str());
2172 std::vector
<string
> ls
;
2174 while((p
= readdir(d
)))
2175 ls
.push_back(p
->d_name
);
2179 std::sort(ls
.begin(), ls
.end());
2181 std::vector
<string
>::iterator it
= ls
.begin(),
2183 for (; it
!= end
; ++it
) {
2184 const string
& fname
= *it
;
2186 if (fname
[fname
.size()-1] == '~')
2189 string style
= stylesdir
;
2193 if (! stat(style
.c_str(), &statbuf
) && S_ISREG(statbuf
.st_mode
))
2194 stylesmenu
->insert(fname
, BScreen::SetStyle
, style
);
2197 stylesmenu
->update();
2200 stylesmenu
->setLabel(label
);
2201 menu
->insert(label
, stylesmenu
);
2202 rootmenuList
.push_back(stylesmenu
);
2205 blackbox
->addMenuTimestamp(stylesdir
);
2209 case 1090: { // workspaces
2212 i18n(ScreenSet
, ScreenWORKSPACESError
,
2213 "BScreen:parseMenuFile: [workspaces] error, "
2214 "no menu label defined\n"));
2218 menu
->insert(label
, workspacemenu
);
2224 return ((menu
->getCount() == 0) ? True
: False
);
2228 void BScreen::shutdown(void) {
2229 XSelectInput(blackbox
->getXDisplay(), getRootWindow(), NoEventMask
);
2230 XSync(blackbox
->getXDisplay(), False
);
2232 while(! windowList
.empty())
2233 unmanageWindow(windowList
.front(), True
);
2235 while(! desktopWindowList
.empty()) {
2236 BlackboxWindow
*win
= blackbox
->searchWindow(desktopWindowList
.front());
2238 unmanageWindow(win
, True
);
2245 void BScreen::showPosition(int x
, int y
) {
2246 if (! geom_visible
) {
2247 XMoveResizeWindow(blackbox
->getXDisplay(), geom_window
,
2248 (getWidth() - geom_w
) / 2,
2249 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
2250 XMapWindow(blackbox
->getXDisplay(), geom_window
);
2251 XRaiseWindow(blackbox
->getXDisplay(), geom_window
);
2253 geom_visible
= True
;
2258 sprintf(label
, i18n(ScreenSet
, ScreenPositionFormat
,
2259 "X: %4d x Y: %4d"), x
, y
);
2261 XClearWindow(blackbox
->getXDisplay(), geom_window
);
2263 resource
.wstyle
.font
->drawString(geom_window
,
2264 resource
.bevel_width
, resource
.bevel_width
,
2265 resource
.wstyle
.l_text_focus
,
2270 void BScreen::showGeometry(unsigned int gx
, unsigned int gy
) {
2271 if (! geom_visible
) {
2272 XMoveResizeWindow(blackbox
->getXDisplay(), geom_window
,
2273 (getWidth() - geom_w
) / 2,
2274 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
2275 XMapWindow(blackbox
->getXDisplay(), geom_window
);
2276 XRaiseWindow(blackbox
->getXDisplay(), geom_window
);
2278 geom_visible
= True
;
2283 sprintf(label
, i18n(ScreenSet
, ScreenGeometryFormat
,
2284 "W: %4d x H: %4d"), gx
, gy
);
2286 XClearWindow(blackbox
->getXDisplay(), geom_window
);
2288 resource
.wstyle
.font
->drawString(geom_window
,
2289 resource
.bevel_width
, resource
.bevel_width
,
2290 resource
.wstyle
.l_text_focus
,
2295 void BScreen::hideGeometry(void) {
2297 XUnmapWindow(blackbox
->getXDisplay(), geom_window
);
2298 geom_visible
= False
;
2303 void BScreen::addStrut(Strut
*strut
) {
2304 strutList
.push_back(strut
);
2308 void BScreen::removeStrut(Strut
*strut
) {
2309 strutList
.remove(strut
);
2313 const Rect
& BScreen::availableArea(void) const {
2315 return getRect(); // return the full screen
2321 const RectList
& BScreen::allAvailableAreas(void) const {
2322 assert(isXineramaActive());
2323 assert(xineramaUsableArea
.size() > 0);
2324 fprintf(stderr
, "1found x %d y %d w %d h %d\n",
2325 xineramaUsableArea
[0].x(), xineramaUsableArea
[0].y(),
2326 xineramaUsableArea
[0].width(), xineramaUsableArea
[0].height());
2327 return xineramaUsableArea
;
2332 void BScreen::updateAvailableArea(void) {
2333 Rect old_area
= usableArea
;
2334 usableArea
= getRect(); // reset to full screen
2337 // reset to the full areas
2338 if (isXineramaActive())
2339 xineramaUsableArea
= getXineramaAreas();
2342 /* these values represent offsets from the screen edge
2343 * we look for the biggest offset on each edge and then apply them
2345 * do not be confused by the similarity to the names of Rect's members
2347 unsigned int current_left
= 0, current_right
= 0, current_top
= 0,
2350 StrutList::const_iterator it
= strutList
.begin(), end
= strutList
.end();
2352 for(; it
!= end
; ++it
) {
2354 if (strut
->left
> current_left
)
2355 current_left
= strut
->left
;
2356 if (strut
->top
> current_top
)
2357 current_top
= strut
->top
;
2358 if (strut
->right
> current_right
)
2359 current_right
= strut
->right
;
2360 if (strut
->bottom
> current_bottom
)
2361 current_bottom
= strut
->bottom
;
2364 usableArea
.setPos(current_left
, current_top
);
2365 usableArea
.setSize(usableArea
.width() - (current_left
+ current_right
),
2366 usableArea
.height() - (current_top
+ current_bottom
));
2369 if (isXineramaActive()) {
2370 // keep each of the ximerama-defined areas inside the strut
2371 RectList::iterator xit
, xend
= xineramaUsableArea
.end();
2372 for (xit
= xineramaUsableArea
.begin(); xit
!= xend
; ++xit
) {
2373 if (xit
->x() < usableArea
.x()) {
2374 xit
->setX(usableArea
.x());
2375 xit
->setWidth(xit
->width() - usableArea
.x());
2377 if (xit
->y() < usableArea
.y()) {
2378 xit
->setY(usableArea
.y());
2379 xit
->setHeight(xit
->height() - usableArea
.y());
2381 if (xit
->x() + xit
->width() > usableArea
.width())
2382 xit
->setWidth(usableArea
.width() - xit
->x());
2383 if (xit
->y() + xit
->height() > usableArea
.height())
2384 xit
->setHeight(usableArea
.height() - xit
->y());
2389 if (old_area
!= usableArea
) {
2390 BlackboxWindowList::iterator it
= windowList
.begin(),
2391 end
= windowList
.end();
2392 for (; it
!= end
; ++it
)
2393 if ((*it
)->isMaximized()) (*it
)->remaximize();
2400 Workspace
* BScreen::getWorkspace(unsigned int index
) {
2401 assert(index
< workspacesList
.size());
2402 return workspacesList
[index
];
2406 void BScreen::buttonPressEvent(const XButtonEvent
*xbutton
) {
2407 if (xbutton
->button
== 1) {
2408 if (! isRootColormapInstalled())
2409 image_control
->installRootColormap();
2411 if (workspacemenu
->isVisible())
2412 workspacemenu
->hide();
2414 if (rootmenu
->isVisible())
2416 } else if (xbutton
->button
== 2) {
2417 showWorkspaceMenu(xbutton
->x_root
, xbutton
->y_root
);
2418 } else if (xbutton
->button
== 3) {
2419 showRootMenu(xbutton
->x_root
, xbutton
->y_root
);
2421 } else if ((xbutton
->button
== 4 && resource
.root_scroll
== NormalScroll
) ||
2422 (xbutton
->button
== 5 && resource
.root_scroll
== ReverseScroll
)) {
2423 if (getCurrentWorkspaceID() >= getWorkspaceCount() - 1)
2424 changeWorkspaceID(0);
2426 changeWorkspaceID(getCurrentWorkspaceID() + 1);
2428 } else if ((xbutton
->button
== 5 && resource
.root_scroll
== NormalScroll
) ||
2429 (xbutton
->button
== 4 && resource
.root_scroll
== ReverseScroll
)) {
2430 if (getCurrentWorkspaceID() == 0)
2431 changeWorkspaceID(getWorkspaceCount() - 1);
2433 changeWorkspaceID(getCurrentWorkspaceID() - 1);
2438 void BScreen::showWorkspaceMenu(int x
, int y
) {
2439 int mx
= x
- (workspacemenu
->getWidth() / 2);
2440 int my
= y
- (workspacemenu
->getTitleHeight() / 2);
2445 if (mx
+ workspacemenu
->getWidth() > getWidth())
2446 mx
= getWidth() - workspacemenu
->getWidth() - getBorderWidth();
2448 if (my
+ workspacemenu
->getHeight() > getHeight())
2449 my
= getHeight() - workspacemenu
->getHeight() - getBorderWidth();
2451 workspacemenu
->move(mx
, my
);
2453 if (! workspacemenu
->isVisible()) {
2454 workspacemenu
->removeParent();
2455 workspacemenu
->show();
2460 void BScreen::showRootMenu(int x
, int y
) {
2461 int mx
= x
- (rootmenu
->getWidth() / 2);
2462 int my
= y
- (rootmenu
->getTitleHeight() / 2);
2467 if (mx
+ rootmenu
->getWidth() > getWidth())
2468 mx
= getWidth() - rootmenu
->getWidth() - getBorderWidth();
2470 if (my
+ rootmenu
->getHeight() > getHeight())
2471 my
= getHeight() - rootmenu
->getHeight() - getBorderWidth();
2473 rootmenu
->move(mx
, my
);
2475 if (! rootmenu
->isVisible()) {
2476 blackbox
->checkMenu();
2482 void BScreen::propertyNotifyEvent(const XPropertyEvent
*pe
) {
2483 if (pe
->atom
== xatom
->getAtom(XAtom::net_desktop_names
)) {
2484 // _NET_WM_DESKTOP_NAMES
2485 WorkspaceList::iterator it
= workspacesList
.begin();
2486 const WorkspaceList::iterator end
= workspacesList
.end();
2487 for (; it
!= end
; ++it
) {
2488 (*it
)->readName(); // re-read its name from the window property
2489 workspacemenu
->changeWorkspaceLabel((*it
)->getID(), (*it
)->getName());
2491 workspacemenu
->update();
2492 toolbar
->reconfigure();
2493 saveWorkspaceNames();
2498 void BScreen::toggleFocusModel(FocusModel model
) {
2499 std::for_each(windowList
.begin(), windowList
.end(),
2500 std::mem_fun(&BlackboxWindow::ungrabButtons
));
2502 if (model
== SloppyFocus
) {
2503 saveSloppyFocus(True
);
2505 // we're cheating here to save writing the config file 3 times
2506 resource
.auto_raise
= False
;
2507 resource
.click_raise
= False
;
2508 saveSloppyFocus(False
);
2511 std::for_each(windowList
.begin(), windowList
.end(),
2512 std::mem_fun(&BlackboxWindow::grabButtons
));
2516 BTexture
BScreen::readDatabaseTexture(const string
&rname
,
2517 const string
&default_color
,
2518 const Configuration
&style
) {
2522 if (style
.getValue(rname
, s
))
2523 texture
= BTexture(s
);
2525 texture
.setTexture(BTexture::Solid
| BTexture::Flat
);
2527 // associate this texture with this screen
2528 texture
.setDisplay(getBaseDisplay(), getScreenNumber());
2529 texture
.setImageControl(image_control
);
2531 texture
.setColor(readDatabaseColor(rname
+ ".color", default_color
, style
));
2532 texture
.setColorTo(readDatabaseColor(rname
+ ".colorTo", default_color
,
2534 texture
.setBorderColor(readDatabaseColor(rname
+ ".borderColor",
2535 default_color
, style
));
2541 BColor
BScreen::readDatabaseColor(const string
&rname
,
2542 const string
&default_color
,
2543 const Configuration
&style
) {
2546 if (style
.getValue(rname
, s
))
2547 color
= BColor(s
, getBaseDisplay(), getScreenNumber());
2549 color
= BColor(default_color
, getBaseDisplay(), getScreenNumber());
2554 BFont
*BScreen::readDatabaseFont(const string
&rbasename
,
2555 const Configuration
&style
) {
2562 if (style
.getValue(rbasename
+ "xft.font", s
) &&
2563 style
.getValue(rbasename
+ "xft.size", i
)) {
2566 bool italic
= False
;
2567 if (style
.getValue(rbasename
+ "xft.flags", s
)) {
2568 if (s
.find("bold") != string::npos
)
2570 if (s
.find("italic") != string::npos
)
2574 BFont
*b
= new BFont(blackbox
->getXDisplay(), this, family
, i
, bold
,
2575 italic
, resource
.shadow_fonts
, resource
.aa_fonts
);
2579 delete b
; // fall back to the normal X font stuff
2583 style
.getValue(rbasename
+ "font", s
);
2584 // if this fails, a blank string will be used, which will cause the fallback
2587 BFont
*b
= new BFont(blackbox
->getXDisplay(), this, s
);
2589 exit(2); // can't continue without a font