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::saveHideToolbar(bool h
) {
411 resource
.hide_toolbar
= h
;
412 if (resource
.hide_toolbar
)
413 toolbar
->unmapToolbar();
415 toolbar
->mapToolbar();
416 config
->setValue(screenstr
+ "hideToolbar", resource
.hide_toolbar
);
420 void BScreen::saveWindowToEdgeSnap(int s
) {
421 resource
.snap_to_edges
= s
;
424 switch (resource
.snap_to_edges
) {
425 case WindowNoSnap
: snap
= "NoSnap"; break;
426 case WindowResistance
: snap
= "Resistance"; break;
427 case WindowSnap
: default: snap
= "Snap"; break;
429 config
->setValue(screenstr
+ "windowToEdgeSnap", snap
);
433 void BScreen::saveWindowToWindowSnap(int s
) {
434 resource
.snap_to_windows
= s
;
437 switch (resource
.snap_to_windows
) {
438 case WindowNoSnap
: snap
= "NoSnap"; break;
439 case WindowResistance
: snap
= "Resistance"; break;
440 case WindowSnap
: default: snap
= "Snap"; break;
442 config
->setValue(screenstr
+ "windowToWindowSnap", snap
);
446 void BScreen::saveResizeZones(unsigned int z
) {
447 resource
.resize_zones
= z
;
448 config
->setValue(screenstr
+ "resizeZones", resource
.resize_zones
);
452 void BScreen::saveWindowCornerSnap(bool s
) {
453 resource
.window_corner_snap
= s
;
454 config
->setValue(screenstr
+ "windowCornerSnap",
455 resource
.window_corner_snap
);
459 void BScreen::saveWorkspaces(unsigned int w
) {
460 resource
.workspaces
= w
;
461 config
->setValue(screenstr
+ "workspaces", resource
.workspaces
);
465 void BScreen::savePlacementPolicy(int p
) {
466 resource
.placement_policy
= p
;
467 const char *placement
;
468 switch (resource
.placement_policy
) {
469 case CascadePlacement
: placement
= "CascadePlacement"; break;
470 case UnderMousePlacement
: placement
= "UnderMousePlacement"; break;
471 case ClickMousePlacement
: placement
= "ClickMousePlacement"; break;
472 case ColSmartPlacement
: placement
= "ColSmartPlacement"; break;
473 case RowSmartPlacement
: default: placement
= "RowSmartPlacement"; break;
475 config
->setValue(screenstr
+ "windowPlacement", placement
);
479 void BScreen::saveResistanceSize(int s
) {
480 resource
.resistance_size
= s
;
481 config
->setValue(screenstr
+ "resistanceSize",
482 resource
.resistance_size
);
486 void BScreen::saveSnapThreshold(int t
) {
487 resource
.snap_threshold
= t
;
488 config
->setValue(screenstr
+ "edgeSnapThreshold",
489 resource
.snap_threshold
);
493 void BScreen::saveSnapOffset(int t
) {
494 resource
.snap_offset
= t
;
495 config
->setValue(screenstr
+ "edgeSnapOffset",
496 resource
.snap_offset
);
500 void BScreen::saveRowPlacementDirection(int d
) {
501 resource
.row_direction
= d
;
502 config
->setValue(screenstr
+ "rowPlacementDirection",
503 resource
.row_direction
== LeftRight
?
504 "LeftToRight" : "RightToLeft");
508 void BScreen::saveColPlacementDirection(int d
) {
509 resource
.col_direction
= d
;
510 config
->setValue(screenstr
+ "colPlacementDirection",
511 resource
.col_direction
== TopBottom
?
512 "TopToBottom" : "BottomToTop");
517 void BScreen::saveStrftimeFormat(const std::string
& format
) {
518 resource
.strftime_format
= format
;
519 config
->setValue(screenstr
+ "strftimeFormat", resource
.strftime_format
);
522 #else // !HAVE_STRFTIME
524 void BScreen::saveDateFormat(int f
) {
525 resource
.date_format
= f
;
526 config
->setValue(screenstr
+ "dateFormat",
527 resource
.date_format
== B_EuropeanDate
?
528 "European" : "American");
532 void BScreen::saveClock24Hour(bool c
) {
533 resource
.clock24hour
= c
;
534 config
->setValue(screenstr
+ "clockFormat", resource
.clock24hour
? 24 : 12);
536 #endif // HAVE_STRFTIME
539 void BScreen::saveWorkspaceNames() {
542 for (unsigned int i
= 0; i
< workspacesList
.size(); ++i
) {
543 names
+= workspacesList
[i
]->getName();
544 if (i
< workspacesList
.size() - 1)
548 config
->setValue(screenstr
+ "workspaceNames", names
);
552 void BScreen::savePlaceIgnoreShaded(bool i
) {
553 resource
.ignore_shaded
= i
;
554 config
->setValue(screenstr
+ "placementIgnoreShaded",
555 resource
.ignore_shaded
);
559 void BScreen::savePlaceIgnoreMaximized(bool i
) {
560 resource
.ignore_maximized
= i
;
561 config
->setValue(screenstr
+ "placementIgnoreMaximized",
562 resource
.ignore_maximized
);
566 void BScreen::saveAllowScrollLock(bool a
) {
567 resource
.allow_scroll_lock
= a
;
568 config
->setValue(screenstr
+ "disableBindingsWithScrollLock",
569 resource
.allow_scroll_lock
);
573 void BScreen::saveWorkspaceWarping(bool w
) {
574 resource
.workspace_warping
= w
;
575 config
->setValue(screenstr
+ "workspaceWarping",
576 resource
.workspace_warping
);
580 void BScreen::saveRootScrollDirection(int d
) {
581 resource
.root_scroll
= d
;
583 switch (resource
.root_scroll
) {
584 case NoScroll
: dir
= "None"; break;
585 case ReverseScroll
: dir
= "Reverse"; break;
586 case NormalScroll
: default: dir
= "Normal"; break;
588 config
->setValue(screenstr
+ "rootScrollDirection", dir
);
592 void BScreen::save_rc(void) {
593 saveSloppyFocus(resource
.sloppy_focus
);
594 saveAutoRaise(resource
.auto_raise
);
595 saveImageDither(doImageDither());
596 saveAAFonts(resource
.aa_fonts
);
597 saveResizeZones(resource
.resize_zones
);
598 saveOpaqueMove(resource
.opaque_move
);
599 saveFullMax(resource
.full_max
);
600 saveFocusNew(resource
.focus_new
);
601 saveFocusLast(resource
.focus_last
);
602 saveHideToolbar(resource
.hide_toolbar
);
603 saveWindowToWindowSnap(resource
.snap_to_windows
);
604 saveWindowToEdgeSnap(resource
.snap_to_edges
);
605 saveWindowCornerSnap(resource
.window_corner_snap
);
606 saveWorkspaces(resource
.workspaces
);
607 savePlacementPolicy(resource
.placement_policy
);
608 saveSnapThreshold(resource
.snap_threshold
);
609 saveSnapOffset(resource
.snap_offset
);
610 saveResistanceSize(resource
.resistance_size
);
611 saveRowPlacementDirection(resource
.row_direction
);
612 saveColPlacementDirection(resource
.col_direction
);
614 saveStrftimeFormat(resource
.strftime_format
);
615 #else // !HAVE_STRFTIME
616 saveDateFormat(resource
.date_format
);
617 savwClock24Hour(resource
.clock24hour
);
618 #endif // HAVE_STRFTIME
619 savePlaceIgnoreShaded(resource
.ignore_shaded
);
620 savePlaceIgnoreMaximized(resource
.ignore_maximized
);
621 saveAllowScrollLock(resource
.allow_scroll_lock
);
622 saveWorkspaceWarping(resource
.workspace_warping
);
623 saveRootScrollDirection(resource
.root_scroll
);
630 void BScreen::load_rc(void) {
634 if (! config
->getValue(screenstr
+ "fullMaximization", resource
.full_max
))
635 resource
.full_max
= false;
637 if (! config
->getValue(screenstr
+ "focusNewWindows", resource
.focus_new
))
638 resource
.focus_new
= false;
640 if (! config
->getValue(screenstr
+ "focusLastWindow", resource
.focus_last
))
641 resource
.focus_last
= false;
643 if (! config
->getValue(screenstr
+ "workspaces", resource
.workspaces
))
644 resource
.workspaces
= 1;
646 if (! config
->getValue(screenstr
+ "opaqueMove", resource
.opaque_move
))
647 resource
.opaque_move
= false;
649 if (! config
->getValue(screenstr
+ "antialiasFonts", resource
.aa_fonts
))
650 resource
.aa_fonts
= true;
652 if (! config
->getValue(screenstr
+ "resizeZones", resource
.resize_zones
) ||
653 (resource
.resize_zones
!= 1 && resource
.resize_zones
!= 2 &&
654 resource
.resize_zones
!= 4))
655 resource
.resize_zones
= 4;
657 if (! config
->getValue(screenstr
+ "hideToolbar", resource
.hide_toolbar
))
658 resource
.hide_toolbar
= false;
660 resource
.snap_to_windows
= WindowResistance
;
661 if (config
->getValue(screenstr
+ "windowToWindowSnap", s
)) {
663 resource
.snap_to_windows
= WindowNoSnap
;
664 else if (s
== "Snap")
665 resource
.snap_to_windows
= WindowSnap
;
668 resource
.snap_to_edges
= WindowResistance
;
669 if (config
->getValue(screenstr
+ "windowToEdgeSnap", s
)) {
671 resource
.snap_to_edges
= WindowNoSnap
;
672 else if (s
== "Snap")
673 resource
.snap_to_edges
= WindowSnap
;
676 if (! config
->getValue(screenstr
+ "windowCornerSnap",
677 resource
.window_corner_snap
))
678 resource
.window_corner_snap
= true;
680 if (! config
->getValue(screenstr
+ "imageDither", b
))
682 image_control
->setDither(b
);
684 if (! config
->getValue(screenstr
+ "edgeSnapOffset",
685 resource
.snap_offset
))
686 resource
.snap_offset
= 0;
687 if (resource
.snap_offset
> 50) // sanity check, setting this huge would
688 resource
.snap_offset
= 50; // seriously suck.
690 if (! config
->getValue(screenstr
+ "edgeSnapThreshold",
691 resource
.snap_threshold
))
692 resource
.snap_threshold
= 4;
694 if (! config
->getValue(screenstr
+ "resistanceSize",
695 resource
.resistance_size
))
696 resource
.resistance_size
= 18;
698 if (config
->getValue(screenstr
+ "rowPlacementDirection", s
) &&
700 resource
.row_direction
= RightLeft
;
702 resource
.row_direction
= LeftRight
;
704 if (config
->getValue(screenstr
+ "colPlacementDirection", s
) &&
706 resource
.col_direction
= BottomTop
;
708 resource
.col_direction
= TopBottom
;
710 if (config
->getValue(screenstr
+ "workspaceNames", s
)) {
711 XAtom::StringVect workspaceNames
;
713 string::const_iterator it
= s
.begin(), end
= s
.end();
715 string::const_iterator tmp
= it
; // current string.begin()
716 it
= std::find(tmp
, end
, ','); // look for comma between tmp and end
717 workspaceNames
.push_back(string(tmp
, it
)); // s[tmp:it]
723 xatom
->setValue(getRootWindow(), XAtom::net_desktop_names
, XAtom::utf8
,
727 resource
.sloppy_focus
= true;
728 resource
.auto_raise
= false;
729 resource
.click_raise
= false;
730 if (config
->getValue(screenstr
+ "focusModel", s
)) {
731 if (s
.find("ClickToFocus") != string::npos
) {
732 resource
.sloppy_focus
= false;
735 if (s
.find("AutoRaise") != string::npos
)
736 resource
.auto_raise
= true;
737 if (s
.find("ClickRaise") != string::npos
)
738 resource
.click_raise
= true;
742 if (config
->getValue(screenstr
+ "windowPlacement", s
)) {
743 if (s
== "CascadePlacement")
744 resource
.placement_policy
= CascadePlacement
;
745 else if (s
== "UnderMousePlacement")
746 resource
.placement_policy
= UnderMousePlacement
;
747 else if (s
== "ClickMousePlacement")
748 resource
.placement_policy
= ClickMousePlacement
;
749 else if (s
== "ColSmartPlacement")
750 resource
.placement_policy
= ColSmartPlacement
;
751 else //if (s == "RowSmartPlacement")
752 resource
.placement_policy
= RowSmartPlacement
;
754 resource
.placement_policy
= RowSmartPlacement
;
757 if (! config
->getValue(screenstr
+ "strftimeFormat",
758 resource
.strftime_format
))
759 resource
.strftime_format
= "%I:%M %p";
760 #else // !HAVE_STRFTIME
763 if (config
->getValue(screenstr
+ "dateFormat", s
) && s
== "European")
764 resource
.date_format
= B_EuropeanDate
;
766 resource
.date_format
= B_AmericanDate
;
768 if (! config
->getValue(screenstr
+ "clockFormat", l
))
770 resource
.clock24hour
= l
== 24;
771 #endif // HAVE_STRFTIME
773 if (! config
->getValue(screenstr
+ "placementIgnoreShaded",
774 resource
.ignore_shaded
))
775 resource
.ignore_shaded
= true;
777 if (! config
->getValue(screenstr
+ "placementIgnoreMaximized",
778 resource
.ignore_maximized
))
779 resource
.ignore_maximized
= true;
781 if (! config
->getValue(screenstr
+ "disableBindingsWithScrollLock",
782 resource
.allow_scroll_lock
))
783 resource
.allow_scroll_lock
= false;
785 if (! config
->getValue(screenstr
+ "workspaceWarping",
786 resource
.workspace_warping
))
787 resource
.workspace_warping
= false;
789 resource
.root_scroll
= NormalScroll
;
790 if (config
->getValue(screenstr
+ "rootScrollDirection", s
)) {
792 resource
.root_scroll
= NoScroll
;
793 else if (s
== "Reverse")
794 resource
.root_scroll
= ReverseScroll
;
799 void BScreen::changeWorkspaceCount(unsigned int new_count
) {
800 assert(new_count
> 0);
802 if (new_count
< workspacesList
.size()) {
804 for (unsigned int i
= workspacesList
.size(); i
> new_count
; --i
)
805 removeLastWorkspace();
806 // removeLast already sets the current workspace to the
807 // last available one.
808 } else if (new_count
> workspacesList
.size()) {
810 for(unsigned int i
= workspacesList
.size(); i
< new_count
; ++i
)
816 void BScreen::reconfigure(void) {
817 // don't reconfigure while saving the initial rc file, it's a waste and it
818 // breaks somethings (workspace names)
819 if (blackbox
->isStartup()) return;
826 // we need to do this explicitly, because just loading this value from the rc
828 changeWorkspaceCount(resource
.workspaces
);
831 gcv
.foreground
= WhitePixel(blackbox
->getXDisplay(),
833 gcv
.function
= GXinvert
;
834 gcv
.subwindow_mode
= IncludeInferiors
;
835 XChangeGC(blackbox
->getXDisplay(), opGC
,
836 GCForeground
| GCFunction
| GCSubwindowMode
, &gcv
);
838 const char *s
= i18n(ScreenSet
, ScreenPositionLength
,
839 "0: 0000 x 0: 0000");
841 geom_w
= resource
.wstyle
.font
->measureString(s
) + resource
.bevel_width
* 2;
842 geom_h
= resource
.wstyle
.font
->height() + resource
.bevel_width
* 2;
844 BTexture
* texture
= &(resource
.wstyle
.l_focus
);
845 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
846 if (geom_pixmap
== ParentRelative
) {
847 texture
= &(resource
.wstyle
.t_focus
);
848 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
851 XSetWindowBackground(blackbox
->getXDisplay(), geom_window
,
852 texture
->color().pixel());
854 XSetWindowBackgroundPixmap(blackbox
->getXDisplay(),
855 geom_window
, geom_pixmap
);
857 XSetWindowBorderWidth(blackbox
->getXDisplay(), geom_window
,
858 resource
.border_width
);
859 XSetWindowBorder(blackbox
->getXDisplay(), geom_window
,
860 resource
.border_color
.pixel());
862 workspacemenu
->reconfigure();
863 iconmenu
->reconfigure();
865 typedef std::vector
<int> SubList
;
866 SubList remember_subs
;
868 // save the current open menus
869 Basemenu
*menu
= rootmenu
;
871 while ((submenu
= menu
->getCurrentSubmenu()) >= 0) {
872 remember_subs
.push_back(submenu
);
873 menu
= menu
->find(submenu
)->submenu();
879 rootmenu
->reconfigure();
881 // reopen the saved menus
883 const SubList::iterator subs_end
= remember_subs
.end();
884 for (SubList::iterator it
= remember_subs
.begin(); it
!= subs_end
; ++it
) {
885 menu
->drawSubmenu(*it
);
886 menu
= menu
->find(*it
)->submenu();
891 configmenu
->reconfigure();
893 toolbar
->reconfigure();
897 std::for_each(workspacesList
.begin(), workspacesList
.end(),
898 std::mem_fun(&Workspace::reconfigure
));
900 BlackboxWindowList::iterator iit
= iconList
.begin();
901 for (; iit
!= iconList
.end(); ++iit
) {
902 BlackboxWindow
*bw
= *iit
;
903 if (bw
->validateClient())
907 image_control
->timeout();
911 void BScreen::rereadMenu(void) {
915 rootmenu
->reconfigure();
919 void BScreen::LoadStyle(void) {
920 Configuration
style(False
);
922 const char *sfile
= blackbox
->getStyleFilename();
924 style
.setFile(sfile
);
925 if (! style
.load()) {
926 style
.setFile(DEFAULTSTYLE
);
928 style
.create(); // hardcoded default values will be used.
932 // merge in the rc file
933 style
.merge(config
->file(), True
);
937 // load fonts/fontsets
938 if (resource
.wstyle
.font
)
939 delete resource
.wstyle
.font
;
940 if (resource
.tstyle
.font
)
941 delete resource
.tstyle
.font
;
942 if (resource
.mstyle
.f_font
)
943 delete resource
.mstyle
.f_font
;
944 if (resource
.mstyle
.t_font
)
945 delete resource
.mstyle
.t_font
;
946 resource
.wstyle
.font
= resource
.tstyle
.font
= resource
.mstyle
.f_font
=
947 resource
.mstyle
.t_font
= (BFont
*) 0;
949 resource
.wstyle
.font
= readDatabaseFont("window.", style
);
950 resource
.tstyle
.font
= readDatabaseFont("toolbar.", style
);
951 resource
.mstyle
.t_font
= readDatabaseFont("menu.title.", style
);
952 resource
.mstyle
.f_font
= readDatabaseFont("menu.frame.", style
);
954 // load window config
955 resource
.wstyle
.t_focus
=
956 readDatabaseTexture("window.title.focus", "white", style
);
957 resource
.wstyle
.t_unfocus
=
958 readDatabaseTexture("window.title.unfocus", "black", style
);
959 resource
.wstyle
.l_focus
=
960 readDatabaseTexture("window.label.focus", "white", style
);
961 resource
.wstyle
.l_unfocus
=
962 readDatabaseTexture("window.label.unfocus", "black", style
);
963 resource
.wstyle
.h_focus
=
964 readDatabaseTexture("window.handle.focus", "white", style
);
965 resource
.wstyle
.h_unfocus
=
966 readDatabaseTexture("window.handle.unfocus", "black", style
);
967 resource
.wstyle
.g_focus
=
968 readDatabaseTexture("window.grip.focus", "white", style
);
969 resource
.wstyle
.g_unfocus
=
970 readDatabaseTexture("window.grip.unfocus", "black", style
);
971 resource
.wstyle
.b_focus
=
972 readDatabaseTexture("window.button.focus", "white", style
);
973 resource
.wstyle
.b_unfocus
=
974 readDatabaseTexture("window.button.unfocus", "black", style
);
975 resource
.wstyle
.b_pressed
=
976 readDatabaseTexture("window.button.pressed", "black", style
);
978 // we create the window.frame texture by hand because it exists only to
979 // make the code cleaner and is not actually used for display
980 BColor color
= readDatabaseColor("window.frame.focusColor", "white", style
);
981 resource
.wstyle
.f_focus
= BTexture("solid flat", getBaseDisplay(),
982 getScreenNumber(), image_control
);
983 resource
.wstyle
.f_focus
.setColor(color
);
985 color
= readDatabaseColor("window.frame.unfocusColor", "white", style
);
986 resource
.wstyle
.f_unfocus
= BTexture("solid flat", getBaseDisplay(),
987 getScreenNumber(), image_control
);
988 resource
.wstyle
.f_unfocus
.setColor(color
);
990 resource
.wstyle
.l_text_focus
=
991 readDatabaseColor("window.label.focus.textColor", "black", style
);
992 resource
.wstyle
.l_text_unfocus
=
993 readDatabaseColor("window.label.unfocus.textColor", "white", style
);
994 resource
.wstyle
.b_pic_focus
=
995 readDatabaseColor("window.button.focus.picColor", "black", style
);
996 resource
.wstyle
.b_pic_unfocus
=
997 readDatabaseColor("window.button.unfocus.picColor", "white", style
);
999 resource
.wstyle
.justify
= LeftJustify
;
1000 if (style
.getValue("window.justify", s
)) {
1001 if (s
== "right" || s
== "Right")
1002 resource
.wstyle
.justify
= RightJustify
;
1003 else if (s
== "center" || s
== "Center")
1004 resource
.wstyle
.justify
= CenterJustify
;
1008 if (resource
.wstyle
.t_focus
.texture() == BTexture::Parent_Relative
)
1009 resource
.wstyle
.t_focus
= resource
.wstyle
.f_focus
;
1010 if (resource
.wstyle
.t_unfocus
.texture() == BTexture::Parent_Relative
)
1011 resource
.wstyle
.t_unfocus
= resource
.wstyle
.f_unfocus
;
1012 if (resource
.wstyle
.h_focus
.texture() == BTexture::Parent_Relative
)
1013 resource
.wstyle
.h_focus
= resource
.wstyle
.f_focus
;
1014 if (resource
.wstyle
.h_unfocus
.texture() == BTexture::Parent_Relative
)
1015 resource
.wstyle
.h_unfocus
= resource
.wstyle
.f_unfocus
;
1017 // load toolbar config
1018 resource
.tstyle
.toolbar
=
1019 readDatabaseTexture("toolbar", "black", style
);
1020 resource
.tstyle
.label
=
1021 readDatabaseTexture("toolbar.label", "black", style
);
1022 resource
.tstyle
.window
=
1023 readDatabaseTexture("toolbar.windowLabel", "black", style
);
1024 resource
.tstyle
.button
=
1025 readDatabaseTexture("toolbar.button", "white", style
);
1026 resource
.tstyle
.pressed
=
1027 readDatabaseTexture("toolbar.button.pressed", "black", style
);
1028 resource
.tstyle
.clock
=
1029 readDatabaseTexture("toolbar.clock", "black", style
);
1030 resource
.tstyle
.l_text
=
1031 readDatabaseColor("toolbar.label.textColor", "white", style
);
1032 resource
.tstyle
.w_text
=
1033 readDatabaseColor("toolbar.windowLabel.textColor", "white", style
);
1034 resource
.tstyle
.c_text
=
1035 readDatabaseColor("toolbar.clock.textColor", "white", style
);
1036 resource
.tstyle
.b_pic
=
1037 readDatabaseColor("toolbar.button.picColor", "black", style
);
1039 resource
.tstyle
.justify
= LeftJustify
;
1040 if (style
.getValue("toolbar.justify", s
)) {
1041 if (s
== "right" || s
== "Right")
1042 resource
.tstyle
.justify
= RightJustify
;
1043 else if (s
== "center" || s
== "Center")
1044 resource
.tstyle
.justify
= CenterJustify
;
1048 if (resource
.tstyle
.toolbar
.texture() == BTexture::Parent_Relative
) {
1049 resource
.tstyle
.toolbar
= BTexture("solid flat", getBaseDisplay(),
1050 getScreenNumber(), image_control
);
1051 resource
.tstyle
.toolbar
.setColor(BColor("black", getBaseDisplay(),
1052 getScreenNumber()));
1056 resource
.mstyle
.title
=
1057 readDatabaseTexture("menu.title", "white", style
);
1058 resource
.mstyle
.frame
=
1059 readDatabaseTexture("menu.frame", "black", style
);
1060 resource
.mstyle
.hilite
=
1061 readDatabaseTexture("menu.hilite", "white", style
);
1062 resource
.mstyle
.t_text
=
1063 readDatabaseColor("menu.title.textColor", "black", style
);
1064 resource
.mstyle
.f_text
=
1065 readDatabaseColor("menu.frame.textColor", "white", style
);
1066 resource
.mstyle
.d_text
=
1067 readDatabaseColor("menu.frame.disableColor", "black", style
);
1068 resource
.mstyle
.h_text
=
1069 readDatabaseColor("menu.hilite.textColor", "black", style
);
1071 resource
.mstyle
.t_justify
= LeftJustify
;
1072 if (style
.getValue("menu.title.justify", s
)) {
1073 if (s
== "right" || s
== "Right")
1074 resource
.mstyle
.t_justify
= RightJustify
;
1075 else if (s
== "center" || s
== "Center")
1076 resource
.mstyle
.t_justify
= CenterJustify
;
1079 resource
.mstyle
.f_justify
= LeftJustify
;
1080 if (style
.getValue("menu.frame.justify", s
)) {
1081 if (s
== "right" || s
== "Right")
1082 resource
.mstyle
.f_justify
= RightJustify
;
1083 else if (s
== "center" || s
== "Center")
1084 resource
.mstyle
.f_justify
= CenterJustify
;
1087 resource
.mstyle
.bullet
= Basemenu::Triangle
;
1088 if (style
.getValue("menu.bullet", s
)) {
1089 if (s
== "empty" || s
== "Empty")
1090 resource
.mstyle
.bullet
= Basemenu::Empty
;
1091 else if (s
== "square" || s
== "Square")
1092 resource
.mstyle
.bullet
= Basemenu::Square
;
1093 else if (s
== "diamond" || s
== "Diamond")
1094 resource
.mstyle
.bullet
= Basemenu::Diamond
;
1097 resource
.mstyle
.bullet_pos
= Basemenu::Left
;
1098 if (style
.getValue("menu.bullet.position", s
)) {
1099 if (s
== "right" || s
== "Right")
1100 resource
.mstyle
.bullet_pos
= Basemenu::Right
;
1104 if (resource
.mstyle
.frame
.texture() == BTexture::Parent_Relative
) {
1105 resource
.mstyle
.frame
= BTexture("solid flat", getBaseDisplay(),
1106 getScreenNumber(), image_control
);
1107 resource
.mstyle
.frame
.setColor(BColor("black", getBaseDisplay(),
1108 getScreenNumber()));
1111 resource
.border_color
=
1112 readDatabaseColor("borderColor", "black", style
);
1114 // load bevel, border and handle widths
1115 if (! style
.getValue("handleWidth", resource
.handle_width
) ||
1116 resource
.handle_width
> (getWidth() / 2) || resource
.handle_width
== 0)
1117 resource
.handle_width
= 6;
1119 if (! style
.getValue("borderWidth", resource
.border_width
))
1120 resource
.border_width
= 1;
1122 if (! style
.getValue("bevelWidth", resource
.bevel_width
) ||
1123 resource
.bevel_width
> (getWidth() / 2) || resource
.bevel_width
== 0)
1124 resource
.bevel_width
= 3;
1126 if (! style
.getValue("frameWidth", resource
.frame_width
) ||
1127 resource
.frame_width
> (getWidth() / 2))
1128 resource
.frame_width
= resource
.bevel_width
;
1130 if (style
.getValue("rootCommand", s
))
1131 bexec(s
, displayString());
1135 void BScreen::addIcon(BlackboxWindow
*w
) {
1138 w
->setWorkspace(BSENTINEL
);
1139 w
->setWindowNumber(iconList
.size());
1141 iconList
.push_back(w
);
1143 const char* title
= w
->getIconTitle();
1144 iconmenu
->insert(title
);
1149 void BScreen::removeIcon(BlackboxWindow
*w
) {
1154 iconmenu
->remove(w
->getWindowNumber());
1157 BlackboxWindowList::iterator it
= iconList
.begin(),
1158 end
= iconList
.end();
1159 for (int i
= 0; it
!= end
; ++it
)
1160 (*it
)->setWindowNumber(i
++);
1164 BlackboxWindow
*BScreen::getIcon(unsigned int index
) {
1165 if (index
< iconList
.size()) {
1166 BlackboxWindowList::iterator it
= iconList
.begin();
1167 while (index
-- > 0) // increment to index
1172 return (BlackboxWindow
*) 0;
1176 unsigned int BScreen::addWorkspace(void) {
1177 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
1178 workspacesList
.push_back(wkspc
);
1179 saveWorkspaces(getWorkspaceCount());
1180 saveWorkspaceNames();
1182 workspacemenu
->insertWorkspace(wkspc
);
1183 workspacemenu
->update();
1185 toolbar
->reconfigure();
1187 updateNetizenWorkspaceCount();
1189 return workspacesList
.size();
1193 unsigned int BScreen::removeLastWorkspace(void) {
1194 if (workspacesList
.size() == 1)
1197 Workspace
*wkspc
= workspacesList
.back();
1199 if (current_workspace
->getID() == wkspc
->getID())
1200 changeWorkspaceID(current_workspace
->getID() - 1);
1204 workspacemenu
->removeWorkspace(wkspc
);
1205 workspacemenu
->update();
1207 workspacesList
.pop_back();
1210 saveWorkspaces(getWorkspaceCount());
1211 saveWorkspaceNames();
1213 toolbar
->reconfigure();
1215 updateNetizenWorkspaceCount();
1217 return workspacesList
.size();
1221 void BScreen::changeWorkspaceID(unsigned int id
) {
1222 if (! current_workspace
|| id
== current_workspace
->getID()) return;
1224 BlackboxWindow
*focused
= blackbox
->getFocusedWindow();
1225 if (focused
&& focused
->getScreen() == this) {
1226 assert(focused
->isStuck() ||
1227 focused
->getWorkspaceNumber() == current_workspace
->getID());
1229 current_workspace
->setLastFocusedWindow(focused
);
1231 // if no window had focus, no need to store a last focus
1232 current_workspace
->setLastFocusedWindow((BlackboxWindow
*) 0);
1235 // when we switch workspaces, unfocus whatever was focused if it is going
1237 if (focused
&& ! focused
->isStuck())
1238 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1240 current_workspace
->hideAll();
1241 workspacemenu
->setItemSelected(current_workspace
->getID() + 2, False
);
1243 current_workspace
= getWorkspace(id
);
1245 xatom
->setValue(getRootWindow(), XAtom::net_current_desktop
,
1246 XAtom::cardinal
, id
);
1248 workspacemenu
->setItemSelected(current_workspace
->getID() + 2, True
);
1249 toolbar
->redrawWorkspaceLabel(True
);
1251 current_workspace
->showAll();
1256 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
1259 XSync(blackbox
->getXDisplay(), False
);
1261 // If sloppy focus and we can find the client window under the pointer,
1263 if (resource
.sloppy_focus
&&
1264 XQueryPointer(blackbox
->getXDisplay(), getRootWindow(), &r
, &c
,
1265 &rx
, &ry
, &x
, &y
, &m
) &&
1267 if ( (win
= blackbox
->searchWindow(c
)) )
1268 f
= win
->setInputFocus();
1271 // If that fails, and we're doing focus_last, try to focus the last window.
1272 if (! f
&& resource
.focus_last
&&
1273 (win
= current_workspace
->getLastFocusedWindow()))
1274 f
= win
->setInputFocus();
1277 if we found a focus target, then we set the focused window explicitly
1278 because it is possible to switch off this workspace before the x server
1279 generates the FocusIn event for the window. if that happens, openbox would
1280 lose track of what window was the 'LastFocused' window on the workspace.
1282 if we did not find a focus target, then set the current focused window to
1286 blackbox
->setFocusedWindow(win
);
1288 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1290 updateNetizenCurrentWorkspace();
1295 * Set the _NET_CLIENT_LIST root window property.
1297 void BScreen::updateClientList(void) {
1298 if (windowList
.size() > 0) {
1299 Window
*windows
= new Window
[windowList
.size()];
1300 Window
*win_it
= windows
;
1301 BlackboxWindowList::iterator it
= windowList
.begin();
1302 const BlackboxWindowList::iterator end
= windowList
.end();
1303 for (; it
!= end
; ++it
, ++win_it
)
1304 *win_it
= (*it
)->getClientWindow();
1305 xatom
->setValue(getRootWindow(), XAtom::net_client_list
, XAtom::window
,
1306 windows
, windowList
.size());
1309 xatom
->setValue(getRootWindow(), XAtom::net_client_list
, XAtom::window
,
1312 updateStackingList();
1317 * Set the _NET_CLIENT_LIST_STACKING root window property.
1319 void BScreen::updateStackingList(void) {
1321 BlackboxWindowList stack_order
;
1324 * Get the stacking order from all of the workspaces.
1325 * We start with the current workspace so that the sticky windows will be
1326 * in the right order on the current workspace.
1327 * XXX: Do we need to have sticky windows in the list once for each workspace?
1329 getCurrentWorkspace()->appendStackOrder(stack_order
);
1330 for (unsigned int i
= 0; i
< getWorkspaceCount(); ++i
)
1331 if (i
!= getCurrentWorkspaceID())
1332 getWorkspace(i
)->appendStackOrder(stack_order
);
1334 if (stack_order
.size() > 0) {
1335 // set the client list atoms
1336 Window
*windows
= new Window
[stack_order
.size()];
1337 Window
*win_it
= windows
;
1338 BlackboxWindowList::iterator it
= stack_order
.begin(),
1339 end
= stack_order
.end();
1340 for (; it
!= end
; ++it
, ++win_it
)
1341 *win_it
= (*it
)->getClientWindow();
1342 xatom
->setValue(getRootWindow(), XAtom::net_client_list_stacking
,
1343 XAtom::window
, windows
, stack_order
.size());
1346 xatom
->setValue(getRootWindow(), XAtom::net_client_list_stacking
,
1347 XAtom::window
, 0, 0);
1351 void BScreen::addSystrayWindow(Window window
) {
1352 XGrabServer(blackbox
->getXDisplay());
1354 XSelectInput(blackbox
->getXDisplay(), window
, SubstructureRedirectMask
);
1355 systrayWindowList
.push_back(window
);
1356 xatom
->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows
,
1358 &systrayWindowList
[0], systrayWindowList
.size());
1359 blackbox
->saveSystrayWindowSearch(window
, this);
1361 XUngrabServer(blackbox
->getXDisplay());
1365 void BScreen::removeSystrayWindow(Window window
) {
1366 XGrabServer(blackbox
->getXDisplay());
1368 WindowList::iterator it
= systrayWindowList
.begin();
1369 const WindowList::iterator end
= systrayWindowList
.end();
1370 for (; it
!= end
; ++it
)
1371 if (*it
== window
) {
1372 systrayWindowList
.erase(it
);
1373 xatom
->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows
,
1375 &systrayWindowList
[0], systrayWindowList
.size());
1376 blackbox
->removeSystrayWindowSearch(window
);
1377 XSelectInput(blackbox
->getXDisplay(), window
, NoEventMask
);
1381 assert(it
!= end
); // not a systray window
1383 XUngrabServer(blackbox
->getXDisplay());
1387 void BScreen::manageWindow(Window w
) {
1388 // is the window a KDE systray window?
1390 if (xatom
->getValue(w
, XAtom::kde_net_wm_system_tray_window_for
,
1391 XAtom::window
, systray
) && systray
!= None
) {
1392 addSystrayWindow(w
);
1396 // is the window a docking app
1397 XWMHints
*wmhint
= XGetWMHints(blackbox
->getXDisplay(), w
);
1398 if (wmhint
&& (wmhint
->flags
& StateHint
) &&
1399 wmhint
->initial_state
== WithdrawnState
) {
1404 new BlackboxWindow(blackbox
, w
, this);
1406 BlackboxWindow
*win
= blackbox
->searchWindow(w
);
1410 if (win
->isDesktop()) {
1411 desktopWindowList
.push_back(win
->getFrameWindow());
1412 } else { // if (win->isNormal()) {
1413 // don't list desktop windows as managed windows
1414 windowList
.push_back(win
);
1417 if (win
->isTopmost())
1418 specialWindowList
.push_back(win
->getFrameWindow());
1421 XMapRequestEvent mre
;
1423 if (blackbox
->isStartup() && win
->isNormal()) win
->restoreAttributes();
1424 win
->mapRequestEvent(&mre
);
1428 void BScreen::unmanageWindow(BlackboxWindow
*w
, bool remap
) {
1429 // is the window a KDE systray window?
1431 if (xatom
->getValue(w
->getClientWindow(),
1432 XAtom::kde_net_wm_system_tray_window_for
,
1433 XAtom::window
, systray
) && systray
!= None
) {
1434 removeSystrayWindow(w
->getClientWindow());
1440 // Remove the modality so that its parent won't try to re-focus the window
1441 if (w
->isModal()) w
->setModal(False
);
1443 if (w
->getWorkspaceNumber() != BSENTINEL
&&
1444 w
->getWindowNumber() != BSENTINEL
) {
1445 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1447 for (unsigned int i
= 0; i
< getNumberOfWorkspaces(); ++i
)
1448 if (i
!= w
->getWorkspaceNumber())
1449 getWorkspace(i
)->removeWindow(w
, True
);
1451 } else if (w
->isIconic())
1454 if (w
->isDesktop()) {
1455 WindowList::iterator it
= desktopWindowList
.begin();
1456 const WindowList::iterator end
= desktopWindowList
.end();
1457 for (; it
!= end
; ++it
)
1458 if (*it
== w
->getFrameWindow()) {
1459 desktopWindowList
.erase(it
);
1462 assert(it
!= end
); // the window wasnt a desktop window?
1463 } else { // if (w->isNormal()) {
1464 // we don't list desktop windows as managed windows
1465 windowList
.remove(w
);
1468 if (w
->isTopmost()) {
1469 WindowList::iterator it
= specialWindowList
.begin();
1470 const WindowList::iterator end
= specialWindowList
.end();
1471 for (; it
!= end
; ++it
)
1472 if (*it
== w
->getFrameWindow()) {
1473 specialWindowList
.erase(it
);
1476 assert(it
!= end
); // the window wasnt a special window?
1480 if (blackbox
->getFocusedWindow() == w
)
1481 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1483 removeNetizen(w
->getClientWindow());
1486 some managed windows can also be window group controllers. when
1487 unmanaging such windows, we should also delete the window group.
1489 BWindowGroup
*group
= blackbox
->searchGroup(w
->getClientWindow());
1496 void BScreen::addNetizen(Netizen
*n
) {
1497 netizenList
.push_back(n
);
1499 n
->sendWorkspaceCount();
1500 n
->sendCurrentWorkspace();
1502 WorkspaceList::iterator it
= workspacesList
.begin();
1503 const WorkspaceList::iterator end
= workspacesList
.end();
1504 for (; it
!= end
; ++it
)
1505 (*it
)->sendWindowList(*n
);
1507 Window f
= ((blackbox
->getFocusedWindow()) ?
1508 blackbox
->getFocusedWindow()->getClientWindow() : None
);
1509 n
->sendWindowFocus(f
);
1513 void BScreen::removeNetizen(Window w
) {
1514 NetizenList::iterator it
= netizenList
.begin();
1515 for (; it
!= netizenList
.end(); ++it
) {
1516 if ((*it
)->getWindowID() == w
) {
1518 netizenList
.erase(it
);
1525 void BScreen::updateWorkArea(void) {
1526 if (workspacesList
.size() > 0) {
1527 unsigned long *dims
= new unsigned long[4 * workspacesList
.size()];
1528 for (unsigned int i
= 0, m
= workspacesList
.size(); i
< m
; ++i
) {
1529 // XXX: this could be different for each workspace
1530 const Rect
&area
= availableArea();
1531 dims
[(i
* 4) + 0] = area
.x();
1532 dims
[(i
* 4) + 1] = area
.y();
1533 dims
[(i
* 4) + 2] = area
.width();
1534 dims
[(i
* 4) + 3] = area
.height();
1536 xatom
->setValue(getRootWindow(), XAtom::net_workarea
, XAtom::cardinal
,
1537 dims
, 4 * workspacesList
.size());
1540 xatom
->setValue(getRootWindow(), XAtom::net_workarea
, XAtom::cardinal
,
1545 void BScreen::updateNetizenCurrentWorkspace(void) {
1546 std::for_each(netizenList
.begin(), netizenList
.end(),
1547 std::mem_fun(&Netizen::sendCurrentWorkspace
));
1551 void BScreen::updateNetizenWorkspaceCount(void) {
1552 xatom
->setValue(getRootWindow(), XAtom::net_number_of_desktops
,
1553 XAtom::cardinal
, workspacesList
.size());
1557 std::for_each(netizenList
.begin(), netizenList
.end(),
1558 std::mem_fun(&Netizen::sendWorkspaceCount
));
1562 void BScreen::updateNetizenWindowFocus(void) {
1563 Window f
= ((blackbox
->getFocusedWindow()) ?
1564 blackbox
->getFocusedWindow()->getClientWindow() : None
);
1566 xatom
->setValue(getRootWindow(), XAtom::net_active_window
,
1569 NetizenList::iterator it
= netizenList
.begin();
1570 for (; it
!= netizenList
.end(); ++it
)
1571 (*it
)->sendWindowFocus(f
);
1575 void BScreen::updateNetizenWindowAdd(Window w
, unsigned long p
) {
1576 NetizenList::iterator it
= netizenList
.begin();
1577 for (; it
!= netizenList
.end(); ++it
) {
1578 (*it
)->sendWindowAdd(w
, p
);
1583 void BScreen::updateNetizenWindowDel(Window w
) {
1584 NetizenList::iterator it
= netizenList
.begin();
1585 for (; it
!= netizenList
.end(); ++it
)
1586 (*it
)->sendWindowDel(w
);
1590 void BScreen::updateNetizenWindowRaise(Window w
) {
1591 NetizenList::iterator it
= netizenList
.begin();
1592 for (; it
!= netizenList
.end(); ++it
)
1593 (*it
)->sendWindowRaise(w
);
1597 void BScreen::updateNetizenWindowLower(Window w
) {
1598 NetizenList::iterator it
= netizenList
.begin();
1599 for (; it
!= netizenList
.end(); ++it
)
1600 (*it
)->sendWindowLower(w
);
1604 void BScreen::updateNetizenConfigNotify(XEvent
*e
) {
1605 NetizenList::iterator it
= netizenList
.begin();
1606 for (; it
!= netizenList
.end(); ++it
)
1607 (*it
)->sendConfigNotify(e
);
1611 void BScreen::raiseWindows(Window
*workspace_stack
, unsigned int num
) {
1612 // the 13 represents the number of blackbox windows such as menus
1618 Window
*session_stack
= new
1619 Window
[(num
+ workspacesList
.size() + rootmenuList
.size() +
1620 specialWindowList
.size() + bbwins
)];
1621 unsigned int i
= 0, k
= num
;
1623 XRaiseWindow(blackbox
->getXDisplay(), iconmenu
->getWindowID());
1624 *(session_stack
+ i
++) = iconmenu
->getWindowID();
1626 WorkspaceList::iterator wit
= workspacesList
.begin();
1627 const WorkspaceList::iterator w_end
= workspacesList
.end();
1628 for (; wit
!= w_end
; ++wit
)
1629 *(session_stack
+ i
++) = (*wit
)->getMenu()->getWindowID();
1631 *(session_stack
+ i
++) = workspacemenu
->getWindowID();
1633 *(session_stack
+ i
++) = configmenu
->getFocusmenu()->getWindowID();
1634 *(session_stack
+ i
++) = configmenu
->getPlacementmenu()->getWindowID();
1635 *(session_stack
+ i
++) = configmenu
->getWindowSnapmenu()->getWindowID();
1636 *(session_stack
+ i
++) = configmenu
->getEdgeSnapmenu()->getWindowID();
1638 *(session_stack
+ i
++) = configmenu
->getXineramamenu()->getWindowID();
1640 *(session_stack
+ i
++) = configmenu
->getWindowID();
1642 *(session_stack
+ i
++) = slit
->getMenu()->getDirectionmenu()->getWindowID();
1643 *(session_stack
+ i
++) = slit
->getMenu()->getPlacementmenu()->getWindowID();
1644 *(session_stack
+ i
++) = slit
->getMenu()->getWindowID();
1646 *(session_stack
+ i
++) =
1647 toolbar
->getMenu()->getPlacementmenu()->getWindowID();
1648 *(session_stack
+ i
++) = toolbar
->getMenu()->getWindowID();
1650 RootmenuList::iterator rit
= rootmenuList
.begin();
1651 for (; rit
!= rootmenuList
.end(); ++rit
)
1652 *(session_stack
+ i
++) = (*rit
)->getWindowID();
1653 *(session_stack
+ i
++) = rootmenu
->getWindowID();
1655 if (toolbar
->isOnTop())
1656 *(session_stack
+ i
++) = toolbar
->getWindowID();
1658 if (slit
->isOnTop())
1659 *(session_stack
+ i
++) = slit
->getWindowID();
1661 WindowList::iterator sit
, send
= specialWindowList
.end();
1662 for (sit
= specialWindowList
.begin(); sit
!= send
; ++sit
)
1663 *(session_stack
+ i
++) = *sit
;
1666 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
1668 XRestackWindows(blackbox
->getXDisplay(), session_stack
, i
);
1670 delete [] session_stack
;
1672 updateStackingList();
1676 void BScreen::lowerWindows(Window
*workspace_stack
, unsigned int num
) {
1677 assert(num
> 0); // this would cause trouble in the XRaiseWindow call
1679 Window
*session_stack
= new Window
[(num
+ desktopWindowList
.size())];
1680 unsigned int i
= 0, k
= num
;
1682 XLowerWindow(blackbox
->getXDisplay(), workspace_stack
[0]);
1685 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
1687 WindowList::iterator dit
= desktopWindowList
.begin();
1688 const WindowList::iterator d_end
= desktopWindowList
.end();
1689 for (; dit
!= d_end
; ++dit
)
1690 *(session_stack
+ i
++) = *dit
;
1692 XRestackWindows(blackbox
->getXDisplay(), session_stack
, i
);
1694 delete [] session_stack
;
1696 updateStackingList();
1700 void BScreen::reassociateWindow(BlackboxWindow
*w
, unsigned int wkspc_id
,
1701 bool ignore_sticky
) {
1704 if (wkspc_id
== BSENTINEL
)
1705 wkspc_id
= current_workspace
->getID();
1707 if (w
->getWorkspaceNumber() == wkspc_id
)
1710 if (w
->isIconic()) {
1712 getWorkspace(wkspc_id
)->addWindow(w
);
1714 for (unsigned int i
= 0; i
< getNumberOfWorkspaces(); ++i
)
1715 if (i
!= w
->getWorkspaceNumber())
1716 getWorkspace(i
)->addWindow(w
, True
);
1717 } else if (ignore_sticky
|| ! w
->isStuck()) {
1720 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1721 getWorkspace(wkspc_id
)->addWindow(w
);
1723 updateStackingList();
1727 void BScreen::propagateWindowName(const BlackboxWindow
*bw
) {
1728 if (bw
->isIconic()) {
1729 iconmenu
->changeItemLabel(bw
->getWindowNumber(), bw
->getIconTitle());
1733 Clientmenu
*clientmenu
= getWorkspace(bw
->getWorkspaceNumber())->getMenu();
1734 clientmenu
->changeItemLabel(bw
->getWindowNumber(), bw
->getTitle());
1735 clientmenu
->update();
1737 if (blackbox
->getFocusedWindow() == bw
)
1738 toolbar
->redrawWindowLabel(True
);
1743 void BScreen::nextFocus(void) {
1744 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1748 // if window is not on this screen, ignore it
1749 if (focused
->getScreen()->getScreenNumber() != getScreenNumber())
1750 focused
= (BlackboxWindow
*) 0;
1753 if (focused
&& current_workspace
->getCount() > 1) {
1754 // next is the next window to recieve focus, current is a place holder
1755 BlackboxWindow
*current
;
1758 next
= current_workspace
->getNextWindowInList(current
);
1759 } while(! next
->setInputFocus() && next
!= focused
);
1761 if (next
!= focused
)
1762 current_workspace
->raiseWindow(next
);
1763 } else if (current_workspace
->getCount() >= 1) {
1764 next
= current_workspace
->getTopWindowOnStack();
1766 current_workspace
->raiseWindow(next
);
1767 next
->setInputFocus();
1772 void BScreen::prevFocus(void) {
1773 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1777 // if window is not on this screen, ignore it
1778 if (focused
->getScreen()->getScreenNumber() != getScreenNumber())
1779 focused
= (BlackboxWindow
*) 0;
1782 if (focused
&& current_workspace
->getCount() > 1) {
1783 // next is the next window to recieve focus, current is a place holder
1784 BlackboxWindow
*current
;
1787 next
= current_workspace
->getPrevWindowInList(current
);
1788 } while(! next
->setInputFocus() && next
!= focused
);
1790 if (next
!= focused
)
1791 current_workspace
->raiseWindow(next
);
1792 } else if (current_workspace
->getCount() >= 1) {
1793 next
= current_workspace
->getTopWindowOnStack();
1795 current_workspace
->raiseWindow(next
);
1796 next
->setInputFocus();
1801 void BScreen::raiseFocus(void) {
1802 BlackboxWindow
*focused
= blackbox
->getFocusedWindow();
1806 // if on this Screen, raise it
1807 if (focused
->getScreen()->getScreenNumber() == getScreenNumber()) {
1808 Workspace
*workspace
= getWorkspace(focused
->getWorkspaceNumber());
1809 workspace
->raiseWindow(focused
);
1814 void BScreen::InitMenu(void) {
1816 rootmenuList
.clear();
1818 while (rootmenu
->getCount())
1819 rootmenu
->remove(0);
1821 rootmenu
= new Rootmenu(this);
1823 bool defaultMenu
= True
;
1825 FILE *menu_file
= (FILE *) 0;
1826 const char *menu_filename
= blackbox
->getMenuFilename();
1829 if (! (menu_file
= fopen(menu_filename
, "r")))
1830 perror(menu_filename
);
1831 if (! menu_file
) { // opening the menu file failed, try the default menu
1832 menu_filename
= DEFAULTMENU
;
1833 if (! (menu_file
= fopen(menu_filename
, "r")))
1834 perror(menu_filename
);
1838 if (feof(menu_file
)) {
1839 fprintf(stderr
, i18n(ScreenSet
, ScreenEmptyMenuFile
,
1840 "%s: Empty menu file"),
1843 char line
[1024], label
[1024];
1844 memset(line
, 0, 1024);
1845 memset(label
, 0, 1024);
1847 while (fgets(line
, 1024, menu_file
) && ! feof(menu_file
)) {
1851 int i
, key
= 0, index
= -1, len
= strlen(line
);
1853 for (i
= 0; i
< len
; i
++) {
1854 if (line
[i
] == '[') index
= 0;
1855 else if (line
[i
] == ']') break;
1856 else if (line
[i
] != ' ')
1858 key
+= tolower(line
[i
]);
1861 if (key
== 517) { // [begin]
1863 for (i
= index
; i
< len
; i
++) {
1864 if (line
[i
] == '(') index
= 0;
1865 else if (line
[i
] == ')') break;
1866 else if (index
++ >= 0) {
1867 if (line
[i
] == '\\' && i
< len
- 1) i
++;
1868 label
[index
- 1] = line
[i
];
1872 if (index
== -1) index
= 0;
1873 label
[index
] = '\0';
1875 rootmenu
->setLabel(label
);
1876 defaultMenu
= parseMenuFile(menu_file
, rootmenu
);
1878 blackbox
->addMenuTimestamp(menu_filename
);
1887 rootmenu
->setInternalMenu();
1888 rootmenu
->insert(i18n(ScreenSet
, Screenxterm
, "xterm"),
1890 i18n(ScreenSet
, Screenxterm
, "xterm"));
1891 rootmenu
->insert(i18n(ScreenSet
, ScreenRestart
, "Restart"),
1893 rootmenu
->insert(i18n(ScreenSet
, ScreenExit
, "Exit"),
1895 rootmenu
->setLabel(i18n(BasemenuSet
, BasemenuBlackboxMenu
,
1902 size_t string_within(char begin
, char end
,
1903 const char *input
, size_t start_at
, size_t length
,
1907 size_t i
= start_at
;
1908 for (; i
< length
; ++i
) {
1909 if (input
[i
] == begin
) {
1911 } else if (input
[i
] == end
) {
1914 if (input
[i
] == '\\' && i
< length
- 1) i
++;
1915 output
[index
++] = input
[i
];
1920 output
[index
] = '\0';
1928 bool BScreen::parseMenuFile(FILE *file
, Rootmenu
*menu
) {
1929 char line
[1024], keyword
[1024], label
[1024], command
[1024];
1932 while (! (done
|| feof(file
))) {
1933 memset(line
, 0, 1024);
1934 memset(label
, 0, 1024);
1935 memset(command
, 0, 1024);
1937 if (! fgets(line
, 1024, file
))
1940 if (line
[0] == '#') // comment, skip it
1943 size_t line_length
= strlen(line
);
1944 unsigned int key
= 0;
1946 // get the keyword enclosed in []'s
1947 size_t pos
= string_within('[', ']', line
, 0, line_length
, keyword
);
1949 if (keyword
[0] == '\0') { // no keyword, no menu entry
1952 size_t len
= strlen(keyword
);
1953 for (size_t i
= 0; i
< len
; ++i
) {
1954 if (keyword
[i
] != ' ')
1955 key
+= tolower(keyword
[i
]);
1959 // get the label enclosed in ()'s
1960 pos
= string_within('(', ')', line
, pos
, line_length
, label
);
1962 // get the command enclosed in {}'s
1963 pos
= string_within('{', '}', line
, pos
, line_length
, command
);
1974 menu
->insert(label
);
1979 if (! (*label
&& *command
)) {
1980 fprintf(stderr
, i18n(ScreenSet
, ScreenEXECError
,
1981 "BScreen::parseMenuFile: [exec] error, "
1982 "no menu label and/or command defined\n"));
1986 menu
->insert(label
, BScreen::Execute
, command
);
1992 fprintf(stderr
, i18n(ScreenSet
, ScreenEXITError
,
1993 "BScreen::parseMenuFile: [exit] error, "
1994 "no menu label defined\n"));
1998 menu
->insert(label
, BScreen::Exit
);
2002 case 561: { // style
2003 if (! (*label
&& *command
)) {
2005 i18n(ScreenSet
, ScreenSTYLEError
,
2006 "BScreen::parseMenuFile: [style] error, "
2007 "no menu label and/or filename defined\n"));
2011 string style
= expandTilde(command
);
2013 menu
->insert(label
, BScreen::SetStyle
, style
.c_str());
2019 fprintf(stderr
, i18n(ScreenSet
, ScreenCONFIGError
,
2020 "BScreen::parseMenufile: [config] error, "
2021 "no label defined"));
2025 menu
->insert(label
, configmenu
);
2029 case 740: { // include
2031 fprintf(stderr
, i18n(ScreenSet
, ScreenINCLUDEError
,
2032 "BScreen::parseMenuFile: [include] error, "
2033 "no filename defined\n"));
2037 string newfile
= expandTilde(label
);
2038 FILE *submenufile
= fopen(newfile
.c_str(), "r");
2040 if (! submenufile
) {
2041 perror(newfile
.c_str());
2046 if (fstat(fileno(submenufile
), &buf
) ||
2047 ! S_ISREG(buf
.st_mode
)) {
2049 i18n(ScreenSet
, ScreenINCLUDEErrorReg
,
2050 "BScreen::parseMenuFile: [include] error: "
2051 "'%s' is not a regular file\n"), newfile
.c_str());
2055 if (! feof(submenufile
)) {
2056 if (! parseMenuFile(submenufile
, menu
))
2057 blackbox
->addMenuTimestamp(newfile
);
2059 fclose(submenufile
);
2065 case 767: { // submenu
2067 fprintf(stderr
, i18n(ScreenSet
, ScreenSUBMENUError
,
2068 "BScreen::parseMenuFile: [submenu] error, "
2069 "no menu label defined\n"));
2073 Rootmenu
*submenu
= new Rootmenu(this);
2076 submenu
->setLabel(command
);
2078 submenu
->setLabel(label
);
2080 parseMenuFile(file
, submenu
);
2082 menu
->insert(label
, submenu
);
2083 rootmenuList
.push_back(submenu
);
2088 case 773: { // restart
2090 fprintf(stderr
, i18n(ScreenSet
, ScreenRESTARTError
,
2091 "BScreen::parseMenuFile: [restart] error, "
2092 "no menu label defined\n"));
2097 menu
->insert(label
, BScreen::RestartOther
, command
);
2099 menu
->insert(label
, BScreen::Restart
);
2104 case 845: { // reconfig
2107 i18n(ScreenSet
, ScreenRECONFIGError
,
2108 "BScreen::parseMenuFile: [reconfig] error, "
2109 "no menu label defined\n"));
2113 menu
->insert(label
, BScreen::Reconfigure
);
2118 case 995: // stylesdir
2119 case 1113: { // stylesmenu
2120 bool newmenu
= ((key
== 1113) ? True
: False
);
2122 if (! *label
|| (! *command
&& newmenu
)) {
2124 i18n(ScreenSet
, ScreenSTYLESDIRError
,
2125 "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
2126 " error, no directory defined\n"));
2130 char *directory
= ((newmenu
) ? command
: label
);
2132 string stylesdir
= expandTilde(directory
);
2134 struct stat statbuf
;
2136 if (stat(stylesdir
.c_str(), &statbuf
) == -1) {
2138 i18n(ScreenSet
, ScreenSTYLESDIRErrorNoExist
,
2139 "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
2140 " error, %s does not exist\n"), stylesdir
.c_str());
2143 if (! S_ISDIR(statbuf
.st_mode
)) {
2145 i18n(ScreenSet
, ScreenSTYLESDIRErrorNotDir
,
2146 "BScreen::parseMenuFile:"
2147 " [stylesdir/stylesmenu] error, %s is not a"
2148 " directory\n"), stylesdir
.c_str());
2152 Rootmenu
*stylesmenu
;
2155 stylesmenu
= new Rootmenu(this);
2159 DIR *d
= opendir(stylesdir
.c_str());
2161 std::vector
<string
> ls
;
2163 while((p
= readdir(d
)))
2164 ls
.push_back(p
->d_name
);
2168 std::sort(ls
.begin(), ls
.end());
2170 std::vector
<string
>::iterator it
= ls
.begin(),
2172 for (; it
!= end
; ++it
) {
2173 const string
& fname
= *it
;
2175 if (fname
[fname
.size()-1] == '~')
2178 string style
= stylesdir
;
2182 if (! stat(style
.c_str(), &statbuf
) && S_ISREG(statbuf
.st_mode
))
2183 stylesmenu
->insert(fname
, BScreen::SetStyle
, style
);
2186 stylesmenu
->update();
2189 stylesmenu
->setLabel(label
);
2190 menu
->insert(label
, stylesmenu
);
2191 rootmenuList
.push_back(stylesmenu
);
2194 blackbox
->addMenuTimestamp(stylesdir
);
2198 case 1090: { // workspaces
2201 i18n(ScreenSet
, ScreenWORKSPACESError
,
2202 "BScreen:parseMenuFile: [workspaces] error, "
2203 "no menu label defined\n"));
2207 menu
->insert(label
, workspacemenu
);
2213 return ((menu
->getCount() == 0) ? True
: False
);
2217 void BScreen::shutdown(void) {
2218 XSelectInput(blackbox
->getXDisplay(), getRootWindow(), NoEventMask
);
2219 XSync(blackbox
->getXDisplay(), False
);
2221 while(! windowList
.empty())
2222 unmanageWindow(windowList
.front(), True
);
2224 while(! desktopWindowList
.empty()) {
2225 BlackboxWindow
*win
= blackbox
->searchWindow(desktopWindowList
.front());
2227 unmanageWindow(win
, True
);
2234 void BScreen::showPosition(int x
, int y
) {
2235 if (! geom_visible
) {
2236 XMoveResizeWindow(blackbox
->getXDisplay(), geom_window
,
2237 (getWidth() - geom_w
) / 2,
2238 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
2239 XMapWindow(blackbox
->getXDisplay(), geom_window
);
2240 XRaiseWindow(blackbox
->getXDisplay(), geom_window
);
2242 geom_visible
= True
;
2247 sprintf(label
, i18n(ScreenSet
, ScreenPositionFormat
,
2248 "X: %4d x Y: %4d"), x
, y
);
2250 XClearWindow(blackbox
->getXDisplay(), geom_window
);
2252 resource
.wstyle
.font
->drawString(geom_window
,
2253 resource
.bevel_width
, resource
.bevel_width
,
2254 resource
.wstyle
.l_text_focus
,
2259 void BScreen::showGeometry(unsigned int gx
, unsigned int gy
) {
2260 if (! geom_visible
) {
2261 XMoveResizeWindow(blackbox
->getXDisplay(), geom_window
,
2262 (getWidth() - geom_w
) / 2,
2263 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
2264 XMapWindow(blackbox
->getXDisplay(), geom_window
);
2265 XRaiseWindow(blackbox
->getXDisplay(), geom_window
);
2267 geom_visible
= True
;
2272 sprintf(label
, i18n(ScreenSet
, ScreenGeometryFormat
,
2273 "W: %4d x H: %4d"), gx
, gy
);
2275 XClearWindow(blackbox
->getXDisplay(), geom_window
);
2277 resource
.wstyle
.font
->drawString(geom_window
,
2278 resource
.bevel_width
, resource
.bevel_width
,
2279 resource
.wstyle
.l_text_focus
,
2284 void BScreen::hideGeometry(void) {
2286 XUnmapWindow(blackbox
->getXDisplay(), geom_window
);
2287 geom_visible
= False
;
2292 void BScreen::addStrut(Strut
*strut
) {
2293 strutList
.push_back(strut
);
2297 void BScreen::removeStrut(Strut
*strut
) {
2298 strutList
.remove(strut
);
2302 const Rect
& BScreen::availableArea(void) const {
2304 return getRect(); // return the full screen
2310 const RectList
& BScreen::allAvailableAreas(void) const {
2311 assert(isXineramaActive());
2312 assert(xineramaUsableArea
.size() > 0);
2313 fprintf(stderr
, "1found x %d y %d w %d h %d\n",
2314 xineramaUsableArea
[0].x(), xineramaUsableArea
[0].y(),
2315 xineramaUsableArea
[0].width(), xineramaUsableArea
[0].height());
2316 return xineramaUsableArea
;
2321 void BScreen::updateAvailableArea(void) {
2322 Rect old_area
= usableArea
;
2323 usableArea
= getRect(); // reset to full screen
2326 // reset to the full areas
2327 if (isXineramaActive())
2328 xineramaUsableArea
= getXineramaAreas();
2331 /* these values represent offsets from the screen edge
2332 * we look for the biggest offset on each edge and then apply them
2334 * do not be confused by the similarity to the names of Rect's members
2336 unsigned int current_left
= 0, current_right
= 0, current_top
= 0,
2339 StrutList::const_iterator it
= strutList
.begin(), end
= strutList
.end();
2341 for(; it
!= end
; ++it
) {
2343 if (strut
->left
> current_left
)
2344 current_left
= strut
->left
;
2345 if (strut
->top
> current_top
)
2346 current_top
= strut
->top
;
2347 if (strut
->right
> current_right
)
2348 current_right
= strut
->right
;
2349 if (strut
->bottom
> current_bottom
)
2350 current_bottom
= strut
->bottom
;
2353 usableArea
.setPos(current_left
, current_top
);
2354 usableArea
.setSize(usableArea
.width() - (current_left
+ current_right
),
2355 usableArea
.height() - (current_top
+ current_bottom
));
2358 if (isXineramaActive()) {
2359 // keep each of the ximerama-defined areas inside the strut
2360 RectList::iterator xit
, xend
= xineramaUsableArea
.end();
2361 for (xit
= xineramaUsableArea
.begin(); xit
!= xend
; ++xit
) {
2362 if (xit
->x() < usableArea
.x()) {
2363 xit
->setX(usableArea
.x());
2364 xit
->setWidth(xit
->width() - usableArea
.x());
2366 if (xit
->y() < usableArea
.y()) {
2367 xit
->setY(usableArea
.y());
2368 xit
->setHeight(xit
->height() - usableArea
.y());
2370 if (xit
->x() + xit
->width() > usableArea
.width())
2371 xit
->setWidth(usableArea
.width() - xit
->x());
2372 if (xit
->y() + xit
->height() > usableArea
.height())
2373 xit
->setHeight(usableArea
.height() - xit
->y());
2378 if (old_area
!= usableArea
) {
2379 BlackboxWindowList::iterator it
= windowList
.begin(),
2380 end
= windowList
.end();
2381 for (; it
!= end
; ++it
)
2382 if ((*it
)->isMaximized()) (*it
)->remaximize();
2389 Workspace
* BScreen::getWorkspace(unsigned int index
) {
2390 assert(index
< workspacesList
.size());
2391 return workspacesList
[index
];
2395 void BScreen::buttonPressEvent(const XButtonEvent
*xbutton
) {
2396 if (xbutton
->button
== 1) {
2397 if (! isRootColormapInstalled())
2398 image_control
->installRootColormap();
2400 if (workspacemenu
->isVisible())
2401 workspacemenu
->hide();
2403 if (rootmenu
->isVisible())
2405 } else if (xbutton
->button
== 2) {
2406 showWorkspaceMenu(xbutton
->x_root
, xbutton
->y_root
);
2407 } else if (xbutton
->button
== 3) {
2408 showRootMenu(xbutton
->x_root
, xbutton
->y_root
);
2410 } else if ((xbutton
->button
== 4 && resource
.root_scroll
== NormalScroll
) ||
2411 (xbutton
->button
== 5 && resource
.root_scroll
== ReverseScroll
)) {
2412 if (getCurrentWorkspaceID() >= getWorkspaceCount() - 1)
2413 changeWorkspaceID(0);
2415 changeWorkspaceID(getCurrentWorkspaceID() + 1);
2417 } else if ((xbutton
->button
== 5 && resource
.root_scroll
== NormalScroll
) ||
2418 (xbutton
->button
== 4 && resource
.root_scroll
== ReverseScroll
)) {
2419 if (getCurrentWorkspaceID() == 0)
2420 changeWorkspaceID(getWorkspaceCount() - 1);
2422 changeWorkspaceID(getCurrentWorkspaceID() - 1);
2427 void BScreen::showWorkspaceMenu(int x
, int y
) {
2428 int mx
= x
- (workspacemenu
->getWidth() / 2);
2429 int my
= y
- (workspacemenu
->getTitleHeight() / 2);
2434 if (mx
+ workspacemenu
->getWidth() > getWidth())
2435 mx
= getWidth() - workspacemenu
->getWidth() - getBorderWidth();
2437 if (my
+ workspacemenu
->getHeight() > getHeight())
2438 my
= getHeight() - workspacemenu
->getHeight() - getBorderWidth();
2440 workspacemenu
->move(mx
, my
);
2442 if (! workspacemenu
->isVisible()) {
2443 workspacemenu
->removeParent();
2444 workspacemenu
->show();
2449 void BScreen::showRootMenu(int x
, int y
) {
2450 int mx
= x
- (rootmenu
->getWidth() / 2);
2451 int my
= y
- (rootmenu
->getTitleHeight() / 2);
2456 if (mx
+ rootmenu
->getWidth() > getWidth())
2457 mx
= getWidth() - rootmenu
->getWidth() - getBorderWidth();
2459 if (my
+ rootmenu
->getHeight() > getHeight())
2460 my
= getHeight() - rootmenu
->getHeight() - getBorderWidth();
2462 rootmenu
->move(mx
, my
);
2464 if (! rootmenu
->isVisible()) {
2465 blackbox
->checkMenu();
2471 void BScreen::propertyNotifyEvent(const XPropertyEvent
*pe
) {
2472 if (pe
->atom
== xatom
->getAtom(XAtom::net_desktop_names
)) {
2473 // _NET_WM_DESKTOP_NAMES
2474 WorkspaceList::iterator it
= workspacesList
.begin();
2475 const WorkspaceList::iterator end
= workspacesList
.end();
2476 for (; it
!= end
; ++it
) {
2477 (*it
)->readName(); // re-read its name from the window property
2478 workspacemenu
->changeWorkspaceLabel((*it
)->getID(), (*it
)->getName());
2480 workspacemenu
->update();
2481 toolbar
->reconfigure();
2482 saveWorkspaceNames();
2487 void BScreen::toggleFocusModel(FocusModel model
) {
2488 std::for_each(windowList
.begin(), windowList
.end(),
2489 std::mem_fun(&BlackboxWindow::ungrabButtons
));
2491 if (model
== SloppyFocus
) {
2492 saveSloppyFocus(True
);
2494 // we're cheating here to save writing the config file 3 times
2495 resource
.auto_raise
= False
;
2496 resource
.click_raise
= False
;
2497 saveSloppyFocus(False
);
2500 std::for_each(windowList
.begin(), windowList
.end(),
2501 std::mem_fun(&BlackboxWindow::grabButtons
));
2505 BTexture
BScreen::readDatabaseTexture(const string
&rname
,
2506 const string
&default_color
,
2507 const Configuration
&style
) {
2511 if (style
.getValue(rname
, s
))
2512 texture
= BTexture(s
);
2514 texture
.setTexture(BTexture::Solid
| BTexture::Flat
);
2516 // associate this texture with this screen
2517 texture
.setDisplay(getBaseDisplay(), getScreenNumber());
2518 texture
.setImageControl(image_control
);
2520 texture
.setColor(readDatabaseColor(rname
+ ".color", default_color
, style
));
2521 texture
.setColorTo(readDatabaseColor(rname
+ ".colorTo", default_color
,
2528 BColor
BScreen::readDatabaseColor(const string
&rname
,
2529 const string
&default_color
,
2530 const Configuration
&style
) {
2533 if (style
.getValue(rname
, s
))
2534 color
= BColor(s
, getBaseDisplay(), getScreenNumber());
2536 color
= BColor(default_color
, getBaseDisplay(), getScreenNumber());
2541 BFont
*BScreen::readDatabaseFont(const string
&rbasename
,
2542 const Configuration
&style
) {
2549 if (style
.getValue(rbasename
+ "xft.font", s
) &&
2550 style
.getValue(rbasename
+ "xft.size", i
)) {
2553 bool italic
= False
;
2554 if (style
.getValue(rbasename
+ "xft.flags", s
)) {
2555 if (s
.find("bold") != string::npos
)
2557 if (s
.find("italic") != string::npos
)
2561 BFont
*b
= new BFont(blackbox
->getXDisplay(), this, family
, i
, bold
,
2562 italic
, resource
.aa_fonts
);
2566 delete b
; // fall back to the normal X font stuff
2570 style
.getValue(rbasename
+ "font", s
);
2571 // if this fails, a blank string will be used, which will cause the fallback
2574 BFont
*b
= new BFont(blackbox
->getXDisplay(), this, s
);
2576 exit(2); // can't continue without a font