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::saveRootMenuButton(unsigned int b
) {
600 resource
.root_menu_button
= b
;
602 switch (resource
.root_menu_button
) {
603 case 0: but
= "None"; break;
604 case 1: but
= "Left"; break;
605 case 2: but
= "Middle"; break;
606 case 3: default: but
= "Right"; break;
608 config
->setValue(screenstr
+ "rootMenuButton", but
);
612 void BScreen::saveWorkspaceMenuButton(unsigned int b
) {
613 resource
.workspace_menu_button
= b
;
615 switch (resource
.workspace_menu_button
) {
616 case 0: but
= "None"; break;
617 case 1: but
= "Left"; break;
618 case 2: default: but
= "Middle"; break;
619 case 3: but
= "Right"; break;
621 config
->setValue(screenstr
+ "workspaceMenuButton", but
);
625 void BScreen::save_rc(void) {
626 saveSloppyFocus(resource
.sloppy_focus
);
627 saveAutoRaise(resource
.auto_raise
);
628 saveImageDither(doImageDither());
629 saveShadowFonts(resource
.shadow_fonts
);
630 saveAAFonts(resource
.aa_fonts
);
631 saveResizeZones(resource
.resize_zones
);
632 saveOpaqueMove(resource
.opaque_move
);
633 saveFullMax(resource
.full_max
);
634 saveFocusNew(resource
.focus_new
);
635 saveFocusLast(resource
.focus_last
);
636 saveHideToolbar(resource
.hide_toolbar
);
637 saveWindowToWindowSnap(resource
.snap_to_windows
);
638 saveWindowToEdgeSnap(resource
.snap_to_edges
);
639 saveWindowCornerSnap(resource
.window_corner_snap
);
640 saveWorkspaces(resource
.workspaces
);
641 savePlacementPolicy(resource
.placement_policy
);
642 saveSnapThreshold(resource
.snap_threshold
);
643 saveSnapOffset(resource
.snap_offset
);
644 saveResistanceSize(resource
.resistance_size
);
645 saveRowPlacementDirection(resource
.row_direction
);
646 saveColPlacementDirection(resource
.col_direction
);
648 saveStrftimeFormat(resource
.strftime_format
);
649 #else // !HAVE_STRFTIME
650 saveDateFormat(resource
.date_format
);
651 savwClock24Hour(resource
.clock24hour
);
652 #endif // HAVE_STRFTIME
653 savePlaceIgnoreShaded(resource
.ignore_shaded
);
654 savePlaceIgnoreMaximized(resource
.ignore_maximized
);
655 saveAllowScrollLock(resource
.allow_scroll_lock
);
656 saveWorkspaceWarping(resource
.workspace_warping
);
657 saveRootScrollDirection(resource
.root_scroll
);
658 saveRootMenuButton(resource
.root_menu_button
);
659 saveWorkspaceMenuButton(resource
.workspace_menu_button
);
666 void BScreen::load_rc(void) {
670 if (! config
->getValue(screenstr
+ "fullMaximization", resource
.full_max
))
671 resource
.full_max
= false;
673 if (! config
->getValue(screenstr
+ "focusNewWindows", resource
.focus_new
))
674 resource
.focus_new
= false;
676 if (! config
->getValue(screenstr
+ "focusLastWindow", resource
.focus_last
))
677 resource
.focus_last
= false;
679 if (! config
->getValue(screenstr
+ "workspaces", resource
.workspaces
))
680 resource
.workspaces
= 1;
682 if (! config
->getValue(screenstr
+ "opaqueMove", resource
.opaque_move
))
683 resource
.opaque_move
= false;
685 if (! config
->getValue(screenstr
+ "dropShadowFonts", resource
.shadow_fonts
))
686 resource
.shadow_fonts
= false;
688 if (! config
->getValue(screenstr
+ "antialiasFonts", resource
.aa_fonts
))
689 resource
.aa_fonts
= true;
691 if (! config
->getValue(screenstr
+ "resizeZones", resource
.resize_zones
) ||
692 (resource
.resize_zones
!= 1 && resource
.resize_zones
!= 2 &&
693 resource
.resize_zones
!= 4))
694 resource
.resize_zones
= 4;
696 if (! config
->getValue(screenstr
+ "hideToolbar", resource
.hide_toolbar
))
697 resource
.hide_toolbar
= false;
699 resource
.snap_to_windows
= WindowResistance
;
700 if (config
->getValue(screenstr
+ "windowToWindowSnap", s
)) {
702 resource
.snap_to_windows
= WindowNoSnap
;
703 else if (s
== "Snap")
704 resource
.snap_to_windows
= WindowSnap
;
707 resource
.snap_to_edges
= WindowResistance
;
708 if (config
->getValue(screenstr
+ "windowToEdgeSnap", s
)) {
710 resource
.snap_to_edges
= WindowNoSnap
;
711 else if (s
== "Snap")
712 resource
.snap_to_edges
= WindowSnap
;
715 if (! config
->getValue(screenstr
+ "windowCornerSnap",
716 resource
.window_corner_snap
))
717 resource
.window_corner_snap
= true;
719 if (! config
->getValue(screenstr
+ "imageDither", b
))
721 image_control
->setDither(b
);
723 if (! config
->getValue(screenstr
+ "edgeSnapOffset",
724 resource
.snap_offset
))
725 resource
.snap_offset
= 0;
726 if (resource
.snap_offset
> 50) // sanity check, setting this huge would
727 resource
.snap_offset
= 50; // seriously suck.
729 if (! config
->getValue(screenstr
+ "edgeSnapThreshold",
730 resource
.snap_threshold
))
731 resource
.snap_threshold
= 4;
733 if (! config
->getValue(screenstr
+ "resistanceSize",
734 resource
.resistance_size
))
735 resource
.resistance_size
= 18;
737 if (config
->getValue(screenstr
+ "rowPlacementDirection", s
) &&
739 resource
.row_direction
= RightLeft
;
741 resource
.row_direction
= LeftRight
;
743 if (config
->getValue(screenstr
+ "colPlacementDirection", s
) &&
745 resource
.col_direction
= BottomTop
;
747 resource
.col_direction
= TopBottom
;
749 if (config
->getValue(screenstr
+ "workspaceNames", s
)) {
750 XAtom::StringVect workspaceNames
;
752 string::const_iterator it
= s
.begin(), end
= s
.end();
754 string::const_iterator tmp
= it
; // current string.begin()
755 it
= std::find(tmp
, end
, ','); // look for comma between tmp and end
756 workspaceNames
.push_back(string(tmp
, it
)); // s[tmp:it]
762 xatom
->setValue(getRootWindow(), XAtom::net_desktop_names
, XAtom::utf8
,
766 resource
.sloppy_focus
= true;
767 resource
.auto_raise
= false;
768 resource
.click_raise
= false;
769 if (config
->getValue(screenstr
+ "focusModel", s
)) {
770 if (s
.find("ClickToFocus") != string::npos
) {
771 resource
.sloppy_focus
= false;
774 if (s
.find("AutoRaise") != string::npos
)
775 resource
.auto_raise
= true;
776 if (s
.find("ClickRaise") != string::npos
)
777 resource
.click_raise
= true;
781 if (config
->getValue(screenstr
+ "windowPlacement", s
)) {
782 if (s
== "CascadePlacement")
783 resource
.placement_policy
= CascadePlacement
;
784 else if (s
== "UnderMousePlacement")
785 resource
.placement_policy
= UnderMousePlacement
;
786 else if (s
== "ClickMousePlacement")
787 resource
.placement_policy
= ClickMousePlacement
;
788 else if (s
== "ColSmartPlacement")
789 resource
.placement_policy
= ColSmartPlacement
;
790 else //if (s == "RowSmartPlacement")
791 resource
.placement_policy
= RowSmartPlacement
;
793 resource
.placement_policy
= RowSmartPlacement
;
796 if (! config
->getValue(screenstr
+ "strftimeFormat",
797 resource
.strftime_format
))
798 resource
.strftime_format
= "%I:%M %p";
799 #else // !HAVE_STRFTIME
802 if (config
->getValue(screenstr
+ "dateFormat", s
) && s
== "European")
803 resource
.date_format
= B_EuropeanDate
;
805 resource
.date_format
= B_AmericanDate
;
807 if (! config
->getValue(screenstr
+ "clockFormat", l
))
809 resource
.clock24hour
= l
== 24;
810 #endif // HAVE_STRFTIME
812 if (! config
->getValue(screenstr
+ "placementIgnoreShaded",
813 resource
.ignore_shaded
))
814 resource
.ignore_shaded
= true;
816 if (! config
->getValue(screenstr
+ "placementIgnoreMaximized",
817 resource
.ignore_maximized
))
818 resource
.ignore_maximized
= true;
820 if (! config
->getValue(screenstr
+ "disableBindingsWithScrollLock",
821 resource
.allow_scroll_lock
))
822 resource
.allow_scroll_lock
= false;
824 if (! config
->getValue(screenstr
+ "workspaceWarping",
825 resource
.workspace_warping
))
826 resource
.workspace_warping
= false;
828 resource
.root_scroll
= NormalScroll
;
829 if (config
->getValue(screenstr
+ "rootScrollDirection", s
)) {
831 resource
.root_scroll
= NoScroll
;
832 else if (s
== "Reverse")
833 resource
.root_scroll
= ReverseScroll
;
836 resource
.root_menu_button
= 3;
837 if (config
->getValue(screenstr
+ "rootMenuButton", s
)) {
839 resource
.root_menu_button
= 0;
840 else if (s
== "Left")
841 resource
.root_menu_button
= 1;
842 else if (s
== "Middle")
843 resource
.root_menu_button
= 2;
846 resource
.workspace_menu_button
= 2;
847 if (config
->getValue(screenstr
+ "workspaceMenuButton", s
)) {
849 resource
.workspace_menu_button
= 0;
850 else if (s
== "Left")
851 resource
.workspace_menu_button
= 1;
852 else if (s
== "Right")
853 resource
.workspace_menu_button
= 3;
855 // cant both be the same
856 if (resource
.workspace_menu_button
== resource
.root_menu_button
)
857 resource
.workspace_menu_button
= 0;
861 void BScreen::changeWorkspaceCount(unsigned int new_count
) {
862 assert(new_count
> 0);
864 if (new_count
< workspacesList
.size()) {
866 for (unsigned int i
= workspacesList
.size(); i
> new_count
; --i
)
867 removeLastWorkspace();
868 // removeLast already sets the current workspace to the
869 // last available one.
870 } else if (new_count
> workspacesList
.size()) {
872 for(unsigned int i
= workspacesList
.size(); i
< new_count
; ++i
)
878 void BScreen::reconfigure(void) {
879 // don't reconfigure while saving the initial rc file, it's a waste and it
880 // breaks somethings (workspace names)
881 if (blackbox
->isStartup()) return;
888 // we need to do this explicitly, because just loading this value from the rc
890 changeWorkspaceCount(resource
.workspaces
);
893 gcv
.foreground
= WhitePixel(blackbox
->getXDisplay(),
895 gcv
.function
= GXinvert
;
896 gcv
.subwindow_mode
= IncludeInferiors
;
897 XChangeGC(blackbox
->getXDisplay(), opGC
,
898 GCForeground
| GCFunction
| GCSubwindowMode
, &gcv
);
900 const char *s
= i18n(ScreenSet
, ScreenPositionLength
,
901 "0: 0000 x 0: 0000");
903 geom_w
= resource
.wstyle
.font
->measureString(s
) + resource
.bevel_width
* 2;
904 geom_h
= resource
.wstyle
.font
->height() + resource
.bevel_width
* 2;
906 BTexture
* texture
= &(resource
.wstyle
.l_focus
);
907 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
908 if (geom_pixmap
== ParentRelative
) {
909 texture
= &(resource
.wstyle
.t_focus
);
910 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
913 XSetWindowBackground(blackbox
->getXDisplay(), geom_window
,
914 texture
->color().pixel());
916 XSetWindowBackgroundPixmap(blackbox
->getXDisplay(),
917 geom_window
, geom_pixmap
);
919 XSetWindowBorderWidth(blackbox
->getXDisplay(), geom_window
,
920 resource
.border_width
);
921 XSetWindowBorder(blackbox
->getXDisplay(), geom_window
,
922 resource
.border_color
.pixel());
924 workspacemenu
->reconfigure();
925 iconmenu
->reconfigure();
927 typedef std::vector
<int> SubList
;
928 SubList remember_subs
;
930 // save the current open menus
931 Basemenu
*menu
= rootmenu
;
933 while ((submenu
= menu
->getCurrentSubmenu()) >= 0) {
934 remember_subs
.push_back(submenu
);
935 menu
= menu
->find(submenu
)->submenu();
941 rootmenu
->reconfigure();
943 // reopen the saved menus
945 const SubList::iterator subs_end
= remember_subs
.end();
946 for (SubList::iterator it
= remember_subs
.begin(); it
!= subs_end
; ++it
) {
947 menu
->drawSubmenu(*it
);
948 menu
= menu
->find(*it
)->submenu();
953 configmenu
->reconfigure();
955 toolbar
->reconfigure();
959 std::for_each(workspacesList
.begin(), workspacesList
.end(),
960 std::mem_fun(&Workspace::reconfigure
));
962 BlackboxWindowList::iterator iit
= iconList
.begin();
963 for (; iit
!= iconList
.end(); ++iit
) {
964 BlackboxWindow
*bw
= *iit
;
965 if (bw
->validateClient())
969 image_control
->timeout();
973 void BScreen::rereadMenu(void) {
977 rootmenu
->reconfigure();
981 void BScreen::LoadStyle(void) {
982 Configuration
style(False
);
984 const char *sfile
= blackbox
->getStyleFilename();
986 style
.setFile(sfile
);
987 if (! style
.load()) {
988 style
.setFile(DEFAULTSTYLE
);
990 style
.create(); // hardcoded default values will be used.
994 // merge in the rc file
995 style
.merge(config
->file(), True
);
999 // load fonts/fontsets
1000 if (resource
.wstyle
.font
)
1001 delete resource
.wstyle
.font
;
1002 if (resource
.tstyle
.font
)
1003 delete resource
.tstyle
.font
;
1004 if (resource
.mstyle
.f_font
)
1005 delete resource
.mstyle
.f_font
;
1006 if (resource
.mstyle
.t_font
)
1007 delete resource
.mstyle
.t_font
;
1008 resource
.wstyle
.font
= resource
.tstyle
.font
= resource
.mstyle
.f_font
=
1009 resource
.mstyle
.t_font
= (BFont
*) 0;
1011 resource
.wstyle
.font
= readDatabaseFont("window.", style
);
1012 resource
.tstyle
.font
= readDatabaseFont("toolbar.", style
);
1013 resource
.mstyle
.t_font
= readDatabaseFont("menu.title.", style
);
1014 resource
.mstyle
.f_font
= readDatabaseFont("menu.frame.", style
);
1016 // load window config
1017 resource
.wstyle
.t_focus
=
1018 readDatabaseTexture("window.title.focus", "white", style
);
1019 resource
.wstyle
.t_unfocus
=
1020 readDatabaseTexture("window.title.unfocus", "black", style
);
1021 resource
.wstyle
.l_focus
=
1022 readDatabaseTexture("window.label.focus", "white", style
);
1023 resource
.wstyle
.l_unfocus
=
1024 readDatabaseTexture("window.label.unfocus", "black", style
);
1025 resource
.wstyle
.h_focus
=
1026 readDatabaseTexture("window.handle.focus", "white", style
);
1027 resource
.wstyle
.h_unfocus
=
1028 readDatabaseTexture("window.handle.unfocus", "black", style
);
1029 resource
.wstyle
.g_focus
=
1030 readDatabaseTexture("window.grip.focus", "white", style
);
1031 resource
.wstyle
.g_unfocus
=
1032 readDatabaseTexture("window.grip.unfocus", "black", style
);
1033 resource
.wstyle
.b_focus
=
1034 readDatabaseTexture("window.button.focus", "white", style
);
1035 resource
.wstyle
.b_unfocus
=
1036 readDatabaseTexture("window.button.unfocus", "black", style
);
1037 resource
.wstyle
.b_pressed
=
1038 readDatabaseTexture("window.button.pressed", "black", style
);
1040 // we create the window.frame texture by hand because it exists only to
1041 // make the code cleaner and is not actually used for display
1042 BColor color
= readDatabaseColor("window.frame.focusColor", "white", style
);
1043 resource
.wstyle
.f_focus
= BTexture("solid flat", getBaseDisplay(),
1044 getScreenNumber(), image_control
);
1045 resource
.wstyle
.f_focus
.setColor(color
);
1047 color
= readDatabaseColor("window.frame.unfocusColor", "white", style
);
1048 resource
.wstyle
.f_unfocus
= BTexture("solid flat", getBaseDisplay(),
1049 getScreenNumber(), image_control
);
1050 resource
.wstyle
.f_unfocus
.setColor(color
);
1052 resource
.wstyle
.l_text_focus
=
1053 readDatabaseColor("window.label.focus.textColor", "black", style
);
1054 resource
.wstyle
.l_text_unfocus
=
1055 readDatabaseColor("window.label.unfocus.textColor", "white", style
);
1056 resource
.wstyle
.b_pic_focus
=
1057 readDatabaseColor("window.button.focus.picColor", "black", style
);
1058 resource
.wstyle
.b_pic_unfocus
=
1059 readDatabaseColor("window.button.unfocus.picColor", "white", style
);
1061 resource
.wstyle
.justify
= LeftJustify
;
1062 if (style
.getValue("window.justify", s
)) {
1063 if (s
== "right" || s
== "Right")
1064 resource
.wstyle
.justify
= RightJustify
;
1065 else if (s
== "center" || s
== "Center")
1066 resource
.wstyle
.justify
= CenterJustify
;
1070 if (resource
.wstyle
.t_focus
.texture() == BTexture::Parent_Relative
)
1071 resource
.wstyle
.t_focus
= resource
.wstyle
.f_focus
;
1072 if (resource
.wstyle
.t_unfocus
.texture() == BTexture::Parent_Relative
)
1073 resource
.wstyle
.t_unfocus
= resource
.wstyle
.f_unfocus
;
1074 if (resource
.wstyle
.h_focus
.texture() == BTexture::Parent_Relative
)
1075 resource
.wstyle
.h_focus
= resource
.wstyle
.f_focus
;
1076 if (resource
.wstyle
.h_unfocus
.texture() == BTexture::Parent_Relative
)
1077 resource
.wstyle
.h_unfocus
= resource
.wstyle
.f_unfocus
;
1079 // load toolbar config
1080 resource
.tstyle
.toolbar
=
1081 readDatabaseTexture("toolbar", "black", style
);
1082 resource
.tstyle
.label
=
1083 readDatabaseTexture("toolbar.label", "black", style
);
1084 resource
.tstyle
.window
=
1085 readDatabaseTexture("toolbar.windowLabel", "black", style
);
1086 resource
.tstyle
.button
=
1087 readDatabaseTexture("toolbar.button", "white", style
);
1088 resource
.tstyle
.pressed
=
1089 readDatabaseTexture("toolbar.button.pressed", "black", style
);
1090 resource
.tstyle
.clock
=
1091 readDatabaseTexture("toolbar.clock", "black", style
);
1092 resource
.tstyle
.l_text
=
1093 readDatabaseColor("toolbar.label.textColor", "white", style
);
1094 resource
.tstyle
.w_text
=
1095 readDatabaseColor("toolbar.windowLabel.textColor", "white", style
);
1096 resource
.tstyle
.c_text
=
1097 readDatabaseColor("toolbar.clock.textColor", "white", style
);
1098 resource
.tstyle
.b_pic
=
1099 readDatabaseColor("toolbar.button.picColor", "black", style
);
1101 resource
.tstyle
.justify
= LeftJustify
;
1102 if (style
.getValue("toolbar.justify", s
)) {
1103 if (s
== "right" || s
== "Right")
1104 resource
.tstyle
.justify
= RightJustify
;
1105 else if (s
== "center" || s
== "Center")
1106 resource
.tstyle
.justify
= CenterJustify
;
1110 if (resource
.tstyle
.toolbar
.texture() == BTexture::Parent_Relative
) {
1111 resource
.tstyle
.toolbar
= BTexture("solid flat", getBaseDisplay(),
1112 getScreenNumber(), image_control
);
1113 resource
.tstyle
.toolbar
.setColor(BColor("black", getBaseDisplay(),
1114 getScreenNumber()));
1118 resource
.mstyle
.title
=
1119 readDatabaseTexture("menu.title", "white", style
);
1120 resource
.mstyle
.frame
=
1121 readDatabaseTexture("menu.frame", "black", style
);
1122 resource
.mstyle
.hilite
=
1123 readDatabaseTexture("menu.hilite", "white", style
);
1124 resource
.mstyle
.t_text
=
1125 readDatabaseColor("menu.title.textColor", "black", style
);
1126 resource
.mstyle
.f_text
=
1127 readDatabaseColor("menu.frame.textColor", "white", style
);
1128 resource
.mstyle
.d_text
=
1129 readDatabaseColor("menu.frame.disableColor", "black", style
);
1130 resource
.mstyle
.h_text
=
1131 readDatabaseColor("menu.hilite.textColor", "black", style
);
1133 resource
.mstyle
.t_justify
= LeftJustify
;
1134 if (style
.getValue("menu.title.justify", s
)) {
1135 if (s
== "right" || s
== "Right")
1136 resource
.mstyle
.t_justify
= RightJustify
;
1137 else if (s
== "center" || s
== "Center")
1138 resource
.mstyle
.t_justify
= CenterJustify
;
1141 resource
.mstyle
.f_justify
= LeftJustify
;
1142 if (style
.getValue("menu.frame.justify", s
)) {
1143 if (s
== "right" || s
== "Right")
1144 resource
.mstyle
.f_justify
= RightJustify
;
1145 else if (s
== "center" || s
== "Center")
1146 resource
.mstyle
.f_justify
= CenterJustify
;
1149 resource
.mstyle
.bullet
= Basemenu::Triangle
;
1150 if (style
.getValue("menu.bullet", s
)) {
1151 if (s
== "empty" || s
== "Empty")
1152 resource
.mstyle
.bullet
= Basemenu::Empty
;
1153 else if (s
== "square" || s
== "Square")
1154 resource
.mstyle
.bullet
= Basemenu::Square
;
1155 else if (s
== "diamond" || s
== "Diamond")
1156 resource
.mstyle
.bullet
= Basemenu::Diamond
;
1159 resource
.mstyle
.bullet_pos
= Basemenu::Left
;
1160 if (style
.getValue("menu.bullet.position", s
)) {
1161 if (s
== "right" || s
== "Right")
1162 resource
.mstyle
.bullet_pos
= Basemenu::Right
;
1166 if (resource
.mstyle
.frame
.texture() == BTexture::Parent_Relative
) {
1167 resource
.mstyle
.frame
= BTexture("solid flat", getBaseDisplay(),
1168 getScreenNumber(), image_control
);
1169 resource
.mstyle
.frame
.setColor(BColor("black", getBaseDisplay(),
1170 getScreenNumber()));
1173 resource
.border_color
=
1174 readDatabaseColor("borderColor", "black", style
);
1176 // load bevel, border and handle widths
1177 if (! style
.getValue("handleWidth", resource
.handle_width
) ||
1178 resource
.handle_width
> (getWidth() / 2) || resource
.handle_width
== 0)
1179 resource
.handle_width
= 6;
1181 if (! style
.getValue("borderWidth", resource
.border_width
))
1182 resource
.border_width
= 1;
1184 if (! style
.getValue("bevelWidth", resource
.bevel_width
) ||
1185 resource
.bevel_width
> (getWidth() / 2) || resource
.bevel_width
== 0)
1186 resource
.bevel_width
= 3;
1188 if (! style
.getValue("frameWidth", resource
.frame_width
) ||
1189 resource
.frame_width
> (getWidth() / 2))
1190 resource
.frame_width
= resource
.bevel_width
;
1192 if (style
.getValue("rootCommand", s
))
1193 bexec(s
, displayString());
1197 void BScreen::addIcon(BlackboxWindow
*w
) {
1200 w
->setWorkspace(BSENTINEL
);
1201 w
->setWindowNumber(iconList
.size());
1203 iconList
.push_back(w
);
1205 const char* title
= w
->getIconTitle();
1206 iconmenu
->insert(title
);
1211 void BScreen::removeIcon(BlackboxWindow
*w
) {
1216 iconmenu
->remove(w
->getWindowNumber());
1219 BlackboxWindowList::iterator it
= iconList
.begin(),
1220 end
= iconList
.end();
1221 for (int i
= 0; it
!= end
; ++it
)
1222 (*it
)->setWindowNumber(i
++);
1226 BlackboxWindow
*BScreen::getIcon(unsigned int index
) {
1227 if (index
< iconList
.size()) {
1228 BlackboxWindowList::iterator it
= iconList
.begin();
1229 while (index
-- > 0) // increment to index
1234 return (BlackboxWindow
*) 0;
1238 unsigned int BScreen::addWorkspace(void) {
1239 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
1240 workspacesList
.push_back(wkspc
);
1241 saveWorkspaces(getWorkspaceCount());
1242 saveWorkspaceNames();
1244 workspacemenu
->insertWorkspace(wkspc
);
1245 workspacemenu
->update();
1247 toolbar
->reconfigure();
1249 updateNetizenWorkspaceCount();
1251 return workspacesList
.size();
1255 unsigned int BScreen::removeLastWorkspace(void) {
1256 if (workspacesList
.size() == 1)
1259 Workspace
*wkspc
= workspacesList
.back();
1261 if (current_workspace
->getID() == wkspc
->getID())
1262 changeWorkspaceID(current_workspace
->getID() - 1);
1266 workspacemenu
->removeWorkspace(wkspc
);
1267 workspacemenu
->update();
1269 workspacesList
.pop_back();
1272 saveWorkspaces(getWorkspaceCount());
1273 saveWorkspaceNames();
1275 toolbar
->reconfigure();
1277 updateNetizenWorkspaceCount();
1279 return workspacesList
.size();
1283 void BScreen::changeWorkspaceID(unsigned int id
) {
1284 if (! current_workspace
|| id
== current_workspace
->getID()) return;
1286 BlackboxWindow
*focused
= blackbox
->getFocusedWindow();
1287 if (focused
&& focused
->getScreen() == this) {
1288 assert(focused
->isStuck() ||
1289 focused
->getWorkspaceNumber() == current_workspace
->getID());
1291 current_workspace
->setLastFocusedWindow(focused
);
1293 // if no window had focus, no need to store a last focus
1294 current_workspace
->setLastFocusedWindow((BlackboxWindow
*) 0);
1297 // when we switch workspaces, unfocus whatever was focused if it is going
1299 if (focused
&& ! focused
->isStuck())
1300 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1302 current_workspace
->hideAll();
1303 workspacemenu
->setItemSelected(current_workspace
->getID() + 2, False
);
1305 current_workspace
= getWorkspace(id
);
1307 xatom
->setValue(getRootWindow(), XAtom::net_current_desktop
,
1308 XAtom::cardinal
, id
);
1310 workspacemenu
->setItemSelected(current_workspace
->getID() + 2, True
);
1311 toolbar
->redrawWorkspaceLabel(True
);
1313 current_workspace
->showAll();
1318 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
1321 XSync(blackbox
->getXDisplay(), False
);
1323 // If sloppy focus and we can find the client window under the pointer,
1325 if (resource
.sloppy_focus
&&
1326 XQueryPointer(blackbox
->getXDisplay(), getRootWindow(), &r
, &c
,
1327 &rx
, &ry
, &x
, &y
, &m
) &&
1329 if ( (win
= blackbox
->searchWindow(c
)) )
1330 f
= win
->setInputFocus();
1333 // If that fails, and we're doing focus_last, try to focus the last window.
1334 if (! f
&& resource
.focus_last
&&
1335 (win
= current_workspace
->getLastFocusedWindow()))
1336 f
= win
->setInputFocus();
1339 if we found a focus target, then we set the focused window explicitly
1340 because it is possible to switch off this workspace before the x server
1341 generates the FocusIn event for the window. if that happens, openbox would
1342 lose track of what window was the 'LastFocused' window on the workspace.
1344 if we did not find a focus target, then set the current focused window to
1348 blackbox
->setFocusedWindow(win
);
1350 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1352 updateNetizenCurrentWorkspace();
1357 * Set the _NET_CLIENT_LIST root window property.
1359 void BScreen::updateClientList(void) {
1360 if (windowList
.size() > 0) {
1361 Window
*windows
= new Window
[windowList
.size()];
1362 Window
*win_it
= windows
;
1363 BlackboxWindowList::iterator it
= windowList
.begin();
1364 const BlackboxWindowList::iterator end
= windowList
.end();
1365 for (; it
!= end
; ++it
, ++win_it
)
1366 *win_it
= (*it
)->getClientWindow();
1367 xatom
->setValue(getRootWindow(), XAtom::net_client_list
, XAtom::window
,
1368 windows
, windowList
.size());
1371 xatom
->setValue(getRootWindow(), XAtom::net_client_list
, XAtom::window
,
1374 updateStackingList();
1379 * Set the _NET_CLIENT_LIST_STACKING root window property.
1381 void BScreen::updateStackingList(void) {
1383 BlackboxWindowList stack_order
;
1386 * Get the stacking order from all of the workspaces.
1387 * We start with the current workspace so that the sticky windows will be
1388 * in the right order on the current workspace.
1389 * XXX: Do we need to have sticky windows in the list once for each workspace?
1391 getCurrentWorkspace()->appendStackOrder(stack_order
);
1392 for (unsigned int i
= 0; i
< getWorkspaceCount(); ++i
)
1393 if (i
!= getCurrentWorkspaceID())
1394 getWorkspace(i
)->appendStackOrder(stack_order
);
1396 if (stack_order
.size() > 0) {
1397 // set the client list atoms
1398 Window
*windows
= new Window
[stack_order
.size()];
1399 Window
*win_it
= windows
;
1400 BlackboxWindowList::iterator it
= stack_order
.begin(),
1401 end
= stack_order
.end();
1402 for (; it
!= end
; ++it
, ++win_it
)
1403 *win_it
= (*it
)->getClientWindow();
1404 xatom
->setValue(getRootWindow(), XAtom::net_client_list_stacking
,
1405 XAtom::window
, windows
, stack_order
.size());
1408 xatom
->setValue(getRootWindow(), XAtom::net_client_list_stacking
,
1409 XAtom::window
, 0, 0);
1413 void BScreen::addSystrayWindow(Window window
) {
1414 XGrabServer(blackbox
->getXDisplay());
1416 XSelectInput(blackbox
->getXDisplay(), window
, StructureNotifyMask
);
1417 systrayWindowList
.push_back(window
);
1418 xatom
->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows
,
1420 &systrayWindowList
[0], systrayWindowList
.size());
1421 blackbox
->saveSystrayWindowSearch(window
, this);
1423 XUngrabServer(blackbox
->getXDisplay());
1427 void BScreen::removeSystrayWindow(Window window
) {
1428 XGrabServer(blackbox
->getXDisplay());
1430 WindowList::iterator it
= systrayWindowList
.begin();
1431 const WindowList::iterator end
= systrayWindowList
.end();
1432 for (; it
!= end
; ++it
)
1433 if (*it
== window
) {
1434 systrayWindowList
.erase(it
);
1435 xatom
->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows
,
1437 &systrayWindowList
[0], systrayWindowList
.size());
1438 blackbox
->removeSystrayWindowSearch(window
);
1439 XSelectInput(blackbox
->getXDisplay(), window
, NoEventMask
);
1443 assert(it
!= end
); // not a systray window
1445 XUngrabServer(blackbox
->getXDisplay());
1449 void BScreen::manageWindow(Window w
) {
1450 // is the window a KDE systray window?
1452 if (xatom
->getValue(w
, XAtom::kde_net_wm_system_tray_window_for
,
1453 XAtom::window
, systray
) && systray
!= None
) {
1454 addSystrayWindow(w
);
1458 // is the window a docking app
1459 XWMHints
*wmhint
= XGetWMHints(blackbox
->getXDisplay(), w
);
1460 if (wmhint
&& (wmhint
->flags
& StateHint
) &&
1461 wmhint
->initial_state
== WithdrawnState
) {
1466 new BlackboxWindow(blackbox
, w
, this);
1468 BlackboxWindow
*win
= blackbox
->searchWindow(w
);
1472 if (win
->isDesktop()) {
1473 desktopWindowList
.push_back(win
->getFrameWindow());
1474 } else { // if (win->isNormal()) {
1475 // don't list desktop windows as managed windows
1476 windowList
.push_back(win
);
1479 if (win
->isTopmost())
1480 specialWindowList
.push_back(win
->getFrameWindow());
1483 XMapRequestEvent mre
;
1485 if (blackbox
->isStartup() && win
->isNormal()) win
->restoreAttributes();
1486 win
->mapRequestEvent(&mre
);
1490 void BScreen::unmanageWindow(BlackboxWindow
*w
, bool remap
) {
1491 // is the window a KDE systray window?
1493 if (xatom
->getValue(w
->getClientWindow(),
1494 XAtom::kde_net_wm_system_tray_window_for
,
1495 XAtom::window
, systray
) && systray
!= None
) {
1496 removeSystrayWindow(w
->getClientWindow());
1502 // Remove the modality so that its parent won't try to re-focus the window
1503 if (w
->isModal()) w
->setModal(False
);
1505 if (w
->getWorkspaceNumber() != BSENTINEL
&&
1506 w
->getWindowNumber() != BSENTINEL
) {
1507 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1509 for (unsigned int i
= 0; i
< getNumberOfWorkspaces(); ++i
)
1510 if (i
!= w
->getWorkspaceNumber())
1511 getWorkspace(i
)->removeWindow(w
, True
);
1513 } else if (w
->isIconic())
1516 if (w
->isDesktop()) {
1517 WindowList::iterator it
= desktopWindowList
.begin();
1518 const WindowList::iterator end
= desktopWindowList
.end();
1519 for (; it
!= end
; ++it
)
1520 if (*it
== w
->getFrameWindow()) {
1521 desktopWindowList
.erase(it
);
1524 assert(it
!= end
); // the window wasnt a desktop window?
1525 } else { // if (w->isNormal()) {
1526 // we don't list desktop windows as managed windows
1527 windowList
.remove(w
);
1530 if (w
->isTopmost()) {
1531 WindowList::iterator it
= specialWindowList
.begin();
1532 const WindowList::iterator end
= specialWindowList
.end();
1533 for (; it
!= end
; ++it
)
1534 if (*it
== w
->getFrameWindow()) {
1535 specialWindowList
.erase(it
);
1538 assert(it
!= end
); // the window wasnt a special window?
1542 if (blackbox
->getFocusedWindow() == w
)
1543 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1545 removeNetizen(w
->getClientWindow());
1548 some managed windows can also be window group controllers. when
1549 unmanaging such windows, we should also delete the window group.
1551 BWindowGroup
*group
= blackbox
->searchGroup(w
->getClientWindow());
1558 void BScreen::addNetizen(Netizen
*n
) {
1559 netizenList
.push_back(n
);
1561 n
->sendWorkspaceCount();
1562 n
->sendCurrentWorkspace();
1564 WorkspaceList::iterator it
= workspacesList
.begin();
1565 const WorkspaceList::iterator end
= workspacesList
.end();
1566 for (; it
!= end
; ++it
)
1567 (*it
)->sendWindowList(*n
);
1569 Window f
= ((blackbox
->getFocusedWindow()) ?
1570 blackbox
->getFocusedWindow()->getClientWindow() : None
);
1571 n
->sendWindowFocus(f
);
1575 void BScreen::removeNetizen(Window w
) {
1576 NetizenList::iterator it
= netizenList
.begin();
1577 for (; it
!= netizenList
.end(); ++it
) {
1578 if ((*it
)->getWindowID() == w
) {
1580 netizenList
.erase(it
);
1587 void BScreen::updateWorkArea(void) {
1588 if (workspacesList
.size() > 0) {
1589 unsigned long *dims
= new unsigned long[4 * workspacesList
.size()];
1590 for (unsigned int i
= 0, m
= workspacesList
.size(); i
< m
; ++i
) {
1591 // XXX: this could be different for each workspace
1592 const Rect
&area
= availableArea();
1593 dims
[(i
* 4) + 0] = area
.x();
1594 dims
[(i
* 4) + 1] = area
.y();
1595 dims
[(i
* 4) + 2] = area
.width();
1596 dims
[(i
* 4) + 3] = area
.height();
1598 xatom
->setValue(getRootWindow(), XAtom::net_workarea
, XAtom::cardinal
,
1599 dims
, 4 * workspacesList
.size());
1602 xatom
->setValue(getRootWindow(), XAtom::net_workarea
, XAtom::cardinal
,
1607 void BScreen::updateNetizenCurrentWorkspace(void) {
1608 std::for_each(netizenList
.begin(), netizenList
.end(),
1609 std::mem_fun(&Netizen::sendCurrentWorkspace
));
1613 void BScreen::updateNetizenWorkspaceCount(void) {
1614 xatom
->setValue(getRootWindow(), XAtom::net_number_of_desktops
,
1615 XAtom::cardinal
, workspacesList
.size());
1619 std::for_each(netizenList
.begin(), netizenList
.end(),
1620 std::mem_fun(&Netizen::sendWorkspaceCount
));
1624 void BScreen::updateNetizenWindowFocus(void) {
1625 Window f
= ((blackbox
->getFocusedWindow()) ?
1626 blackbox
->getFocusedWindow()->getClientWindow() : None
);
1628 xatom
->setValue(getRootWindow(), XAtom::net_active_window
,
1631 NetizenList::iterator it
= netizenList
.begin();
1632 for (; it
!= netizenList
.end(); ++it
)
1633 (*it
)->sendWindowFocus(f
);
1637 void BScreen::updateNetizenWindowAdd(Window w
, unsigned long p
) {
1638 NetizenList::iterator it
= netizenList
.begin();
1639 for (; it
!= netizenList
.end(); ++it
) {
1640 (*it
)->sendWindowAdd(w
, p
);
1645 void BScreen::updateNetizenWindowDel(Window w
) {
1646 NetizenList::iterator it
= netizenList
.begin();
1647 for (; it
!= netizenList
.end(); ++it
)
1648 (*it
)->sendWindowDel(w
);
1652 void BScreen::updateNetizenWindowRaise(Window w
) {
1653 NetizenList::iterator it
= netizenList
.begin();
1654 for (; it
!= netizenList
.end(); ++it
)
1655 (*it
)->sendWindowRaise(w
);
1659 void BScreen::updateNetizenWindowLower(Window w
) {
1660 NetizenList::iterator it
= netizenList
.begin();
1661 for (; it
!= netizenList
.end(); ++it
)
1662 (*it
)->sendWindowLower(w
);
1666 void BScreen::updateNetizenConfigNotify(XEvent
*e
) {
1667 NetizenList::iterator it
= netizenList
.begin();
1668 for (; it
!= netizenList
.end(); ++it
)
1669 (*it
)->sendConfigNotify(e
);
1673 void BScreen::raiseWindows(Window
*workspace_stack
, unsigned int num
) {
1674 // the 13 represents the number of blackbox windows such as menus
1680 Window
*session_stack
= new
1681 Window
[(num
+ workspacesList
.size() + rootmenuList
.size() +
1682 specialWindowList
.size() + bbwins
)];
1683 unsigned int i
= 0, k
= num
;
1685 XRaiseWindow(blackbox
->getXDisplay(), iconmenu
->getWindowID());
1686 *(session_stack
+ i
++) = iconmenu
->getWindowID();
1688 WorkspaceList::iterator wit
= workspacesList
.begin();
1689 const WorkspaceList::iterator w_end
= workspacesList
.end();
1690 for (; wit
!= w_end
; ++wit
)
1691 *(session_stack
+ i
++) = (*wit
)->getMenu()->getWindowID();
1693 *(session_stack
+ i
++) = workspacemenu
->getWindowID();
1695 *(session_stack
+ i
++) = configmenu
->getFocusmenu()->getWindowID();
1696 *(session_stack
+ i
++) = configmenu
->getPlacementmenu()->getWindowID();
1697 *(session_stack
+ i
++) = configmenu
->getWindowSnapmenu()->getWindowID();
1698 *(session_stack
+ i
++) = configmenu
->getEdgeSnapmenu()->getWindowID();
1700 *(session_stack
+ i
++) = configmenu
->getXineramamenu()->getWindowID();
1702 *(session_stack
+ i
++) = configmenu
->getWindowID();
1704 *(session_stack
+ i
++) = slit
->getMenu()->getDirectionmenu()->getWindowID();
1705 *(session_stack
+ i
++) = slit
->getMenu()->getPlacementmenu()->getWindowID();
1706 *(session_stack
+ i
++) = slit
->getMenu()->getWindowID();
1708 *(session_stack
+ i
++) =
1709 toolbar
->getMenu()->getPlacementmenu()->getWindowID();
1710 *(session_stack
+ i
++) = toolbar
->getMenu()->getWindowID();
1712 RootmenuList::iterator rit
= rootmenuList
.begin();
1713 for (; rit
!= rootmenuList
.end(); ++rit
)
1714 *(session_stack
+ i
++) = (*rit
)->getWindowID();
1715 *(session_stack
+ i
++) = rootmenu
->getWindowID();
1717 if (toolbar
->isOnTop())
1718 *(session_stack
+ i
++) = toolbar
->getWindowID();
1720 if (slit
->isOnTop())
1721 *(session_stack
+ i
++) = slit
->getWindowID();
1723 WindowList::iterator sit
, send
= specialWindowList
.end();
1724 for (sit
= specialWindowList
.begin(); sit
!= send
; ++sit
)
1725 *(session_stack
+ i
++) = *sit
;
1728 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
1730 XRestackWindows(blackbox
->getXDisplay(), session_stack
, i
);
1732 delete [] session_stack
;
1734 updateStackingList();
1738 void BScreen::lowerWindows(Window
*workspace_stack
, unsigned int num
) {
1739 assert(num
> 0); // this would cause trouble in the XRaiseWindow call
1741 Window
*session_stack
= new Window
[(num
+ desktopWindowList
.size())];
1742 unsigned int i
= 0, k
= num
;
1744 XLowerWindow(blackbox
->getXDisplay(), workspace_stack
[0]);
1747 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
1749 WindowList::iterator dit
= desktopWindowList
.begin();
1750 const WindowList::iterator d_end
= desktopWindowList
.end();
1751 for (; dit
!= d_end
; ++dit
)
1752 *(session_stack
+ i
++) = *dit
;
1754 XRestackWindows(blackbox
->getXDisplay(), session_stack
, i
);
1756 delete [] session_stack
;
1758 updateStackingList();
1762 void BScreen::reassociateWindow(BlackboxWindow
*w
, unsigned int wkspc_id
,
1763 bool ignore_sticky
) {
1766 if (wkspc_id
== BSENTINEL
)
1767 wkspc_id
= current_workspace
->getID();
1769 if (w
->getWorkspaceNumber() == wkspc_id
)
1772 if (w
->isIconic()) {
1774 getWorkspace(wkspc_id
)->addWindow(w
);
1776 for (unsigned int i
= 0; i
< getNumberOfWorkspaces(); ++i
)
1777 if (i
!= w
->getWorkspaceNumber())
1778 getWorkspace(i
)->addWindow(w
, True
);
1779 } else if (ignore_sticky
|| ! w
->isStuck()) {
1782 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1783 getWorkspace(wkspc_id
)->addWindow(w
);
1785 updateStackingList();
1789 void BScreen::propagateWindowName(const BlackboxWindow
*bw
) {
1790 if (bw
->isIconic()) {
1791 iconmenu
->changeItemLabel(bw
->getWindowNumber(), bw
->getIconTitle());
1795 Clientmenu
*clientmenu
= getWorkspace(bw
->getWorkspaceNumber())->getMenu();
1796 clientmenu
->changeItemLabel(bw
->getWindowNumber(), bw
->getTitle());
1797 clientmenu
->update();
1799 if (blackbox
->getFocusedWindow() == bw
)
1800 toolbar
->redrawWindowLabel(True
);
1805 void BScreen::nextFocus(void) {
1806 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1810 // if window is not on this screen, ignore it
1811 if (focused
->getScreen()->getScreenNumber() != getScreenNumber())
1812 focused
= (BlackboxWindow
*) 0;
1815 if (focused
&& current_workspace
->getCount() > 1) {
1816 // next is the next window to recieve focus, current is a place holder
1817 BlackboxWindow
*current
;
1820 next
= current_workspace
->getNextWindowInList(current
);
1821 } while(! next
->setInputFocus() && next
!= focused
);
1823 if (next
!= focused
)
1824 current_workspace
->raiseWindow(next
);
1825 } else if (current_workspace
->getCount() >= 1) {
1826 next
= current_workspace
->getTopWindowOnStack();
1828 current_workspace
->raiseWindow(next
);
1829 next
->setInputFocus();
1834 void BScreen::prevFocus(void) {
1835 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1839 // if window is not on this screen, ignore it
1840 if (focused
->getScreen()->getScreenNumber() != getScreenNumber())
1841 focused
= (BlackboxWindow
*) 0;
1844 if (focused
&& current_workspace
->getCount() > 1) {
1845 // next is the next window to recieve focus, current is a place holder
1846 BlackboxWindow
*current
;
1849 next
= current_workspace
->getPrevWindowInList(current
);
1850 } while(! next
->setInputFocus() && next
!= focused
);
1852 if (next
!= focused
)
1853 current_workspace
->raiseWindow(next
);
1854 } else if (current_workspace
->getCount() >= 1) {
1855 next
= current_workspace
->getTopWindowOnStack();
1857 current_workspace
->raiseWindow(next
);
1858 next
->setInputFocus();
1863 void BScreen::raiseFocus(void) {
1864 BlackboxWindow
*focused
= blackbox
->getFocusedWindow();
1868 // if on this Screen, raise it
1869 if (focused
->getScreen()->getScreenNumber() == getScreenNumber()) {
1870 Workspace
*workspace
= getWorkspace(focused
->getWorkspaceNumber());
1871 workspace
->raiseWindow(focused
);
1876 void BScreen::InitMenu(void) {
1878 rootmenuList
.clear();
1880 while (rootmenu
->getCount())
1881 rootmenu
->remove(0);
1883 rootmenu
= new Rootmenu(this);
1885 bool defaultMenu
= True
;
1887 FILE *menu_file
= (FILE *) 0;
1888 const char *menu_filename
= blackbox
->getMenuFilename();
1891 if (! (menu_file
= fopen(menu_filename
, "r")))
1892 perror(menu_filename
);
1893 if (! menu_file
) { // opening the menu file failed, try the default menu
1894 menu_filename
= DEFAULTMENU
;
1895 if (! (menu_file
= fopen(menu_filename
, "r")))
1896 perror(menu_filename
);
1900 if (feof(menu_file
)) {
1901 fprintf(stderr
, i18n(ScreenSet
, ScreenEmptyMenuFile
,
1902 "%s: Empty menu file"),
1905 char line
[1024], label
[1024];
1906 memset(line
, 0, 1024);
1907 memset(label
, 0, 1024);
1909 while (fgets(line
, 1024, menu_file
) && ! feof(menu_file
)) {
1913 int i
, key
= 0, index
= -1, len
= strlen(line
);
1915 for (i
= 0; i
< len
; i
++) {
1916 if (line
[i
] == '[') index
= 0;
1917 else if (line
[i
] == ']') break;
1918 else if (line
[i
] != ' ')
1920 key
+= tolower(line
[i
]);
1923 if (key
== 517) { // [begin]
1925 for (i
= index
; i
< len
; i
++) {
1926 if (line
[i
] == '(') index
= 0;
1927 else if (line
[i
] == ')') break;
1928 else if (index
++ >= 0) {
1929 if (line
[i
] == '\\' && i
< len
- 1) i
++;
1930 label
[index
- 1] = line
[i
];
1934 if (index
== -1) index
= 0;
1935 label
[index
] = '\0';
1937 rootmenu
->setLabel(label
);
1938 defaultMenu
= parseMenuFile(menu_file
, rootmenu
);
1940 blackbox
->addMenuTimestamp(menu_filename
);
1949 rootmenu
->setInternalMenu();
1950 rootmenu
->insert(i18n(ScreenSet
, Screenxterm
, "xterm"),
1952 i18n(ScreenSet
, Screenxterm
, "xterm"));
1953 rootmenu
->insert(i18n(ScreenSet
, ScreenRestart
, "Restart"),
1955 rootmenu
->insert(i18n(ScreenSet
, ScreenExit
, "Exit"),
1957 rootmenu
->setLabel(i18n(BasemenuSet
, BasemenuBlackboxMenu
,
1964 size_t string_within(char begin
, char end
,
1965 const char *input
, size_t start_at
, size_t length
,
1969 size_t i
= start_at
;
1970 for (; i
< length
; ++i
) {
1971 if (input
[i
] == begin
) {
1973 } else if (input
[i
] == end
) {
1976 if (input
[i
] == '\\' && i
< length
- 1) i
++;
1977 output
[index
++] = input
[i
];
1982 output
[index
] = '\0';
1990 bool BScreen::parseMenuFile(FILE *file
, Rootmenu
*menu
) {
1991 char line
[1024], keyword
[1024], label
[1024], command
[1024];
1994 while (! (done
|| feof(file
))) {
1995 memset(line
, 0, 1024);
1996 memset(label
, 0, 1024);
1997 memset(command
, 0, 1024);
1999 if (! fgets(line
, 1024, file
))
2002 if (line
[0] == '#') // comment, skip it
2005 size_t line_length
= strlen(line
);
2006 unsigned int key
= 0;
2008 // get the keyword enclosed in []'s
2009 size_t pos
= string_within('[', ']', line
, 0, line_length
, keyword
);
2011 if (keyword
[0] == '\0') { // no keyword, no menu entry
2014 size_t len
= strlen(keyword
);
2015 for (size_t i
= 0; i
< len
; ++i
) {
2016 if (keyword
[i
] != ' ')
2017 key
+= tolower(keyword
[i
]);
2021 // get the label enclosed in ()'s
2022 pos
= string_within('(', ')', line
, pos
, line_length
, label
);
2024 // get the command enclosed in {}'s
2025 pos
= string_within('{', '}', line
, pos
, line_length
, command
);
2036 menu
->insert(label
);
2041 if (! (*label
&& *command
)) {
2042 fprintf(stderr
, i18n(ScreenSet
, ScreenEXECError
,
2043 "BScreen::parseMenuFile: [exec] error, "
2044 "no menu label and/or command defined\n"));
2048 menu
->insert(label
, BScreen::Execute
, command
);
2054 fprintf(stderr
, i18n(ScreenSet
, ScreenEXITError
,
2055 "BScreen::parseMenuFile: [exit] error, "
2056 "no menu label defined\n"));
2060 menu
->insert(label
, BScreen::Exit
);
2064 case 561: { // style
2065 if (! (*label
&& *command
)) {
2067 i18n(ScreenSet
, ScreenSTYLEError
,
2068 "BScreen::parseMenuFile: [style] error, "
2069 "no menu label and/or filename defined\n"));
2073 string style
= expandTilde(command
);
2075 menu
->insert(label
, BScreen::SetStyle
, style
.c_str());
2081 fprintf(stderr
, i18n(ScreenSet
, ScreenCONFIGError
,
2082 "BScreen::parseMenufile: [config] error, "
2083 "no label defined"));
2087 menu
->insert(label
, configmenu
);
2091 case 740: { // include
2093 fprintf(stderr
, i18n(ScreenSet
, ScreenINCLUDEError
,
2094 "BScreen::parseMenuFile: [include] error, "
2095 "no filename defined\n"));
2099 string newfile
= expandTilde(label
);
2100 FILE *submenufile
= fopen(newfile
.c_str(), "r");
2102 if (! submenufile
) {
2103 perror(newfile
.c_str());
2108 if (fstat(fileno(submenufile
), &buf
) ||
2109 ! S_ISREG(buf
.st_mode
)) {
2111 i18n(ScreenSet
, ScreenINCLUDEErrorReg
,
2112 "BScreen::parseMenuFile: [include] error: "
2113 "'%s' is not a regular file\n"), newfile
.c_str());
2117 if (! feof(submenufile
)) {
2118 if (! parseMenuFile(submenufile
, menu
))
2119 blackbox
->addMenuTimestamp(newfile
);
2121 fclose(submenufile
);
2127 case 767: { // submenu
2129 fprintf(stderr
, i18n(ScreenSet
, ScreenSUBMENUError
,
2130 "BScreen::parseMenuFile: [submenu] error, "
2131 "no menu label defined\n"));
2135 Rootmenu
*submenu
= new Rootmenu(this);
2138 submenu
->setLabel(command
);
2140 submenu
->setLabel(label
);
2142 parseMenuFile(file
, submenu
);
2144 menu
->insert(label
, submenu
);
2145 rootmenuList
.push_back(submenu
);
2150 case 773: { // restart
2152 fprintf(stderr
, i18n(ScreenSet
, ScreenRESTARTError
,
2153 "BScreen::parseMenuFile: [restart] error, "
2154 "no menu label defined\n"));
2159 menu
->insert(label
, BScreen::RestartOther
, command
);
2161 menu
->insert(label
, BScreen::Restart
);
2166 case 845: { // reconfig
2169 i18n(ScreenSet
, ScreenRECONFIGError
,
2170 "BScreen::parseMenuFile: [reconfig] error, "
2171 "no menu label defined\n"));
2175 menu
->insert(label
, BScreen::Reconfigure
);
2180 case 995: // stylesdir
2181 case 1113: { // stylesmenu
2182 bool newmenu
= ((key
== 1113) ? True
: False
);
2184 if (! *label
|| (! *command
&& newmenu
)) {
2186 i18n(ScreenSet
, ScreenSTYLESDIRError
,
2187 "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
2188 " error, no directory defined\n"));
2192 char *directory
= ((newmenu
) ? command
: label
);
2194 string stylesdir
= expandTilde(directory
);
2196 struct stat statbuf
;
2198 if (stat(stylesdir
.c_str(), &statbuf
) == -1) {
2200 i18n(ScreenSet
, ScreenSTYLESDIRErrorNoExist
,
2201 "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
2202 " error, %s does not exist\n"), stylesdir
.c_str());
2205 if (! S_ISDIR(statbuf
.st_mode
)) {
2207 i18n(ScreenSet
, ScreenSTYLESDIRErrorNotDir
,
2208 "BScreen::parseMenuFile:"
2209 " [stylesdir/stylesmenu] error, %s is not a"
2210 " directory\n"), stylesdir
.c_str());
2214 Rootmenu
*stylesmenu
;
2217 stylesmenu
= new Rootmenu(this);
2221 DIR *d
= opendir(stylesdir
.c_str());
2223 std::vector
<string
> ls
;
2225 while((p
= readdir(d
)))
2226 ls
.push_back(p
->d_name
);
2230 std::sort(ls
.begin(), ls
.end());
2232 std::vector
<string
>::iterator it
= ls
.begin(),
2234 for (; it
!= end
; ++it
) {
2235 const string
& fname
= *it
;
2237 if (fname
[fname
.size()-1] == '~')
2240 string style
= stylesdir
;
2244 if (! stat(style
.c_str(), &statbuf
) && S_ISREG(statbuf
.st_mode
))
2245 stylesmenu
->insert(fname
, BScreen::SetStyle
, style
);
2248 stylesmenu
->update();
2251 stylesmenu
->setLabel(label
);
2252 menu
->insert(label
, stylesmenu
);
2253 rootmenuList
.push_back(stylesmenu
);
2256 blackbox
->addMenuTimestamp(stylesdir
);
2260 case 1090: { // workspaces
2263 i18n(ScreenSet
, ScreenWORKSPACESError
,
2264 "BScreen:parseMenuFile: [workspaces] error, "
2265 "no menu label defined\n"));
2269 menu
->insert(label
, workspacemenu
);
2275 return ((menu
->getCount() == 0) ? True
: False
);
2279 void BScreen::shutdown(void) {
2280 XSelectInput(blackbox
->getXDisplay(), getRootWindow(), NoEventMask
);
2281 XSync(blackbox
->getXDisplay(), False
);
2283 while(! windowList
.empty())
2284 unmanageWindow(windowList
.front(), True
);
2286 while(! desktopWindowList
.empty()) {
2287 BlackboxWindow
*win
= blackbox
->searchWindow(desktopWindowList
.front());
2289 unmanageWindow(win
, True
);
2296 void BScreen::showPosition(int x
, int y
) {
2297 if (! geom_visible
) {
2298 XMoveResizeWindow(blackbox
->getXDisplay(), geom_window
,
2299 (getWidth() - geom_w
) / 2,
2300 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
2301 XMapWindow(blackbox
->getXDisplay(), geom_window
);
2302 XRaiseWindow(blackbox
->getXDisplay(), geom_window
);
2304 geom_visible
= True
;
2309 sprintf(label
, i18n(ScreenSet
, ScreenPositionFormat
,
2310 "X: %4d x Y: %4d"), x
, y
);
2312 XClearWindow(blackbox
->getXDisplay(), geom_window
);
2314 resource
.wstyle
.font
->drawString(geom_window
,
2315 resource
.bevel_width
, resource
.bevel_width
,
2316 resource
.wstyle
.l_text_focus
,
2321 void BScreen::showGeometry(unsigned int gx
, unsigned int gy
) {
2322 if (! geom_visible
) {
2323 XMoveResizeWindow(blackbox
->getXDisplay(), geom_window
,
2324 (getWidth() - geom_w
) / 2,
2325 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
2326 XMapWindow(blackbox
->getXDisplay(), geom_window
);
2327 XRaiseWindow(blackbox
->getXDisplay(), geom_window
);
2329 geom_visible
= True
;
2334 sprintf(label
, i18n(ScreenSet
, ScreenGeometryFormat
,
2335 "W: %4d x H: %4d"), gx
, gy
);
2337 XClearWindow(blackbox
->getXDisplay(), geom_window
);
2339 resource
.wstyle
.font
->drawString(geom_window
,
2340 resource
.bevel_width
, resource
.bevel_width
,
2341 resource
.wstyle
.l_text_focus
,
2346 void BScreen::hideGeometry(void) {
2348 XUnmapWindow(blackbox
->getXDisplay(), geom_window
);
2349 geom_visible
= False
;
2354 void BScreen::addStrut(Strut
*strut
) {
2355 strutList
.push_back(strut
);
2359 void BScreen::removeStrut(Strut
*strut
) {
2360 strutList
.remove(strut
);
2364 const Rect
& BScreen::availableArea(void) const {
2366 return getRect(); // return the full screen
2372 const RectList
& BScreen::allAvailableAreas(void) const {
2373 assert(isXineramaActive());
2374 assert(xineramaUsableArea
.size() > 0);
2375 fprintf(stderr
, "1found x %d y %d w %d h %d\n",
2376 xineramaUsableArea
[0].x(), xineramaUsableArea
[0].y(),
2377 xineramaUsableArea
[0].width(), xineramaUsableArea
[0].height());
2378 return xineramaUsableArea
;
2383 void BScreen::updateAvailableArea(void) {
2384 Rect old_area
= usableArea
;
2385 usableArea
= getRect(); // reset to full screen
2388 // reset to the full areas
2389 if (isXineramaActive())
2390 xineramaUsableArea
= getXineramaAreas();
2393 /* these values represent offsets from the screen edge
2394 * we look for the biggest offset on each edge and then apply them
2396 * do not be confused by the similarity to the names of Rect's members
2398 unsigned int current_left
= 0, current_right
= 0, current_top
= 0,
2401 StrutList::const_iterator it
= strutList
.begin(), end
= strutList
.end();
2403 for(; it
!= end
; ++it
) {
2405 if (strut
->left
> current_left
)
2406 current_left
= strut
->left
;
2407 if (strut
->top
> current_top
)
2408 current_top
= strut
->top
;
2409 if (strut
->right
> current_right
)
2410 current_right
= strut
->right
;
2411 if (strut
->bottom
> current_bottom
)
2412 current_bottom
= strut
->bottom
;
2415 usableArea
.setPos(current_left
, current_top
);
2416 usableArea
.setSize(usableArea
.width() - (current_left
+ current_right
),
2417 usableArea
.height() - (current_top
+ current_bottom
));
2420 if (isXineramaActive()) {
2421 // keep each of the ximerama-defined areas inside the strut
2422 RectList::iterator xit
, xend
= xineramaUsableArea
.end();
2423 for (xit
= xineramaUsableArea
.begin(); xit
!= xend
; ++xit
) {
2424 if (xit
->x() < usableArea
.x()) {
2425 xit
->setX(usableArea
.x());
2426 xit
->setWidth(xit
->width() - usableArea
.x());
2428 if (xit
->y() < usableArea
.y()) {
2429 xit
->setY(usableArea
.y());
2430 xit
->setHeight(xit
->height() - usableArea
.y());
2432 if (xit
->x() + xit
->width() > usableArea
.width())
2433 xit
->setWidth(usableArea
.width() - xit
->x());
2434 if (xit
->y() + xit
->height() > usableArea
.height())
2435 xit
->setHeight(usableArea
.height() - xit
->y());
2440 if (old_area
!= usableArea
) {
2441 BlackboxWindowList::iterator it
= windowList
.begin(),
2442 end
= windowList
.end();
2443 for (; it
!= end
; ++it
)
2444 if ((*it
)->isMaximized()) (*it
)->remaximize();
2451 Workspace
* BScreen::getWorkspace(unsigned int index
) {
2452 assert(index
< workspacesList
.size());
2453 return workspacesList
[index
];
2457 void BScreen::buttonPressEvent(const XButtonEvent
*xbutton
) {
2458 if (xbutton
->button
== 1) {
2459 if (! isRootColormapInstalled())
2460 image_control
->installRootColormap();
2462 if (workspacemenu
->isVisible())
2463 workspacemenu
->hide();
2465 if (rootmenu
->isVisible())
2468 } else if ((xbutton
->button
== 4 && resource
.root_scroll
== NormalScroll
) ||
2469 (xbutton
->button
== 5 && resource
.root_scroll
== ReverseScroll
)) {
2470 if (getCurrentWorkspaceID() >= getWorkspaceCount() - 1)
2471 changeWorkspaceID(0);
2473 changeWorkspaceID(getCurrentWorkspaceID() + 1);
2475 } else if ((xbutton
->button
== 5 && resource
.root_scroll
== NormalScroll
) ||
2476 (xbutton
->button
== 4 && resource
.root_scroll
== ReverseScroll
)) {
2477 if (getCurrentWorkspaceID() == 0)
2478 changeWorkspaceID(getWorkspaceCount() - 1);
2480 changeWorkspaceID(getCurrentWorkspaceID() - 1);
2483 if (resource
.root_menu_button
> 0 &&
2484 xbutton
->button
== resource
.root_menu_button
)
2485 showRootMenu(xbutton
->x_root
, xbutton
->y_root
);
2486 else if (resource
.workspace_menu_button
> 0 &&
2487 xbutton
->button
== resource
.workspace_menu_button
)
2488 showWorkspaceMenu(xbutton
->x_root
, xbutton
->y_root
);
2492 void BScreen::showWorkspaceMenu(int x
, int y
) {
2493 int mx
= x
- (workspacemenu
->getWidth() / 2);
2494 int my
= y
- (workspacemenu
->getTitleHeight() / 2);
2499 if (mx
+ workspacemenu
->getWidth() > getWidth())
2500 mx
= getWidth() - workspacemenu
->getWidth() - getBorderWidth();
2502 if (my
+ workspacemenu
->getHeight() > getHeight())
2503 my
= getHeight() - workspacemenu
->getHeight() - getBorderWidth();
2505 workspacemenu
->move(mx
, my
);
2507 if (! workspacemenu
->isVisible()) {
2508 workspacemenu
->removeParent();
2509 workspacemenu
->show();
2514 void BScreen::showRootMenu(int x
, int y
) {
2515 int mx
= x
- (rootmenu
->getWidth() / 2);
2516 int my
= y
- (rootmenu
->getTitleHeight() / 2);
2521 if (mx
+ rootmenu
->getWidth() > getWidth())
2522 mx
= getWidth() - rootmenu
->getWidth() - getBorderWidth();
2524 if (my
+ rootmenu
->getHeight() > getHeight())
2525 my
= getHeight() - rootmenu
->getHeight() - getBorderWidth();
2527 rootmenu
->move(mx
, my
);
2529 if (! rootmenu
->isVisible()) {
2530 blackbox
->checkMenu();
2536 void BScreen::propertyNotifyEvent(const XPropertyEvent
*pe
) {
2537 if (pe
->atom
== xatom
->getAtom(XAtom::net_desktop_names
)) {
2538 // _NET_WM_DESKTOP_NAMES
2539 WorkspaceList::iterator it
= workspacesList
.begin();
2540 const WorkspaceList::iterator end
= workspacesList
.end();
2541 for (; it
!= end
; ++it
) {
2542 (*it
)->readName(); // re-read its name from the window property
2543 workspacemenu
->changeWorkspaceLabel((*it
)->getID(), (*it
)->getName());
2545 workspacemenu
->update();
2546 toolbar
->reconfigure();
2547 saveWorkspaceNames();
2552 void BScreen::toggleFocusModel(FocusModel model
) {
2553 std::for_each(windowList
.begin(), windowList
.end(),
2554 std::mem_fun(&BlackboxWindow::ungrabButtons
));
2556 if (model
== SloppyFocus
) {
2557 saveSloppyFocus(True
);
2559 // we're cheating here to save writing the config file 3 times
2560 resource
.auto_raise
= False
;
2561 resource
.click_raise
= False
;
2562 saveSloppyFocus(False
);
2565 std::for_each(windowList
.begin(), windowList
.end(),
2566 std::mem_fun(&BlackboxWindow::grabButtons
));
2570 BTexture
BScreen::readDatabaseTexture(const string
&rname
,
2571 const string
&default_color
,
2572 const Configuration
&style
) {
2576 if (style
.getValue(rname
, s
))
2577 texture
= BTexture(s
);
2579 texture
.setTexture(BTexture::Solid
| BTexture::Flat
);
2581 // associate this texture with this screen
2582 texture
.setDisplay(getBaseDisplay(), getScreenNumber());
2583 texture
.setImageControl(image_control
);
2585 texture
.setColor(readDatabaseColor(rname
+ ".color", default_color
, style
));
2586 texture
.setColorTo(readDatabaseColor(rname
+ ".colorTo", default_color
,
2588 texture
.setBorderColor(readDatabaseColor(rname
+ ".borderColor",
2589 default_color
, style
));
2595 BColor
BScreen::readDatabaseColor(const string
&rname
,
2596 const string
&default_color
,
2597 const Configuration
&style
) {
2600 if (style
.getValue(rname
, s
))
2601 color
= BColor(s
, getBaseDisplay(), getScreenNumber());
2603 color
= BColor(default_color
, getBaseDisplay(), getScreenNumber());
2608 BFont
*BScreen::readDatabaseFont(const string
&rbasename
,
2609 const Configuration
&style
) {
2616 if (style
.getValue(rbasename
+ "xft.font", s
) &&
2617 style
.getValue(rbasename
+ "xft.size", i
)) {
2620 bool italic
= False
;
2621 if (style
.getValue(rbasename
+ "xft.flags", s
)) {
2622 if (s
.find("bold") != string::npos
)
2624 if (s
.find("italic") != string::npos
)
2628 BFont
*b
= new BFont(blackbox
->getXDisplay(), this, family
, i
, bold
,
2629 italic
, resource
.shadow_fonts
, resource
.aa_fonts
);
2633 delete b
; // fall back to the normal X font stuff
2637 style
.getValue(rbasename
+ "font", s
);
2638 // if this fails, a blank string will be used, which will cause the fallback
2641 BFont
*b
= new BFont(blackbox
->getXDisplay(), this, s
);
2643 exit(2); // can't continue without a font