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"
64 #include "bbwindow.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(Openbox::instance
->timerManager(),
136 this, True
, blackbox
->getColorsPerChannel(),
137 blackbox
->getCacheLife(), blackbox
->getCacheMax());
138 image_control
->installRootColormap();
139 root_colormap_installed
= True
;
145 gcv
.foreground
= WhitePixel(otk::OBDisplay::display
, getScreenNumber())
146 ^ BlackPixel(otk::OBDisplay::display
, getScreenNumber());
147 gcv
.function
= GXxor
;
148 gcv
.subwindow_mode
= IncludeInferiors
;
149 opGC
= XCreateGC(otk::OBDisplay::display
, getRootWindow(),
150 GCForeground
| GCFunction
| GCSubwindowMode
, &gcv
);
152 const char *s
= "0: 0000 x 0: 0000";
153 geom_w
= resource
.wstyle
.font
->measureString(s
) + resource
.bevel_width
* 2;
154 geom_h
= resource
.wstyle
.font
->height() + resource
.bevel_width
* 2;
156 XSetWindowAttributes attrib
;
157 unsigned long mask
= CWBorderPixel
| CWColormap
| CWSaveUnder
;
158 attrib
.border_pixel
= getBorderColor()->pixel();
159 attrib
.colormap
= getColormap();
160 attrib
.save_under
= True
;
162 geom_window
= XCreateWindow(otk::OBDisplay::display
, getRootWindow(),
163 0, 0, geom_w
, geom_h
, resource
.border_width
,
164 getDepth(), InputOutput
, getVisual(),
166 geom_visible
= False
;
168 otk::BTexture
* texture
= &(resource
.wstyle
.l_focus
);
169 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
170 if (geom_pixmap
== ParentRelative
) {
171 texture
= &(resource
.wstyle
.t_focus
);
172 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
175 XSetWindowBackground(otk::OBDisplay::display
, geom_window
,
176 texture
->color().pixel());
178 XSetWindowBackgroundPixmap(otk::OBDisplay::display
,
179 geom_window
, geom_pixmap
);
181 if (resource
.workspaces
> 0) {
182 for (unsigned int i
= 0; i
< resource
.workspaces
; ++i
) {
183 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
184 workspacesList
.push_back(wkspc
);
188 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
189 workspacesList
.push_back(wkspc
);
191 saveWorkspaceNames();
193 updateNetizenWorkspaceCount();
195 current_workspace
= workspacesList
.front();
197 xatom
->setValue(getRootWindow(), XAtom::net_current_desktop
,
198 XAtom::cardinal
, 0); //first workspace
200 raiseWindows(0, 0); // this also initializes the empty stacking list
202 updateClientList(); // initialize the client lists, which will be empty
203 updateAvailableArea();
205 changeWorkspaceID(0);
207 unsigned int i
, j
, nchild
;
208 Window r
, p
, *children
;
209 XQueryTree(otk::OBDisplay::display
, getRootWindow(), &r
, &p
,
212 // preen the window list of all icon windows... for better dockapp support
213 for (i
= 0; i
< nchild
; i
++) {
214 if (children
[i
] == None
) continue;
216 XWMHints
*wmhints
= XGetWMHints(otk::OBDisplay::display
,
220 if ((wmhints
->flags
& IconWindowHint
) &&
221 (wmhints
->icon_window
!= children
[i
])) {
222 for (j
= 0; j
< nchild
; j
++) {
223 if (children
[j
] == wmhints
->icon_window
) {
234 // manage shown windows
235 for (i
= 0; i
< nchild
; ++i
) {
236 if (children
[i
] == None
|| ! blackbox
->validateWindow(children
[i
]))
239 XWindowAttributes attrib
;
240 if (XGetWindowAttributes(otk::OBDisplay::display
, children
[i
], &attrib
)) {
241 if (attrib
.override_redirect
) continue;
243 if (attrib
.map_state
!= IsUnmapped
) {
244 manageWindow(children
[i
]);
251 // call this again just in case a window we found updates the Strut list
252 updateAvailableArea();
256 BScreen::~BScreen(void) {
257 if (! managed
) return;
259 if (geom_pixmap
!= None
)
260 image_control
->removeImage(geom_pixmap
);
262 if (geom_window
!= None
)
263 XDestroyWindow(otk::OBDisplay::display
, geom_window
);
265 std::for_each(workspacesList
.begin(), workspacesList
.end(),
266 otk::PointerAssassin());
268 std::for_each(iconList
.begin(), iconList
.end(), otk::PointerAssassin());
270 while (! systrayWindowList
.empty())
271 removeSystrayWindow(systrayWindowList
[0]);
273 delete image_control
;
275 if (resource
.wstyle
.font
)
276 delete resource
.wstyle
.font
;
278 if (resource
.wstyle
.close_button
.mask
!= None
)
279 XFreePixmap(otk::OBDisplay::display
, resource
.wstyle
.close_button
.mask
);
280 if (resource
.wstyle
.max_button
.mask
!= None
)
281 XFreePixmap(otk::OBDisplay::display
, resource
.wstyle
.max_button
.mask
);
282 if (resource
.wstyle
.icon_button
.mask
!= None
)
283 XFreePixmap(otk::OBDisplay::display
, resource
.wstyle
.icon_button
.mask
);
284 if (resource
.wstyle
.stick_button
.mask
!= None
)
285 XFreePixmap(otk::OBDisplay::display
, resource
.wstyle
.stick_button
.mask
);
287 resource
.wstyle
.max_button
.mask
= resource
.wstyle
.close_button
.mask
=
288 resource
.wstyle
.icon_button
.mask
=
289 resource
.wstyle
.stick_button
.mask
= None
;
291 XFreeGC(otk::OBDisplay::display
, opGC
);
295 void BScreen::saveSloppyFocus(bool s
) {
296 resource
.sloppy_focus
= s
;
299 if (resource
.sloppy_focus
) {
300 fmodel
= "SloppyFocus";
301 if (resource
.auto_raise
) fmodel
+= " AutoRaise";
302 if (resource
.click_raise
) fmodel
+= " ClickRaise";
304 fmodel
= "ClickToFocus";
306 config
->setValue(screenstr
+ "focusModel", fmodel
);
310 void BScreen::saveAutoRaise(bool a
) {
311 resource
.auto_raise
= a
;
312 saveSloppyFocus(resource
.sloppy_focus
);
316 void BScreen::saveClickRaise(bool c
) {
317 resource
.click_raise
= c
;
318 saveSloppyFocus(resource
.sloppy_focus
);
322 void BScreen::saveImageDither(bool d
) {
323 image_control
->setDither(d
);
324 config
->setValue(screenstr
+ "imageDither", doImageDither());
328 void BScreen::saveOpaqueMove(bool o
) {
329 resource
.opaque_move
= o
;
330 config
->setValue(screenstr
+ "opaqueMove", resource
.opaque_move
);
334 void BScreen::saveFullMax(bool f
) {
335 resource
.full_max
= f
;
336 config
->setValue(screenstr
+ "fullMaximization", resource
.full_max
);
340 void BScreen::saveFocusNew(bool f
) {
341 resource
.focus_new
= f
;
342 config
->setValue(screenstr
+ "focusNewWindows", resource
.focus_new
);
346 void BScreen::saveFocusLast(bool f
) {
347 resource
.focus_last
= f
;
348 config
->setValue(screenstr
+ "focusLastWindow", resource
.focus_last
);
352 void BScreen::saveAAFonts(bool f
) {
353 resource
.aa_fonts
= f
;
354 config
->setValue(screenstr
+ "antialiasFonts", resource
.aa_fonts
);
359 void BScreen::saveShadowFonts(bool f
) {
360 resource
.shadow_fonts
= f
;
361 config
->setValue(screenstr
+ "dropShadowFonts", resource
.shadow_fonts
);
366 void BScreen::saveWindowToEdgeSnap(int s
) {
367 resource
.snap_to_edges
= s
;
370 switch (resource
.snap_to_edges
) {
371 case WindowNoSnap
: snap
= "NoSnap"; break;
372 case WindowResistance
: snap
= "Resistance"; break;
373 case WindowSnap
: default: snap
= "Snap"; break;
375 config
->setValue(screenstr
+ "windowToEdgeSnap", snap
);
379 void BScreen::saveWindowToWindowSnap(int s
) {
380 resource
.snap_to_windows
= s
;
383 switch (resource
.snap_to_windows
) {
384 case WindowNoSnap
: snap
= "NoSnap"; break;
385 case WindowResistance
: snap
= "Resistance"; break;
386 case WindowSnap
: default: snap
= "Snap"; break;
388 config
->setValue(screenstr
+ "windowToWindowSnap", snap
);
392 void BScreen::saveResizeZones(unsigned int z
) {
393 resource
.resize_zones
= z
;
394 config
->setValue(screenstr
+ "resizeZones", resource
.resize_zones
);
398 void BScreen::saveWindowCornerSnap(bool s
) {
399 resource
.window_corner_snap
= s
;
400 config
->setValue(screenstr
+ "windowCornerSnap",
401 resource
.window_corner_snap
);
405 void BScreen::saveWorkspaces(unsigned int w
) {
406 resource
.workspaces
= w
;
407 config
->setValue(screenstr
+ "workspaces", resource
.workspaces
);
411 void BScreen::savePlacementPolicy(int p
) {
412 resource
.placement_policy
= p
;
413 const char *placement
;
414 switch (resource
.placement_policy
) {
415 case CascadePlacement
: placement
= "CascadePlacement"; break;
416 case UnderMousePlacement
: placement
= "UnderMousePlacement"; break;
417 case ClickMousePlacement
: placement
= "ClickMousePlacement"; break;
418 case ColSmartPlacement
: placement
= "ColSmartPlacement"; break;
419 case RowSmartPlacement
: default: placement
= "RowSmartPlacement"; break;
421 config
->setValue(screenstr
+ "windowPlacement", placement
);
425 void BScreen::saveResistanceSize(int s
) {
426 resource
.resistance_size
= s
;
427 config
->setValue(screenstr
+ "resistanceSize",
428 resource
.resistance_size
);
432 void BScreen::saveSnapThreshold(int t
) {
433 resource
.snap_threshold
= t
;
434 config
->setValue(screenstr
+ "edgeSnapThreshold",
435 resource
.snap_threshold
);
439 void BScreen::saveSnapOffset(int t
) {
440 resource
.snap_offset
= t
;
441 config
->setValue(screenstr
+ "edgeSnapOffset",
442 resource
.snap_offset
);
446 void BScreen::saveRowPlacementDirection(int d
) {
447 resource
.row_direction
= d
;
448 config
->setValue(screenstr
+ "rowPlacementDirection",
449 resource
.row_direction
== LeftRight
?
450 "LeftToRight" : "RightToLeft");
454 void BScreen::saveColPlacementDirection(int d
) {
455 resource
.col_direction
= d
;
456 config
->setValue(screenstr
+ "colPlacementDirection",
457 resource
.col_direction
== TopBottom
?
458 "TopToBottom" : "BottomToTop");
462 void BScreen::saveStrftimeFormat(const std::string
& format
) {
463 resource
.strftime_format
= format
;
464 config
->setValue(screenstr
+ "strftimeFormat", resource
.strftime_format
);
468 void BScreen::saveWorkspaceNames() {
471 for (unsigned int i
= 0; i
< workspacesList
.size(); ++i
) {
472 names
+= workspacesList
[i
]->getName();
473 if (i
< workspacesList
.size() - 1)
477 config
->setValue(screenstr
+ "workspaceNames", names
);
481 void BScreen::savePlaceIgnoreShaded(bool i
) {
482 resource
.ignore_shaded
= i
;
483 config
->setValue(screenstr
+ "placementIgnoreShaded",
484 resource
.ignore_shaded
);
488 void BScreen::savePlaceIgnoreMaximized(bool i
) {
489 resource
.ignore_maximized
= i
;
490 config
->setValue(screenstr
+ "placementIgnoreMaximized",
491 resource
.ignore_maximized
);
495 void BScreen::saveAllowScrollLock(bool a
) {
496 resource
.allow_scroll_lock
= a
;
497 config
->setValue(screenstr
+ "disableBindingsWithScrollLock",
498 resource
.allow_scroll_lock
);
502 void BScreen::saveWorkspaceWarping(bool w
) {
503 resource
.workspace_warping
= w
;
504 config
->setValue(screenstr
+ "workspaceWarping",
505 resource
.workspace_warping
);
509 void BScreen::saveRootScrollDirection(int d
) {
510 resource
.root_scroll
= d
;
512 switch (resource
.root_scroll
) {
513 case NoScroll
: dir
= "None"; break;
514 case ReverseScroll
: dir
= "Reverse"; break;
515 case NormalScroll
: default: dir
= "Normal"; break;
517 config
->setValue(screenstr
+ "rootScrollDirection", dir
);
521 void BScreen::save_rc(void) {
522 saveSloppyFocus(resource
.sloppy_focus
);
523 saveAutoRaise(resource
.auto_raise
);
524 saveImageDither(doImageDither());
525 saveShadowFonts(resource
.shadow_fonts
);
526 saveAAFonts(resource
.aa_fonts
);
527 saveResizeZones(resource
.resize_zones
);
528 saveOpaqueMove(resource
.opaque_move
);
529 saveFullMax(resource
.full_max
);
530 saveFocusNew(resource
.focus_new
);
531 saveFocusLast(resource
.focus_last
);
532 saveWindowToWindowSnap(resource
.snap_to_windows
);
533 saveWindowToEdgeSnap(resource
.snap_to_edges
);
534 saveWindowCornerSnap(resource
.window_corner_snap
);
535 saveWorkspaces(resource
.workspaces
);
536 savePlacementPolicy(resource
.placement_policy
);
537 saveSnapThreshold(resource
.snap_threshold
);
538 saveSnapOffset(resource
.snap_offset
);
539 saveResistanceSize(resource
.resistance_size
);
540 saveRowPlacementDirection(resource
.row_direction
);
541 saveColPlacementDirection(resource
.col_direction
);
542 saveStrftimeFormat(resource
.strftime_format
);
543 savePlaceIgnoreShaded(resource
.ignore_shaded
);
544 savePlaceIgnoreMaximized(resource
.ignore_maximized
);
545 saveAllowScrollLock(resource
.allow_scroll_lock
);
546 saveWorkspaceWarping(resource
.workspace_warping
);
547 saveRootScrollDirection(resource
.root_scroll
);
551 void BScreen::load_rc(void) {
555 if (! config
->getValue(screenstr
+ "fullMaximization", resource
.full_max
))
556 resource
.full_max
= false;
558 if (! config
->getValue(screenstr
+ "focusNewWindows", resource
.focus_new
))
559 resource
.focus_new
= false;
561 if (! config
->getValue(screenstr
+ "focusLastWindow", resource
.focus_last
))
562 resource
.focus_last
= false;
564 if (! config
->getValue(screenstr
+ "workspaces", resource
.workspaces
))
565 resource
.workspaces
= 1;
567 if (! config
->getValue(screenstr
+ "opaqueMove", resource
.opaque_move
))
568 resource
.opaque_move
= false;
570 if (! config
->getValue(screenstr
+ "antialiasFonts", resource
.aa_fonts
))
571 resource
.aa_fonts
= true;
573 if (! resource
.aa_fonts
||
574 ! config
->getValue(screenstr
+ "dropShadowFonts", resource
.shadow_fonts
))
575 resource
.shadow_fonts
= false;
577 if (! config
->getValue(screenstr
+ "resizeZones", resource
.resize_zones
) ||
578 (resource
.resize_zones
!= 1 && resource
.resize_zones
!= 2 &&
579 resource
.resize_zones
!= 4))
580 resource
.resize_zones
= 4;
582 resource
.snap_to_windows
= WindowResistance
;
583 if (config
->getValue(screenstr
+ "windowToWindowSnap", s
)) {
585 resource
.snap_to_windows
= WindowNoSnap
;
586 else if (s
== "Snap")
587 resource
.snap_to_windows
= WindowSnap
;
590 resource
.snap_to_edges
= WindowResistance
;
591 if (config
->getValue(screenstr
+ "windowToEdgeSnap", s
)) {
593 resource
.snap_to_edges
= WindowNoSnap
;
594 else if (s
== "Snap")
595 resource
.snap_to_edges
= WindowSnap
;
598 if (! config
->getValue(screenstr
+ "windowCornerSnap",
599 resource
.window_corner_snap
))
600 resource
.window_corner_snap
= true;
602 if (! config
->getValue(screenstr
+ "imageDither", b
))
604 image_control
->setDither(b
);
606 if (! config
->getValue(screenstr
+ "edgeSnapOffset",
607 resource
.snap_offset
))
608 resource
.snap_offset
= 0;
609 if (resource
.snap_offset
> 50) // sanity check, setting this huge would
610 resource
.snap_offset
= 50; // seriously suck.
612 if (! config
->getValue(screenstr
+ "edgeSnapThreshold",
613 resource
.snap_threshold
))
614 resource
.snap_threshold
= 4;
616 if (! config
->getValue(screenstr
+ "resistanceSize",
617 resource
.resistance_size
))
618 resource
.resistance_size
= 18;
620 if (config
->getValue(screenstr
+ "rowPlacementDirection", s
) &&
622 resource
.row_direction
= RightLeft
;
624 resource
.row_direction
= LeftRight
;
626 if (config
->getValue(screenstr
+ "colPlacementDirection", s
) &&
628 resource
.col_direction
= BottomTop
;
630 resource
.col_direction
= TopBottom
;
632 if (config
->getValue(screenstr
+ "workspaceNames", s
)) {
633 XAtom::StringVect workspaceNames
;
635 string::const_iterator it
= s
.begin(), end
= s
.end();
637 string::const_iterator tmp
= it
; // current string.begin()
638 it
= std::find(tmp
, end
, ','); // look for comma between tmp and end
639 workspaceNames
.push_back(string(tmp
, it
)); // s[tmp:it]
645 xatom
->setValue(getRootWindow(), XAtom::net_desktop_names
, XAtom::utf8
,
649 resource
.sloppy_focus
= true;
650 resource
.auto_raise
= false;
651 resource
.click_raise
= false;
652 if (config
->getValue(screenstr
+ "focusModel", s
)) {
653 if (s
.find("ClickToFocus") != string::npos
) {
654 resource
.sloppy_focus
= false;
657 if (s
.find("AutoRaise") != string::npos
)
658 resource
.auto_raise
= true;
659 if (s
.find("ClickRaise") != string::npos
)
660 resource
.click_raise
= true;
664 if (config
->getValue(screenstr
+ "windowPlacement", s
)) {
665 if (s
== "CascadePlacement")
666 resource
.placement_policy
= CascadePlacement
;
667 else if (s
== "UnderMousePlacement")
668 resource
.placement_policy
= UnderMousePlacement
;
669 else if (s
== "ClickMousePlacement")
670 resource
.placement_policy
= ClickMousePlacement
;
671 else if (s
== "ColSmartPlacement")
672 resource
.placement_policy
= ColSmartPlacement
;
673 else //if (s == "RowSmartPlacement")
674 resource
.placement_policy
= RowSmartPlacement
;
676 resource
.placement_policy
= RowSmartPlacement
;
678 if (! config
->getValue(screenstr
+ "strftimeFormat",
679 resource
.strftime_format
))
680 resource
.strftime_format
= "%I:%M %p";
682 if (! config
->getValue(screenstr
+ "placementIgnoreShaded",
683 resource
.ignore_shaded
))
684 resource
.ignore_shaded
= true;
686 if (! config
->getValue(screenstr
+ "placementIgnoreMaximized",
687 resource
.ignore_maximized
))
688 resource
.ignore_maximized
= true;
690 if (! config
->getValue(screenstr
+ "disableBindingsWithScrollLock",
691 resource
.allow_scroll_lock
))
692 resource
.allow_scroll_lock
= false;
694 if (! config
->getValue(screenstr
+ "workspaceWarping",
695 resource
.workspace_warping
))
696 resource
.workspace_warping
= false;
698 resource
.root_scroll
= NormalScroll
;
699 if (config
->getValue(screenstr
+ "rootScrollDirection", s
)) {
701 resource
.root_scroll
= NoScroll
;
702 else if (s
== "Reverse")
703 resource
.root_scroll
= ReverseScroll
;
708 void BScreen::changeWorkspaceCount(unsigned int new_count
) {
709 assert(new_count
> 0);
711 if (new_count
< workspacesList
.size()) {
713 for (unsigned int i
= workspacesList
.size(); i
> new_count
; --i
)
714 removeLastWorkspace();
715 // removeLast already sets the current workspace to the
716 // last available one.
717 } else if (new_count
> workspacesList
.size()) {
719 for(unsigned int i
= workspacesList
.size(); i
< new_count
; ++i
)
725 void BScreen::reconfigure(void) {
726 // don't reconfigure while saving the initial rc file, it's a waste and it
727 // breaks somethings (workspace names)
728 if (blackbox
->state() == Openbox::State_Starting
) return;
733 // we need to do this explicitly, because just loading this value from the rc
735 changeWorkspaceCount(resource
.workspaces
);
738 gcv
.foreground
= WhitePixel(otk::OBDisplay::display
,
740 gcv
.function
= GXinvert
;
741 gcv
.subwindow_mode
= IncludeInferiors
;
742 XChangeGC(otk::OBDisplay::display
, opGC
,
743 GCForeground
| GCFunction
| GCSubwindowMode
, &gcv
);
745 const char *s
= "0: 0000 x 0: 0000";
747 geom_w
= resource
.wstyle
.font
->measureString(s
) + resource
.bevel_width
* 2;
748 geom_h
= resource
.wstyle
.font
->height() + resource
.bevel_width
* 2;
750 otk::BTexture
* texture
= &(resource
.wstyle
.l_focus
);
751 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
752 if (geom_pixmap
== ParentRelative
) {
753 texture
= &(resource
.wstyle
.t_focus
);
754 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
757 XSetWindowBackground(otk::OBDisplay::display
, geom_window
,
758 texture
->color().pixel());
760 XSetWindowBackgroundPixmap(otk::OBDisplay::display
,
761 geom_window
, geom_pixmap
);
763 XSetWindowBorderWidth(otk::OBDisplay::display
, geom_window
,
764 resource
.border_width
);
765 XSetWindowBorder(otk::OBDisplay::display
, geom_window
,
766 resource
.border_color
.pixel());
768 typedef std::vector
<int> SubList
;
769 SubList remember_subs
;
773 std::for_each(workspacesList
.begin(), workspacesList
.end(),
774 std::mem_fun(&Workspace::reconfigure
));
776 BlackboxWindowList::iterator iit
= iconList
.begin();
777 for (; iit
!= iconList
.end(); ++iit
) {
778 BlackboxWindow
*bw
= *iit
;
779 if (bw
->validateClient())
783 otk::BImageControl::timeout(image_control
);
787 void BScreen::LoadStyle(void) {
788 Configuration
style(False
);
790 const char *sfile
= blackbox
->getStyleFilename();
792 style
.setFile(sfile
);
793 if (! style
.load()) {
794 style
.setFile(DEFAULTSTYLE
);
796 style
.create(); // hardcoded default values will be used.
800 // merge in the rc file
801 style
.merge(config
->file(), True
);
805 // load fonts/fontsets
806 if (resource
.wstyle
.font
)
807 delete resource
.wstyle
.font
;
809 resource
.wstyle
.font
= readDatabaseFont("window.", style
);
811 // load window config
812 resource
.wstyle
.t_focus
=
813 readDatabaseTexture("window.title.focus", "white", style
);
814 resource
.wstyle
.t_unfocus
=
815 readDatabaseTexture("window.title.unfocus", "black", style
);
816 resource
.wstyle
.l_focus
=
817 readDatabaseTexture("window.label.focus", "white", style
);
818 resource
.wstyle
.l_unfocus
=
819 readDatabaseTexture("window.label.unfocus", "black", style
);
820 resource
.wstyle
.h_focus
=
821 readDatabaseTexture("window.handle.focus", "white", style
);
822 resource
.wstyle
.h_unfocus
=
823 readDatabaseTexture("window.handle.unfocus", "black", style
);
824 resource
.wstyle
.g_focus
=
825 readDatabaseTexture("window.grip.focus", "white", style
);
826 resource
.wstyle
.g_unfocus
=
827 readDatabaseTexture("window.grip.unfocus", "black", style
);
828 resource
.wstyle
.b_focus
=
829 readDatabaseTexture("window.button.focus", "white", style
);
830 resource
.wstyle
.b_unfocus
=
831 readDatabaseTexture("window.button.unfocus", "black", style
);
832 resource
.wstyle
.b_pressed
=
833 readDatabaseTexture("window.button.pressed", "black", style
);
835 //if neither of these can be found, we will use the previous resource
836 resource
.wstyle
.b_pressed_focus
=
837 readDatabaseTexture("window.button.pressed.focus", "black", style
, true);
838 resource
.wstyle
.b_pressed_unfocus
=
839 readDatabaseTexture("window.button.pressed.unfocus", "black", style
, true);
841 if (resource
.wstyle
.close_button
.mask
!= None
)
842 XFreePixmap(otk::OBDisplay::display
, resource
.wstyle
.close_button
.mask
);
843 if (resource
.wstyle
.max_button
.mask
!= None
)
844 XFreePixmap(otk::OBDisplay::display
, resource
.wstyle
.max_button
.mask
);
845 if (resource
.wstyle
.icon_button
.mask
!= None
)
846 XFreePixmap(otk::OBDisplay::display
, resource
.wstyle
.icon_button
.mask
);
847 if (resource
.wstyle
.stick_button
.mask
!= None
)
848 XFreePixmap(otk::OBDisplay::display
, resource
.wstyle
.stick_button
.mask
);
850 resource
.wstyle
.close_button
.mask
= resource
.wstyle
.max_button
.mask
=
851 resource
.wstyle
.icon_button
.mask
=
852 resource
.wstyle
.icon_button
.mask
= None
;
854 readDatabaseMask("window.button.close.mask", resource
.wstyle
.close_button
,
856 readDatabaseMask("window.button.max.mask", resource
.wstyle
.max_button
,
858 readDatabaseMask("window.button.icon.mask", resource
.wstyle
.icon_button
,
860 readDatabaseMask("window.button.stick.mask", resource
.wstyle
.stick_button
,
863 // we create the window.frame texture by hand because it exists only to
864 // make the code cleaner and is not actually used for display
865 otk::BColor color
= readDatabaseColor("window.frame.focusColor", "white",
867 resource
.wstyle
.f_focus
= otk::BTexture("solid flat", getScreenNumber(),
869 resource
.wstyle
.f_focus
.setColor(color
);
871 color
= readDatabaseColor("window.frame.unfocusColor", "white", style
);
872 resource
.wstyle
.f_unfocus
= otk::BTexture("solid flat", getScreenNumber(),
874 resource
.wstyle
.f_unfocus
.setColor(color
);
876 resource
.wstyle
.l_text_focus
=
877 readDatabaseColor("window.label.focus.textColor", "black", style
);
878 resource
.wstyle
.l_text_unfocus
=
879 readDatabaseColor("window.label.unfocus.textColor", "white", style
);
880 resource
.wstyle
.b_pic_focus
=
881 readDatabaseColor("window.button.focus.picColor", "black", style
);
882 resource
.wstyle
.b_pic_unfocus
=
883 readDatabaseColor("window.button.unfocus.picColor", "white", style
);
885 resource
.wstyle
.justify
= LeftJustify
;
886 if (style
.getValue("window.justify", s
)) {
887 if (s
== "right" || s
== "Right")
888 resource
.wstyle
.justify
= RightJustify
;
889 else if (s
== "center" || s
== "Center")
890 resource
.wstyle
.justify
= CenterJustify
;
894 if (resource
.wstyle
.t_focus
.texture() == otk::BTexture::Parent_Relative
)
895 resource
.wstyle
.t_focus
= resource
.wstyle
.f_focus
;
896 if (resource
.wstyle
.t_unfocus
.texture() == otk::BTexture::Parent_Relative
)
897 resource
.wstyle
.t_unfocus
= resource
.wstyle
.f_unfocus
;
898 if (resource
.wstyle
.h_focus
.texture() == otk::BTexture::Parent_Relative
)
899 resource
.wstyle
.h_focus
= resource
.wstyle
.f_focus
;
900 if (resource
.wstyle
.h_unfocus
.texture() == otk::BTexture::Parent_Relative
)
901 resource
.wstyle
.h_unfocus
= resource
.wstyle
.f_unfocus
;
903 resource
.border_color
=
904 readDatabaseColor("borderColor", "black", style
);
906 // load bevel, border and handle widths
907 if (! style
.getValue("handleWidth", resource
.handle_width
) ||
908 resource
.handle_width
> (getWidth() / 2) || resource
.handle_width
== 0)
909 resource
.handle_width
= 6;
911 if (! style
.getValue("borderWidth", resource
.border_width
))
912 resource
.border_width
= 1;
914 if (! style
.getValue("bevelWidth", resource
.bevel_width
) ||
915 resource
.bevel_width
> (getWidth() / 2) || resource
.bevel_width
== 0)
916 resource
.bevel_width
= 3;
918 if (! style
.getValue("frameWidth", resource
.frame_width
) ||
919 resource
.frame_width
> (getWidth() / 2))
920 resource
.frame_width
= resource
.bevel_width
;
922 if (style
.getValue("rootCommand", s
))
923 bexec(s
, displayString());
927 void BScreen::addIcon(BlackboxWindow
*w
) {
930 w
->setWorkspace(BSENTINEL
);
931 w
->setWindowNumber(iconList
.size());
933 iconList
.push_back(w
);
937 void BScreen::removeIcon(BlackboxWindow
*w
) {
942 BlackboxWindowList::iterator it
= iconList
.begin(),
943 end
= iconList
.end();
944 for (int i
= 0; it
!= end
; ++it
)
945 (*it
)->setWindowNumber(i
++);
949 BlackboxWindow
*BScreen::getIcon(unsigned int index
) {
950 if (index
< iconList
.size()) {
951 BlackboxWindowList::iterator it
= iconList
.begin();
952 while (index
-- > 0) // increment to index
957 return (BlackboxWindow
*) 0;
961 unsigned int BScreen::addWorkspace(void) {
962 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
963 workspacesList
.push_back(wkspc
);
964 saveWorkspaces(getWorkspaceCount());
965 saveWorkspaceNames();
967 return workspacesList
.size();
971 unsigned int BScreen::removeLastWorkspace(void) {
972 if (workspacesList
.size() == 1)
975 Workspace
*wkspc
= workspacesList
.back();
977 if (current_workspace
->getID() == wkspc
->getID())
978 changeWorkspaceID(current_workspace
->getID() - 1);
982 workspacesList
.pop_back();
985 saveWorkspaces(getWorkspaceCount());
986 saveWorkspaceNames();
988 updateNetizenWorkspaceCount();
990 return workspacesList
.size();
994 void BScreen::changeWorkspaceID(unsigned int id
) {
995 if (! current_workspace
|| id
== current_workspace
->getID()) return;
997 BlackboxWindow
*focused
= blackbox
->getFocusedWindow();
998 if (focused
&& focused
->getScreen() == this) {
999 assert(focused
->isStuck() ||
1000 focused
->getWorkspaceNumber() == current_workspace
->getID());
1002 current_workspace
->setLastFocusedWindow(focused
);
1004 // if no window had focus, no need to store a last focus
1005 current_workspace
->setLastFocusedWindow((BlackboxWindow
*) 0);
1008 // when we switch workspaces, unfocus whatever was focused if it is going
1010 if (focused
&& ! focused
->isStuck())
1011 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1013 current_workspace
->hideAll();
1015 current_workspace
= getWorkspace(id
);
1017 xatom
->setValue(getRootWindow(), XAtom::net_current_desktop
,
1018 XAtom::cardinal
, id
);
1020 current_workspace
->showAll();
1025 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
1028 XSync(otk::OBDisplay::display
, False
);
1030 // If sloppy focus and we can find the client window under the pointer,
1032 if (resource
.sloppy_focus
&&
1033 XQueryPointer(otk::OBDisplay::display
, getRootWindow(), &r
, &c
,
1034 &rx
, &ry
, &x
, &y
, &m
) &&
1036 if ( (win
= blackbox
->searchWindow(c
)) )
1037 f
= win
->setInputFocus();
1040 // If that fails, and we're doing focus_last, try to focus the last window.
1041 if (! f
&& resource
.focus_last
&&
1042 (win
= current_workspace
->getLastFocusedWindow()))
1043 f
= win
->setInputFocus();
1046 if we found a focus target, then we set the focused window explicitly
1047 because it is possible to switch off this workspace before the x server
1048 generates the FocusIn event for the window. if that happens, openbox would
1049 lose track of what window was the 'LastFocused' window on the workspace.
1051 if we did not find a focus target, then set the current focused window to
1055 blackbox
->setFocusedWindow(win
);
1057 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1062 * Set the _NET_CLIENT_LIST root window property.
1064 void BScreen::updateClientList(void) {
1065 if (windowList
.size() > 0) {
1066 Window
*windows
= new Window
[windowList
.size()];
1067 Window
*win_it
= windows
;
1068 BlackboxWindowList::iterator it
= windowList
.begin();
1069 const BlackboxWindowList::iterator end
= windowList
.end();
1070 for (; it
!= end
; ++it
, ++win_it
)
1071 *win_it
= (*it
)->getClientWindow();
1072 xatom
->setValue(getRootWindow(), XAtom::net_client_list
, XAtom::window
,
1073 windows
, windowList
.size());
1076 xatom
->setValue(getRootWindow(), XAtom::net_client_list
, XAtom::window
,
1079 updateStackingList();
1084 * Set the _NET_CLIENT_LIST_STACKING root window property.
1086 void BScreen::updateStackingList(void) {
1088 BlackboxWindowList stack_order
;
1091 * Get the stacking order from all of the workspaces.
1092 * We start with the current workspace so that the sticky windows will be
1093 * in the right order on the current workspace.
1094 * XXX: Do we need to have sticky windows in the list once for each workspace?
1096 getCurrentWorkspace()->appendStackOrder(stack_order
);
1097 for (unsigned int i
= 0; i
< getWorkspaceCount(); ++i
)
1098 if (i
!= getCurrentWorkspaceID())
1099 getWorkspace(i
)->appendStackOrder(stack_order
);
1101 if (stack_order
.size() > 0) {
1102 // set the client list atoms
1103 Window
*windows
= new Window
[stack_order
.size()];
1104 Window
*win_it
= windows
;
1105 BlackboxWindowList::iterator it
= stack_order
.begin(),
1106 end
= stack_order
.end();
1107 for (; it
!= end
; ++it
, ++win_it
)
1108 *win_it
= (*it
)->getClientWindow();
1109 xatom
->setValue(getRootWindow(), XAtom::net_client_list_stacking
,
1110 XAtom::window
, windows
, stack_order
.size());
1113 xatom
->setValue(getRootWindow(), XAtom::net_client_list_stacking
,
1114 XAtom::window
, 0, 0);
1118 void BScreen::addSystrayWindow(Window window
) {
1119 XGrabServer(otk::OBDisplay::display
);
1121 XSelectInput(otk::OBDisplay::display
, window
, StructureNotifyMask
);
1122 systrayWindowList
.push_back(window
);
1123 xatom
->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows
,
1125 &systrayWindowList
[0], systrayWindowList
.size());
1126 blackbox
->saveSystrayWindowSearch(window
, this);
1128 XUngrabServer(otk::OBDisplay::display
);
1132 void BScreen::removeSystrayWindow(Window window
) {
1133 XGrabServer(otk::OBDisplay::display
);
1135 WindowList::iterator it
= systrayWindowList
.begin();
1136 const WindowList::iterator end
= systrayWindowList
.end();
1137 for (; it
!= end
; ++it
)
1138 if (*it
== window
) {
1139 systrayWindowList
.erase(it
);
1140 xatom
->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows
,
1142 &systrayWindowList
[0], systrayWindowList
.size());
1143 blackbox
->removeSystrayWindowSearch(window
);
1144 XSelectInput(otk::OBDisplay::display
, window
, NoEventMask
);
1148 assert(it
!= end
); // not a systray window
1150 XUngrabServer(otk::OBDisplay::display
);
1154 void BScreen::manageWindow(Window w
) {
1155 // is the window a KDE systray window?
1157 if (xatom
->getValue(w
, XAtom::kde_net_wm_system_tray_window_for
,
1158 XAtom::window
, systray
) && systray
!= None
) {
1159 addSystrayWindow(w
);
1163 // is the window a docking app
1164 XWMHints
*wmhint
= XGetWMHints(otk::OBDisplay::display
, w
);
1165 if (wmhint
&& (wmhint
->flags
& StateHint
) &&
1166 wmhint
->initial_state
== WithdrawnState
) {
1167 //slit->addClient(w);
1171 new BlackboxWindow(blackbox
, w
, this);
1173 BlackboxWindow
*win
= blackbox
->searchWindow(w
);
1177 if (win
->isDesktop()) {
1178 desktopWindowList
.push_back(win
->getFrameWindow());
1179 } else { // if (win->isNormal()) {
1180 // don't list desktop windows as managed windows
1181 windowList
.push_back(win
);
1184 if (win
->isTopmost())
1185 specialWindowList
.push_back(win
->getFrameWindow());
1188 XMapRequestEvent mre
;
1190 if (blackbox
->state() == Openbox::State_Starting
&&
1192 win
->restoreAttributes();
1193 win
->mapRequestEvent(&mre
);
1197 void BScreen::unmanageWindow(BlackboxWindow
*w
, bool remap
) {
1198 // is the window a KDE systray window?
1200 if (xatom
->getValue(w
->getClientWindow(),
1201 XAtom::kde_net_wm_system_tray_window_for
,
1202 XAtom::window
, systray
) && systray
!= None
) {
1203 removeSystrayWindow(w
->getClientWindow());
1209 // Remove the modality so that its parent won't try to re-focus the window
1210 if (w
->isModal()) w
->setModal(False
);
1212 if (w
->getWorkspaceNumber() != BSENTINEL
&&
1213 w
->getWindowNumber() != BSENTINEL
) {
1214 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1216 for (unsigned int i
= 0; i
< getNumberOfWorkspaces(); ++i
)
1217 if (i
!= w
->getWorkspaceNumber())
1218 getWorkspace(i
)->removeWindow(w
, True
);
1220 } else if (w
->isIconic())
1223 if (w
->isDesktop()) {
1224 WindowList::iterator it
= desktopWindowList
.begin();
1225 const WindowList::iterator end
= desktopWindowList
.end();
1226 for (; it
!= end
; ++it
)
1227 if (*it
== w
->getFrameWindow()) {
1228 desktopWindowList
.erase(it
);
1231 assert(it
!= end
); // the window wasnt a desktop window?
1232 } else { // if (w->isNormal()) {
1233 // we don't list desktop windows as managed windows
1234 windowList
.remove(w
);
1237 if (w
->isTopmost()) {
1238 WindowList::iterator it
= specialWindowList
.begin();
1239 const WindowList::iterator end
= specialWindowList
.end();
1240 for (; it
!= end
; ++it
)
1241 if (*it
== w
->getFrameWindow()) {
1242 specialWindowList
.erase(it
);
1245 assert(it
!= end
); // the window wasnt a special window?
1249 if (blackbox
->getFocusedWindow() == w
)
1250 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1253 some managed windows can also be window group controllers. when
1254 unmanaging such windows, we should also delete the window group.
1256 BWindowGroup
*group
= blackbox
->searchGroup(w
->getClientWindow());
1263 void BScreen::updateWorkArea(void) {
1264 if (workspacesList
.size() > 0) {
1265 unsigned long *dims
= new unsigned long[4 * workspacesList
.size()];
1266 for (unsigned int i
= 0, m
= workspacesList
.size(); i
< m
; ++i
) {
1267 // XXX: this could be different for each workspace
1268 const otk::Rect
&area
= availableArea();
1269 dims
[(i
* 4) + 0] = area
.x();
1270 dims
[(i
* 4) + 1] = area
.y();
1271 dims
[(i
* 4) + 2] = area
.width();
1272 dims
[(i
* 4) + 3] = area
.height();
1274 xatom
->setValue(getRootWindow(), XAtom::net_workarea
, XAtom::cardinal
,
1275 dims
, 4 * workspacesList
.size());
1278 xatom
->setValue(getRootWindow(), XAtom::net_workarea
, XAtom::cardinal
,
1283 void BScreen::updateNetizenWorkspaceCount(void) {
1284 xatom
->setValue(getRootWindow(), XAtom::net_number_of_desktops
,
1285 XAtom::cardinal
, workspacesList
.size());
1291 void BScreen::updateNetizenWindowFocus(void) {
1292 Window f
= ((blackbox
->getFocusedWindow()) ?
1293 blackbox
->getFocusedWindow()->getClientWindow() : None
);
1295 xatom
->setValue(getRootWindow(), XAtom::net_active_window
,
1300 void BScreen::raiseWindows(Window
*workspace_stack
, unsigned int num
) {
1301 // the 13 represents the number of blackbox windows such as menus
1307 Window
*session_stack
= new
1308 Window
[(num
+ specialWindowList
.size() + bbwins
)];
1309 unsigned int i
= 0, k
= num
;
1311 WindowList::iterator sit
, send
= specialWindowList
.end();
1312 for (sit
= specialWindowList
.begin(); sit
!= send
; ++sit
)
1313 *(session_stack
+ i
++) = *sit
;
1316 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
1318 XRestackWindows(otk::OBDisplay::display
, session_stack
, i
);
1320 delete [] session_stack
;
1322 updateStackingList();
1326 void BScreen::lowerWindows(Window
*workspace_stack
, unsigned int num
) {
1327 assert(num
> 0); // this would cause trouble in the XRaiseWindow call
1329 Window
*session_stack
= new Window
[(num
+ desktopWindowList
.size())];
1330 unsigned int i
= 0, k
= num
;
1332 XLowerWindow(otk::OBDisplay::display
, workspace_stack
[0]);
1335 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
1337 WindowList::iterator dit
= desktopWindowList
.begin();
1338 const WindowList::iterator d_end
= desktopWindowList
.end();
1339 for (; dit
!= d_end
; ++dit
)
1340 *(session_stack
+ i
++) = *dit
;
1342 XRestackWindows(otk::OBDisplay::display
, session_stack
, i
);
1344 delete [] session_stack
;
1346 updateStackingList();
1350 void BScreen::reassociateWindow(BlackboxWindow
*w
, unsigned int wkspc_id
,
1351 bool ignore_sticky
) {
1354 if (wkspc_id
== BSENTINEL
)
1355 wkspc_id
= current_workspace
->getID();
1357 if (w
->getWorkspaceNumber() == wkspc_id
)
1360 if (w
->isIconic()) {
1362 getWorkspace(wkspc_id
)->addWindow(w
);
1364 for (unsigned int i
= 0; i
< getNumberOfWorkspaces(); ++i
)
1365 if (i
!= w
->getWorkspaceNumber())
1366 getWorkspace(i
)->addWindow(w
, True
);
1367 } else if (ignore_sticky
|| ! w
->isStuck()) {
1370 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1371 getWorkspace(wkspc_id
)->addWindow(w
);
1373 updateStackingList();
1377 void BScreen::propagateWindowName(const BlackboxWindow
*bw
) {
1378 if (bw
->isIconic()) {
1384 void BScreen::nextFocus(void) const {
1385 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1389 focused
->getScreen()->getScreenNumber() == getScreenNumber() &&
1390 current_workspace
->getCount() > 1) {
1392 next
= current_workspace
->getNextWindowInList(next
);
1393 } while (next
!= focused
&& ! next
->setInputFocus());
1395 if (next
!= focused
)
1396 current_workspace
->raiseWindow(next
);
1397 } else if (current_workspace
->getCount() > 0) {
1398 next
= current_workspace
->getTopWindowOnStack();
1399 next
->setInputFocus();
1400 current_workspace
->raiseWindow(next
);
1405 void BScreen::prevFocus(void) const {
1406 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1410 // if window is not on this screen, ignore it
1411 if (focused
->getScreen()->getScreenNumber() != getScreenNumber())
1412 focused
= (BlackboxWindow
*) 0;
1416 focused
->getScreen()->getScreenNumber() == getScreenNumber() &&
1417 current_workspace
->getCount() > 1) {
1418 // next is the next window to receive focus, current is a place holder
1420 next
= current_workspace
->getPrevWindowInList(next
);
1421 } while (next
!= focused
&& ! next
->setInputFocus());
1423 if (next
!= focused
)
1424 current_workspace
->raiseWindow(next
);
1425 } else if (current_workspace
->getCount() > 0) {
1426 next
= current_workspace
->getTopWindowOnStack();
1427 next
->setInputFocus();
1428 current_workspace
->raiseWindow(next
);
1433 void BScreen::raiseFocus(void) const {
1434 BlackboxWindow
*focused
= blackbox
->getFocusedWindow();
1438 // if on this Screen, raise it
1439 if (focused
->getScreen()->getScreenNumber() == getScreenNumber()) {
1440 Workspace
*workspace
= getWorkspace(focused
->getWorkspaceNumber());
1441 workspace
->raiseWindow(focused
);
1446 void BScreen::shutdown(void) {
1447 XSelectInput(otk::OBDisplay::display
, getRootWindow(), NoEventMask
);
1448 XSync(otk::OBDisplay::display
, False
);
1450 while(! windowList
.empty())
1451 unmanageWindow(windowList
.front(), True
);
1453 while(! desktopWindowList
.empty()) {
1454 BlackboxWindow
*win
= blackbox
->searchWindow(desktopWindowList
.front());
1456 unmanageWindow(win
, True
);
1461 void BScreen::showPosition(int x
, int y
) {
1462 if (! geom_visible
) {
1463 XMoveResizeWindow(otk::OBDisplay::display
, geom_window
,
1464 (getWidth() - geom_w
) / 2,
1465 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
1466 XMapWindow(otk::OBDisplay::display
, geom_window
);
1467 XRaiseWindow(otk::OBDisplay::display
, geom_window
);
1469 geom_visible
= True
;
1474 sprintf(label
, "X: %4d x Y: %4d", x
, y
);
1476 XClearWindow(otk::OBDisplay::display
, geom_window
);
1478 resource
.wstyle
.font
->drawString(geom_window
,
1479 resource
.bevel_width
, resource
.bevel_width
,
1480 resource
.wstyle
.l_text_focus
,
1485 void BScreen::showGeometry(unsigned int gx
, unsigned int gy
) {
1486 if (! geom_visible
) {
1487 XMoveResizeWindow(otk::OBDisplay::display
, geom_window
,
1488 (getWidth() - geom_w
) / 2,
1489 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
1490 XMapWindow(otk::OBDisplay::display
, geom_window
);
1491 XRaiseWindow(otk::OBDisplay::display
, geom_window
);
1493 geom_visible
= True
;
1498 sprintf(label
, "W: %4d x H: %4d", gx
, gy
);
1500 XClearWindow(otk::OBDisplay::display
, geom_window
);
1502 resource
.wstyle
.font
->drawString(geom_window
,
1503 resource
.bevel_width
, resource
.bevel_width
,
1504 resource
.wstyle
.l_text_focus
,
1509 void BScreen::hideGeometry(void) {
1511 XUnmapWindow(otk::OBDisplay::display
, geom_window
);
1512 geom_visible
= False
;
1517 void BScreen::addStrut(Strut
*strut
) {
1518 strutList
.push_back(strut
);
1522 void BScreen::removeStrut(Strut
*strut
) {
1523 strutList
.remove(strut
);
1527 const otk::Rect
& BScreen::availableArea(void) const {
1529 return getRect(); // return the full screen
1535 const RectList
& BScreen::allAvailableAreas(void) const {
1536 assert(isXineramaActive());
1537 assert(xineramaUsableArea
.size() > 0);
1538 fprintf(stderr
, "1found x %d y %d w %d h %d\n",
1539 xineramaUsableArea
[0].x(), xineramaUsableArea
[0].y(),
1540 xineramaUsableArea
[0].width(), xineramaUsableArea
[0].height());
1541 return xineramaUsableArea
;
1546 void BScreen::updateAvailableArea(void) {
1547 otk::Rect old_area
= usableArea
;
1548 usableArea
= getRect(); // reset to full screen
1551 // reset to the full areas
1552 if (isXineramaActive())
1553 xineramaUsableArea
= getXineramaAreas();
1556 /* these values represent offsets from the screen edge
1557 * we look for the biggest offset on each edge and then apply them
1559 * do not be confused by the similarity to the names of Rect's members
1561 unsigned int current_left
= 0, current_right
= 0, current_top
= 0,
1564 StrutList::const_iterator it
= strutList
.begin(), end
= strutList
.end();
1566 for(; it
!= end
; ++it
) {
1568 if (strut
->left
> current_left
)
1569 current_left
= strut
->left
;
1570 if (strut
->top
> current_top
)
1571 current_top
= strut
->top
;
1572 if (strut
->right
> current_right
)
1573 current_right
= strut
->right
;
1574 if (strut
->bottom
> current_bottom
)
1575 current_bottom
= strut
->bottom
;
1578 usableArea
.setPos(current_left
, current_top
);
1579 usableArea
.setSize(usableArea
.width() - (current_left
+ current_right
),
1580 usableArea
.height() - (current_top
+ current_bottom
));
1583 if (isXineramaActive()) {
1584 // keep each of the ximerama-defined areas inside the strut
1585 RectList::iterator xit
, xend
= xineramaUsableArea
.end();
1586 for (xit
= xineramaUsableArea
.begin(); xit
!= xend
; ++xit
) {
1587 if (xit
->x() < usableArea
.x()) {
1588 xit
->setX(usableArea
.x());
1589 xit
->setWidth(xit
->width() - usableArea
.x());
1591 if (xit
->y() < usableArea
.y()) {
1592 xit
->setY(usableArea
.y());
1593 xit
->setHeight(xit
->height() - usableArea
.y());
1595 if (xit
->x() + xit
->width() > usableArea
.width())
1596 xit
->setWidth(usableArea
.width() - xit
->x());
1597 if (xit
->y() + xit
->height() > usableArea
.height())
1598 xit
->setHeight(usableArea
.height() - xit
->y());
1603 if (old_area
!= usableArea
) {
1604 BlackboxWindowList::iterator it
= windowList
.begin(),
1605 end
= windowList
.end();
1606 for (; it
!= end
; ++it
)
1607 if ((*it
)->isMaximized()) (*it
)->remaximize();
1614 Workspace
* BScreen::getWorkspace(unsigned int index
) const {
1615 assert(index
< workspacesList
.size());
1616 return workspacesList
[index
];
1620 void BScreen::buttonPressEvent(const XButtonEvent
*xbutton
) {
1621 if (xbutton
->button
== 1) {
1622 if (! isRootColormapInstalled())
1623 image_control
->installRootColormap();
1626 } else if ((xbutton
->button
== 4 && resource
.root_scroll
== NormalScroll
) ||
1627 (xbutton
->button
== 5 && resource
.root_scroll
== ReverseScroll
)) {
1628 if (getCurrentWorkspaceID() >= getWorkspaceCount() - 1)
1629 changeWorkspaceID(0);
1631 changeWorkspaceID(getCurrentWorkspaceID() + 1);
1633 } else if ((xbutton
->button
== 5 && resource
.root_scroll
== NormalScroll
) ||
1634 (xbutton
->button
== 4 && resource
.root_scroll
== ReverseScroll
)) {
1635 if (getCurrentWorkspaceID() == 0)
1636 changeWorkspaceID(getWorkspaceCount() - 1);
1638 changeWorkspaceID(getCurrentWorkspaceID() - 1);
1643 void BScreen::propertyNotifyEvent(const XPropertyEvent
*pe
) {
1644 if (pe
->atom
== xatom
->getAtom(XAtom::net_desktop_names
)) {
1645 // _NET_WM_DESKTOP_NAMES
1646 WorkspaceList::iterator it
= workspacesList
.begin();
1647 const WorkspaceList::iterator end
= workspacesList
.end();
1648 for (; it
!= end
; ++it
) {
1649 (*it
)->readName(); // re-read its name from the window property
1650 //workspacemenu->changeWorkspaceLabel((*it)->getID(), (*it)->getName());
1652 //workspacemenu->update();
1653 saveWorkspaceNames();
1658 void BScreen::toggleFocusModel(FocusModel model
) {
1659 std::for_each(windowList
.begin(), windowList
.end(),
1660 std::mem_fun(&BlackboxWindow::ungrabButtons
));
1662 if (model
== SloppyFocus
) {
1663 saveSloppyFocus(True
);
1665 // we're cheating here to save writing the config file 3 times
1666 resource
.auto_raise
= False
;
1667 resource
.click_raise
= False
;
1668 saveSloppyFocus(False
);
1671 std::for_each(windowList
.begin(), windowList
.end(),
1672 std::mem_fun(&BlackboxWindow::grabButtons
));
1675 void BScreen::readDatabaseMask(const string
&rname
, PixmapMask
&pixmapMask
,
1676 const Configuration
&style
) {
1678 int hx
, hy
; //ignored
1679 int ret
= BitmapOpenFailed
; //default to failure.
1681 if (style
.getValue(rname
, s
))
1683 if (s
[0] != '/' && s
[0] != '~')
1685 std::string xbmFile
= std::string("~/.openbox/buttons/") + s
;
1686 ret
= XReadBitmapFile(otk::OBDisplay::display
, getRootWindow(),
1687 expandTilde(xbmFile
).c_str(), &pixmapMask
.w
,
1688 &pixmapMask
.h
, &pixmapMask
.mask
, &hx
, &hy
);
1690 ret
= XReadBitmapFile(otk::OBDisplay::display
, getRootWindow(),
1691 expandTilde(s
).c_str(), &pixmapMask
.w
,
1692 &pixmapMask
.h
, &pixmapMask
.mask
, &hx
, &hy
);
1694 if (ret
== BitmapSuccess
)
1698 pixmapMask
.mask
= None
;
1699 pixmapMask
.w
= pixmapMask
.h
= 0;
1702 otk::BTexture
BScreen::readDatabaseTexture(const string
&rname
,
1703 const string
&default_color
,
1704 const Configuration
&style
,
1705 bool allowNoTexture
) {
1706 otk::BTexture texture
;
1709 if (style
.getValue(rname
, s
))
1710 texture
= otk::BTexture(s
);
1711 else if (allowNoTexture
) //no default
1712 texture
.setTexture(otk::BTexture::NoTexture
);
1714 texture
.setTexture(otk::BTexture::Solid
| otk::BTexture::Flat
);
1716 // associate this texture with this screen
1717 texture
.setScreen(getScreenNumber());
1718 texture
.setImageControl(image_control
);
1720 if (texture
.texture() != otk::BTexture::NoTexture
) {
1721 texture
.setColor(readDatabaseColor(rname
+ ".color", default_color
,
1723 texture
.setColorTo(readDatabaseColor(rname
+ ".colorTo", default_color
,
1725 texture
.setBorderColor(readDatabaseColor(rname
+ ".borderColor",
1726 default_color
, style
));
1733 otk::BColor
BScreen::readDatabaseColor(const string
&rname
,
1734 const string
&default_color
,
1735 const Configuration
&style
) {
1738 if (style
.getValue(rname
, s
))
1739 color
= otk::BColor(s
, getScreenNumber());
1741 color
= otk::BColor(default_color
, getScreenNumber());
1746 otk::BFont
*BScreen::readDatabaseFont(const string
&rbasename
,
1747 const Configuration
&style
) {
1753 if (style
.getValue(rbasename
+ "xft.font", s
) &&
1754 style
.getValue(rbasename
+ "xft.size", i
)) {
1757 bool italic
= False
;
1758 bool dropShadow
= False
;
1760 if (style
.getValue(rbasename
+ "xft.flags", s
)) {
1761 if (s
.find("bold") != string::npos
)
1763 if (s
.find("italic") != string::npos
)
1765 if (s
.find("shadow") != string::npos
)
1769 unsigned char offset
= 1;
1770 if (style
.getValue(rbasename
+ "xft.shadow.offset", s
)) {
1771 offset
= atoi(s
.c_str()); //doesn't detect errors
1772 if (offset
> CHAR_MAX
)
1776 unsigned char tint
= 0x40;
1777 if (style
.getValue(rbasename
+ "xft.shadow.tint", s
)) {
1778 tint
= atoi(s
.c_str());
1782 otk::BFont
*b
= new otk::BFont(getScreenNumber(), family
, i
, bold
, italic
,
1783 dropShadow
&& resource
.shadow_fonts
,
1784 offset
, tint
, resource
.aa_fonts
);
1790 exit(2); // can't continue without a font