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
58 #include "otk/font.hh"
59 #include "otk/gccache.hh"
60 #include "otk/image.hh"
61 #include "otk/assassin.hh"
65 #include "workspace.hh"
69 #ifndef FONT_ELEMENT_SIZE
70 #define FONT_ELEMENT_SIZE 50
71 #endif // FONT_ELEMENT_SIZE
75 static bool running
= True
;
77 static int anotherWMRunning(Display
*display
, XErrorEvent
*) {
79 "BScreen::BScreen: an error occured while querying the X server.\n"
80 " another window manager already running on display %s.\n",
81 DisplayString(display
));
89 BScreen::BScreen(Blackbox
*bb
, unsigned int scrn
) : ScreenInfo(scrn
) {
91 screenstr
= "session.screen" + itostring(scrn
) + '.';
92 config
= blackbox
->getConfig();
93 xatom
= blackbox
->getXAtom();
95 event_mask
= ColormapChangeMask
| EnterWindowMask
| PropertyChangeMask
|
96 SubstructureRedirectMask
| ButtonPressMask
| ButtonReleaseMask
;
98 XErrorHandler old
= XSetErrorHandler((XErrorHandler
) anotherWMRunning
);
99 XSelectInput(otk::OBDisplay::display
, getRootWindow(), event_mask
);
100 XSync(otk::OBDisplay::display
, False
);
101 XSetErrorHandler((XErrorHandler
) old
);
104 if (! managed
) return;
106 fprintf(stderr
, "BScreen::BScreen: managing screen %d "
107 "using visual 0x%lx, depth %d\n",
108 getScreenNumber(), XVisualIDFromVisual(getVisual()),
111 resource
.wstyle
.font
= (otk::BFont
*) 0;
115 xatom
->setSupported(this); // set-up netwm support
117 xatom
->setValue(getRootWindow(), XAtom::blackbox_pid
, XAtom::cardinal
,
118 (unsigned long) getpid());
119 #endif // HAVE_GETPID
120 unsigned long geometry
[] = { getWidth(),
122 xatom
->setValue(getRootWindow(), XAtom::net_desktop_geometry
,
123 XAtom::cardinal
, geometry
, 2);
124 unsigned long viewport
[] = {0,0};
125 xatom
->setValue(getRootWindow(), XAtom::net_desktop_viewport
,
126 XAtom::cardinal
, viewport
, 2);
129 XDefineCursor(otk::OBDisplay::display
, getRootWindow(),
130 blackbox
->getSessionCursor());
132 updateAvailableArea();
135 new otk::BImageControl(this, True
, blackbox
->getColorsPerChannel(),
136 blackbox
->getCacheLife(), blackbox
->getCacheMax());
137 image_control
->installRootColormap();
138 root_colormap_installed
= True
;
144 gcv
.foreground
= WhitePixel(otk::OBDisplay::display
, getScreenNumber())
145 ^ BlackPixel(otk::OBDisplay::display
, getScreenNumber());
146 gcv
.function
= GXxor
;
147 gcv
.subwindow_mode
= IncludeInferiors
;
148 opGC
= XCreateGC(otk::OBDisplay::display
, getRootWindow(),
149 GCForeground
| GCFunction
| GCSubwindowMode
, &gcv
);
151 const char *s
= "0: 0000 x 0: 0000";
152 geom_w
= resource
.wstyle
.font
->measureString(s
) + resource
.bevel_width
* 2;
153 geom_h
= resource
.wstyle
.font
->height() + resource
.bevel_width
* 2;
155 XSetWindowAttributes attrib
;
156 unsigned long mask
= CWBorderPixel
| CWColormap
| CWSaveUnder
;
157 attrib
.border_pixel
= getBorderColor()->pixel();
158 attrib
.colormap
= getColormap();
159 attrib
.save_under
= True
;
161 geom_window
= XCreateWindow(otk::OBDisplay::display
, getRootWindow(),
162 0, 0, geom_w
, geom_h
, resource
.border_width
,
163 getDepth(), InputOutput
, getVisual(),
165 geom_visible
= False
;
167 otk::BTexture
* texture
= &(resource
.wstyle
.l_focus
);
168 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
169 if (geom_pixmap
== ParentRelative
) {
170 texture
= &(resource
.wstyle
.t_focus
);
171 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
174 XSetWindowBackground(otk::OBDisplay::display
, geom_window
,
175 texture
->color().pixel());
177 XSetWindowBackgroundPixmap(otk::OBDisplay::display
,
178 geom_window
, geom_pixmap
);
180 if (resource
.workspaces
> 0) {
181 for (unsigned int i
= 0; i
< resource
.workspaces
; ++i
) {
182 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
183 workspacesList
.push_back(wkspc
);
187 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
188 workspacesList
.push_back(wkspc
);
190 saveWorkspaceNames();
192 updateNetizenWorkspaceCount();
194 current_workspace
= workspacesList
.front();
196 xatom
->setValue(getRootWindow(), XAtom::net_current_desktop
,
197 XAtom::cardinal
, 0); //first workspace
199 raiseWindows(0, 0); // this also initializes the empty stacking list
201 updateClientList(); // initialize the client lists, which will be empty
202 updateAvailableArea();
204 changeWorkspaceID(0);
206 unsigned int i
, j
, nchild
;
207 Window r
, p
, *children
;
208 XQueryTree(otk::OBDisplay::display
, getRootWindow(), &r
, &p
,
211 // preen the window list of all icon windows... for better dockapp support
212 for (i
= 0; i
< nchild
; i
++) {
213 if (children
[i
] == None
) continue;
215 XWMHints
*wmhints
= XGetWMHints(otk::OBDisplay::display
,
219 if ((wmhints
->flags
& IconWindowHint
) &&
220 (wmhints
->icon_window
!= children
[i
])) {
221 for (j
= 0; j
< nchild
; j
++) {
222 if (children
[j
] == wmhints
->icon_window
) {
233 // manage shown windows
234 for (i
= 0; i
< nchild
; ++i
) {
235 if (children
[i
] == None
|| ! blackbox
->validateWindow(children
[i
]))
238 XWindowAttributes attrib
;
239 if (XGetWindowAttributes(otk::OBDisplay::display
, children
[i
], &attrib
)) {
240 if (attrib
.override_redirect
) continue;
242 if (attrib
.map_state
!= IsUnmapped
) {
243 manageWindow(children
[i
]);
250 // call this again just in case a window we found updates the Strut list
251 updateAvailableArea();
255 BScreen::~BScreen(void) {
256 if (! managed
) return;
258 if (geom_pixmap
!= None
)
259 image_control
->removeImage(geom_pixmap
);
261 if (geom_window
!= None
)
262 XDestroyWindow(otk::OBDisplay::display
, geom_window
);
264 std::for_each(workspacesList
.begin(), workspacesList
.end(),
265 otk::PointerAssassin());
267 std::for_each(iconList
.begin(), iconList
.end(), otk::PointerAssassin());
269 while (! systrayWindowList
.empty())
270 removeSystrayWindow(systrayWindowList
[0]);
272 delete image_control
;
274 if (resource
.wstyle
.font
)
275 delete resource
.wstyle
.font
;
277 if (resource
.wstyle
.close_button
.mask
!= None
)
278 XFreePixmap(otk::OBDisplay::display
, resource
.wstyle
.close_button
.mask
);
279 if (resource
.wstyle
.max_button
.mask
!= None
)
280 XFreePixmap(otk::OBDisplay::display
, resource
.wstyle
.max_button
.mask
);
281 if (resource
.wstyle
.icon_button
.mask
!= None
)
282 XFreePixmap(otk::OBDisplay::display
, resource
.wstyle
.icon_button
.mask
);
283 if (resource
.wstyle
.stick_button
.mask
!= None
)
284 XFreePixmap(otk::OBDisplay::display
, resource
.wstyle
.stick_button
.mask
);
286 resource
.wstyle
.max_button
.mask
= resource
.wstyle
.close_button
.mask
=
287 resource
.wstyle
.icon_button
.mask
=
288 resource
.wstyle
.stick_button
.mask
= None
;
290 XFreeGC(otk::OBDisplay::display
, opGC
);
294 void BScreen::saveSloppyFocus(bool s
) {
295 resource
.sloppy_focus
= s
;
298 if (resource
.sloppy_focus
) {
299 fmodel
= "SloppyFocus";
300 if (resource
.auto_raise
) fmodel
+= " AutoRaise";
301 if (resource
.click_raise
) fmodel
+= " ClickRaise";
303 fmodel
= "ClickToFocus";
305 config
->setValue(screenstr
+ "focusModel", fmodel
);
309 void BScreen::saveAutoRaise(bool a
) {
310 resource
.auto_raise
= a
;
311 saveSloppyFocus(resource
.sloppy_focus
);
315 void BScreen::saveClickRaise(bool c
) {
316 resource
.click_raise
= c
;
317 saveSloppyFocus(resource
.sloppy_focus
);
321 void BScreen::saveImageDither(bool d
) {
322 image_control
->setDither(d
);
323 config
->setValue(screenstr
+ "imageDither", doImageDither());
327 void BScreen::saveOpaqueMove(bool o
) {
328 resource
.opaque_move
= o
;
329 config
->setValue(screenstr
+ "opaqueMove", resource
.opaque_move
);
333 void BScreen::saveFullMax(bool f
) {
334 resource
.full_max
= f
;
335 config
->setValue(screenstr
+ "fullMaximization", resource
.full_max
);
339 void BScreen::saveFocusNew(bool f
) {
340 resource
.focus_new
= f
;
341 config
->setValue(screenstr
+ "focusNewWindows", resource
.focus_new
);
345 void BScreen::saveFocusLast(bool f
) {
346 resource
.focus_last
= f
;
347 config
->setValue(screenstr
+ "focusLastWindow", resource
.focus_last
);
351 void BScreen::saveAAFonts(bool f
) {
352 resource
.aa_fonts
= f
;
353 config
->setValue(screenstr
+ "antialiasFonts", resource
.aa_fonts
);
358 void BScreen::saveShadowFonts(bool f
) {
359 resource
.shadow_fonts
= f
;
360 config
->setValue(screenstr
+ "dropShadowFonts", resource
.shadow_fonts
);
365 void BScreen::saveWindowToEdgeSnap(int s
) {
366 resource
.snap_to_edges
= s
;
369 switch (resource
.snap_to_edges
) {
370 case WindowNoSnap
: snap
= "NoSnap"; break;
371 case WindowResistance
: snap
= "Resistance"; break;
372 case WindowSnap
: default: snap
= "Snap"; break;
374 config
->setValue(screenstr
+ "windowToEdgeSnap", snap
);
378 void BScreen::saveWindowToWindowSnap(int s
) {
379 resource
.snap_to_windows
= s
;
382 switch (resource
.snap_to_windows
) {
383 case WindowNoSnap
: snap
= "NoSnap"; break;
384 case WindowResistance
: snap
= "Resistance"; break;
385 case WindowSnap
: default: snap
= "Snap"; break;
387 config
->setValue(screenstr
+ "windowToWindowSnap", snap
);
391 void BScreen::saveResizeZones(unsigned int z
) {
392 resource
.resize_zones
= z
;
393 config
->setValue(screenstr
+ "resizeZones", resource
.resize_zones
);
397 void BScreen::saveWindowCornerSnap(bool s
) {
398 resource
.window_corner_snap
= s
;
399 config
->setValue(screenstr
+ "windowCornerSnap",
400 resource
.window_corner_snap
);
404 void BScreen::saveWorkspaces(unsigned int w
) {
405 resource
.workspaces
= w
;
406 config
->setValue(screenstr
+ "workspaces", resource
.workspaces
);
410 void BScreen::savePlacementPolicy(int p
) {
411 resource
.placement_policy
= p
;
412 const char *placement
;
413 switch (resource
.placement_policy
) {
414 case CascadePlacement
: placement
= "CascadePlacement"; break;
415 case UnderMousePlacement
: placement
= "UnderMousePlacement"; break;
416 case ClickMousePlacement
: placement
= "ClickMousePlacement"; break;
417 case ColSmartPlacement
: placement
= "ColSmartPlacement"; break;
418 case RowSmartPlacement
: default: placement
= "RowSmartPlacement"; break;
420 config
->setValue(screenstr
+ "windowPlacement", placement
);
424 void BScreen::saveResistanceSize(int s
) {
425 resource
.resistance_size
= s
;
426 config
->setValue(screenstr
+ "resistanceSize",
427 resource
.resistance_size
);
431 void BScreen::saveSnapThreshold(int t
) {
432 resource
.snap_threshold
= t
;
433 config
->setValue(screenstr
+ "edgeSnapThreshold",
434 resource
.snap_threshold
);
438 void BScreen::saveSnapOffset(int t
) {
439 resource
.snap_offset
= t
;
440 config
->setValue(screenstr
+ "edgeSnapOffset",
441 resource
.snap_offset
);
445 void BScreen::saveRowPlacementDirection(int d
) {
446 resource
.row_direction
= d
;
447 config
->setValue(screenstr
+ "rowPlacementDirection",
448 resource
.row_direction
== LeftRight
?
449 "LeftToRight" : "RightToLeft");
453 void BScreen::saveColPlacementDirection(int d
) {
454 resource
.col_direction
= d
;
455 config
->setValue(screenstr
+ "colPlacementDirection",
456 resource
.col_direction
== TopBottom
?
457 "TopToBottom" : "BottomToTop");
461 void BScreen::saveStrftimeFormat(const std::string
& format
) {
462 resource
.strftime_format
= format
;
463 config
->setValue(screenstr
+ "strftimeFormat", resource
.strftime_format
);
467 void BScreen::saveWorkspaceNames() {
470 for (unsigned int i
= 0; i
< workspacesList
.size(); ++i
) {
471 names
+= workspacesList
[i
]->getName();
472 if (i
< workspacesList
.size() - 1)
476 config
->setValue(screenstr
+ "workspaceNames", names
);
480 void BScreen::savePlaceIgnoreShaded(bool i
) {
481 resource
.ignore_shaded
= i
;
482 config
->setValue(screenstr
+ "placementIgnoreShaded",
483 resource
.ignore_shaded
);
487 void BScreen::savePlaceIgnoreMaximized(bool i
) {
488 resource
.ignore_maximized
= i
;
489 config
->setValue(screenstr
+ "placementIgnoreMaximized",
490 resource
.ignore_maximized
);
494 void BScreen::saveAllowScrollLock(bool a
) {
495 resource
.allow_scroll_lock
= a
;
496 config
->setValue(screenstr
+ "disableBindingsWithScrollLock",
497 resource
.allow_scroll_lock
);
501 void BScreen::saveWorkspaceWarping(bool w
) {
502 resource
.workspace_warping
= w
;
503 config
->setValue(screenstr
+ "workspaceWarping",
504 resource
.workspace_warping
);
508 void BScreen::saveRootScrollDirection(int d
) {
509 resource
.root_scroll
= d
;
511 switch (resource
.root_scroll
) {
512 case NoScroll
: dir
= "None"; break;
513 case ReverseScroll
: dir
= "Reverse"; break;
514 case NormalScroll
: default: dir
= "Normal"; break;
516 config
->setValue(screenstr
+ "rootScrollDirection", dir
);
520 void BScreen::save_rc(void) {
521 saveSloppyFocus(resource
.sloppy_focus
);
522 saveAutoRaise(resource
.auto_raise
);
523 saveImageDither(doImageDither());
524 saveShadowFonts(resource
.shadow_fonts
);
525 saveAAFonts(resource
.aa_fonts
);
526 saveResizeZones(resource
.resize_zones
);
527 saveOpaqueMove(resource
.opaque_move
);
528 saveFullMax(resource
.full_max
);
529 saveFocusNew(resource
.focus_new
);
530 saveFocusLast(resource
.focus_last
);
531 saveWindowToWindowSnap(resource
.snap_to_windows
);
532 saveWindowToEdgeSnap(resource
.snap_to_edges
);
533 saveWindowCornerSnap(resource
.window_corner_snap
);
534 saveWorkspaces(resource
.workspaces
);
535 savePlacementPolicy(resource
.placement_policy
);
536 saveSnapThreshold(resource
.snap_threshold
);
537 saveSnapOffset(resource
.snap_offset
);
538 saveResistanceSize(resource
.resistance_size
);
539 saveRowPlacementDirection(resource
.row_direction
);
540 saveColPlacementDirection(resource
.col_direction
);
541 saveStrftimeFormat(resource
.strftime_format
);
542 savePlaceIgnoreShaded(resource
.ignore_shaded
);
543 savePlaceIgnoreMaximized(resource
.ignore_maximized
);
544 saveAllowScrollLock(resource
.allow_scroll_lock
);
545 saveWorkspaceWarping(resource
.workspace_warping
);
546 saveRootScrollDirection(resource
.root_scroll
);
550 void BScreen::load_rc(void) {
554 if (! config
->getValue(screenstr
+ "fullMaximization", resource
.full_max
))
555 resource
.full_max
= false;
557 if (! config
->getValue(screenstr
+ "focusNewWindows", resource
.focus_new
))
558 resource
.focus_new
= false;
560 if (! config
->getValue(screenstr
+ "focusLastWindow", resource
.focus_last
))
561 resource
.focus_last
= false;
563 if (! config
->getValue(screenstr
+ "workspaces", resource
.workspaces
))
564 resource
.workspaces
= 1;
566 if (! config
->getValue(screenstr
+ "opaqueMove", resource
.opaque_move
))
567 resource
.opaque_move
= false;
569 if (! config
->getValue(screenstr
+ "antialiasFonts", resource
.aa_fonts
))
570 resource
.aa_fonts
= true;
572 if (! resource
.aa_fonts
||
573 ! config
->getValue(screenstr
+ "dropShadowFonts", resource
.shadow_fonts
))
574 resource
.shadow_fonts
= false;
576 if (! config
->getValue(screenstr
+ "resizeZones", resource
.resize_zones
) ||
577 (resource
.resize_zones
!= 1 && resource
.resize_zones
!= 2 &&
578 resource
.resize_zones
!= 4))
579 resource
.resize_zones
= 4;
581 resource
.snap_to_windows
= WindowResistance
;
582 if (config
->getValue(screenstr
+ "windowToWindowSnap", s
)) {
584 resource
.snap_to_windows
= WindowNoSnap
;
585 else if (s
== "Snap")
586 resource
.snap_to_windows
= WindowSnap
;
589 resource
.snap_to_edges
= WindowResistance
;
590 if (config
->getValue(screenstr
+ "windowToEdgeSnap", s
)) {
592 resource
.snap_to_edges
= WindowNoSnap
;
593 else if (s
== "Snap")
594 resource
.snap_to_edges
= WindowSnap
;
597 if (! config
->getValue(screenstr
+ "windowCornerSnap",
598 resource
.window_corner_snap
))
599 resource
.window_corner_snap
= true;
601 if (! config
->getValue(screenstr
+ "imageDither", b
))
603 image_control
->setDither(b
);
605 if (! config
->getValue(screenstr
+ "edgeSnapOffset",
606 resource
.snap_offset
))
607 resource
.snap_offset
= 0;
608 if (resource
.snap_offset
> 50) // sanity check, setting this huge would
609 resource
.snap_offset
= 50; // seriously suck.
611 if (! config
->getValue(screenstr
+ "edgeSnapThreshold",
612 resource
.snap_threshold
))
613 resource
.snap_threshold
= 4;
615 if (! config
->getValue(screenstr
+ "resistanceSize",
616 resource
.resistance_size
))
617 resource
.resistance_size
= 18;
619 if (config
->getValue(screenstr
+ "rowPlacementDirection", s
) &&
621 resource
.row_direction
= RightLeft
;
623 resource
.row_direction
= LeftRight
;
625 if (config
->getValue(screenstr
+ "colPlacementDirection", s
) &&
627 resource
.col_direction
= BottomTop
;
629 resource
.col_direction
= TopBottom
;
631 if (config
->getValue(screenstr
+ "workspaceNames", s
)) {
632 XAtom::StringVect workspaceNames
;
634 string::const_iterator it
= s
.begin(), end
= s
.end();
636 string::const_iterator tmp
= it
; // current string.begin()
637 it
= std::find(tmp
, end
, ','); // look for comma between tmp and end
638 workspaceNames
.push_back(string(tmp
, it
)); // s[tmp:it]
644 xatom
->setValue(getRootWindow(), XAtom::net_desktop_names
, XAtom::utf8
,
648 resource
.sloppy_focus
= true;
649 resource
.auto_raise
= false;
650 resource
.click_raise
= false;
651 if (config
->getValue(screenstr
+ "focusModel", s
)) {
652 if (s
.find("ClickToFocus") != string::npos
) {
653 resource
.sloppy_focus
= false;
656 if (s
.find("AutoRaise") != string::npos
)
657 resource
.auto_raise
= true;
658 if (s
.find("ClickRaise") != string::npos
)
659 resource
.click_raise
= true;
663 if (config
->getValue(screenstr
+ "windowPlacement", s
)) {
664 if (s
== "CascadePlacement")
665 resource
.placement_policy
= CascadePlacement
;
666 else if (s
== "UnderMousePlacement")
667 resource
.placement_policy
= UnderMousePlacement
;
668 else if (s
== "ClickMousePlacement")
669 resource
.placement_policy
= ClickMousePlacement
;
670 else if (s
== "ColSmartPlacement")
671 resource
.placement_policy
= ColSmartPlacement
;
672 else //if (s == "RowSmartPlacement")
673 resource
.placement_policy
= RowSmartPlacement
;
675 resource
.placement_policy
= RowSmartPlacement
;
677 if (! config
->getValue(screenstr
+ "strftimeFormat",
678 resource
.strftime_format
))
679 resource
.strftime_format
= "%I:%M %p";
681 if (! config
->getValue(screenstr
+ "placementIgnoreShaded",
682 resource
.ignore_shaded
))
683 resource
.ignore_shaded
= true;
685 if (! config
->getValue(screenstr
+ "placementIgnoreMaximized",
686 resource
.ignore_maximized
))
687 resource
.ignore_maximized
= true;
689 if (! config
->getValue(screenstr
+ "disableBindingsWithScrollLock",
690 resource
.allow_scroll_lock
))
691 resource
.allow_scroll_lock
= false;
693 if (! config
->getValue(screenstr
+ "workspaceWarping",
694 resource
.workspace_warping
))
695 resource
.workspace_warping
= false;
697 resource
.root_scroll
= NormalScroll
;
698 if (config
->getValue(screenstr
+ "rootScrollDirection", s
)) {
700 resource
.root_scroll
= NoScroll
;
701 else if (s
== "Reverse")
702 resource
.root_scroll
= ReverseScroll
;
707 void BScreen::changeWorkspaceCount(unsigned int new_count
) {
708 assert(new_count
> 0);
710 if (new_count
< workspacesList
.size()) {
712 for (unsigned int i
= workspacesList
.size(); i
> new_count
; --i
)
713 removeLastWorkspace();
714 // removeLast already sets the current workspace to the
715 // last available one.
716 } else if (new_count
> workspacesList
.size()) {
718 for(unsigned int i
= workspacesList
.size(); i
< new_count
; ++i
)
724 void BScreen::reconfigure(void) {
725 // don't reconfigure while saving the initial rc file, it's a waste and it
726 // breaks somethings (workspace names)
727 if (blackbox
->state() == Openbox::State_Starting
) return;
732 // we need to do this explicitly, because just loading this value from the rc
734 changeWorkspaceCount(resource
.workspaces
);
737 gcv
.foreground
= WhitePixel(otk::OBDisplay::display
,
739 gcv
.function
= GXinvert
;
740 gcv
.subwindow_mode
= IncludeInferiors
;
741 XChangeGC(otk::OBDisplay::display
, opGC
,
742 GCForeground
| GCFunction
| GCSubwindowMode
, &gcv
);
744 const char *s
= "0: 0000 x 0: 0000";
746 geom_w
= resource
.wstyle
.font
->measureString(s
) + resource
.bevel_width
* 2;
747 geom_h
= resource
.wstyle
.font
->height() + resource
.bevel_width
* 2;
749 otk::BTexture
* texture
= &(resource
.wstyle
.l_focus
);
750 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
751 if (geom_pixmap
== ParentRelative
) {
752 texture
= &(resource
.wstyle
.t_focus
);
753 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
756 XSetWindowBackground(otk::OBDisplay::display
, geom_window
,
757 texture
->color().pixel());
759 XSetWindowBackgroundPixmap(otk::OBDisplay::display
,
760 geom_window
, geom_pixmap
);
762 XSetWindowBorderWidth(otk::OBDisplay::display
, geom_window
,
763 resource
.border_width
);
764 XSetWindowBorder(otk::OBDisplay::display
, geom_window
,
765 resource
.border_color
.pixel());
767 typedef std::vector
<int> SubList
;
768 SubList remember_subs
;
772 std::for_each(workspacesList
.begin(), workspacesList
.end(),
773 std::mem_fun(&Workspace::reconfigure
));
775 BlackboxWindowList::iterator iit
= iconList
.begin();
776 for (; iit
!= iconList
.end(); ++iit
) {
777 BlackboxWindow
*bw
= *iit
;
778 if (bw
->validateClient())
782 image_control
->timeout();
786 void BScreen::LoadStyle(void) {
787 Configuration
style(False
);
789 const char *sfile
= blackbox
->getStyleFilename();
791 style
.setFile(sfile
);
792 if (! style
.load()) {
793 style
.setFile(DEFAULTSTYLE
);
795 style
.create(); // hardcoded default values will be used.
799 // merge in the rc file
800 style
.merge(config
->file(), True
);
804 // load fonts/fontsets
805 if (resource
.wstyle
.font
)
806 delete resource
.wstyle
.font
;
808 resource
.wstyle
.font
= readDatabaseFont("window.", style
);
810 // load window config
811 resource
.wstyle
.t_focus
=
812 readDatabaseTexture("window.title.focus", "white", style
);
813 resource
.wstyle
.t_unfocus
=
814 readDatabaseTexture("window.title.unfocus", "black", style
);
815 resource
.wstyle
.l_focus
=
816 readDatabaseTexture("window.label.focus", "white", style
);
817 resource
.wstyle
.l_unfocus
=
818 readDatabaseTexture("window.label.unfocus", "black", style
);
819 resource
.wstyle
.h_focus
=
820 readDatabaseTexture("window.handle.focus", "white", style
);
821 resource
.wstyle
.h_unfocus
=
822 readDatabaseTexture("window.handle.unfocus", "black", style
);
823 resource
.wstyle
.g_focus
=
824 readDatabaseTexture("window.grip.focus", "white", style
);
825 resource
.wstyle
.g_unfocus
=
826 readDatabaseTexture("window.grip.unfocus", "black", style
);
827 resource
.wstyle
.b_focus
=
828 readDatabaseTexture("window.button.focus", "white", style
);
829 resource
.wstyle
.b_unfocus
=
830 readDatabaseTexture("window.button.unfocus", "black", style
);
831 resource
.wstyle
.b_pressed
=
832 readDatabaseTexture("window.button.pressed", "black", style
);
834 //if neither of these can be found, we will use the previous resource
835 resource
.wstyle
.b_pressed_focus
=
836 readDatabaseTexture("window.button.pressed.focus", "black", style
, true);
837 resource
.wstyle
.b_pressed_unfocus
=
838 readDatabaseTexture("window.button.pressed.unfocus", "black", style
, true);
840 if (resource
.wstyle
.close_button
.mask
!= None
)
841 XFreePixmap(otk::OBDisplay::display
, resource
.wstyle
.close_button
.mask
);
842 if (resource
.wstyle
.max_button
.mask
!= None
)
843 XFreePixmap(otk::OBDisplay::display
, resource
.wstyle
.max_button
.mask
);
844 if (resource
.wstyle
.icon_button
.mask
!= None
)
845 XFreePixmap(otk::OBDisplay::display
, resource
.wstyle
.icon_button
.mask
);
846 if (resource
.wstyle
.stick_button
.mask
!= None
)
847 XFreePixmap(otk::OBDisplay::display
, resource
.wstyle
.stick_button
.mask
);
849 resource
.wstyle
.close_button
.mask
= resource
.wstyle
.max_button
.mask
=
850 resource
.wstyle
.icon_button
.mask
=
851 resource
.wstyle
.icon_button
.mask
= None
;
853 readDatabaseMask("window.button.close.mask", resource
.wstyle
.close_button
,
855 readDatabaseMask("window.button.max.mask", resource
.wstyle
.max_button
,
857 readDatabaseMask("window.button.icon.mask", resource
.wstyle
.icon_button
,
859 readDatabaseMask("window.button.stick.mask", resource
.wstyle
.stick_button
,
862 // we create the window.frame texture by hand because it exists only to
863 // make the code cleaner and is not actually used for display
864 otk::BColor color
= readDatabaseColor("window.frame.focusColor", "white",
866 resource
.wstyle
.f_focus
= otk::BTexture("solid flat", getScreenNumber(),
868 resource
.wstyle
.f_focus
.setColor(color
);
870 color
= readDatabaseColor("window.frame.unfocusColor", "white", style
);
871 resource
.wstyle
.f_unfocus
= otk::BTexture("solid flat", getScreenNumber(),
873 resource
.wstyle
.f_unfocus
.setColor(color
);
875 resource
.wstyle
.l_text_focus
=
876 readDatabaseColor("window.label.focus.textColor", "black", style
);
877 resource
.wstyle
.l_text_unfocus
=
878 readDatabaseColor("window.label.unfocus.textColor", "white", style
);
879 resource
.wstyle
.b_pic_focus
=
880 readDatabaseColor("window.button.focus.picColor", "black", style
);
881 resource
.wstyle
.b_pic_unfocus
=
882 readDatabaseColor("window.button.unfocus.picColor", "white", style
);
884 resource
.wstyle
.justify
= LeftJustify
;
885 if (style
.getValue("window.justify", s
)) {
886 if (s
== "right" || s
== "Right")
887 resource
.wstyle
.justify
= RightJustify
;
888 else if (s
== "center" || s
== "Center")
889 resource
.wstyle
.justify
= CenterJustify
;
893 if (resource
.wstyle
.t_focus
.texture() == otk::BTexture::Parent_Relative
)
894 resource
.wstyle
.t_focus
= resource
.wstyle
.f_focus
;
895 if (resource
.wstyle
.t_unfocus
.texture() == otk::BTexture::Parent_Relative
)
896 resource
.wstyle
.t_unfocus
= resource
.wstyle
.f_unfocus
;
897 if (resource
.wstyle
.h_focus
.texture() == otk::BTexture::Parent_Relative
)
898 resource
.wstyle
.h_focus
= resource
.wstyle
.f_focus
;
899 if (resource
.wstyle
.h_unfocus
.texture() == otk::BTexture::Parent_Relative
)
900 resource
.wstyle
.h_unfocus
= resource
.wstyle
.f_unfocus
;
902 resource
.border_color
=
903 readDatabaseColor("borderColor", "black", style
);
905 // load bevel, border and handle widths
906 if (! style
.getValue("handleWidth", resource
.handle_width
) ||
907 resource
.handle_width
> (getWidth() / 2) || resource
.handle_width
== 0)
908 resource
.handle_width
= 6;
910 if (! style
.getValue("borderWidth", resource
.border_width
))
911 resource
.border_width
= 1;
913 if (! style
.getValue("bevelWidth", resource
.bevel_width
) ||
914 resource
.bevel_width
> (getWidth() / 2) || resource
.bevel_width
== 0)
915 resource
.bevel_width
= 3;
917 if (! style
.getValue("frameWidth", resource
.frame_width
) ||
918 resource
.frame_width
> (getWidth() / 2))
919 resource
.frame_width
= resource
.bevel_width
;
921 if (style
.getValue("rootCommand", s
))
922 bexec(s
, displayString());
926 void BScreen::addIcon(BlackboxWindow
*w
) {
929 w
->setWorkspace(BSENTINEL
);
930 w
->setWindowNumber(iconList
.size());
932 iconList
.push_back(w
);
936 void BScreen::removeIcon(BlackboxWindow
*w
) {
941 BlackboxWindowList::iterator it
= iconList
.begin(),
942 end
= iconList
.end();
943 for (int i
= 0; it
!= end
; ++it
)
944 (*it
)->setWindowNumber(i
++);
948 BlackboxWindow
*BScreen::getIcon(unsigned int index
) {
949 if (index
< iconList
.size()) {
950 BlackboxWindowList::iterator it
= iconList
.begin();
951 while (index
-- > 0) // increment to index
956 return (BlackboxWindow
*) 0;
960 unsigned int BScreen::addWorkspace(void) {
961 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
962 workspacesList
.push_back(wkspc
);
963 saveWorkspaces(getWorkspaceCount());
964 saveWorkspaceNames();
966 return workspacesList
.size();
970 unsigned int BScreen::removeLastWorkspace(void) {
971 if (workspacesList
.size() == 1)
974 Workspace
*wkspc
= workspacesList
.back();
976 if (current_workspace
->getID() == wkspc
->getID())
977 changeWorkspaceID(current_workspace
->getID() - 1);
981 workspacesList
.pop_back();
984 saveWorkspaces(getWorkspaceCount());
985 saveWorkspaceNames();
987 updateNetizenWorkspaceCount();
989 return workspacesList
.size();
993 void BScreen::changeWorkspaceID(unsigned int id
) {
994 if (! current_workspace
|| id
== current_workspace
->getID()) return;
996 BlackboxWindow
*focused
= blackbox
->getFocusedWindow();
997 if (focused
&& focused
->getScreen() == this) {
998 assert(focused
->isStuck() ||
999 focused
->getWorkspaceNumber() == current_workspace
->getID());
1001 current_workspace
->setLastFocusedWindow(focused
);
1003 // if no window had focus, no need to store a last focus
1004 current_workspace
->setLastFocusedWindow((BlackboxWindow
*) 0);
1007 // when we switch workspaces, unfocus whatever was focused if it is going
1009 if (focused
&& ! focused
->isStuck())
1010 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1012 current_workspace
->hideAll();
1014 current_workspace
= getWorkspace(id
);
1016 xatom
->setValue(getRootWindow(), XAtom::net_current_desktop
,
1017 XAtom::cardinal
, id
);
1019 current_workspace
->showAll();
1024 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
1027 XSync(otk::OBDisplay::display
, False
);
1029 // If sloppy focus and we can find the client window under the pointer,
1031 if (resource
.sloppy_focus
&&
1032 XQueryPointer(otk::OBDisplay::display
, getRootWindow(), &r
, &c
,
1033 &rx
, &ry
, &x
, &y
, &m
) &&
1035 if ( (win
= blackbox
->searchWindow(c
)) )
1036 f
= win
->setInputFocus();
1039 // If that fails, and we're doing focus_last, try to focus the last window.
1040 if (! f
&& resource
.focus_last
&&
1041 (win
= current_workspace
->getLastFocusedWindow()))
1042 f
= win
->setInputFocus();
1045 if we found a focus target, then we set the focused window explicitly
1046 because it is possible to switch off this workspace before the x server
1047 generates the FocusIn event for the window. if that happens, openbox would
1048 lose track of what window was the 'LastFocused' window on the workspace.
1050 if we did not find a focus target, then set the current focused window to
1054 blackbox
->setFocusedWindow(win
);
1056 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1061 * Set the _NET_CLIENT_LIST root window property.
1063 void BScreen::updateClientList(void) {
1064 if (windowList
.size() > 0) {
1065 Window
*windows
= new Window
[windowList
.size()];
1066 Window
*win_it
= windows
;
1067 BlackboxWindowList::iterator it
= windowList
.begin();
1068 const BlackboxWindowList::iterator end
= windowList
.end();
1069 for (; it
!= end
; ++it
, ++win_it
)
1070 *win_it
= (*it
)->getClientWindow();
1071 xatom
->setValue(getRootWindow(), XAtom::net_client_list
, XAtom::window
,
1072 windows
, windowList
.size());
1075 xatom
->setValue(getRootWindow(), XAtom::net_client_list
, XAtom::window
,
1078 updateStackingList();
1083 * Set the _NET_CLIENT_LIST_STACKING root window property.
1085 void BScreen::updateStackingList(void) {
1087 BlackboxWindowList stack_order
;
1090 * Get the stacking order from all of the workspaces.
1091 * We start with the current workspace so that the sticky windows will be
1092 * in the right order on the current workspace.
1093 * XXX: Do we need to have sticky windows in the list once for each workspace?
1095 getCurrentWorkspace()->appendStackOrder(stack_order
);
1096 for (unsigned int i
= 0; i
< getWorkspaceCount(); ++i
)
1097 if (i
!= getCurrentWorkspaceID())
1098 getWorkspace(i
)->appendStackOrder(stack_order
);
1100 if (stack_order
.size() > 0) {
1101 // set the client list atoms
1102 Window
*windows
= new Window
[stack_order
.size()];
1103 Window
*win_it
= windows
;
1104 BlackboxWindowList::iterator it
= stack_order
.begin(),
1105 end
= stack_order
.end();
1106 for (; it
!= end
; ++it
, ++win_it
)
1107 *win_it
= (*it
)->getClientWindow();
1108 xatom
->setValue(getRootWindow(), XAtom::net_client_list_stacking
,
1109 XAtom::window
, windows
, stack_order
.size());
1112 xatom
->setValue(getRootWindow(), XAtom::net_client_list_stacking
,
1113 XAtom::window
, 0, 0);
1117 void BScreen::addSystrayWindow(Window window
) {
1118 XGrabServer(otk::OBDisplay::display
);
1120 XSelectInput(otk::OBDisplay::display
, window
, StructureNotifyMask
);
1121 systrayWindowList
.push_back(window
);
1122 xatom
->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows
,
1124 &systrayWindowList
[0], systrayWindowList
.size());
1125 blackbox
->saveSystrayWindowSearch(window
, this);
1127 XUngrabServer(otk::OBDisplay::display
);
1131 void BScreen::removeSystrayWindow(Window window
) {
1132 XGrabServer(otk::OBDisplay::display
);
1134 WindowList::iterator it
= systrayWindowList
.begin();
1135 const WindowList::iterator end
= systrayWindowList
.end();
1136 for (; it
!= end
; ++it
)
1137 if (*it
== window
) {
1138 systrayWindowList
.erase(it
);
1139 xatom
->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows
,
1141 &systrayWindowList
[0], systrayWindowList
.size());
1142 blackbox
->removeSystrayWindowSearch(window
);
1143 XSelectInput(otk::OBDisplay::display
, window
, NoEventMask
);
1147 assert(it
!= end
); // not a systray window
1149 XUngrabServer(otk::OBDisplay::display
);
1153 void BScreen::manageWindow(Window w
) {
1154 // is the window a KDE systray window?
1156 if (xatom
->getValue(w
, XAtom::kde_net_wm_system_tray_window_for
,
1157 XAtom::window
, systray
) && systray
!= None
) {
1158 addSystrayWindow(w
);
1162 // is the window a docking app
1163 XWMHints
*wmhint
= XGetWMHints(otk::OBDisplay::display
, w
);
1164 if (wmhint
&& (wmhint
->flags
& StateHint
) &&
1165 wmhint
->initial_state
== WithdrawnState
) {
1166 //slit->addClient(w);
1170 new BlackboxWindow(blackbox
, w
, this);
1172 BlackboxWindow
*win
= blackbox
->searchWindow(w
);
1176 if (win
->isDesktop()) {
1177 desktopWindowList
.push_back(win
->getFrameWindow());
1178 } else { // if (win->isNormal()) {
1179 // don't list desktop windows as managed windows
1180 windowList
.push_back(win
);
1183 if (win
->isTopmost())
1184 specialWindowList
.push_back(win
->getFrameWindow());
1187 XMapRequestEvent mre
;
1189 if (blackbox
->state() == Openbox::State_Starting
&&
1191 win
->restoreAttributes();
1192 win
->mapRequestEvent(&mre
);
1196 void BScreen::unmanageWindow(BlackboxWindow
*w
, bool remap
) {
1197 // is the window a KDE systray window?
1199 if (xatom
->getValue(w
->getClientWindow(),
1200 XAtom::kde_net_wm_system_tray_window_for
,
1201 XAtom::window
, systray
) && systray
!= None
) {
1202 removeSystrayWindow(w
->getClientWindow());
1208 // Remove the modality so that its parent won't try to re-focus the window
1209 if (w
->isModal()) w
->setModal(False
);
1211 if (w
->getWorkspaceNumber() != BSENTINEL
&&
1212 w
->getWindowNumber() != BSENTINEL
) {
1213 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1215 for (unsigned int i
= 0; i
< getNumberOfWorkspaces(); ++i
)
1216 if (i
!= w
->getWorkspaceNumber())
1217 getWorkspace(i
)->removeWindow(w
, True
);
1219 } else if (w
->isIconic())
1222 if (w
->isDesktop()) {
1223 WindowList::iterator it
= desktopWindowList
.begin();
1224 const WindowList::iterator end
= desktopWindowList
.end();
1225 for (; it
!= end
; ++it
)
1226 if (*it
== w
->getFrameWindow()) {
1227 desktopWindowList
.erase(it
);
1230 assert(it
!= end
); // the window wasnt a desktop window?
1231 } else { // if (w->isNormal()) {
1232 // we don't list desktop windows as managed windows
1233 windowList
.remove(w
);
1236 if (w
->isTopmost()) {
1237 WindowList::iterator it
= specialWindowList
.begin();
1238 const WindowList::iterator end
= specialWindowList
.end();
1239 for (; it
!= end
; ++it
)
1240 if (*it
== w
->getFrameWindow()) {
1241 specialWindowList
.erase(it
);
1244 assert(it
!= end
); // the window wasnt a special window?
1248 if (blackbox
->getFocusedWindow() == w
)
1249 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1252 some managed windows can also be window group controllers. when
1253 unmanaging such windows, we should also delete the window group.
1255 BWindowGroup
*group
= blackbox
->searchGroup(w
->getClientWindow());
1262 void BScreen::updateWorkArea(void) {
1263 if (workspacesList
.size() > 0) {
1264 unsigned long *dims
= new unsigned long[4 * workspacesList
.size()];
1265 for (unsigned int i
= 0, m
= workspacesList
.size(); i
< m
; ++i
) {
1266 // XXX: this could be different for each workspace
1267 const otk::Rect
&area
= availableArea();
1268 dims
[(i
* 4) + 0] = area
.x();
1269 dims
[(i
* 4) + 1] = area
.y();
1270 dims
[(i
* 4) + 2] = area
.width();
1271 dims
[(i
* 4) + 3] = area
.height();
1273 xatom
->setValue(getRootWindow(), XAtom::net_workarea
, XAtom::cardinal
,
1274 dims
, 4 * workspacesList
.size());
1277 xatom
->setValue(getRootWindow(), XAtom::net_workarea
, XAtom::cardinal
,
1282 void BScreen::updateNetizenWorkspaceCount(void) {
1283 xatom
->setValue(getRootWindow(), XAtom::net_number_of_desktops
,
1284 XAtom::cardinal
, workspacesList
.size());
1290 void BScreen::updateNetizenWindowFocus(void) {
1291 Window f
= ((blackbox
->getFocusedWindow()) ?
1292 blackbox
->getFocusedWindow()->getClientWindow() : None
);
1294 xatom
->setValue(getRootWindow(), XAtom::net_active_window
,
1299 void BScreen::raiseWindows(Window
*workspace_stack
, unsigned int num
) {
1300 // the 13 represents the number of blackbox windows such as menus
1306 Window
*session_stack
= new
1307 Window
[(num
+ specialWindowList
.size() + bbwins
)];
1308 unsigned int i
= 0, k
= num
;
1310 WindowList::iterator sit
, send
= specialWindowList
.end();
1311 for (sit
= specialWindowList
.begin(); sit
!= send
; ++sit
)
1312 *(session_stack
+ i
++) = *sit
;
1315 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
1317 XRestackWindows(otk::OBDisplay::display
, session_stack
, i
);
1319 delete [] session_stack
;
1321 updateStackingList();
1325 void BScreen::lowerWindows(Window
*workspace_stack
, unsigned int num
) {
1326 assert(num
> 0); // this would cause trouble in the XRaiseWindow call
1328 Window
*session_stack
= new Window
[(num
+ desktopWindowList
.size())];
1329 unsigned int i
= 0, k
= num
;
1331 XLowerWindow(otk::OBDisplay::display
, workspace_stack
[0]);
1334 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
1336 WindowList::iterator dit
= desktopWindowList
.begin();
1337 const WindowList::iterator d_end
= desktopWindowList
.end();
1338 for (; dit
!= d_end
; ++dit
)
1339 *(session_stack
+ i
++) = *dit
;
1341 XRestackWindows(otk::OBDisplay::display
, session_stack
, i
);
1343 delete [] session_stack
;
1345 updateStackingList();
1349 void BScreen::reassociateWindow(BlackboxWindow
*w
, unsigned int wkspc_id
,
1350 bool ignore_sticky
) {
1353 if (wkspc_id
== BSENTINEL
)
1354 wkspc_id
= current_workspace
->getID();
1356 if (w
->getWorkspaceNumber() == wkspc_id
)
1359 if (w
->isIconic()) {
1361 getWorkspace(wkspc_id
)->addWindow(w
);
1363 for (unsigned int i
= 0; i
< getNumberOfWorkspaces(); ++i
)
1364 if (i
!= w
->getWorkspaceNumber())
1365 getWorkspace(i
)->addWindow(w
, True
);
1366 } else if (ignore_sticky
|| ! w
->isStuck()) {
1369 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1370 getWorkspace(wkspc_id
)->addWindow(w
);
1372 updateStackingList();
1376 void BScreen::propagateWindowName(const BlackboxWindow
*bw
) {
1377 if (bw
->isIconic()) {
1383 void BScreen::nextFocus(void) const {
1384 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1388 focused
->getScreen()->getScreenNumber() == getScreenNumber() &&
1389 current_workspace
->getCount() > 1) {
1391 next
= current_workspace
->getNextWindowInList(next
);
1392 } while (next
!= focused
&& ! next
->setInputFocus());
1394 if (next
!= focused
)
1395 current_workspace
->raiseWindow(next
);
1396 } else if (current_workspace
->getCount() > 0) {
1397 next
= current_workspace
->getTopWindowOnStack();
1398 next
->setInputFocus();
1399 current_workspace
->raiseWindow(next
);
1404 void BScreen::prevFocus(void) const {
1405 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1409 // if window is not on this screen, ignore it
1410 if (focused
->getScreen()->getScreenNumber() != getScreenNumber())
1411 focused
= (BlackboxWindow
*) 0;
1415 focused
->getScreen()->getScreenNumber() == getScreenNumber() &&
1416 current_workspace
->getCount() > 1) {
1417 // next is the next window to receive focus, current is a place holder
1419 next
= current_workspace
->getPrevWindowInList(next
);
1420 } while (next
!= focused
&& ! next
->setInputFocus());
1422 if (next
!= focused
)
1423 current_workspace
->raiseWindow(next
);
1424 } else if (current_workspace
->getCount() > 0) {
1425 next
= current_workspace
->getTopWindowOnStack();
1426 next
->setInputFocus();
1427 current_workspace
->raiseWindow(next
);
1432 void BScreen::raiseFocus(void) const {
1433 BlackboxWindow
*focused
= blackbox
->getFocusedWindow();
1437 // if on this Screen, raise it
1438 if (focused
->getScreen()->getScreenNumber() == getScreenNumber()) {
1439 Workspace
*workspace
= getWorkspace(focused
->getWorkspaceNumber());
1440 workspace
->raiseWindow(focused
);
1445 void BScreen::shutdown(void) {
1446 XSelectInput(otk::OBDisplay::display
, getRootWindow(), NoEventMask
);
1447 XSync(otk::OBDisplay::display
, False
);
1449 while(! windowList
.empty())
1450 unmanageWindow(windowList
.front(), True
);
1452 while(! desktopWindowList
.empty()) {
1453 BlackboxWindow
*win
= blackbox
->searchWindow(desktopWindowList
.front());
1455 unmanageWindow(win
, True
);
1460 void BScreen::showPosition(int x
, int y
) {
1461 if (! geom_visible
) {
1462 XMoveResizeWindow(otk::OBDisplay::display
, geom_window
,
1463 (getWidth() - geom_w
) / 2,
1464 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
1465 XMapWindow(otk::OBDisplay::display
, geom_window
);
1466 XRaiseWindow(otk::OBDisplay::display
, geom_window
);
1468 geom_visible
= True
;
1473 sprintf(label
, "X: %4d x Y: %4d", x
, y
);
1475 XClearWindow(otk::OBDisplay::display
, geom_window
);
1477 resource
.wstyle
.font
->drawString(geom_window
,
1478 resource
.bevel_width
, resource
.bevel_width
,
1479 resource
.wstyle
.l_text_focus
,
1484 void BScreen::showGeometry(unsigned int gx
, unsigned int gy
) {
1485 if (! geom_visible
) {
1486 XMoveResizeWindow(otk::OBDisplay::display
, geom_window
,
1487 (getWidth() - geom_w
) / 2,
1488 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
1489 XMapWindow(otk::OBDisplay::display
, geom_window
);
1490 XRaiseWindow(otk::OBDisplay::display
, geom_window
);
1492 geom_visible
= True
;
1497 sprintf(label
, "W: %4d x H: %4d", gx
, gy
);
1499 XClearWindow(otk::OBDisplay::display
, geom_window
);
1501 resource
.wstyle
.font
->drawString(geom_window
,
1502 resource
.bevel_width
, resource
.bevel_width
,
1503 resource
.wstyle
.l_text_focus
,
1508 void BScreen::hideGeometry(void) {
1510 XUnmapWindow(otk::OBDisplay::display
, geom_window
);
1511 geom_visible
= False
;
1516 void BScreen::addStrut(Strut
*strut
) {
1517 strutList
.push_back(strut
);
1521 void BScreen::removeStrut(Strut
*strut
) {
1522 strutList
.remove(strut
);
1526 const otk::Rect
& BScreen::availableArea(void) const {
1528 return getRect(); // return the full screen
1534 const RectList
& BScreen::allAvailableAreas(void) const {
1535 assert(isXineramaActive());
1536 assert(xineramaUsableArea
.size() > 0);
1537 fprintf(stderr
, "1found x %d y %d w %d h %d\n",
1538 xineramaUsableArea
[0].x(), xineramaUsableArea
[0].y(),
1539 xineramaUsableArea
[0].width(), xineramaUsableArea
[0].height());
1540 return xineramaUsableArea
;
1545 void BScreen::updateAvailableArea(void) {
1546 otk::Rect old_area
= usableArea
;
1547 usableArea
= getRect(); // reset to full screen
1550 // reset to the full areas
1551 if (isXineramaActive())
1552 xineramaUsableArea
= getXineramaAreas();
1555 /* these values represent offsets from the screen edge
1556 * we look for the biggest offset on each edge and then apply them
1558 * do not be confused by the similarity to the names of Rect's members
1560 unsigned int current_left
= 0, current_right
= 0, current_top
= 0,
1563 StrutList::const_iterator it
= strutList
.begin(), end
= strutList
.end();
1565 for(; it
!= end
; ++it
) {
1567 if (strut
->left
> current_left
)
1568 current_left
= strut
->left
;
1569 if (strut
->top
> current_top
)
1570 current_top
= strut
->top
;
1571 if (strut
->right
> current_right
)
1572 current_right
= strut
->right
;
1573 if (strut
->bottom
> current_bottom
)
1574 current_bottom
= strut
->bottom
;
1577 usableArea
.setPos(current_left
, current_top
);
1578 usableArea
.setSize(usableArea
.width() - (current_left
+ current_right
),
1579 usableArea
.height() - (current_top
+ current_bottom
));
1582 if (isXineramaActive()) {
1583 // keep each of the ximerama-defined areas inside the strut
1584 RectList::iterator xit
, xend
= xineramaUsableArea
.end();
1585 for (xit
= xineramaUsableArea
.begin(); xit
!= xend
; ++xit
) {
1586 if (xit
->x() < usableArea
.x()) {
1587 xit
->setX(usableArea
.x());
1588 xit
->setWidth(xit
->width() - usableArea
.x());
1590 if (xit
->y() < usableArea
.y()) {
1591 xit
->setY(usableArea
.y());
1592 xit
->setHeight(xit
->height() - usableArea
.y());
1594 if (xit
->x() + xit
->width() > usableArea
.width())
1595 xit
->setWidth(usableArea
.width() - xit
->x());
1596 if (xit
->y() + xit
->height() > usableArea
.height())
1597 xit
->setHeight(usableArea
.height() - xit
->y());
1602 if (old_area
!= usableArea
) {
1603 BlackboxWindowList::iterator it
= windowList
.begin(),
1604 end
= windowList
.end();
1605 for (; it
!= end
; ++it
)
1606 if ((*it
)->isMaximized()) (*it
)->remaximize();
1613 Workspace
* BScreen::getWorkspace(unsigned int index
) const {
1614 assert(index
< workspacesList
.size());
1615 return workspacesList
[index
];
1619 void BScreen::buttonPressEvent(const XButtonEvent
*xbutton
) {
1620 if (xbutton
->button
== 1) {
1621 if (! isRootColormapInstalled())
1622 image_control
->installRootColormap();
1625 } else if ((xbutton
->button
== 4 && resource
.root_scroll
== NormalScroll
) ||
1626 (xbutton
->button
== 5 && resource
.root_scroll
== ReverseScroll
)) {
1627 if (getCurrentWorkspaceID() >= getWorkspaceCount() - 1)
1628 changeWorkspaceID(0);
1630 changeWorkspaceID(getCurrentWorkspaceID() + 1);
1632 } else if ((xbutton
->button
== 5 && resource
.root_scroll
== NormalScroll
) ||
1633 (xbutton
->button
== 4 && resource
.root_scroll
== ReverseScroll
)) {
1634 if (getCurrentWorkspaceID() == 0)
1635 changeWorkspaceID(getWorkspaceCount() - 1);
1637 changeWorkspaceID(getCurrentWorkspaceID() - 1);
1642 void BScreen::propertyNotifyEvent(const XPropertyEvent
*pe
) {
1643 if (pe
->atom
== xatom
->getAtom(XAtom::net_desktop_names
)) {
1644 // _NET_WM_DESKTOP_NAMES
1645 WorkspaceList::iterator it
= workspacesList
.begin();
1646 const WorkspaceList::iterator end
= workspacesList
.end();
1647 for (; it
!= end
; ++it
) {
1648 (*it
)->readName(); // re-read its name from the window property
1649 //workspacemenu->changeWorkspaceLabel((*it)->getID(), (*it)->getName());
1651 //workspacemenu->update();
1652 saveWorkspaceNames();
1657 void BScreen::toggleFocusModel(FocusModel model
) {
1658 std::for_each(windowList
.begin(), windowList
.end(),
1659 std::mem_fun(&BlackboxWindow::ungrabButtons
));
1661 if (model
== SloppyFocus
) {
1662 saveSloppyFocus(True
);
1664 // we're cheating here to save writing the config file 3 times
1665 resource
.auto_raise
= False
;
1666 resource
.click_raise
= False
;
1667 saveSloppyFocus(False
);
1670 std::for_each(windowList
.begin(), windowList
.end(),
1671 std::mem_fun(&BlackboxWindow::grabButtons
));
1674 void BScreen::readDatabaseMask(const string
&rname
, PixmapMask
&pixmapMask
,
1675 const Configuration
&style
) {
1677 int hx
, hy
; //ignored
1678 int ret
= BitmapOpenFailed
; //default to failure.
1680 if (style
.getValue(rname
, s
))
1682 if (s
[0] != '/' && s
[0] != '~')
1684 std::string xbmFile
= std::string("~/.openbox/buttons/") + s
;
1685 ret
= XReadBitmapFile(otk::OBDisplay::display
, getRootWindow(),
1686 expandTilde(xbmFile
).c_str(), &pixmapMask
.w
,
1687 &pixmapMask
.h
, &pixmapMask
.mask
, &hx
, &hy
);
1689 ret
= XReadBitmapFile(otk::OBDisplay::display
, getRootWindow(),
1690 expandTilde(s
).c_str(), &pixmapMask
.w
,
1691 &pixmapMask
.h
, &pixmapMask
.mask
, &hx
, &hy
);
1693 if (ret
== BitmapSuccess
)
1697 pixmapMask
.mask
= None
;
1698 pixmapMask
.w
= pixmapMask
.h
= 0;
1701 otk::BTexture
BScreen::readDatabaseTexture(const string
&rname
,
1702 const string
&default_color
,
1703 const Configuration
&style
,
1704 bool allowNoTexture
) {
1705 otk::BTexture texture
;
1708 if (style
.getValue(rname
, s
))
1709 texture
= otk::BTexture(s
);
1710 else if (allowNoTexture
) //no default
1711 texture
.setTexture(otk::BTexture::NoTexture
);
1713 texture
.setTexture(otk::BTexture::Solid
| otk::BTexture::Flat
);
1715 // associate this texture with this screen
1716 texture
.setScreen(getScreenNumber());
1717 texture
.setImageControl(image_control
);
1719 if (texture
.texture() != otk::BTexture::NoTexture
) {
1720 texture
.setColor(readDatabaseColor(rname
+ ".color", default_color
,
1722 texture
.setColorTo(readDatabaseColor(rname
+ ".colorTo", default_color
,
1724 texture
.setBorderColor(readDatabaseColor(rname
+ ".borderColor",
1725 default_color
, style
));
1732 otk::BColor
BScreen::readDatabaseColor(const string
&rname
,
1733 const string
&default_color
,
1734 const Configuration
&style
) {
1737 if (style
.getValue(rname
, s
))
1738 color
= otk::BColor(s
, getScreenNumber());
1740 color
= otk::BColor(default_color
, getScreenNumber());
1745 otk::BFont
*BScreen::readDatabaseFont(const string
&rbasename
,
1746 const Configuration
&style
) {
1752 if (style
.getValue(rbasename
+ "xft.font", s
) &&
1753 style
.getValue(rbasename
+ "xft.size", i
)) {
1756 bool italic
= False
;
1757 bool dropShadow
= False
;
1759 if (style
.getValue(rbasename
+ "xft.flags", s
)) {
1760 if (s
.find("bold") != string::npos
)
1762 if (s
.find("italic") != string::npos
)
1764 if (s
.find("shadow") != string::npos
)
1768 unsigned char offset
= 1;
1769 if (style
.getValue(rbasename
+ "xft.shadow.offset", s
)) {
1770 offset
= atoi(s
.c_str()); //doesn't detect errors
1771 if (offset
> CHAR_MAX
)
1775 unsigned char tint
= 0x40;
1776 if (style
.getValue(rbasename
+ "xft.shadow.tint", s
)) {
1777 tint
= atoi(s
.c_str());
1781 otk::BFont
*b
= new otk::BFont(getScreenNumber(), family
, i
, bold
, italic
,
1782 dropShadow
&& resource
.shadow_fonts
,
1783 offset
, tint
, resource
.aa_fonts
);
1789 exit(2); // can't continue without a font