1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
5 #endif // HAVE_CONFIG_H
9 #include <X11/keysym.h>
12 # include <X11/Xlib.h>
13 # include <X11/extensions/Xinerama.h>
18 #endif // HAVE_STDLIB_H
22 #endif // HAVE_STRING_H
26 #endif // HAVE_CTYPE_H
29 # include <sys/types.h>
31 #endif // HAVE_UNISTD_H
35 #endif // HAVE_DIRENT_H
39 #endif // HAVE_LOCALE_H
41 #ifdef HAVE_SYS_STAT_H
42 # include <sys/stat.h>
43 #endif // HAVE_SYS_STAT_H
47 #endif // HAVE_STDARG_H
57 #include "blackbox.hh"
64 #include "workspace.hh"
68 #ifndef FONT_ELEMENT_SIZE
69 #define FONT_ELEMENT_SIZE 50
70 #endif // FONT_ELEMENT_SIZE
73 static bool running
= True
;
75 static int anotherWMRunning(Display
*display
, XErrorEvent
*) {
77 "BScreen::BScreen: an error occured while querying the X server.\n"
78 " another window manager already running on display %s.\n",
79 DisplayString(display
));
87 BScreen::BScreen(Blackbox
*bb
, unsigned int scrn
) : ScreenInfo(bb
, scrn
) {
89 screenstr
= "session.screen" + itostring(scrn
) + '.';
90 config
= blackbox
->getConfig();
91 xatom
= blackbox
->getXAtom();
93 event_mask
= ColormapChangeMask
| EnterWindowMask
| PropertyChangeMask
|
94 SubstructureRedirectMask
| ButtonPressMask
| ButtonReleaseMask
;
96 XErrorHandler old
= XSetErrorHandler((XErrorHandler
) anotherWMRunning
);
97 XSelectInput(getBaseDisplay()->getXDisplay(), getRootWindow(), event_mask
);
98 XSync(getBaseDisplay()->getXDisplay(), False
);
99 XSetErrorHandler((XErrorHandler
) old
);
102 if (! managed
) return;
104 fprintf(stderr
, "BScreen::BScreen: managing screen %d "
105 "using visual 0x%lx, depth %d\n",
106 getScreenNumber(), XVisualIDFromVisual(getVisual()),
109 resource
.wstyle
.font
= (BFont
*) 0;
113 xatom
->setSupported(this); // set-up netwm support
115 xatom
->setValue(getRootWindow(), XAtom::blackbox_pid
, XAtom::cardinal
,
116 (unsigned long) getpid());
117 #endif // HAVE_GETPID
118 unsigned long geometry
[] = { getWidth(),
120 xatom
->setValue(getRootWindow(), XAtom::net_desktop_geometry
,
121 XAtom::cardinal
, geometry
, 2);
122 unsigned long viewport
[] = {0,0};
123 xatom
->setValue(getRootWindow(), XAtom::net_desktop_viewport
,
124 XAtom::cardinal
, viewport
, 2);
127 XDefineCursor(blackbox
->getXDisplay(), getRootWindow(),
128 blackbox
->getSessionCursor());
130 updateAvailableArea();
133 new BImageControl(blackbox
, this, True
, blackbox
->getColorsPerChannel(),
134 blackbox
->getCacheLife(), blackbox
->getCacheMax());
135 image_control
->installRootColormap();
136 root_colormap_installed
= True
;
142 gcv
.foreground
= WhitePixel(blackbox
->getXDisplay(), getScreenNumber())
143 ^ BlackPixel(blackbox
->getXDisplay(), getScreenNumber());
144 gcv
.function
= GXxor
;
145 gcv
.subwindow_mode
= IncludeInferiors
;
146 opGC
= XCreateGC(blackbox
->getXDisplay(), getRootWindow(),
147 GCForeground
| GCFunction
| GCSubwindowMode
, &gcv
);
149 const char *s
= "0: 0000 x 0: 0000";
150 geom_w
= resource
.wstyle
.font
->measureString(s
) + resource
.bevel_width
* 2;
151 geom_h
= resource
.wstyle
.font
->height() + resource
.bevel_width
* 2;
153 XSetWindowAttributes attrib
;
154 unsigned long mask
= CWBorderPixel
| CWColormap
| CWSaveUnder
;
155 attrib
.border_pixel
= getBorderColor()->pixel();
156 attrib
.colormap
= getColormap();
157 attrib
.save_under
= True
;
159 geom_window
= XCreateWindow(blackbox
->getXDisplay(), getRootWindow(),
160 0, 0, geom_w
, geom_h
, resource
.border_width
,
161 getDepth(), InputOutput
, getVisual(),
163 geom_visible
= False
;
165 BTexture
* texture
= &(resource
.wstyle
.l_focus
);
166 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
167 if (geom_pixmap
== ParentRelative
) {
168 texture
= &(resource
.wstyle
.t_focus
);
169 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
172 XSetWindowBackground(blackbox
->getXDisplay(), geom_window
,
173 texture
->color().pixel());
175 XSetWindowBackgroundPixmap(blackbox
->getXDisplay(),
176 geom_window
, geom_pixmap
);
178 if (resource
.workspaces
> 0) {
179 for (unsigned int i
= 0; i
< resource
.workspaces
; ++i
) {
180 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
181 workspacesList
.push_back(wkspc
);
185 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
186 workspacesList
.push_back(wkspc
);
188 saveWorkspaceNames();
190 updateNetizenWorkspaceCount();
192 current_workspace
= workspacesList
.front();
194 xatom
->setValue(getRootWindow(), XAtom::net_current_desktop
,
195 XAtom::cardinal
, 0); //first workspace
197 raiseWindows(0, 0); // this also initializes the empty stacking list
199 updateClientList(); // initialize the client lists, which will be empty
200 updateAvailableArea();
202 changeWorkspaceID(0);
204 unsigned int i
, j
, nchild
;
205 Window r
, p
, *children
;
206 XQueryTree(blackbox
->getXDisplay(), getRootWindow(), &r
, &p
,
209 // preen the window list of all icon windows... for better dockapp support
210 for (i
= 0; i
< nchild
; i
++) {
211 if (children
[i
] == None
) continue;
213 XWMHints
*wmhints
= XGetWMHints(blackbox
->getXDisplay(),
217 if ((wmhints
->flags
& IconWindowHint
) &&
218 (wmhints
->icon_window
!= children
[i
])) {
219 for (j
= 0; j
< nchild
; j
++) {
220 if (children
[j
] == wmhints
->icon_window
) {
231 // manage shown windows
232 for (i
= 0; i
< nchild
; ++i
) {
233 if (children
[i
] == None
|| ! blackbox
->validateWindow(children
[i
]))
236 XWindowAttributes attrib
;
237 if (XGetWindowAttributes(blackbox
->getXDisplay(), children
[i
], &attrib
)) {
238 if (attrib
.override_redirect
) continue;
240 if (attrib
.map_state
!= IsUnmapped
) {
241 manageWindow(children
[i
]);
248 // call this again just in case a window we found updates the Strut list
249 updateAvailableArea();
253 BScreen::~BScreen(void) {
254 if (! managed
) return;
256 if (geom_pixmap
!= None
)
257 image_control
->removeImage(geom_pixmap
);
259 if (geom_window
!= None
)
260 XDestroyWindow(blackbox
->getXDisplay(), geom_window
);
262 std::for_each(workspacesList
.begin(), workspacesList
.end(),
265 std::for_each(iconList
.begin(), iconList
.end(), PointerAssassin());
267 while (! systrayWindowList
.empty())
268 removeSystrayWindow(systrayWindowList
[0]);
270 delete image_control
;
272 if (resource
.wstyle
.font
)
273 delete resource
.wstyle
.font
;
275 if (resource
.wstyle
.close_button
.mask
!= None
)
276 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.close_button
.mask
);
277 if (resource
.wstyle
.max_button
.mask
!= None
)
278 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.max_button
.mask
);
279 if (resource
.wstyle
.icon_button
.mask
!= None
)
280 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.icon_button
.mask
);
281 if (resource
.wstyle
.stick_button
.mask
!= None
)
282 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.stick_button
.mask
);
284 resource
.wstyle
.max_button
.mask
= resource
.wstyle
.close_button
.mask
=
285 resource
.wstyle
.icon_button
.mask
=
286 resource
.wstyle
.stick_button
.mask
= None
;
288 XFreeGC(blackbox
->getXDisplay(), opGC
);
292 void BScreen::saveSloppyFocus(bool s
) {
293 resource
.sloppy_focus
= s
;
296 if (resource
.sloppy_focus
) {
297 fmodel
= "SloppyFocus";
298 if (resource
.auto_raise
) fmodel
+= " AutoRaise";
299 if (resource
.click_raise
) fmodel
+= " ClickRaise";
301 fmodel
= "ClickToFocus";
303 config
->setValue(screenstr
+ "focusModel", fmodel
);
307 void BScreen::saveAutoRaise(bool a
) {
308 resource
.auto_raise
= a
;
309 saveSloppyFocus(resource
.sloppy_focus
);
313 void BScreen::saveClickRaise(bool c
) {
314 resource
.click_raise
= c
;
315 saveSloppyFocus(resource
.sloppy_focus
);
319 void BScreen::saveImageDither(bool d
) {
320 image_control
->setDither(d
);
321 config
->setValue(screenstr
+ "imageDither", doImageDither());
325 void BScreen::saveOpaqueMove(bool o
) {
326 resource
.opaque_move
= o
;
327 config
->setValue(screenstr
+ "opaqueMove", resource
.opaque_move
);
331 void BScreen::saveFullMax(bool f
) {
332 resource
.full_max
= f
;
333 config
->setValue(screenstr
+ "fullMaximization", resource
.full_max
);
337 void BScreen::saveFocusNew(bool f
) {
338 resource
.focus_new
= f
;
339 config
->setValue(screenstr
+ "focusNewWindows", resource
.focus_new
);
343 void BScreen::saveFocusLast(bool f
) {
344 resource
.focus_last
= f
;
345 config
->setValue(screenstr
+ "focusLastWindow", resource
.focus_last
);
349 void BScreen::saveAAFonts(bool f
) {
350 resource
.aa_fonts
= f
;
351 config
->setValue(screenstr
+ "antialiasFonts", resource
.aa_fonts
);
356 void BScreen::saveShadowFonts(bool f
) {
357 resource
.shadow_fonts
= f
;
358 config
->setValue(screenstr
+ "dropShadowFonts", resource
.shadow_fonts
);
363 void BScreen::saveWindowToEdgeSnap(int s
) {
364 resource
.snap_to_edges
= s
;
367 switch (resource
.snap_to_edges
) {
368 case WindowNoSnap
: snap
= "NoSnap"; break;
369 case WindowResistance
: snap
= "Resistance"; break;
370 case WindowSnap
: default: snap
= "Snap"; break;
372 config
->setValue(screenstr
+ "windowToEdgeSnap", snap
);
376 void BScreen::saveWindowToWindowSnap(int s
) {
377 resource
.snap_to_windows
= s
;
380 switch (resource
.snap_to_windows
) {
381 case WindowNoSnap
: snap
= "NoSnap"; break;
382 case WindowResistance
: snap
= "Resistance"; break;
383 case WindowSnap
: default: snap
= "Snap"; break;
385 config
->setValue(screenstr
+ "windowToWindowSnap", snap
);
389 void BScreen::saveResizeZones(unsigned int z
) {
390 resource
.resize_zones
= z
;
391 config
->setValue(screenstr
+ "resizeZones", resource
.resize_zones
);
395 void BScreen::saveWindowCornerSnap(bool s
) {
396 resource
.window_corner_snap
= s
;
397 config
->setValue(screenstr
+ "windowCornerSnap",
398 resource
.window_corner_snap
);
402 void BScreen::saveWorkspaces(unsigned int w
) {
403 resource
.workspaces
= w
;
404 config
->setValue(screenstr
+ "workspaces", resource
.workspaces
);
408 void BScreen::savePlacementPolicy(int p
) {
409 resource
.placement_policy
= p
;
410 const char *placement
;
411 switch (resource
.placement_policy
) {
412 case CascadePlacement
: placement
= "CascadePlacement"; break;
413 case UnderMousePlacement
: placement
= "UnderMousePlacement"; break;
414 case ClickMousePlacement
: placement
= "ClickMousePlacement"; break;
415 case ColSmartPlacement
: placement
= "ColSmartPlacement"; break;
416 case RowSmartPlacement
: default: placement
= "RowSmartPlacement"; break;
418 config
->setValue(screenstr
+ "windowPlacement", placement
);
422 void BScreen::saveResistanceSize(int s
) {
423 resource
.resistance_size
= s
;
424 config
->setValue(screenstr
+ "resistanceSize",
425 resource
.resistance_size
);
429 void BScreen::saveSnapThreshold(int t
) {
430 resource
.snap_threshold
= t
;
431 config
->setValue(screenstr
+ "edgeSnapThreshold",
432 resource
.snap_threshold
);
436 void BScreen::saveSnapOffset(int t
) {
437 resource
.snap_offset
= t
;
438 config
->setValue(screenstr
+ "edgeSnapOffset",
439 resource
.snap_offset
);
443 void BScreen::saveRowPlacementDirection(int d
) {
444 resource
.row_direction
= d
;
445 config
->setValue(screenstr
+ "rowPlacementDirection",
446 resource
.row_direction
== LeftRight
?
447 "LeftToRight" : "RightToLeft");
451 void BScreen::saveColPlacementDirection(int d
) {
452 resource
.col_direction
= d
;
453 config
->setValue(screenstr
+ "colPlacementDirection",
454 resource
.col_direction
== TopBottom
?
455 "TopToBottom" : "BottomToTop");
459 void BScreen::saveStrftimeFormat(const std::string
& format
) {
460 resource
.strftime_format
= format
;
461 config
->setValue(screenstr
+ "strftimeFormat", resource
.strftime_format
);
465 void BScreen::saveWorkspaceNames() {
468 for (unsigned int i
= 0; i
< workspacesList
.size(); ++i
) {
469 names
+= workspacesList
[i
]->getName();
470 if (i
< workspacesList
.size() - 1)
474 config
->setValue(screenstr
+ "workspaceNames", names
);
478 void BScreen::savePlaceIgnoreShaded(bool i
) {
479 resource
.ignore_shaded
= i
;
480 config
->setValue(screenstr
+ "placementIgnoreShaded",
481 resource
.ignore_shaded
);
485 void BScreen::savePlaceIgnoreMaximized(bool i
) {
486 resource
.ignore_maximized
= i
;
487 config
->setValue(screenstr
+ "placementIgnoreMaximized",
488 resource
.ignore_maximized
);
492 void BScreen::saveAllowScrollLock(bool a
) {
493 resource
.allow_scroll_lock
= a
;
494 config
->setValue(screenstr
+ "disableBindingsWithScrollLock",
495 resource
.allow_scroll_lock
);
499 void BScreen::saveWorkspaceWarping(bool w
) {
500 resource
.workspace_warping
= w
;
501 config
->setValue(screenstr
+ "workspaceWarping",
502 resource
.workspace_warping
);
506 void BScreen::saveRootScrollDirection(int d
) {
507 resource
.root_scroll
= d
;
509 switch (resource
.root_scroll
) {
510 case NoScroll
: dir
= "None"; break;
511 case ReverseScroll
: dir
= "Reverse"; break;
512 case NormalScroll
: default: dir
= "Normal"; break;
514 config
->setValue(screenstr
+ "rootScrollDirection", dir
);
518 void BScreen::save_rc(void) {
519 saveSloppyFocus(resource
.sloppy_focus
);
520 saveAutoRaise(resource
.auto_raise
);
521 saveImageDither(doImageDither());
522 saveShadowFonts(resource
.shadow_fonts
);
523 saveAAFonts(resource
.aa_fonts
);
524 saveResizeZones(resource
.resize_zones
);
525 saveOpaqueMove(resource
.opaque_move
);
526 saveFullMax(resource
.full_max
);
527 saveFocusNew(resource
.focus_new
);
528 saveFocusLast(resource
.focus_last
);
529 saveWindowToWindowSnap(resource
.snap_to_windows
);
530 saveWindowToEdgeSnap(resource
.snap_to_edges
);
531 saveWindowCornerSnap(resource
.window_corner_snap
);
532 saveWorkspaces(resource
.workspaces
);
533 savePlacementPolicy(resource
.placement_policy
);
534 saveSnapThreshold(resource
.snap_threshold
);
535 saveSnapOffset(resource
.snap_offset
);
536 saveResistanceSize(resource
.resistance_size
);
537 saveRowPlacementDirection(resource
.row_direction
);
538 saveColPlacementDirection(resource
.col_direction
);
539 saveStrftimeFormat(resource
.strftime_format
);
540 savePlaceIgnoreShaded(resource
.ignore_shaded
);
541 savePlaceIgnoreMaximized(resource
.ignore_maximized
);
542 saveAllowScrollLock(resource
.allow_scroll_lock
);
543 saveWorkspaceWarping(resource
.workspace_warping
);
544 saveRootScrollDirection(resource
.root_scroll
);
548 void BScreen::load_rc(void) {
552 if (! config
->getValue(screenstr
+ "fullMaximization", resource
.full_max
))
553 resource
.full_max
= false;
555 if (! config
->getValue(screenstr
+ "focusNewWindows", resource
.focus_new
))
556 resource
.focus_new
= false;
558 if (! config
->getValue(screenstr
+ "focusLastWindow", resource
.focus_last
))
559 resource
.focus_last
= false;
561 if (! config
->getValue(screenstr
+ "workspaces", resource
.workspaces
))
562 resource
.workspaces
= 1;
564 if (! config
->getValue(screenstr
+ "opaqueMove", resource
.opaque_move
))
565 resource
.opaque_move
= false;
567 if (! config
->getValue(screenstr
+ "antialiasFonts", resource
.aa_fonts
))
568 resource
.aa_fonts
= true;
570 if (! resource
.aa_fonts
||
571 ! config
->getValue(screenstr
+ "dropShadowFonts", resource
.shadow_fonts
))
572 resource
.shadow_fonts
= false;
574 if (! config
->getValue(screenstr
+ "resizeZones", resource
.resize_zones
) ||
575 (resource
.resize_zones
!= 1 && resource
.resize_zones
!= 2 &&
576 resource
.resize_zones
!= 4))
577 resource
.resize_zones
= 4;
579 resource
.snap_to_windows
= WindowResistance
;
580 if (config
->getValue(screenstr
+ "windowToWindowSnap", s
)) {
582 resource
.snap_to_windows
= WindowNoSnap
;
583 else if (s
== "Snap")
584 resource
.snap_to_windows
= WindowSnap
;
587 resource
.snap_to_edges
= WindowResistance
;
588 if (config
->getValue(screenstr
+ "windowToEdgeSnap", s
)) {
590 resource
.snap_to_edges
= WindowNoSnap
;
591 else if (s
== "Snap")
592 resource
.snap_to_edges
= WindowSnap
;
595 if (! config
->getValue(screenstr
+ "windowCornerSnap",
596 resource
.window_corner_snap
))
597 resource
.window_corner_snap
= true;
599 if (! config
->getValue(screenstr
+ "imageDither", b
))
601 image_control
->setDither(b
);
603 if (! config
->getValue(screenstr
+ "edgeSnapOffset",
604 resource
.snap_offset
))
605 resource
.snap_offset
= 0;
606 if (resource
.snap_offset
> 50) // sanity check, setting this huge would
607 resource
.snap_offset
= 50; // seriously suck.
609 if (! config
->getValue(screenstr
+ "edgeSnapThreshold",
610 resource
.snap_threshold
))
611 resource
.snap_threshold
= 4;
613 if (! config
->getValue(screenstr
+ "resistanceSize",
614 resource
.resistance_size
))
615 resource
.resistance_size
= 18;
617 if (config
->getValue(screenstr
+ "rowPlacementDirection", s
) &&
619 resource
.row_direction
= RightLeft
;
621 resource
.row_direction
= LeftRight
;
623 if (config
->getValue(screenstr
+ "colPlacementDirection", s
) &&
625 resource
.col_direction
= BottomTop
;
627 resource
.col_direction
= TopBottom
;
629 if (config
->getValue(screenstr
+ "workspaceNames", s
)) {
630 XAtom::StringVect workspaceNames
;
632 string::const_iterator it
= s
.begin(), end
= s
.end();
634 string::const_iterator tmp
= it
; // current string.begin()
635 it
= std::find(tmp
, end
, ','); // look for comma between tmp and end
636 workspaceNames
.push_back(string(tmp
, it
)); // s[tmp:it]
642 xatom
->setValue(getRootWindow(), XAtom::net_desktop_names
, XAtom::utf8
,
646 resource
.sloppy_focus
= true;
647 resource
.auto_raise
= false;
648 resource
.click_raise
= false;
649 if (config
->getValue(screenstr
+ "focusModel", s
)) {
650 if (s
.find("ClickToFocus") != string::npos
) {
651 resource
.sloppy_focus
= false;
654 if (s
.find("AutoRaise") != string::npos
)
655 resource
.auto_raise
= true;
656 if (s
.find("ClickRaise") != string::npos
)
657 resource
.click_raise
= true;
661 if (config
->getValue(screenstr
+ "windowPlacement", s
)) {
662 if (s
== "CascadePlacement")
663 resource
.placement_policy
= CascadePlacement
;
664 else if (s
== "UnderMousePlacement")
665 resource
.placement_policy
= UnderMousePlacement
;
666 else if (s
== "ClickMousePlacement")
667 resource
.placement_policy
= ClickMousePlacement
;
668 else if (s
== "ColSmartPlacement")
669 resource
.placement_policy
= ColSmartPlacement
;
670 else //if (s == "RowSmartPlacement")
671 resource
.placement_policy
= RowSmartPlacement
;
673 resource
.placement_policy
= RowSmartPlacement
;
675 if (! config
->getValue(screenstr
+ "strftimeFormat",
676 resource
.strftime_format
))
677 resource
.strftime_format
= "%I:%M %p";
679 if (! config
->getValue(screenstr
+ "placementIgnoreShaded",
680 resource
.ignore_shaded
))
681 resource
.ignore_shaded
= true;
683 if (! config
->getValue(screenstr
+ "placementIgnoreMaximized",
684 resource
.ignore_maximized
))
685 resource
.ignore_maximized
= true;
687 if (! config
->getValue(screenstr
+ "disableBindingsWithScrollLock",
688 resource
.allow_scroll_lock
))
689 resource
.allow_scroll_lock
= false;
691 if (! config
->getValue(screenstr
+ "workspaceWarping",
692 resource
.workspace_warping
))
693 resource
.workspace_warping
= false;
695 resource
.root_scroll
= NormalScroll
;
696 if (config
->getValue(screenstr
+ "rootScrollDirection", s
)) {
698 resource
.root_scroll
= NoScroll
;
699 else if (s
== "Reverse")
700 resource
.root_scroll
= ReverseScroll
;
705 void BScreen::changeWorkspaceCount(unsigned int new_count
) {
706 assert(new_count
> 0);
708 if (new_count
< workspacesList
.size()) {
710 for (unsigned int i
= workspacesList
.size(); i
> new_count
; --i
)
711 removeLastWorkspace();
712 // removeLast already sets the current workspace to the
713 // last available one.
714 } else if (new_count
> workspacesList
.size()) {
716 for(unsigned int i
= workspacesList
.size(); i
< new_count
; ++i
)
722 void BScreen::reconfigure(void) {
723 // don't reconfigure while saving the initial rc file, it's a waste and it
724 // breaks somethings (workspace names)
725 if (blackbox
->isStartup()) return;
730 // we need to do this explicitly, because just loading this value from the rc
732 changeWorkspaceCount(resource
.workspaces
);
735 gcv
.foreground
= WhitePixel(blackbox
->getXDisplay(),
737 gcv
.function
= GXinvert
;
738 gcv
.subwindow_mode
= IncludeInferiors
;
739 XChangeGC(blackbox
->getXDisplay(), opGC
,
740 GCForeground
| GCFunction
| GCSubwindowMode
, &gcv
);
742 const char *s
= "0: 0000 x 0: 0000";
744 geom_w
= resource
.wstyle
.font
->measureString(s
) + resource
.bevel_width
* 2;
745 geom_h
= resource
.wstyle
.font
->height() + resource
.bevel_width
* 2;
747 BTexture
* texture
= &(resource
.wstyle
.l_focus
);
748 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
749 if (geom_pixmap
== ParentRelative
) {
750 texture
= &(resource
.wstyle
.t_focus
);
751 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
754 XSetWindowBackground(blackbox
->getXDisplay(), geom_window
,
755 texture
->color().pixel());
757 XSetWindowBackgroundPixmap(blackbox
->getXDisplay(),
758 geom_window
, geom_pixmap
);
760 XSetWindowBorderWidth(blackbox
->getXDisplay(), geom_window
,
761 resource
.border_width
);
762 XSetWindowBorder(blackbox
->getXDisplay(), geom_window
,
763 resource
.border_color
.pixel());
765 typedef std::vector
<int> SubList
;
766 SubList remember_subs
;
770 std::for_each(workspacesList
.begin(), workspacesList
.end(),
771 std::mem_fun(&Workspace::reconfigure
));
773 BlackboxWindowList::iterator iit
= iconList
.begin();
774 for (; iit
!= iconList
.end(); ++iit
) {
775 BlackboxWindow
*bw
= *iit
;
776 if (bw
->validateClient())
780 image_control
->timeout();
784 void BScreen::LoadStyle(void) {
785 Configuration
style(False
);
787 const char *sfile
= blackbox
->getStyleFilename();
789 style
.setFile(sfile
);
790 if (! style
.load()) {
791 style
.setFile(DEFAULTSTYLE
);
793 style
.create(); // hardcoded default values will be used.
797 // merge in the rc file
798 style
.merge(config
->file(), True
);
802 // load fonts/fontsets
803 if (resource
.wstyle
.font
)
804 delete resource
.wstyle
.font
;
806 resource
.wstyle
.font
= readDatabaseFont("window.", style
);
808 // load window config
809 resource
.wstyle
.t_focus
=
810 readDatabaseTexture("window.title.focus", "white", style
);
811 resource
.wstyle
.t_unfocus
=
812 readDatabaseTexture("window.title.unfocus", "black", style
);
813 resource
.wstyle
.l_focus
=
814 readDatabaseTexture("window.label.focus", "white", style
);
815 resource
.wstyle
.l_unfocus
=
816 readDatabaseTexture("window.label.unfocus", "black", style
);
817 resource
.wstyle
.h_focus
=
818 readDatabaseTexture("window.handle.focus", "white", style
);
819 resource
.wstyle
.h_unfocus
=
820 readDatabaseTexture("window.handle.unfocus", "black", style
);
821 resource
.wstyle
.g_focus
=
822 readDatabaseTexture("window.grip.focus", "white", style
);
823 resource
.wstyle
.g_unfocus
=
824 readDatabaseTexture("window.grip.unfocus", "black", style
);
825 resource
.wstyle
.b_focus
=
826 readDatabaseTexture("window.button.focus", "white", style
);
827 resource
.wstyle
.b_unfocus
=
828 readDatabaseTexture("window.button.unfocus", "black", style
);
829 resource
.wstyle
.b_pressed
=
830 readDatabaseTexture("window.button.pressed", "black", style
);
832 //if neither of these can be found, we will use the previous resource
833 resource
.wstyle
.b_pressed_focus
=
834 readDatabaseTexture("window.button.pressed.focus", "black", style
, true);
835 resource
.wstyle
.b_pressed_unfocus
=
836 readDatabaseTexture("window.button.pressed.unfocus", "black", style
, true);
838 if (resource
.wstyle
.close_button
.mask
!= None
)
839 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.close_button
.mask
);
840 if (resource
.wstyle
.max_button
.mask
!= None
)
841 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.max_button
.mask
);
842 if (resource
.wstyle
.icon_button
.mask
!= None
)
843 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.icon_button
.mask
);
844 if (resource
.wstyle
.stick_button
.mask
!= None
)
845 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.stick_button
.mask
);
847 resource
.wstyle
.close_button
.mask
= resource
.wstyle
.max_button
.mask
=
848 resource
.wstyle
.icon_button
.mask
=
849 resource
.wstyle
.icon_button
.mask
= None
;
851 readDatabaseMask("window.button.close.mask", resource
.wstyle
.close_button
,
853 readDatabaseMask("window.button.max.mask", resource
.wstyle
.max_button
,
855 readDatabaseMask("window.button.icon.mask", resource
.wstyle
.icon_button
,
857 readDatabaseMask("window.button.stick.mask", resource
.wstyle
.stick_button
,
860 // we create the window.frame texture by hand because it exists only to
861 // make the code cleaner and is not actually used for display
862 BColor color
= readDatabaseColor("window.frame.focusColor", "white", style
);
863 resource
.wstyle
.f_focus
= BTexture("solid flat", getBaseDisplay(),
864 getScreenNumber(), image_control
);
865 resource
.wstyle
.f_focus
.setColor(color
);
867 color
= readDatabaseColor("window.frame.unfocusColor", "white", style
);
868 resource
.wstyle
.f_unfocus
= BTexture("solid flat", getBaseDisplay(),
869 getScreenNumber(), image_control
);
870 resource
.wstyle
.f_unfocus
.setColor(color
);
872 resource
.wstyle
.l_text_focus
=
873 readDatabaseColor("window.label.focus.textColor", "black", style
);
874 resource
.wstyle
.l_text_unfocus
=
875 readDatabaseColor("window.label.unfocus.textColor", "white", style
);
876 resource
.wstyle
.b_pic_focus
=
877 readDatabaseColor("window.button.focus.picColor", "black", style
);
878 resource
.wstyle
.b_pic_unfocus
=
879 readDatabaseColor("window.button.unfocus.picColor", "white", style
);
881 resource
.wstyle
.justify
= LeftJustify
;
882 if (style
.getValue("window.justify", s
)) {
883 if (s
== "right" || s
== "Right")
884 resource
.wstyle
.justify
= RightJustify
;
885 else if (s
== "center" || s
== "Center")
886 resource
.wstyle
.justify
= CenterJustify
;
890 if (resource
.wstyle
.t_focus
.texture() == BTexture::Parent_Relative
)
891 resource
.wstyle
.t_focus
= resource
.wstyle
.f_focus
;
892 if (resource
.wstyle
.t_unfocus
.texture() == BTexture::Parent_Relative
)
893 resource
.wstyle
.t_unfocus
= resource
.wstyle
.f_unfocus
;
894 if (resource
.wstyle
.h_focus
.texture() == BTexture::Parent_Relative
)
895 resource
.wstyle
.h_focus
= resource
.wstyle
.f_focus
;
896 if (resource
.wstyle
.h_unfocus
.texture() == BTexture::Parent_Relative
)
897 resource
.wstyle
.h_unfocus
= resource
.wstyle
.f_unfocus
;
899 resource
.border_color
=
900 readDatabaseColor("borderColor", "black", style
);
902 // load bevel, border and handle widths
903 if (! style
.getValue("handleWidth", resource
.handle_width
) ||
904 resource
.handle_width
> (getWidth() / 2) || resource
.handle_width
== 0)
905 resource
.handle_width
= 6;
907 if (! style
.getValue("borderWidth", resource
.border_width
))
908 resource
.border_width
= 1;
910 if (! style
.getValue("bevelWidth", resource
.bevel_width
) ||
911 resource
.bevel_width
> (getWidth() / 2) || resource
.bevel_width
== 0)
912 resource
.bevel_width
= 3;
914 if (! style
.getValue("frameWidth", resource
.frame_width
) ||
915 resource
.frame_width
> (getWidth() / 2))
916 resource
.frame_width
= resource
.bevel_width
;
918 if (style
.getValue("rootCommand", s
))
919 bexec(s
, displayString());
923 void BScreen::addIcon(BlackboxWindow
*w
) {
926 w
->setWorkspace(BSENTINEL
);
927 w
->setWindowNumber(iconList
.size());
929 iconList
.push_back(w
);
933 void BScreen::removeIcon(BlackboxWindow
*w
) {
938 BlackboxWindowList::iterator it
= iconList
.begin(),
939 end
= iconList
.end();
940 for (int i
= 0; it
!= end
; ++it
)
941 (*it
)->setWindowNumber(i
++);
945 BlackboxWindow
*BScreen::getIcon(unsigned int index
) {
946 if (index
< iconList
.size()) {
947 BlackboxWindowList::iterator it
= iconList
.begin();
948 while (index
-- > 0) // increment to index
953 return (BlackboxWindow
*) 0;
957 unsigned int BScreen::addWorkspace(void) {
958 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
959 workspacesList
.push_back(wkspc
);
960 saveWorkspaces(getWorkspaceCount());
961 saveWorkspaceNames();
963 return workspacesList
.size();
967 unsigned int BScreen::removeLastWorkspace(void) {
968 if (workspacesList
.size() == 1)
971 Workspace
*wkspc
= workspacesList
.back();
973 if (current_workspace
->getID() == wkspc
->getID())
974 changeWorkspaceID(current_workspace
->getID() - 1);
978 workspacesList
.pop_back();
981 saveWorkspaces(getWorkspaceCount());
982 saveWorkspaceNames();
984 updateNetizenWorkspaceCount();
986 return workspacesList
.size();
990 void BScreen::changeWorkspaceID(unsigned int id
) {
991 if (! current_workspace
|| id
== current_workspace
->getID()) return;
993 BlackboxWindow
*focused
= blackbox
->getFocusedWindow();
994 if (focused
&& focused
->getScreen() == this) {
995 assert(focused
->isStuck() ||
996 focused
->getWorkspaceNumber() == current_workspace
->getID());
998 current_workspace
->setLastFocusedWindow(focused
);
1000 // if no window had focus, no need to store a last focus
1001 current_workspace
->setLastFocusedWindow((BlackboxWindow
*) 0);
1004 // when we switch workspaces, unfocus whatever was focused if it is going
1006 if (focused
&& ! focused
->isStuck())
1007 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1009 current_workspace
->hideAll();
1011 current_workspace
= getWorkspace(id
);
1013 xatom
->setValue(getRootWindow(), XAtom::net_current_desktop
,
1014 XAtom::cardinal
, id
);
1016 current_workspace
->showAll();
1021 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
1024 XSync(blackbox
->getXDisplay(), False
);
1026 // If sloppy focus and we can find the client window under the pointer,
1028 if (resource
.sloppy_focus
&&
1029 XQueryPointer(blackbox
->getXDisplay(), getRootWindow(), &r
, &c
,
1030 &rx
, &ry
, &x
, &y
, &m
) &&
1032 if ( (win
= blackbox
->searchWindow(c
)) )
1033 f
= win
->setInputFocus();
1036 // If that fails, and we're doing focus_last, try to focus the last window.
1037 if (! f
&& resource
.focus_last
&&
1038 (win
= current_workspace
->getLastFocusedWindow()))
1039 f
= win
->setInputFocus();
1042 if we found a focus target, then we set the focused window explicitly
1043 because it is possible to switch off this workspace before the x server
1044 generates the FocusIn event for the window. if that happens, openbox would
1045 lose track of what window was the 'LastFocused' window on the workspace.
1047 if we did not find a focus target, then set the current focused window to
1051 blackbox
->setFocusedWindow(win
);
1053 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1058 * Set the _NET_CLIENT_LIST root window property.
1060 void BScreen::updateClientList(void) {
1061 if (windowList
.size() > 0) {
1062 Window
*windows
= new Window
[windowList
.size()];
1063 Window
*win_it
= windows
;
1064 BlackboxWindowList::iterator it
= windowList
.begin();
1065 const BlackboxWindowList::iterator end
= windowList
.end();
1066 for (; it
!= end
; ++it
, ++win_it
)
1067 *win_it
= (*it
)->getClientWindow();
1068 xatom
->setValue(getRootWindow(), XAtom::net_client_list
, XAtom::window
,
1069 windows
, windowList
.size());
1072 xatom
->setValue(getRootWindow(), XAtom::net_client_list
, XAtom::window
,
1075 updateStackingList();
1080 * Set the _NET_CLIENT_LIST_STACKING root window property.
1082 void BScreen::updateStackingList(void) {
1084 BlackboxWindowList stack_order
;
1087 * Get the stacking order from all of the workspaces.
1088 * We start with the current workspace so that the sticky windows will be
1089 * in the right order on the current workspace.
1090 * XXX: Do we need to have sticky windows in the list once for each workspace?
1092 getCurrentWorkspace()->appendStackOrder(stack_order
);
1093 for (unsigned int i
= 0; i
< getWorkspaceCount(); ++i
)
1094 if (i
!= getCurrentWorkspaceID())
1095 getWorkspace(i
)->appendStackOrder(stack_order
);
1097 if (stack_order
.size() > 0) {
1098 // set the client list atoms
1099 Window
*windows
= new Window
[stack_order
.size()];
1100 Window
*win_it
= windows
;
1101 BlackboxWindowList::iterator it
= stack_order
.begin(),
1102 end
= stack_order
.end();
1103 for (; it
!= end
; ++it
, ++win_it
)
1104 *win_it
= (*it
)->getClientWindow();
1105 xatom
->setValue(getRootWindow(), XAtom::net_client_list_stacking
,
1106 XAtom::window
, windows
, stack_order
.size());
1109 xatom
->setValue(getRootWindow(), XAtom::net_client_list_stacking
,
1110 XAtom::window
, 0, 0);
1114 void BScreen::addSystrayWindow(Window window
) {
1115 XGrabServer(blackbox
->getXDisplay());
1117 XSelectInput(blackbox
->getXDisplay(), window
, StructureNotifyMask
);
1118 systrayWindowList
.push_back(window
);
1119 xatom
->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows
,
1121 &systrayWindowList
[0], systrayWindowList
.size());
1122 blackbox
->saveSystrayWindowSearch(window
, this);
1124 XUngrabServer(blackbox
->getXDisplay());
1128 void BScreen::removeSystrayWindow(Window window
) {
1129 XGrabServer(blackbox
->getXDisplay());
1131 WindowList::iterator it
= systrayWindowList
.begin();
1132 const WindowList::iterator end
= systrayWindowList
.end();
1133 for (; it
!= end
; ++it
)
1134 if (*it
== window
) {
1135 systrayWindowList
.erase(it
);
1136 xatom
->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows
,
1138 &systrayWindowList
[0], systrayWindowList
.size());
1139 blackbox
->removeSystrayWindowSearch(window
);
1140 XSelectInput(blackbox
->getXDisplay(), window
, NoEventMask
);
1144 assert(it
!= end
); // not a systray window
1146 XUngrabServer(blackbox
->getXDisplay());
1150 void BScreen::manageWindow(Window w
) {
1151 // is the window a KDE systray window?
1153 if (xatom
->getValue(w
, XAtom::kde_net_wm_system_tray_window_for
,
1154 XAtom::window
, systray
) && systray
!= None
) {
1155 addSystrayWindow(w
);
1159 // is the window a docking app
1160 XWMHints
*wmhint
= XGetWMHints(blackbox
->getXDisplay(), w
);
1161 if (wmhint
&& (wmhint
->flags
& StateHint
) &&
1162 wmhint
->initial_state
== WithdrawnState
) {
1163 //slit->addClient(w);
1167 new BlackboxWindow(blackbox
, w
, this);
1169 BlackboxWindow
*win
= blackbox
->searchWindow(w
);
1173 if (win
->isDesktop()) {
1174 desktopWindowList
.push_back(win
->getFrameWindow());
1175 } else { // if (win->isNormal()) {
1176 // don't list desktop windows as managed windows
1177 windowList
.push_back(win
);
1180 if (win
->isTopmost())
1181 specialWindowList
.push_back(win
->getFrameWindow());
1184 XMapRequestEvent mre
;
1186 if (blackbox
->isStartup() && win
->isNormal()) win
->restoreAttributes();
1187 win
->mapRequestEvent(&mre
);
1191 void BScreen::unmanageWindow(BlackboxWindow
*w
, bool remap
) {
1192 // is the window a KDE systray window?
1194 if (xatom
->getValue(w
->getClientWindow(),
1195 XAtom::kde_net_wm_system_tray_window_for
,
1196 XAtom::window
, systray
) && systray
!= None
) {
1197 removeSystrayWindow(w
->getClientWindow());
1203 // Remove the modality so that its parent won't try to re-focus the window
1204 if (w
->isModal()) w
->setModal(False
);
1206 if (w
->getWorkspaceNumber() != BSENTINEL
&&
1207 w
->getWindowNumber() != BSENTINEL
) {
1208 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1210 for (unsigned int i
= 0; i
< getNumberOfWorkspaces(); ++i
)
1211 if (i
!= w
->getWorkspaceNumber())
1212 getWorkspace(i
)->removeWindow(w
, True
);
1214 } else if (w
->isIconic())
1217 if (w
->isDesktop()) {
1218 WindowList::iterator it
= desktopWindowList
.begin();
1219 const WindowList::iterator end
= desktopWindowList
.end();
1220 for (; it
!= end
; ++it
)
1221 if (*it
== w
->getFrameWindow()) {
1222 desktopWindowList
.erase(it
);
1225 assert(it
!= end
); // the window wasnt a desktop window?
1226 } else { // if (w->isNormal()) {
1227 // we don't list desktop windows as managed windows
1228 windowList
.remove(w
);
1231 if (w
->isTopmost()) {
1232 WindowList::iterator it
= specialWindowList
.begin();
1233 const WindowList::iterator end
= specialWindowList
.end();
1234 for (; it
!= end
; ++it
)
1235 if (*it
== w
->getFrameWindow()) {
1236 specialWindowList
.erase(it
);
1239 assert(it
!= end
); // the window wasnt a special window?
1243 if (blackbox
->getFocusedWindow() == w
)
1244 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1247 some managed windows can also be window group controllers. when
1248 unmanaging such windows, we should also delete the window group.
1250 BWindowGroup
*group
= blackbox
->searchGroup(w
->getClientWindow());
1257 void BScreen::updateWorkArea(void) {
1258 if (workspacesList
.size() > 0) {
1259 unsigned long *dims
= new unsigned long[4 * workspacesList
.size()];
1260 for (unsigned int i
= 0, m
= workspacesList
.size(); i
< m
; ++i
) {
1261 // XXX: this could be different for each workspace
1262 const Rect
&area
= availableArea();
1263 dims
[(i
* 4) + 0] = area
.x();
1264 dims
[(i
* 4) + 1] = area
.y();
1265 dims
[(i
* 4) + 2] = area
.width();
1266 dims
[(i
* 4) + 3] = area
.height();
1268 xatom
->setValue(getRootWindow(), XAtom::net_workarea
, XAtom::cardinal
,
1269 dims
, 4 * workspacesList
.size());
1272 xatom
->setValue(getRootWindow(), XAtom::net_workarea
, XAtom::cardinal
,
1277 void BScreen::updateNetizenWorkspaceCount(void) {
1278 xatom
->setValue(getRootWindow(), XAtom::net_number_of_desktops
,
1279 XAtom::cardinal
, workspacesList
.size());
1285 void BScreen::updateNetizenWindowFocus(void) {
1286 Window f
= ((blackbox
->getFocusedWindow()) ?
1287 blackbox
->getFocusedWindow()->getClientWindow() : None
);
1289 xatom
->setValue(getRootWindow(), XAtom::net_active_window
,
1294 void BScreen::raiseWindows(Window
*workspace_stack
, unsigned int num
) {
1295 // the 13 represents the number of blackbox windows such as menus
1301 Window
*session_stack
= new
1302 Window
[(num
+ specialWindowList
.size() + bbwins
)];
1303 unsigned int i
= 0, k
= num
;
1305 WindowList::iterator sit
, send
= specialWindowList
.end();
1306 for (sit
= specialWindowList
.begin(); sit
!= send
; ++sit
)
1307 *(session_stack
+ i
++) = *sit
;
1310 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
1312 XRestackWindows(blackbox
->getXDisplay(), session_stack
, i
);
1314 delete [] session_stack
;
1316 updateStackingList();
1320 void BScreen::lowerWindows(Window
*workspace_stack
, unsigned int num
) {
1321 assert(num
> 0); // this would cause trouble in the XRaiseWindow call
1323 Window
*session_stack
= new Window
[(num
+ desktopWindowList
.size())];
1324 unsigned int i
= 0, k
= num
;
1326 XLowerWindow(blackbox
->getXDisplay(), workspace_stack
[0]);
1329 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
1331 WindowList::iterator dit
= desktopWindowList
.begin();
1332 const WindowList::iterator d_end
= desktopWindowList
.end();
1333 for (; dit
!= d_end
; ++dit
)
1334 *(session_stack
+ i
++) = *dit
;
1336 XRestackWindows(blackbox
->getXDisplay(), session_stack
, i
);
1338 delete [] session_stack
;
1340 updateStackingList();
1344 void BScreen::reassociateWindow(BlackboxWindow
*w
, unsigned int wkspc_id
,
1345 bool ignore_sticky
) {
1348 if (wkspc_id
== BSENTINEL
)
1349 wkspc_id
= current_workspace
->getID();
1351 if (w
->getWorkspaceNumber() == wkspc_id
)
1354 if (w
->isIconic()) {
1356 getWorkspace(wkspc_id
)->addWindow(w
);
1358 for (unsigned int i
= 0; i
< getNumberOfWorkspaces(); ++i
)
1359 if (i
!= w
->getWorkspaceNumber())
1360 getWorkspace(i
)->addWindow(w
, True
);
1361 } else if (ignore_sticky
|| ! w
->isStuck()) {
1364 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1365 getWorkspace(wkspc_id
)->addWindow(w
);
1367 updateStackingList();
1371 void BScreen::propagateWindowName(const BlackboxWindow
*bw
) {
1372 if (bw
->isIconic()) {
1378 void BScreen::nextFocus(void) const {
1379 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1383 focused
->getScreen()->getScreenNumber() == getScreenNumber() &&
1384 current_workspace
->getCount() > 1) {
1386 next
= current_workspace
->getNextWindowInList(next
);
1387 } while (next
!= focused
&& ! next
->setInputFocus());
1389 if (next
!= focused
)
1390 current_workspace
->raiseWindow(next
);
1391 } else if (current_workspace
->getCount() > 0) {
1392 next
= current_workspace
->getTopWindowOnStack();
1393 next
->setInputFocus();
1394 current_workspace
->raiseWindow(next
);
1399 void BScreen::prevFocus(void) const {
1400 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1404 // if window is not on this screen, ignore it
1405 if (focused
->getScreen()->getScreenNumber() != getScreenNumber())
1406 focused
= (BlackboxWindow
*) 0;
1410 focused
->getScreen()->getScreenNumber() == getScreenNumber() &&
1411 current_workspace
->getCount() > 1) {
1412 // next is the next window to receive focus, current is a place holder
1414 next
= current_workspace
->getPrevWindowInList(next
);
1415 } while (next
!= focused
&& ! next
->setInputFocus());
1417 if (next
!= focused
)
1418 current_workspace
->raiseWindow(next
);
1419 } else if (current_workspace
->getCount() > 0) {
1420 next
= current_workspace
->getTopWindowOnStack();
1421 next
->setInputFocus();
1422 current_workspace
->raiseWindow(next
);
1427 void BScreen::raiseFocus(void) const {
1428 BlackboxWindow
*focused
= blackbox
->getFocusedWindow();
1432 // if on this Screen, raise it
1433 if (focused
->getScreen()->getScreenNumber() == getScreenNumber()) {
1434 Workspace
*workspace
= getWorkspace(focused
->getWorkspaceNumber());
1435 workspace
->raiseWindow(focused
);
1440 void BScreen::shutdown(void) {
1441 XSelectInput(blackbox
->getXDisplay(), getRootWindow(), NoEventMask
);
1442 XSync(blackbox
->getXDisplay(), False
);
1444 while(! windowList
.empty())
1445 unmanageWindow(windowList
.front(), True
);
1447 while(! desktopWindowList
.empty()) {
1448 BlackboxWindow
*win
= blackbox
->searchWindow(desktopWindowList
.front());
1450 unmanageWindow(win
, True
);
1455 void BScreen::showPosition(int x
, int y
) {
1456 if (! geom_visible
) {
1457 XMoveResizeWindow(blackbox
->getXDisplay(), geom_window
,
1458 (getWidth() - geom_w
) / 2,
1459 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
1460 XMapWindow(blackbox
->getXDisplay(), geom_window
);
1461 XRaiseWindow(blackbox
->getXDisplay(), geom_window
);
1463 geom_visible
= True
;
1468 sprintf(label
, "X: %4d x Y: %4d", x
, y
);
1470 XClearWindow(blackbox
->getXDisplay(), geom_window
);
1472 resource
.wstyle
.font
->drawString(geom_window
,
1473 resource
.bevel_width
, resource
.bevel_width
,
1474 resource
.wstyle
.l_text_focus
,
1479 void BScreen::showGeometry(unsigned int gx
, unsigned int gy
) {
1480 if (! geom_visible
) {
1481 XMoveResizeWindow(blackbox
->getXDisplay(), geom_window
,
1482 (getWidth() - geom_w
) / 2,
1483 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
1484 XMapWindow(blackbox
->getXDisplay(), geom_window
);
1485 XRaiseWindow(blackbox
->getXDisplay(), geom_window
);
1487 geom_visible
= True
;
1492 sprintf(label
, "W: %4d x H: %4d", gx
, gy
);
1494 XClearWindow(blackbox
->getXDisplay(), geom_window
);
1496 resource
.wstyle
.font
->drawString(geom_window
,
1497 resource
.bevel_width
, resource
.bevel_width
,
1498 resource
.wstyle
.l_text_focus
,
1503 void BScreen::hideGeometry(void) {
1505 XUnmapWindow(blackbox
->getXDisplay(), geom_window
);
1506 geom_visible
= False
;
1511 void BScreen::addStrut(Strut
*strut
) {
1512 strutList
.push_back(strut
);
1516 void BScreen::removeStrut(Strut
*strut
) {
1517 strutList
.remove(strut
);
1521 const Rect
& BScreen::availableArea(void) const {
1523 return getRect(); // return the full screen
1529 const RectList
& BScreen::allAvailableAreas(void) const {
1530 assert(isXineramaActive());
1531 assert(xineramaUsableArea
.size() > 0);
1532 fprintf(stderr
, "1found x %d y %d w %d h %d\n",
1533 xineramaUsableArea
[0].x(), xineramaUsableArea
[0].y(),
1534 xineramaUsableArea
[0].width(), xineramaUsableArea
[0].height());
1535 return xineramaUsableArea
;
1540 void BScreen::updateAvailableArea(void) {
1541 Rect old_area
= usableArea
;
1542 usableArea
= getRect(); // reset to full screen
1545 // reset to the full areas
1546 if (isXineramaActive())
1547 xineramaUsableArea
= getXineramaAreas();
1550 /* these values represent offsets from the screen edge
1551 * we look for the biggest offset on each edge and then apply them
1553 * do not be confused by the similarity to the names of Rect's members
1555 unsigned int current_left
= 0, current_right
= 0, current_top
= 0,
1558 StrutList::const_iterator it
= strutList
.begin(), end
= strutList
.end();
1560 for(; it
!= end
; ++it
) {
1562 if (strut
->left
> current_left
)
1563 current_left
= strut
->left
;
1564 if (strut
->top
> current_top
)
1565 current_top
= strut
->top
;
1566 if (strut
->right
> current_right
)
1567 current_right
= strut
->right
;
1568 if (strut
->bottom
> current_bottom
)
1569 current_bottom
= strut
->bottom
;
1572 usableArea
.setPos(current_left
, current_top
);
1573 usableArea
.setSize(usableArea
.width() - (current_left
+ current_right
),
1574 usableArea
.height() - (current_top
+ current_bottom
));
1577 if (isXineramaActive()) {
1578 // keep each of the ximerama-defined areas inside the strut
1579 RectList::iterator xit
, xend
= xineramaUsableArea
.end();
1580 for (xit
= xineramaUsableArea
.begin(); xit
!= xend
; ++xit
) {
1581 if (xit
->x() < usableArea
.x()) {
1582 xit
->setX(usableArea
.x());
1583 xit
->setWidth(xit
->width() - usableArea
.x());
1585 if (xit
->y() < usableArea
.y()) {
1586 xit
->setY(usableArea
.y());
1587 xit
->setHeight(xit
->height() - usableArea
.y());
1589 if (xit
->x() + xit
->width() > usableArea
.width())
1590 xit
->setWidth(usableArea
.width() - xit
->x());
1591 if (xit
->y() + xit
->height() > usableArea
.height())
1592 xit
->setHeight(usableArea
.height() - xit
->y());
1597 if (old_area
!= usableArea
) {
1598 BlackboxWindowList::iterator it
= windowList
.begin(),
1599 end
= windowList
.end();
1600 for (; it
!= end
; ++it
)
1601 if ((*it
)->isMaximized()) (*it
)->remaximize();
1608 Workspace
* BScreen::getWorkspace(unsigned int index
) const {
1609 assert(index
< workspacesList
.size());
1610 return workspacesList
[index
];
1614 void BScreen::buttonPressEvent(const XButtonEvent
*xbutton
) {
1615 if (xbutton
->button
== 1) {
1616 if (! isRootColormapInstalled())
1617 image_control
->installRootColormap();
1620 } else if ((xbutton
->button
== 4 && resource
.root_scroll
== NormalScroll
) ||
1621 (xbutton
->button
== 5 && resource
.root_scroll
== ReverseScroll
)) {
1622 if (getCurrentWorkspaceID() >= getWorkspaceCount() - 1)
1623 changeWorkspaceID(0);
1625 changeWorkspaceID(getCurrentWorkspaceID() + 1);
1627 } else if ((xbutton
->button
== 5 && resource
.root_scroll
== NormalScroll
) ||
1628 (xbutton
->button
== 4 && resource
.root_scroll
== ReverseScroll
)) {
1629 if (getCurrentWorkspaceID() == 0)
1630 changeWorkspaceID(getWorkspaceCount() - 1);
1632 changeWorkspaceID(getCurrentWorkspaceID() - 1);
1637 void BScreen::propertyNotifyEvent(const XPropertyEvent
*pe
) {
1638 if (pe
->atom
== xatom
->getAtom(XAtom::net_desktop_names
)) {
1639 // _NET_WM_DESKTOP_NAMES
1640 WorkspaceList::iterator it
= workspacesList
.begin();
1641 const WorkspaceList::iterator end
= workspacesList
.end();
1642 for (; it
!= end
; ++it
) {
1643 (*it
)->readName(); // re-read its name from the window property
1644 //workspacemenu->changeWorkspaceLabel((*it)->getID(), (*it)->getName());
1646 //workspacemenu->update();
1647 saveWorkspaceNames();
1652 void BScreen::toggleFocusModel(FocusModel model
) {
1653 std::for_each(windowList
.begin(), windowList
.end(),
1654 std::mem_fun(&BlackboxWindow::ungrabButtons
));
1656 if (model
== SloppyFocus
) {
1657 saveSloppyFocus(True
);
1659 // we're cheating here to save writing the config file 3 times
1660 resource
.auto_raise
= False
;
1661 resource
.click_raise
= False
;
1662 saveSloppyFocus(False
);
1665 std::for_each(windowList
.begin(), windowList
.end(),
1666 std::mem_fun(&BlackboxWindow::grabButtons
));
1669 void BScreen::readDatabaseMask(const string
&rname
, PixmapMask
&pixmapMask
,
1670 const Configuration
&style
) {
1672 int hx
, hy
; //ignored
1673 int ret
= BitmapOpenFailed
; //default to failure.
1675 if (style
.getValue(rname
, s
))
1677 if (s
[0] != '/' && s
[0] != '~')
1679 std::string xbmFile
= std::string("~/.openbox/buttons/") + s
;
1680 ret
= XReadBitmapFile(blackbox
->getXDisplay(), getRootWindow(),
1681 expandTilde(xbmFile
).c_str(), &pixmapMask
.w
,
1682 &pixmapMask
.h
, &pixmapMask
.mask
, &hx
, &hy
);
1684 ret
= XReadBitmapFile(blackbox
->getXDisplay(), getRootWindow(),
1685 expandTilde(s
).c_str(), &pixmapMask
.w
,
1686 &pixmapMask
.h
, &pixmapMask
.mask
, &hx
, &hy
);
1688 if (ret
== BitmapSuccess
)
1692 pixmapMask
.mask
= None
;
1693 pixmapMask
.w
= pixmapMask
.h
= 0;
1696 BTexture
BScreen::readDatabaseTexture(const string
&rname
,
1697 const string
&default_color
,
1698 const Configuration
&style
,
1699 bool allowNoTexture
) {
1703 if (style
.getValue(rname
, s
))
1704 texture
= BTexture(s
);
1705 else if (allowNoTexture
) //no default
1706 texture
.setTexture(BTexture::NoTexture
);
1708 texture
.setTexture(BTexture::Solid
| BTexture::Flat
);
1710 // associate this texture with this screen
1711 texture
.setDisplay(getBaseDisplay(), getScreenNumber());
1712 texture
.setImageControl(image_control
);
1714 if (texture
.texture() != BTexture::NoTexture
) {
1715 texture
.setColor(readDatabaseColor(rname
+ ".color", default_color
,
1717 texture
.setColorTo(readDatabaseColor(rname
+ ".colorTo", default_color
,
1719 texture
.setBorderColor(readDatabaseColor(rname
+ ".borderColor",
1720 default_color
, style
));
1727 BColor
BScreen::readDatabaseColor(const string
&rname
,
1728 const string
&default_color
,
1729 const Configuration
&style
) {
1732 if (style
.getValue(rname
, s
))
1733 color
= BColor(s
, getBaseDisplay(), getScreenNumber());
1735 color
= BColor(default_color
, getBaseDisplay(), getScreenNumber());
1740 BFont
*BScreen::readDatabaseFont(const string
&rbasename
,
1741 const Configuration
&style
) {
1747 if (style
.getValue(rbasename
+ "xft.font", s
) &&
1748 style
.getValue(rbasename
+ "xft.size", i
)) {
1751 bool italic
= False
;
1752 bool dropShadow
= False
;
1754 if (style
.getValue(rbasename
+ "xft.flags", s
)) {
1755 if (s
.find("bold") != string::npos
)
1757 if (s
.find("italic") != string::npos
)
1759 if (s
.find("shadow") != string::npos
)
1763 unsigned char offset
= 1;
1764 if (style
.getValue(rbasename
+ "xft.shadow.offset", s
)) {
1765 offset
= atoi(s
.c_str()); //doesn't detect errors
1766 if (offset
> CHAR_MAX
)
1770 unsigned char tint
= 0x40;
1771 if (style
.getValue(rbasename
+ "xft.shadow.tint", s
)) {
1772 tint
= atoi(s
.c_str());
1776 BFont
*b
= new BFont(blackbox
->getXDisplay(), this, family
, i
, bold
,
1777 italic
, dropShadow
&& resource
.shadow_fonts
, offset
,
1778 tint
, resource
.aa_fonts
);
1784 exit(2); // can't continue without a font