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
78 #include "blackbox.hh"
85 #include "workspace.hh"
89 #ifndef FONT_ELEMENT_SIZE
90 #define FONT_ELEMENT_SIZE 50
91 #endif // FONT_ELEMENT_SIZE
94 static bool running
= True
;
96 static int anotherWMRunning(Display
*display
, XErrorEvent
*) {
98 "BScreen::BScreen: an error occured while querying the X server.\n"
99 " another window manager already running on display %s.\n",
100 DisplayString(display
));
108 BScreen::BScreen(Blackbox
*bb
, unsigned int scrn
) : ScreenInfo(bb
, scrn
) {
110 screenstr
= "session.screen" + itostring(scrn
) + '.';
111 config
= blackbox
->getConfig();
112 xatom
= blackbox
->getXAtom();
114 event_mask
= ColormapChangeMask
| EnterWindowMask
| PropertyChangeMask
|
115 SubstructureRedirectMask
| ButtonPressMask
| ButtonReleaseMask
;
117 XErrorHandler old
= XSetErrorHandler((XErrorHandler
) anotherWMRunning
);
118 XSelectInput(getBaseDisplay()->getXDisplay(), getRootWindow(), event_mask
);
119 XSync(getBaseDisplay()->getXDisplay(), False
);
120 XSetErrorHandler((XErrorHandler
) old
);
123 if (! managed
) return;
125 fprintf(stderr
, "BScreen::BScreen: managing screen %d "
126 "using visual 0x%lx, depth %d\n",
127 getScreenNumber(), XVisualIDFromVisual(getVisual()),
130 resource
.wstyle
.font
= (BFont
*) 0;
134 xatom
->setSupported(this); // set-up netwm support
136 xatom
->setValue(getRootWindow(), XAtom::blackbox_pid
, XAtom::cardinal
,
137 (unsigned long) getpid());
138 #endif // HAVE_GETPID
139 unsigned long geometry
[] = { getWidth(),
141 xatom
->setValue(getRootWindow(), XAtom::net_desktop_geometry
,
142 XAtom::cardinal
, geometry
, 2);
143 unsigned long viewport
[] = {0,0};
144 xatom
->setValue(getRootWindow(), XAtom::net_desktop_viewport
,
145 XAtom::cardinal
, viewport
, 2);
148 XDefineCursor(blackbox
->getXDisplay(), getRootWindow(),
149 blackbox
->getSessionCursor());
151 updateAvailableArea();
154 new BImageControl(blackbox
, this, True
, blackbox
->getColorsPerChannel(),
155 blackbox
->getCacheLife(), blackbox
->getCacheMax());
156 image_control
->installRootColormap();
157 root_colormap_installed
= True
;
163 gcv
.foreground
= WhitePixel(blackbox
->getXDisplay(), getScreenNumber())
164 ^ BlackPixel(blackbox
->getXDisplay(), getScreenNumber());
165 gcv
.function
= GXxor
;
166 gcv
.subwindow_mode
= IncludeInferiors
;
167 opGC
= XCreateGC(blackbox
->getXDisplay(), getRootWindow(),
168 GCForeground
| GCFunction
| GCSubwindowMode
, &gcv
);
170 const char *s
= "0: 0000 x 0: 0000";
171 geom_w
= resource
.wstyle
.font
->measureString(s
) + resource
.bevel_width
* 2;
172 geom_h
= resource
.wstyle
.font
->height() + resource
.bevel_width
* 2;
174 XSetWindowAttributes attrib
;
175 unsigned long mask
= CWBorderPixel
| CWColormap
| CWSaveUnder
;
176 attrib
.border_pixel
= getBorderColor()->pixel();
177 attrib
.colormap
= getColormap();
178 attrib
.save_under
= True
;
180 geom_window
= XCreateWindow(blackbox
->getXDisplay(), getRootWindow(),
181 0, 0, geom_w
, geom_h
, resource
.border_width
,
182 getDepth(), InputOutput
, getVisual(),
184 geom_visible
= False
;
186 BTexture
* texture
= &(resource
.wstyle
.l_focus
);
187 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
188 if (geom_pixmap
== ParentRelative
) {
189 texture
= &(resource
.wstyle
.t_focus
);
190 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
193 XSetWindowBackground(blackbox
->getXDisplay(), geom_window
,
194 texture
->color().pixel());
196 XSetWindowBackgroundPixmap(blackbox
->getXDisplay(),
197 geom_window
, geom_pixmap
);
199 if (resource
.workspaces
> 0) {
200 for (unsigned int i
= 0; i
< resource
.workspaces
; ++i
) {
201 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
202 workspacesList
.push_back(wkspc
);
206 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
207 workspacesList
.push_back(wkspc
);
209 saveWorkspaceNames();
211 updateNetizenWorkspaceCount();
213 current_workspace
= workspacesList
.front();
215 xatom
->setValue(getRootWindow(), XAtom::net_current_desktop
,
216 XAtom::cardinal
, 0); //first workspace
218 raiseWindows(0, 0); // this also initializes the empty stacking list
220 updateClientList(); // initialize the client lists, which will be empty
221 updateAvailableArea();
223 changeWorkspaceID(0);
225 unsigned int i
, j
, nchild
;
226 Window r
, p
, *children
;
227 XQueryTree(blackbox
->getXDisplay(), getRootWindow(), &r
, &p
,
230 // preen the window list of all icon windows... for better dockapp support
231 for (i
= 0; i
< nchild
; i
++) {
232 if (children
[i
] == None
) continue;
234 XWMHints
*wmhints
= XGetWMHints(blackbox
->getXDisplay(),
238 if ((wmhints
->flags
& IconWindowHint
) &&
239 (wmhints
->icon_window
!= children
[i
])) {
240 for (j
= 0; j
< nchild
; j
++) {
241 if (children
[j
] == wmhints
->icon_window
) {
252 // manage shown windows
253 for (i
= 0; i
< nchild
; ++i
) {
254 if (children
[i
] == None
|| ! blackbox
->validateWindow(children
[i
]))
257 XWindowAttributes attrib
;
258 if (XGetWindowAttributes(blackbox
->getXDisplay(), children
[i
], &attrib
)) {
259 if (attrib
.override_redirect
) continue;
261 if (attrib
.map_state
!= IsUnmapped
) {
262 manageWindow(children
[i
]);
269 // call this again just in case a window we found updates the Strut list
270 updateAvailableArea();
274 BScreen::~BScreen(void) {
275 if (! managed
) return;
277 if (geom_pixmap
!= None
)
278 image_control
->removeImage(geom_pixmap
);
280 if (geom_window
!= None
)
281 XDestroyWindow(blackbox
->getXDisplay(), geom_window
);
283 std::for_each(workspacesList
.begin(), workspacesList
.end(),
286 std::for_each(iconList
.begin(), iconList
.end(), PointerAssassin());
288 while (! systrayWindowList
.empty())
289 removeSystrayWindow(systrayWindowList
[0]);
291 delete image_control
;
293 if (resource
.wstyle
.font
)
294 delete resource
.wstyle
.font
;
297 if (resource
.wstyle
.close_button
.mask
!= None
)
298 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.close_button
.mask
);
299 if (resource
.wstyle
.max_button
.mask
!= None
)
300 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.max_button
.mask
);
301 if (resource
.wstyle
.icon_button
.mask
!= None
)
302 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.icon_button
.mask
);
303 if (resource
.wstyle
.stick_button
.mask
!= None
)
304 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.stick_button
.mask
);
306 resource
.wstyle
.max_button
.mask
= resource
.wstyle
.close_button
.mask
=
307 resource
.wstyle
.icon_button
.mask
=
308 resource
.wstyle
.stick_button
.mask
= None
;
309 #endif // BITMAPBUTTONS
311 XFreeGC(blackbox
->getXDisplay(), opGC
);
315 void BScreen::saveSloppyFocus(bool s
) {
316 resource
.sloppy_focus
= s
;
319 if (resource
.sloppy_focus
) {
320 fmodel
= "SloppyFocus";
321 if (resource
.auto_raise
) fmodel
+= " AutoRaise";
322 if (resource
.click_raise
) fmodel
+= " ClickRaise";
324 fmodel
= "ClickToFocus";
326 config
->setValue(screenstr
+ "focusModel", fmodel
);
330 void BScreen::saveAutoRaise(bool a
) {
331 resource
.auto_raise
= a
;
332 saveSloppyFocus(resource
.sloppy_focus
);
336 void BScreen::saveClickRaise(bool c
) {
337 resource
.click_raise
= c
;
338 saveSloppyFocus(resource
.sloppy_focus
);
342 void BScreen::saveImageDither(bool d
) {
343 image_control
->setDither(d
);
344 config
->setValue(screenstr
+ "imageDither", doImageDither());
348 void BScreen::saveOpaqueMove(bool o
) {
349 resource
.opaque_move
= o
;
350 config
->setValue(screenstr
+ "opaqueMove", resource
.opaque_move
);
354 void BScreen::saveFullMax(bool f
) {
355 resource
.full_max
= f
;
356 config
->setValue(screenstr
+ "fullMaximization", resource
.full_max
);
360 void BScreen::saveFocusNew(bool f
) {
361 resource
.focus_new
= f
;
362 config
->setValue(screenstr
+ "focusNewWindows", resource
.focus_new
);
366 void BScreen::saveFocusLast(bool f
) {
367 resource
.focus_last
= f
;
368 config
->setValue(screenstr
+ "focusLastWindow", resource
.focus_last
);
372 void BScreen::saveAAFonts(bool f
) {
373 resource
.aa_fonts
= f
;
374 config
->setValue(screenstr
+ "antialiasFonts", resource
.aa_fonts
);
379 void BScreen::saveShadowFonts(bool f
) {
380 resource
.shadow_fonts
= f
;
381 config
->setValue(screenstr
+ "dropShadowFonts", resource
.shadow_fonts
);
386 void BScreen::saveWindowToEdgeSnap(int s
) {
387 resource
.snap_to_edges
= s
;
390 switch (resource
.snap_to_edges
) {
391 case WindowNoSnap
: snap
= "NoSnap"; break;
392 case WindowResistance
: snap
= "Resistance"; break;
393 case WindowSnap
: default: snap
= "Snap"; break;
395 config
->setValue(screenstr
+ "windowToEdgeSnap", snap
);
399 void BScreen::saveWindowToWindowSnap(int s
) {
400 resource
.snap_to_windows
= s
;
403 switch (resource
.snap_to_windows
) {
404 case WindowNoSnap
: snap
= "NoSnap"; break;
405 case WindowResistance
: snap
= "Resistance"; break;
406 case WindowSnap
: default: snap
= "Snap"; break;
408 config
->setValue(screenstr
+ "windowToWindowSnap", snap
);
412 void BScreen::saveResizeZones(unsigned int z
) {
413 resource
.resize_zones
= z
;
414 config
->setValue(screenstr
+ "resizeZones", resource
.resize_zones
);
418 void BScreen::saveWindowCornerSnap(bool s
) {
419 resource
.window_corner_snap
= s
;
420 config
->setValue(screenstr
+ "windowCornerSnap",
421 resource
.window_corner_snap
);
425 void BScreen::saveWorkspaces(unsigned int w
) {
426 resource
.workspaces
= w
;
427 config
->setValue(screenstr
+ "workspaces", resource
.workspaces
);
431 void BScreen::savePlacementPolicy(int p
) {
432 resource
.placement_policy
= p
;
433 const char *placement
;
434 switch (resource
.placement_policy
) {
435 case CascadePlacement
: placement
= "CascadePlacement"; break;
436 case UnderMousePlacement
: placement
= "UnderMousePlacement"; break;
437 case ClickMousePlacement
: placement
= "ClickMousePlacement"; break;
438 case ColSmartPlacement
: placement
= "ColSmartPlacement"; break;
439 case RowSmartPlacement
: default: placement
= "RowSmartPlacement"; break;
441 config
->setValue(screenstr
+ "windowPlacement", placement
);
445 void BScreen::saveResistanceSize(int s
) {
446 resource
.resistance_size
= s
;
447 config
->setValue(screenstr
+ "resistanceSize",
448 resource
.resistance_size
);
452 void BScreen::saveSnapThreshold(int t
) {
453 resource
.snap_threshold
= t
;
454 config
->setValue(screenstr
+ "edgeSnapThreshold",
455 resource
.snap_threshold
);
459 void BScreen::saveSnapOffset(int t
) {
460 resource
.snap_offset
= t
;
461 config
->setValue(screenstr
+ "edgeSnapOffset",
462 resource
.snap_offset
);
466 void BScreen::saveRowPlacementDirection(int d
) {
467 resource
.row_direction
= d
;
468 config
->setValue(screenstr
+ "rowPlacementDirection",
469 resource
.row_direction
== LeftRight
?
470 "LeftToRight" : "RightToLeft");
474 void BScreen::saveColPlacementDirection(int d
) {
475 resource
.col_direction
= d
;
476 config
->setValue(screenstr
+ "colPlacementDirection",
477 resource
.col_direction
== TopBottom
?
478 "TopToBottom" : "BottomToTop");
482 void BScreen::saveStrftimeFormat(const std::string
& format
) {
483 resource
.strftime_format
= format
;
484 config
->setValue(screenstr
+ "strftimeFormat", resource
.strftime_format
);
488 void BScreen::saveWorkspaceNames() {
491 for (unsigned int i
= 0; i
< workspacesList
.size(); ++i
) {
492 names
+= workspacesList
[i
]->getName();
493 if (i
< workspacesList
.size() - 1)
497 config
->setValue(screenstr
+ "workspaceNames", names
);
501 void BScreen::savePlaceIgnoreShaded(bool i
) {
502 resource
.ignore_shaded
= i
;
503 config
->setValue(screenstr
+ "placementIgnoreShaded",
504 resource
.ignore_shaded
);
508 void BScreen::savePlaceIgnoreMaximized(bool i
) {
509 resource
.ignore_maximized
= i
;
510 config
->setValue(screenstr
+ "placementIgnoreMaximized",
511 resource
.ignore_maximized
);
515 void BScreen::saveAllowScrollLock(bool a
) {
516 resource
.allow_scroll_lock
= a
;
517 config
->setValue(screenstr
+ "disableBindingsWithScrollLock",
518 resource
.allow_scroll_lock
);
522 void BScreen::saveWorkspaceWarping(bool w
) {
523 resource
.workspace_warping
= w
;
524 config
->setValue(screenstr
+ "workspaceWarping",
525 resource
.workspace_warping
);
529 void BScreen::saveRootScrollDirection(int d
) {
530 resource
.root_scroll
= d
;
532 switch (resource
.root_scroll
) {
533 case NoScroll
: dir
= "None"; break;
534 case ReverseScroll
: dir
= "Reverse"; break;
535 case NormalScroll
: default: dir
= "Normal"; break;
537 config
->setValue(screenstr
+ "rootScrollDirection", dir
);
541 void BScreen::save_rc(void) {
542 saveSloppyFocus(resource
.sloppy_focus
);
543 saveAutoRaise(resource
.auto_raise
);
544 saveImageDither(doImageDither());
545 saveShadowFonts(resource
.shadow_fonts
);
546 saveAAFonts(resource
.aa_fonts
);
547 saveResizeZones(resource
.resize_zones
);
548 saveOpaqueMove(resource
.opaque_move
);
549 saveFullMax(resource
.full_max
);
550 saveFocusNew(resource
.focus_new
);
551 saveFocusLast(resource
.focus_last
);
552 saveWindowToWindowSnap(resource
.snap_to_windows
);
553 saveWindowToEdgeSnap(resource
.snap_to_edges
);
554 saveWindowCornerSnap(resource
.window_corner_snap
);
555 saveWorkspaces(resource
.workspaces
);
556 savePlacementPolicy(resource
.placement_policy
);
557 saveSnapThreshold(resource
.snap_threshold
);
558 saveSnapOffset(resource
.snap_offset
);
559 saveResistanceSize(resource
.resistance_size
);
560 saveRowPlacementDirection(resource
.row_direction
);
561 saveColPlacementDirection(resource
.col_direction
);
562 saveStrftimeFormat(resource
.strftime_format
);
563 savePlaceIgnoreShaded(resource
.ignore_shaded
);
564 savePlaceIgnoreMaximized(resource
.ignore_maximized
);
565 saveAllowScrollLock(resource
.allow_scroll_lock
);
566 saveWorkspaceWarping(resource
.workspace_warping
);
567 saveRootScrollDirection(resource
.root_scroll
);
571 void BScreen::load_rc(void) {
575 if (! config
->getValue(screenstr
+ "fullMaximization", resource
.full_max
))
576 resource
.full_max
= false;
578 if (! config
->getValue(screenstr
+ "focusNewWindows", resource
.focus_new
))
579 resource
.focus_new
= false;
581 if (! config
->getValue(screenstr
+ "focusLastWindow", resource
.focus_last
))
582 resource
.focus_last
= false;
584 if (! config
->getValue(screenstr
+ "workspaces", resource
.workspaces
))
585 resource
.workspaces
= 1;
587 if (! config
->getValue(screenstr
+ "opaqueMove", resource
.opaque_move
))
588 resource
.opaque_move
= false;
590 if (! config
->getValue(screenstr
+ "antialiasFonts", resource
.aa_fonts
))
591 resource
.aa_fonts
= true;
593 if (! resource
.aa_fonts
||
594 ! config
->getValue(screenstr
+ "dropShadowFonts", resource
.shadow_fonts
))
595 resource
.shadow_fonts
= false;
597 if (! config
->getValue(screenstr
+ "resizeZones", resource
.resize_zones
) ||
598 (resource
.resize_zones
!= 1 && resource
.resize_zones
!= 2 &&
599 resource
.resize_zones
!= 4))
600 resource
.resize_zones
= 4;
602 resource
.snap_to_windows
= WindowResistance
;
603 if (config
->getValue(screenstr
+ "windowToWindowSnap", s
)) {
605 resource
.snap_to_windows
= WindowNoSnap
;
606 else if (s
== "Snap")
607 resource
.snap_to_windows
= WindowSnap
;
610 resource
.snap_to_edges
= WindowResistance
;
611 if (config
->getValue(screenstr
+ "windowToEdgeSnap", s
)) {
613 resource
.snap_to_edges
= WindowNoSnap
;
614 else if (s
== "Snap")
615 resource
.snap_to_edges
= WindowSnap
;
618 if (! config
->getValue(screenstr
+ "windowCornerSnap",
619 resource
.window_corner_snap
))
620 resource
.window_corner_snap
= true;
622 if (! config
->getValue(screenstr
+ "imageDither", b
))
624 image_control
->setDither(b
);
626 if (! config
->getValue(screenstr
+ "edgeSnapOffset",
627 resource
.snap_offset
))
628 resource
.snap_offset
= 0;
629 if (resource
.snap_offset
> 50) // sanity check, setting this huge would
630 resource
.snap_offset
= 50; // seriously suck.
632 if (! config
->getValue(screenstr
+ "edgeSnapThreshold",
633 resource
.snap_threshold
))
634 resource
.snap_threshold
= 4;
636 if (! config
->getValue(screenstr
+ "resistanceSize",
637 resource
.resistance_size
))
638 resource
.resistance_size
= 18;
640 if (config
->getValue(screenstr
+ "rowPlacementDirection", s
) &&
642 resource
.row_direction
= RightLeft
;
644 resource
.row_direction
= LeftRight
;
646 if (config
->getValue(screenstr
+ "colPlacementDirection", s
) &&
648 resource
.col_direction
= BottomTop
;
650 resource
.col_direction
= TopBottom
;
652 if (config
->getValue(screenstr
+ "workspaceNames", s
)) {
653 XAtom::StringVect workspaceNames
;
655 string::const_iterator it
= s
.begin(), end
= s
.end();
657 string::const_iterator tmp
= it
; // current string.begin()
658 it
= std::find(tmp
, end
, ','); // look for comma between tmp and end
659 workspaceNames
.push_back(string(tmp
, it
)); // s[tmp:it]
665 xatom
->setValue(getRootWindow(), XAtom::net_desktop_names
, XAtom::utf8
,
669 resource
.sloppy_focus
= true;
670 resource
.auto_raise
= false;
671 resource
.click_raise
= false;
672 if (config
->getValue(screenstr
+ "focusModel", s
)) {
673 if (s
.find("ClickToFocus") != string::npos
) {
674 resource
.sloppy_focus
= false;
677 if (s
.find("AutoRaise") != string::npos
)
678 resource
.auto_raise
= true;
679 if (s
.find("ClickRaise") != string::npos
)
680 resource
.click_raise
= true;
684 if (config
->getValue(screenstr
+ "windowPlacement", s
)) {
685 if (s
== "CascadePlacement")
686 resource
.placement_policy
= CascadePlacement
;
687 else if (s
== "UnderMousePlacement")
688 resource
.placement_policy
= UnderMousePlacement
;
689 else if (s
== "ClickMousePlacement")
690 resource
.placement_policy
= ClickMousePlacement
;
691 else if (s
== "ColSmartPlacement")
692 resource
.placement_policy
= ColSmartPlacement
;
693 else //if (s == "RowSmartPlacement")
694 resource
.placement_policy
= RowSmartPlacement
;
696 resource
.placement_policy
= RowSmartPlacement
;
698 if (! config
->getValue(screenstr
+ "strftimeFormat",
699 resource
.strftime_format
))
700 resource
.strftime_format
= "%I:%M %p";
702 if (! config
->getValue(screenstr
+ "placementIgnoreShaded",
703 resource
.ignore_shaded
))
704 resource
.ignore_shaded
= true;
706 if (! config
->getValue(screenstr
+ "placementIgnoreMaximized",
707 resource
.ignore_maximized
))
708 resource
.ignore_maximized
= true;
710 if (! config
->getValue(screenstr
+ "disableBindingsWithScrollLock",
711 resource
.allow_scroll_lock
))
712 resource
.allow_scroll_lock
= false;
714 if (! config
->getValue(screenstr
+ "workspaceWarping",
715 resource
.workspace_warping
))
716 resource
.workspace_warping
= false;
718 resource
.root_scroll
= NormalScroll
;
719 if (config
->getValue(screenstr
+ "rootScrollDirection", s
)) {
721 resource
.root_scroll
= NoScroll
;
722 else if (s
== "Reverse")
723 resource
.root_scroll
= ReverseScroll
;
728 void BScreen::changeWorkspaceCount(unsigned int new_count
) {
729 assert(new_count
> 0);
731 if (new_count
< workspacesList
.size()) {
733 for (unsigned int i
= workspacesList
.size(); i
> new_count
; --i
)
734 removeLastWorkspace();
735 // removeLast already sets the current workspace to the
736 // last available one.
737 } else if (new_count
> workspacesList
.size()) {
739 for(unsigned int i
= workspacesList
.size(); i
< new_count
; ++i
)
745 void BScreen::reconfigure(void) {
746 // don't reconfigure while saving the initial rc file, it's a waste and it
747 // breaks somethings (workspace names)
748 if (blackbox
->isStartup()) return;
753 // we need to do this explicitly, because just loading this value from the rc
755 changeWorkspaceCount(resource
.workspaces
);
758 gcv
.foreground
= WhitePixel(blackbox
->getXDisplay(),
760 gcv
.function
= GXinvert
;
761 gcv
.subwindow_mode
= IncludeInferiors
;
762 XChangeGC(blackbox
->getXDisplay(), opGC
,
763 GCForeground
| GCFunction
| GCSubwindowMode
, &gcv
);
765 const char *s
= "0: 0000 x 0: 0000";
767 geom_w
= resource
.wstyle
.font
->measureString(s
) + resource
.bevel_width
* 2;
768 geom_h
= resource
.wstyle
.font
->height() + resource
.bevel_width
* 2;
770 BTexture
* texture
= &(resource
.wstyle
.l_focus
);
771 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
772 if (geom_pixmap
== ParentRelative
) {
773 texture
= &(resource
.wstyle
.t_focus
);
774 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
777 XSetWindowBackground(blackbox
->getXDisplay(), geom_window
,
778 texture
->color().pixel());
780 XSetWindowBackgroundPixmap(blackbox
->getXDisplay(),
781 geom_window
, geom_pixmap
);
783 XSetWindowBorderWidth(blackbox
->getXDisplay(), geom_window
,
784 resource
.border_width
);
785 XSetWindowBorder(blackbox
->getXDisplay(), geom_window
,
786 resource
.border_color
.pixel());
788 typedef std::vector
<int> SubList
;
789 SubList remember_subs
;
793 std::for_each(workspacesList
.begin(), workspacesList
.end(),
794 std::mem_fun(&Workspace::reconfigure
));
796 BlackboxWindowList::iterator iit
= iconList
.begin();
797 for (; iit
!= iconList
.end(); ++iit
) {
798 BlackboxWindow
*bw
= *iit
;
799 if (bw
->validateClient())
803 image_control
->timeout();
807 void BScreen::LoadStyle(void) {
808 Configuration
style(False
);
810 const char *sfile
= blackbox
->getStyleFilename();
812 style
.setFile(sfile
);
813 if (! style
.load()) {
814 style
.setFile(DEFAULTSTYLE
);
816 style
.create(); // hardcoded default values will be used.
820 // merge in the rc file
821 style
.merge(config
->file(), True
);
825 // load fonts/fontsets
826 if (resource
.wstyle
.font
)
827 delete resource
.wstyle
.font
;
829 resource
.wstyle
.font
= readDatabaseFont("window.", style
);
831 // load window config
832 resource
.wstyle
.t_focus
=
833 readDatabaseTexture("window.title.focus", "white", style
);
834 resource
.wstyle
.t_unfocus
=
835 readDatabaseTexture("window.title.unfocus", "black", style
);
836 resource
.wstyle
.l_focus
=
837 readDatabaseTexture("window.label.focus", "white", style
);
838 resource
.wstyle
.l_unfocus
=
839 readDatabaseTexture("window.label.unfocus", "black", style
);
840 resource
.wstyle
.h_focus
=
841 readDatabaseTexture("window.handle.focus", "white", style
);
842 resource
.wstyle
.h_unfocus
=
843 readDatabaseTexture("window.handle.unfocus", "black", style
);
844 resource
.wstyle
.g_focus
=
845 readDatabaseTexture("window.grip.focus", "white", style
);
846 resource
.wstyle
.g_unfocus
=
847 readDatabaseTexture("window.grip.unfocus", "black", style
);
848 resource
.wstyle
.b_focus
=
849 readDatabaseTexture("window.button.focus", "white", style
);
850 resource
.wstyle
.b_unfocus
=
851 readDatabaseTexture("window.button.unfocus", "black", style
);
852 resource
.wstyle
.b_pressed
=
853 readDatabaseTexture("window.button.pressed", "black", style
);
855 //if neither of these can be found, we will use the previous resource
856 resource
.wstyle
.b_pressed_focus
=
857 readDatabaseTexture("window.button.pressed.focus", "black", style
, true);
858 resource
.wstyle
.b_pressed_unfocus
=
859 readDatabaseTexture("window.button.pressed.unfocus", "black", style
, true);
862 if (resource
.wstyle
.close_button
.mask
!= None
)
863 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.close_button
.mask
);
864 if (resource
.wstyle
.max_button
.mask
!= None
)
865 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.max_button
.mask
);
866 if (resource
.wstyle
.icon_button
.mask
!= None
)
867 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.icon_button
.mask
);
868 if (resource
.wstyle
.stick_button
.mask
!= None
)
869 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.stick_button
.mask
);
871 resource
.wstyle
.close_button
.mask
= resource
.wstyle
.max_button
.mask
=
872 resource
.wstyle
.icon_button
.mask
=
873 resource
.wstyle
.icon_button
.mask
= None
;
875 readDatabaseMask("window.button.close.mask", resource
.wstyle
.close_button
,
877 readDatabaseMask("window.button.max.mask", resource
.wstyle
.max_button
,
879 readDatabaseMask("window.button.icon.mask", resource
.wstyle
.icon_button
,
881 readDatabaseMask("window.button.stick.mask", resource
.wstyle
.stick_button
,
883 #endif // BITMAPBUTTONS
885 // we create the window.frame texture by hand because it exists only to
886 // make the code cleaner and is not actually used for display
887 BColor color
= readDatabaseColor("window.frame.focusColor", "white", style
);
888 resource
.wstyle
.f_focus
= BTexture("solid flat", getBaseDisplay(),
889 getScreenNumber(), image_control
);
890 resource
.wstyle
.f_focus
.setColor(color
);
892 color
= readDatabaseColor("window.frame.unfocusColor", "white", style
);
893 resource
.wstyle
.f_unfocus
= BTexture("solid flat", getBaseDisplay(),
894 getScreenNumber(), image_control
);
895 resource
.wstyle
.f_unfocus
.setColor(color
);
897 resource
.wstyle
.l_text_focus
=
898 readDatabaseColor("window.label.focus.textColor", "black", style
);
899 resource
.wstyle
.l_text_unfocus
=
900 readDatabaseColor("window.label.unfocus.textColor", "white", style
);
901 resource
.wstyle
.b_pic_focus
=
902 readDatabaseColor("window.button.focus.picColor", "black", style
);
903 resource
.wstyle
.b_pic_unfocus
=
904 readDatabaseColor("window.button.unfocus.picColor", "white", style
);
906 resource
.wstyle
.justify
= LeftJustify
;
907 if (style
.getValue("window.justify", s
)) {
908 if (s
== "right" || s
== "Right")
909 resource
.wstyle
.justify
= RightJustify
;
910 else if (s
== "center" || s
== "Center")
911 resource
.wstyle
.justify
= CenterJustify
;
915 if (resource
.wstyle
.t_focus
.texture() == BTexture::Parent_Relative
)
916 resource
.wstyle
.t_focus
= resource
.wstyle
.f_focus
;
917 if (resource
.wstyle
.t_unfocus
.texture() == BTexture::Parent_Relative
)
918 resource
.wstyle
.t_unfocus
= resource
.wstyle
.f_unfocus
;
919 if (resource
.wstyle
.h_focus
.texture() == BTexture::Parent_Relative
)
920 resource
.wstyle
.h_focus
= resource
.wstyle
.f_focus
;
921 if (resource
.wstyle
.h_unfocus
.texture() == BTexture::Parent_Relative
)
922 resource
.wstyle
.h_unfocus
= resource
.wstyle
.f_unfocus
;
924 resource
.border_color
=
925 readDatabaseColor("borderColor", "black", style
);
927 // load bevel, border and handle widths
928 if (! style
.getValue("handleWidth", resource
.handle_width
) ||
929 resource
.handle_width
> (getWidth() / 2) || resource
.handle_width
== 0)
930 resource
.handle_width
= 6;
932 if (! style
.getValue("borderWidth", resource
.border_width
))
933 resource
.border_width
= 1;
935 if (! style
.getValue("bevelWidth", resource
.bevel_width
) ||
936 resource
.bevel_width
> (getWidth() / 2) || resource
.bevel_width
== 0)
937 resource
.bevel_width
= 3;
939 if (! style
.getValue("frameWidth", resource
.frame_width
) ||
940 resource
.frame_width
> (getWidth() / 2))
941 resource
.frame_width
= resource
.bevel_width
;
943 if (style
.getValue("rootCommand", s
))
944 bexec(s
, displayString());
948 void BScreen::addIcon(BlackboxWindow
*w
) {
951 w
->setWorkspace(BSENTINEL
);
952 w
->setWindowNumber(iconList
.size());
954 iconList
.push_back(w
);
958 void BScreen::removeIcon(BlackboxWindow
*w
) {
963 BlackboxWindowList::iterator it
= iconList
.begin(),
964 end
= iconList
.end();
965 for (int i
= 0; it
!= end
; ++it
)
966 (*it
)->setWindowNumber(i
++);
970 BlackboxWindow
*BScreen::getIcon(unsigned int index
) {
971 if (index
< iconList
.size()) {
972 BlackboxWindowList::iterator it
= iconList
.begin();
973 while (index
-- > 0) // increment to index
978 return (BlackboxWindow
*) 0;
982 unsigned int BScreen::addWorkspace(void) {
983 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
984 workspacesList
.push_back(wkspc
);
985 saveWorkspaces(getWorkspaceCount());
986 saveWorkspaceNames();
988 return workspacesList
.size();
992 unsigned int BScreen::removeLastWorkspace(void) {
993 if (workspacesList
.size() == 1)
996 Workspace
*wkspc
= workspacesList
.back();
998 if (current_workspace
->getID() == wkspc
->getID())
999 changeWorkspaceID(current_workspace
->getID() - 1);
1003 workspacesList
.pop_back();
1006 saveWorkspaces(getWorkspaceCount());
1007 saveWorkspaceNames();
1009 updateNetizenWorkspaceCount();
1011 return workspacesList
.size();
1015 void BScreen::changeWorkspaceID(unsigned int id
) {
1016 if (! current_workspace
|| id
== current_workspace
->getID()) return;
1018 BlackboxWindow
*focused
= blackbox
->getFocusedWindow();
1019 if (focused
&& focused
->getScreen() == this) {
1020 assert(focused
->isStuck() ||
1021 focused
->getWorkspaceNumber() == current_workspace
->getID());
1023 current_workspace
->setLastFocusedWindow(focused
);
1025 // if no window had focus, no need to store a last focus
1026 current_workspace
->setLastFocusedWindow((BlackboxWindow
*) 0);
1029 // when we switch workspaces, unfocus whatever was focused if it is going
1031 if (focused
&& ! focused
->isStuck())
1032 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1034 current_workspace
->hideAll();
1036 current_workspace
= getWorkspace(id
);
1038 xatom
->setValue(getRootWindow(), XAtom::net_current_desktop
,
1039 XAtom::cardinal
, id
);
1041 current_workspace
->showAll();
1046 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
1049 XSync(blackbox
->getXDisplay(), False
);
1051 // If sloppy focus and we can find the client window under the pointer,
1053 if (resource
.sloppy_focus
&&
1054 XQueryPointer(blackbox
->getXDisplay(), getRootWindow(), &r
, &c
,
1055 &rx
, &ry
, &x
, &y
, &m
) &&
1057 if ( (win
= blackbox
->searchWindow(c
)) )
1058 f
= win
->setInputFocus();
1061 // If that fails, and we're doing focus_last, try to focus the last window.
1062 if (! f
&& resource
.focus_last
&&
1063 (win
= current_workspace
->getLastFocusedWindow()))
1064 f
= win
->setInputFocus();
1067 if we found a focus target, then we set the focused window explicitly
1068 because it is possible to switch off this workspace before the x server
1069 generates the FocusIn event for the window. if that happens, openbox would
1070 lose track of what window was the 'LastFocused' window on the workspace.
1072 if we did not find a focus target, then set the current focused window to
1076 blackbox
->setFocusedWindow(win
);
1078 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1083 * Set the _NET_CLIENT_LIST root window property.
1085 void BScreen::updateClientList(void) {
1086 if (windowList
.size() > 0) {
1087 Window
*windows
= new Window
[windowList
.size()];
1088 Window
*win_it
= windows
;
1089 BlackboxWindowList::iterator it
= windowList
.begin();
1090 const BlackboxWindowList::iterator end
= windowList
.end();
1091 for (; it
!= end
; ++it
, ++win_it
)
1092 *win_it
= (*it
)->getClientWindow();
1093 xatom
->setValue(getRootWindow(), XAtom::net_client_list
, XAtom::window
,
1094 windows
, windowList
.size());
1097 xatom
->setValue(getRootWindow(), XAtom::net_client_list
, XAtom::window
,
1100 updateStackingList();
1105 * Set the _NET_CLIENT_LIST_STACKING root window property.
1107 void BScreen::updateStackingList(void) {
1109 BlackboxWindowList stack_order
;
1112 * Get the stacking order from all of the workspaces.
1113 * We start with the current workspace so that the sticky windows will be
1114 * in the right order on the current workspace.
1115 * XXX: Do we need to have sticky windows in the list once for each workspace?
1117 getCurrentWorkspace()->appendStackOrder(stack_order
);
1118 for (unsigned int i
= 0; i
< getWorkspaceCount(); ++i
)
1119 if (i
!= getCurrentWorkspaceID())
1120 getWorkspace(i
)->appendStackOrder(stack_order
);
1122 if (stack_order
.size() > 0) {
1123 // set the client list atoms
1124 Window
*windows
= new Window
[stack_order
.size()];
1125 Window
*win_it
= windows
;
1126 BlackboxWindowList::iterator it
= stack_order
.begin(),
1127 end
= stack_order
.end();
1128 for (; it
!= end
; ++it
, ++win_it
)
1129 *win_it
= (*it
)->getClientWindow();
1130 xatom
->setValue(getRootWindow(), XAtom::net_client_list_stacking
,
1131 XAtom::window
, windows
, stack_order
.size());
1134 xatom
->setValue(getRootWindow(), XAtom::net_client_list_stacking
,
1135 XAtom::window
, 0, 0);
1139 void BScreen::addSystrayWindow(Window window
) {
1140 XGrabServer(blackbox
->getXDisplay());
1142 XSelectInput(blackbox
->getXDisplay(), window
, StructureNotifyMask
);
1143 systrayWindowList
.push_back(window
);
1144 xatom
->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows
,
1146 &systrayWindowList
[0], systrayWindowList
.size());
1147 blackbox
->saveSystrayWindowSearch(window
, this);
1149 XUngrabServer(blackbox
->getXDisplay());
1153 void BScreen::removeSystrayWindow(Window window
) {
1154 XGrabServer(blackbox
->getXDisplay());
1156 WindowList::iterator it
= systrayWindowList
.begin();
1157 const WindowList::iterator end
= systrayWindowList
.end();
1158 for (; it
!= end
; ++it
)
1159 if (*it
== window
) {
1160 systrayWindowList
.erase(it
);
1161 xatom
->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows
,
1163 &systrayWindowList
[0], systrayWindowList
.size());
1164 blackbox
->removeSystrayWindowSearch(window
);
1165 XSelectInput(blackbox
->getXDisplay(), window
, NoEventMask
);
1169 assert(it
!= end
); // not a systray window
1171 XUngrabServer(blackbox
->getXDisplay());
1175 void BScreen::manageWindow(Window w
) {
1176 // is the window a KDE systray window?
1178 if (xatom
->getValue(w
, XAtom::kde_net_wm_system_tray_window_for
,
1179 XAtom::window
, systray
) && systray
!= None
) {
1180 addSystrayWindow(w
);
1184 // is the window a docking app
1185 XWMHints
*wmhint
= XGetWMHints(blackbox
->getXDisplay(), w
);
1186 if (wmhint
&& (wmhint
->flags
& StateHint
) &&
1187 wmhint
->initial_state
== WithdrawnState
) {
1188 //slit->addClient(w);
1192 new BlackboxWindow(blackbox
, w
, this);
1194 BlackboxWindow
*win
= blackbox
->searchWindow(w
);
1198 if (win
->isDesktop()) {
1199 desktopWindowList
.push_back(win
->getFrameWindow());
1200 } else { // if (win->isNormal()) {
1201 // don't list desktop windows as managed windows
1202 windowList
.push_back(win
);
1205 if (win
->isTopmost())
1206 specialWindowList
.push_back(win
->getFrameWindow());
1209 XMapRequestEvent mre
;
1211 if (blackbox
->isStartup() && win
->isNormal()) win
->restoreAttributes();
1212 win
->mapRequestEvent(&mre
);
1216 void BScreen::unmanageWindow(BlackboxWindow
*w
, bool remap
) {
1217 // is the window a KDE systray window?
1219 if (xatom
->getValue(w
->getClientWindow(),
1220 XAtom::kde_net_wm_system_tray_window_for
,
1221 XAtom::window
, systray
) && systray
!= None
) {
1222 removeSystrayWindow(w
->getClientWindow());
1228 // Remove the modality so that its parent won't try to re-focus the window
1229 if (w
->isModal()) w
->setModal(False
);
1231 if (w
->getWorkspaceNumber() != BSENTINEL
&&
1232 w
->getWindowNumber() != BSENTINEL
) {
1233 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1235 for (unsigned int i
= 0; i
< getNumberOfWorkspaces(); ++i
)
1236 if (i
!= w
->getWorkspaceNumber())
1237 getWorkspace(i
)->removeWindow(w
, True
);
1239 } else if (w
->isIconic())
1242 if (w
->isDesktop()) {
1243 WindowList::iterator it
= desktopWindowList
.begin();
1244 const WindowList::iterator end
= desktopWindowList
.end();
1245 for (; it
!= end
; ++it
)
1246 if (*it
== w
->getFrameWindow()) {
1247 desktopWindowList
.erase(it
);
1250 assert(it
!= end
); // the window wasnt a desktop window?
1251 } else { // if (w->isNormal()) {
1252 // we don't list desktop windows as managed windows
1253 windowList
.remove(w
);
1256 if (w
->isTopmost()) {
1257 WindowList::iterator it
= specialWindowList
.begin();
1258 const WindowList::iterator end
= specialWindowList
.end();
1259 for (; it
!= end
; ++it
)
1260 if (*it
== w
->getFrameWindow()) {
1261 specialWindowList
.erase(it
);
1264 assert(it
!= end
); // the window wasnt a special window?
1268 if (blackbox
->getFocusedWindow() == w
)
1269 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1272 some managed windows can also be window group controllers. when
1273 unmanaging such windows, we should also delete the window group.
1275 BWindowGroup
*group
= blackbox
->searchGroup(w
->getClientWindow());
1282 void BScreen::updateWorkArea(void) {
1283 if (workspacesList
.size() > 0) {
1284 unsigned long *dims
= new unsigned long[4 * workspacesList
.size()];
1285 for (unsigned int i
= 0, m
= workspacesList
.size(); i
< m
; ++i
) {
1286 // XXX: this could be different for each workspace
1287 const Rect
&area
= availableArea();
1288 dims
[(i
* 4) + 0] = area
.x();
1289 dims
[(i
* 4) + 1] = area
.y();
1290 dims
[(i
* 4) + 2] = area
.width();
1291 dims
[(i
* 4) + 3] = area
.height();
1293 xatom
->setValue(getRootWindow(), XAtom::net_workarea
, XAtom::cardinal
,
1294 dims
, 4 * workspacesList
.size());
1297 xatom
->setValue(getRootWindow(), XAtom::net_workarea
, XAtom::cardinal
,
1302 void BScreen::updateNetizenWorkspaceCount(void) {
1303 xatom
->setValue(getRootWindow(), XAtom::net_number_of_desktops
,
1304 XAtom::cardinal
, workspacesList
.size());
1310 void BScreen::updateNetizenWindowFocus(void) {
1311 Window f
= ((blackbox
->getFocusedWindow()) ?
1312 blackbox
->getFocusedWindow()->getClientWindow() : None
);
1314 xatom
->setValue(getRootWindow(), XAtom::net_active_window
,
1319 void BScreen::raiseWindows(Window
*workspace_stack
, unsigned int num
) {
1320 // the 13 represents the number of blackbox windows such as menus
1326 Window
*session_stack
= new
1327 Window
[(num
+ specialWindowList
.size() + bbwins
)];
1328 unsigned int i
= 0, k
= num
;
1330 WindowList::iterator sit
, send
= specialWindowList
.end();
1331 for (sit
= specialWindowList
.begin(); sit
!= send
; ++sit
)
1332 *(session_stack
+ i
++) = *sit
;
1335 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
1337 XRestackWindows(blackbox
->getXDisplay(), session_stack
, i
);
1339 delete [] session_stack
;
1341 updateStackingList();
1345 void BScreen::lowerWindows(Window
*workspace_stack
, unsigned int num
) {
1346 assert(num
> 0); // this would cause trouble in the XRaiseWindow call
1348 Window
*session_stack
= new Window
[(num
+ desktopWindowList
.size())];
1349 unsigned int i
= 0, k
= num
;
1351 XLowerWindow(blackbox
->getXDisplay(), workspace_stack
[0]);
1354 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
1356 WindowList::iterator dit
= desktopWindowList
.begin();
1357 const WindowList::iterator d_end
= desktopWindowList
.end();
1358 for (; dit
!= d_end
; ++dit
)
1359 *(session_stack
+ i
++) = *dit
;
1361 XRestackWindows(blackbox
->getXDisplay(), session_stack
, i
);
1363 delete [] session_stack
;
1365 updateStackingList();
1369 void BScreen::reassociateWindow(BlackboxWindow
*w
, unsigned int wkspc_id
,
1370 bool ignore_sticky
) {
1373 if (wkspc_id
== BSENTINEL
)
1374 wkspc_id
= current_workspace
->getID();
1376 if (w
->getWorkspaceNumber() == wkspc_id
)
1379 if (w
->isIconic()) {
1381 getWorkspace(wkspc_id
)->addWindow(w
);
1383 for (unsigned int i
= 0; i
< getNumberOfWorkspaces(); ++i
)
1384 if (i
!= w
->getWorkspaceNumber())
1385 getWorkspace(i
)->addWindow(w
, True
);
1386 } else if (ignore_sticky
|| ! w
->isStuck()) {
1389 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1390 getWorkspace(wkspc_id
)->addWindow(w
);
1392 updateStackingList();
1396 void BScreen::propagateWindowName(const BlackboxWindow
*bw
) {
1397 if (bw
->isIconic()) {
1403 void BScreen::nextFocus(void) const {
1404 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1408 focused
->getScreen()->getScreenNumber() == getScreenNumber() &&
1409 current_workspace
->getCount() > 1) {
1411 next
= current_workspace
->getNextWindowInList(next
);
1412 } while (next
!= focused
&& ! next
->setInputFocus());
1414 if (next
!= focused
)
1415 current_workspace
->raiseWindow(next
);
1416 } else if (current_workspace
->getCount() > 0) {
1417 next
= current_workspace
->getTopWindowOnStack();
1418 next
->setInputFocus();
1419 current_workspace
->raiseWindow(next
);
1424 void BScreen::prevFocus(void) const {
1425 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1429 // if window is not on this screen, ignore it
1430 if (focused
->getScreen()->getScreenNumber() != getScreenNumber())
1431 focused
= (BlackboxWindow
*) 0;
1435 focused
->getScreen()->getScreenNumber() == getScreenNumber() &&
1436 current_workspace
->getCount() > 1) {
1437 // next is the next window to receive focus, current is a place holder
1439 next
= current_workspace
->getPrevWindowInList(next
);
1440 } while (next
!= focused
&& ! next
->setInputFocus());
1442 if (next
!= focused
)
1443 current_workspace
->raiseWindow(next
);
1444 } else if (current_workspace
->getCount() > 0) {
1445 next
= current_workspace
->getTopWindowOnStack();
1446 next
->setInputFocus();
1447 current_workspace
->raiseWindow(next
);
1452 void BScreen::raiseFocus(void) const {
1453 BlackboxWindow
*focused
= blackbox
->getFocusedWindow();
1457 // if on this Screen, raise it
1458 if (focused
->getScreen()->getScreenNumber() == getScreenNumber()) {
1459 Workspace
*workspace
= getWorkspace(focused
->getWorkspaceNumber());
1460 workspace
->raiseWindow(focused
);
1465 void BScreen::shutdown(void) {
1466 XSelectInput(blackbox
->getXDisplay(), getRootWindow(), NoEventMask
);
1467 XSync(blackbox
->getXDisplay(), False
);
1469 while(! windowList
.empty())
1470 unmanageWindow(windowList
.front(), True
);
1472 while(! desktopWindowList
.empty()) {
1473 BlackboxWindow
*win
= blackbox
->searchWindow(desktopWindowList
.front());
1475 unmanageWindow(win
, True
);
1480 void BScreen::showPosition(int x
, int y
) {
1481 if (! geom_visible
) {
1482 XMoveResizeWindow(blackbox
->getXDisplay(), geom_window
,
1483 (getWidth() - geom_w
) / 2,
1484 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
1485 XMapWindow(blackbox
->getXDisplay(), geom_window
);
1486 XRaiseWindow(blackbox
->getXDisplay(), geom_window
);
1488 geom_visible
= True
;
1493 sprintf(label
, "X: %4d x Y: %4d", x
, y
);
1495 XClearWindow(blackbox
->getXDisplay(), geom_window
);
1497 resource
.wstyle
.font
->drawString(geom_window
,
1498 resource
.bevel_width
, resource
.bevel_width
,
1499 resource
.wstyle
.l_text_focus
,
1504 void BScreen::showGeometry(unsigned int gx
, unsigned int gy
) {
1505 if (! geom_visible
) {
1506 XMoveResizeWindow(blackbox
->getXDisplay(), geom_window
,
1507 (getWidth() - geom_w
) / 2,
1508 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
1509 XMapWindow(blackbox
->getXDisplay(), geom_window
);
1510 XRaiseWindow(blackbox
->getXDisplay(), geom_window
);
1512 geom_visible
= True
;
1517 sprintf(label
, "W: %4d x H: %4d", gx
, gy
);
1519 XClearWindow(blackbox
->getXDisplay(), geom_window
);
1521 resource
.wstyle
.font
->drawString(geom_window
,
1522 resource
.bevel_width
, resource
.bevel_width
,
1523 resource
.wstyle
.l_text_focus
,
1528 void BScreen::hideGeometry(void) {
1530 XUnmapWindow(blackbox
->getXDisplay(), geom_window
);
1531 geom_visible
= False
;
1536 void BScreen::addStrut(Strut
*strut
) {
1537 strutList
.push_back(strut
);
1541 void BScreen::removeStrut(Strut
*strut
) {
1542 strutList
.remove(strut
);
1546 const Rect
& BScreen::availableArea(void) const {
1548 return getRect(); // return the full screen
1554 const RectList
& BScreen::allAvailableAreas(void) const {
1555 assert(isXineramaActive());
1556 assert(xineramaUsableArea
.size() > 0);
1557 fprintf(stderr
, "1found x %d y %d w %d h %d\n",
1558 xineramaUsableArea
[0].x(), xineramaUsableArea
[0].y(),
1559 xineramaUsableArea
[0].width(), xineramaUsableArea
[0].height());
1560 return xineramaUsableArea
;
1565 void BScreen::updateAvailableArea(void) {
1566 Rect old_area
= usableArea
;
1567 usableArea
= getRect(); // reset to full screen
1570 // reset to the full areas
1571 if (isXineramaActive())
1572 xineramaUsableArea
= getXineramaAreas();
1575 /* these values represent offsets from the screen edge
1576 * we look for the biggest offset on each edge and then apply them
1578 * do not be confused by the similarity to the names of Rect's members
1580 unsigned int current_left
= 0, current_right
= 0, current_top
= 0,
1583 StrutList::const_iterator it
= strutList
.begin(), end
= strutList
.end();
1585 for(; it
!= end
; ++it
) {
1587 if (strut
->left
> current_left
)
1588 current_left
= strut
->left
;
1589 if (strut
->top
> current_top
)
1590 current_top
= strut
->top
;
1591 if (strut
->right
> current_right
)
1592 current_right
= strut
->right
;
1593 if (strut
->bottom
> current_bottom
)
1594 current_bottom
= strut
->bottom
;
1597 usableArea
.setPos(current_left
, current_top
);
1598 usableArea
.setSize(usableArea
.width() - (current_left
+ current_right
),
1599 usableArea
.height() - (current_top
+ current_bottom
));
1602 if (isXineramaActive()) {
1603 // keep each of the ximerama-defined areas inside the strut
1604 RectList::iterator xit
, xend
= xineramaUsableArea
.end();
1605 for (xit
= xineramaUsableArea
.begin(); xit
!= xend
; ++xit
) {
1606 if (xit
->x() < usableArea
.x()) {
1607 xit
->setX(usableArea
.x());
1608 xit
->setWidth(xit
->width() - usableArea
.x());
1610 if (xit
->y() < usableArea
.y()) {
1611 xit
->setY(usableArea
.y());
1612 xit
->setHeight(xit
->height() - usableArea
.y());
1614 if (xit
->x() + xit
->width() > usableArea
.width())
1615 xit
->setWidth(usableArea
.width() - xit
->x());
1616 if (xit
->y() + xit
->height() > usableArea
.height())
1617 xit
->setHeight(usableArea
.height() - xit
->y());
1622 if (old_area
!= usableArea
) {
1623 BlackboxWindowList::iterator it
= windowList
.begin(),
1624 end
= windowList
.end();
1625 for (; it
!= end
; ++it
)
1626 if ((*it
)->isMaximized()) (*it
)->remaximize();
1633 Workspace
* BScreen::getWorkspace(unsigned int index
) const {
1634 assert(index
< workspacesList
.size());
1635 return workspacesList
[index
];
1639 void BScreen::buttonPressEvent(const XButtonEvent
*xbutton
) {
1640 if (xbutton
->button
== 1) {
1641 if (! isRootColormapInstalled())
1642 image_control
->installRootColormap();
1645 } else if ((xbutton
->button
== 4 && resource
.root_scroll
== NormalScroll
) ||
1646 (xbutton
->button
== 5 && resource
.root_scroll
== ReverseScroll
)) {
1647 if (getCurrentWorkspaceID() >= getWorkspaceCount() - 1)
1648 changeWorkspaceID(0);
1650 changeWorkspaceID(getCurrentWorkspaceID() + 1);
1652 } else if ((xbutton
->button
== 5 && resource
.root_scroll
== NormalScroll
) ||
1653 (xbutton
->button
== 4 && resource
.root_scroll
== ReverseScroll
)) {
1654 if (getCurrentWorkspaceID() == 0)
1655 changeWorkspaceID(getWorkspaceCount() - 1);
1657 changeWorkspaceID(getCurrentWorkspaceID() - 1);
1662 void BScreen::propertyNotifyEvent(const XPropertyEvent
*pe
) {
1663 if (pe
->atom
== xatom
->getAtom(XAtom::net_desktop_names
)) {
1664 // _NET_WM_DESKTOP_NAMES
1665 WorkspaceList::iterator it
= workspacesList
.begin();
1666 const WorkspaceList::iterator end
= workspacesList
.end();
1667 for (; it
!= end
; ++it
) {
1668 (*it
)->readName(); // re-read its name from the window property
1669 //workspacemenu->changeWorkspaceLabel((*it)->getID(), (*it)->getName());
1671 //workspacemenu->update();
1672 saveWorkspaceNames();
1677 void BScreen::toggleFocusModel(FocusModel model
) {
1678 std::for_each(windowList
.begin(), windowList
.end(),
1679 std::mem_fun(&BlackboxWindow::ungrabButtons
));
1681 if (model
== SloppyFocus
) {
1682 saveSloppyFocus(True
);
1684 // we're cheating here to save writing the config file 3 times
1685 resource
.auto_raise
= False
;
1686 resource
.click_raise
= False
;
1687 saveSloppyFocus(False
);
1690 std::for_each(windowList
.begin(), windowList
.end(),
1691 std::mem_fun(&BlackboxWindow::grabButtons
));
1694 #ifdef BITMAPBUTTONS
1695 void BScreen::readDatabaseMask(const string
&rname
, PixmapMask
&pixmapMask
,
1696 const Configuration
&style
) {
1698 int hx
, hy
; //ignored
1699 int ret
= BitmapOpenFailed
; //default to failure.
1701 if (style
.getValue(rname
, s
))
1703 if (s
[0] != '/' && s
[0] != '~')
1705 std::string xbmFile
= std::string("~/.openbox/buttons/") + s
;
1706 ret
= XReadBitmapFile(blackbox
->getXDisplay(), getRootWindow(),
1707 expandTilde(xbmFile
).c_str(), &pixmapMask
.w
,
1708 &pixmapMask
.h
, &pixmapMask
.mask
, &hx
, &hy
);
1710 ret
= XReadBitmapFile(blackbox
->getXDisplay(), getRootWindow(),
1711 expandTilde(s
).c_str(), &pixmapMask
.w
,
1712 &pixmapMask
.h
, &pixmapMask
.mask
, &hx
, &hy
);
1714 if (ret
== BitmapSuccess
)
1718 pixmapMask
.mask
= None
;
1719 pixmapMask
.w
= pixmapMask
.h
= 0;
1721 #endif // BITMAPSUCCESS
1723 BTexture
BScreen::readDatabaseTexture(const string
&rname
,
1724 const string
&default_color
,
1725 const Configuration
&style
,
1726 bool allowNoTexture
) {
1730 if (style
.getValue(rname
, s
))
1731 texture
= BTexture(s
);
1732 else if (allowNoTexture
) //no default
1733 texture
.setTexture(BTexture::NoTexture
);
1735 texture
.setTexture(BTexture::Solid
| BTexture::Flat
);
1737 // associate this texture with this screen
1738 texture
.setDisplay(getBaseDisplay(), getScreenNumber());
1739 texture
.setImageControl(image_control
);
1741 if (texture
.texture() != BTexture::NoTexture
) {
1742 texture
.setColor(readDatabaseColor(rname
+ ".color", default_color
,
1744 texture
.setColorTo(readDatabaseColor(rname
+ ".colorTo", default_color
,
1746 texture
.setBorderColor(readDatabaseColor(rname
+ ".borderColor",
1747 default_color
, style
));
1754 BColor
BScreen::readDatabaseColor(const string
&rname
,
1755 const string
&default_color
,
1756 const Configuration
&style
) {
1759 if (style
.getValue(rname
, s
))
1760 color
= BColor(s
, getBaseDisplay(), getScreenNumber());
1762 color
= BColor(default_color
, getBaseDisplay(), getScreenNumber());
1767 BFont
*BScreen::readDatabaseFont(const string
&rbasename
,
1768 const Configuration
&style
) {
1774 if (style
.getValue(rbasename
+ "xft.font", s
) &&
1775 style
.getValue(rbasename
+ "xft.size", i
)) {
1778 bool italic
= False
;
1779 bool dropShadow
= False
;
1781 if (style
.getValue(rbasename
+ "xft.flags", s
)) {
1782 if (s
.find("bold") != string::npos
)
1784 if (s
.find("italic") != string::npos
)
1786 if (s
.find("shadow") != string::npos
)
1790 unsigned char offset
= 1;
1791 if (style
.getValue(rbasename
+ "xft.shadow.offset", s
)) {
1792 offset
= atoi(s
.c_str()); //doesn't detect errors
1793 if (offset
> CHAR_MAX
)
1797 unsigned char tint
= 0x40;
1798 if (style
.getValue(rbasename
+ "xft.shadow.tint", s
)) {
1799 tint
= atoi(s
.c_str());
1803 BFont
*b
= new BFont(blackbox
->getXDisplay(), this, family
, i
, bold
,
1804 italic
, dropShadow
&& resource
.shadow_fonts
, offset
,
1805 tint
, resource
.aa_fonts
);
1811 exit(2); // can't continue without a font