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"
68 #ifndef FONT_ELEMENT_SIZE
69 #define FONT_ELEMENT_SIZE 50
70 #endif // FONT_ELEMENT_SIZE
74 static bool running
= True
;
76 static int anotherWMRunning(Display
*display
, XErrorEvent
*) {
78 "BScreen::BScreen: an error occured while querying the X server.\n"
79 " another window manager already running on display %s.\n",
80 DisplayString(display
));
88 BScreen::BScreen(Blackbox
*bb
, unsigned int scrn
) : ScreenInfo(scrn
) {
90 screenstr
= "session.screen" + itostring(scrn
) + '.';
91 config
= blackbox
->getConfig();
92 xatom
= blackbox
->getXAtom();
94 event_mask
= ColormapChangeMask
| EnterWindowMask
| PropertyChangeMask
|
95 SubstructureRedirectMask
| ButtonPressMask
| ButtonReleaseMask
;
97 XErrorHandler old
= XSetErrorHandler((XErrorHandler
) anotherWMRunning
);
98 XSelectInput(otk::OBDisplay::display
, getRootWindow(), event_mask
);
99 XSync(otk::OBDisplay::display
, False
);
100 XSetErrorHandler((XErrorHandler
) old
);
103 if (! managed
) return;
105 fprintf(stderr
, "BScreen::BScreen: managing screen %d "
106 "using visual 0x%lx, depth %d\n",
107 getScreenNumber(), XVisualIDFromVisual(getVisual()),
110 resource
.wstyle
.font
= (otk::BFont
*) 0;
114 // xatom->setSupported(this); // set-up netwm support
116 xatom
->setValue(getRootWindow(), otk::OBProperty::blackbox_pid
, otk::OBProperty::cardinal
,
117 (unsigned long) getpid());
118 #endif // HAVE_GETPID
119 unsigned long geometry
[] = { getWidth(),
121 xatom
->set(getRootWindow(), otk::OBProperty::net_desktop_geometry
,
122 otk::OBProperty::Atom_Cardinal
, geometry
, 2);
123 unsigned long viewport
[] = {0,0};
124 xatom
->set(getRootWindow(), otk::OBProperty::net_desktop_viewport
,
125 otk::OBProperty::Atom_Cardinal
, viewport
, 2);
128 XDefineCursor(otk::OBDisplay::display
, getRootWindow(),
129 blackbox
->getSessionCursor());
131 updateAvailableArea();
134 new otk::BImageControl(Openbox::instance
->timerManager(),
135 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
->set(getRootWindow(), otk::OBProperty::net_current_desktop
,
197 otk::OBProperty::Atom_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 otk::OBProperty::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
->set(getRootWindow(), otk::OBProperty::net_desktop_names
,
645 otk::OBProperty::utf8
, workspaceNames
);
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 otk::BImageControl::timeout(image_control
);
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
->set(getRootWindow(), otk::OBProperty::net_current_desktop
,
1017 otk::OBProperty::Atom_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
->set(getRootWindow(), otk::OBProperty::net_client_list
,
1072 otk::OBProperty::Atom_Window
, windows
, windowList
.size());
1075 xatom
->set(getRootWindow(), otk::OBProperty::net_client_list
,
1076 otk::OBProperty::Atom_Window
, 0, 0);
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
->set(getRootWindow(), otk::OBProperty::net_client_list_stacking
,
1109 otk::OBProperty::Atom_Window
, windows
, stack_order
.size());
1112 xatom
->set(getRootWindow(), otk::OBProperty::net_client_list_stacking
,
1113 otk::OBProperty::Atom_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
->set(getRootWindow(), otk::OBProperty::kde_net_system_tray_windows
,
1123 otk::OBProperty::Atom_Window
,
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
->set(getRootWindow(),
1140 otk::OBProperty::kde_net_system_tray_windows
,
1141 otk::OBProperty::Atom_Window
,
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
->get(w
, otk::OBProperty::kde_net_wm_system_tray_window_for
,
1158 otk::OBProperty::Atom_Window
, &systray
) &&
1161 addSystrayWindow(w
);
1165 // is the window a docking app
1166 XWMHints
*wmhint
= XGetWMHints(otk::OBDisplay::display
, w
);
1167 if (wmhint
&& (wmhint
->flags
& StateHint
) &&
1168 wmhint
->initial_state
== WithdrawnState
) {
1169 //slit->addClient(w);
1173 new BlackboxWindow(blackbox
, w
, this);
1175 BlackboxWindow
*win
= blackbox
->searchWindow(w
);
1179 if (win
->isDesktop()) {
1180 desktopWindowList
.push_back(win
->getFrameWindow());
1181 } else { // if (win->isNormal()) {
1182 // don't list desktop windows as managed windows
1183 windowList
.push_back(win
);
1186 if (win
->isTopmost())
1187 specialWindowList
.push_back(win
->getFrameWindow());
1190 XMapRequestEvent mre
;
1192 if (blackbox
->state() == Openbox::State_Starting
&&
1194 win
->restoreAttributes();
1195 win
->mapRequestEvent(&mre
);
1199 void BScreen::unmanageWindow(BlackboxWindow
*w
, bool remap
) {
1200 // is the window a KDE systray window?
1202 if (xatom
->get(w
->getClientWindow(),
1203 otk::OBProperty::kde_net_wm_system_tray_window_for
,
1204 otk::OBProperty::Atom_Window
, &systray
) &&
1207 removeSystrayWindow(w
->getClientWindow());
1213 // Remove the modality so that its parent won't try to re-focus the window
1214 if (w
->isModal()) w
->setModal(False
);
1216 if (w
->getWorkspaceNumber() != BSENTINEL
&&
1217 w
->getWindowNumber() != BSENTINEL
) {
1218 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1220 for (unsigned int i
= 0; i
< getNumberOfWorkspaces(); ++i
)
1221 if (i
!= w
->getWorkspaceNumber())
1222 getWorkspace(i
)->removeWindow(w
, True
);
1224 } else if (w
->isIconic())
1227 if (w
->isDesktop()) {
1228 WindowList::iterator it
= desktopWindowList
.begin();
1229 const WindowList::iterator end
= desktopWindowList
.end();
1230 for (; it
!= end
; ++it
)
1231 if (*it
== w
->getFrameWindow()) {
1232 desktopWindowList
.erase(it
);
1235 assert(it
!= end
); // the window wasnt a desktop window?
1236 } else { // if (w->isNormal()) {
1237 // we don't list desktop windows as managed windows
1238 windowList
.remove(w
);
1241 if (w
->isTopmost()) {
1242 WindowList::iterator it
= specialWindowList
.begin();
1243 const WindowList::iterator end
= specialWindowList
.end();
1244 for (; it
!= end
; ++it
)
1245 if (*it
== w
->getFrameWindow()) {
1246 specialWindowList
.erase(it
);
1249 assert(it
!= end
); // the window wasnt a special window?
1253 if (blackbox
->getFocusedWindow() == w
)
1254 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1257 some managed windows can also be window group controllers. when
1258 unmanaging such windows, we should also delete the window group.
1260 BWindowGroup
*group
= blackbox
->searchGroup(w
->getClientWindow());
1267 void BScreen::updateWorkArea(void) {
1268 if (workspacesList
.size() > 0) {
1269 unsigned long *dims
= new unsigned long[4 * workspacesList
.size()];
1270 for (unsigned int i
= 0, m
= workspacesList
.size(); i
< m
; ++i
) {
1271 // XXX: this could be different for each workspace
1272 const otk::Rect
&area
= availableArea();
1273 dims
[(i
* 4) + 0] = area
.x();
1274 dims
[(i
* 4) + 1] = area
.y();
1275 dims
[(i
* 4) + 2] = area
.width();
1276 dims
[(i
* 4) + 3] = area
.height();
1278 xatom
->set(getRootWindow(), otk::OBProperty::net_workarea
,
1279 otk::OBProperty::Atom_Cardinal
,
1280 dims
, 4 * workspacesList
.size());
1283 xatom
->set(getRootWindow(), otk::OBProperty::net_workarea
,
1284 otk::OBProperty::Atom_Cardinal
, 0, 0);
1288 void BScreen::updateNetizenWorkspaceCount(void) {
1289 xatom
->set(getRootWindow(), otk::OBProperty::net_number_of_desktops
,
1290 otk::OBProperty::Atom_Cardinal
, workspacesList
.size());
1296 void BScreen::updateNetizenWindowFocus(void) {
1297 Window f
= ((blackbox
->getFocusedWindow()) ?
1298 blackbox
->getFocusedWindow()->getClientWindow() : None
);
1300 xatom
->set(getRootWindow(), otk::OBProperty::net_active_window
,
1301 otk::OBProperty::Atom_Window
, f
);
1305 void BScreen::raiseWindows(Window
*workspace_stack
, unsigned int num
) {
1306 // the 13 represents the number of blackbox windows such as menus
1312 Window
*session_stack
= new
1313 Window
[(num
+ specialWindowList
.size() + bbwins
)];
1314 unsigned int i
= 0, k
= num
;
1316 WindowList::iterator sit
, send
= specialWindowList
.end();
1317 for (sit
= specialWindowList
.begin(); sit
!= send
; ++sit
)
1318 *(session_stack
+ i
++) = *sit
;
1321 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
1323 XRestackWindows(otk::OBDisplay::display
, session_stack
, i
);
1325 delete [] session_stack
;
1327 updateStackingList();
1331 void BScreen::lowerWindows(Window
*workspace_stack
, unsigned int num
) {
1332 assert(num
> 0); // this would cause trouble in the XRaiseWindow call
1334 Window
*session_stack
= new Window
[(num
+ desktopWindowList
.size())];
1335 unsigned int i
= 0, k
= num
;
1337 XLowerWindow(otk::OBDisplay::display
, workspace_stack
[0]);
1340 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
1342 WindowList::iterator dit
= desktopWindowList
.begin();
1343 const WindowList::iterator d_end
= desktopWindowList
.end();
1344 for (; dit
!= d_end
; ++dit
)
1345 *(session_stack
+ i
++) = *dit
;
1347 XRestackWindows(otk::OBDisplay::display
, session_stack
, i
);
1349 delete [] session_stack
;
1351 updateStackingList();
1355 void BScreen::reassociateWindow(BlackboxWindow
*w
, unsigned int wkspc_id
,
1356 bool ignore_sticky
) {
1359 if (wkspc_id
== BSENTINEL
)
1360 wkspc_id
= current_workspace
->getID();
1362 if (w
->getWorkspaceNumber() == wkspc_id
)
1365 if (w
->isIconic()) {
1367 getWorkspace(wkspc_id
)->addWindow(w
);
1369 for (unsigned int i
= 0; i
< getNumberOfWorkspaces(); ++i
)
1370 if (i
!= w
->getWorkspaceNumber())
1371 getWorkspace(i
)->addWindow(w
, True
);
1372 } else if (ignore_sticky
|| ! w
->isStuck()) {
1375 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1376 getWorkspace(wkspc_id
)->addWindow(w
);
1378 updateStackingList();
1382 void BScreen::propagateWindowName(const BlackboxWindow
*bw
) {
1383 if (bw
->isIconic()) {
1389 void BScreen::nextFocus(void) const {
1390 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1394 focused
->getScreen()->getScreenNumber() == getScreenNumber() &&
1395 current_workspace
->getCount() > 1) {
1397 next
= current_workspace
->getNextWindowInList(next
);
1398 } while (next
!= focused
&& ! next
->setInputFocus());
1400 if (next
!= focused
)
1401 current_workspace
->raiseWindow(next
);
1402 } else if (current_workspace
->getCount() > 0) {
1403 next
= current_workspace
->getTopWindowOnStack();
1404 next
->setInputFocus();
1405 current_workspace
->raiseWindow(next
);
1410 void BScreen::prevFocus(void) const {
1411 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1415 // if window is not on this screen, ignore it
1416 if (focused
->getScreen()->getScreenNumber() != getScreenNumber())
1417 focused
= (BlackboxWindow
*) 0;
1421 focused
->getScreen()->getScreenNumber() == getScreenNumber() &&
1422 current_workspace
->getCount() > 1) {
1423 // next is the next window to receive focus, current is a place holder
1425 next
= current_workspace
->getPrevWindowInList(next
);
1426 } while (next
!= focused
&& ! next
->setInputFocus());
1428 if (next
!= focused
)
1429 current_workspace
->raiseWindow(next
);
1430 } else if (current_workspace
->getCount() > 0) {
1431 next
= current_workspace
->getTopWindowOnStack();
1432 next
->setInputFocus();
1433 current_workspace
->raiseWindow(next
);
1438 void BScreen::raiseFocus(void) const {
1439 BlackboxWindow
*focused
= blackbox
->getFocusedWindow();
1443 // if on this Screen, raise it
1444 if (focused
->getScreen()->getScreenNumber() == getScreenNumber()) {
1445 Workspace
*workspace
= getWorkspace(focused
->getWorkspaceNumber());
1446 workspace
->raiseWindow(focused
);
1451 void BScreen::shutdown(void) {
1452 XSelectInput(otk::OBDisplay::display
, getRootWindow(), NoEventMask
);
1453 XSync(otk::OBDisplay::display
, False
);
1455 while(! windowList
.empty())
1456 unmanageWindow(windowList
.front(), True
);
1458 while(! desktopWindowList
.empty()) {
1459 BlackboxWindow
*win
= blackbox
->searchWindow(desktopWindowList
.front());
1461 unmanageWindow(win
, True
);
1466 void BScreen::showPosition(int x
, int y
) {
1467 if (! geom_visible
) {
1468 XMoveResizeWindow(otk::OBDisplay::display
, geom_window
,
1469 (getWidth() - geom_w
) / 2,
1470 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
1471 XMapWindow(otk::OBDisplay::display
, geom_window
);
1472 XRaiseWindow(otk::OBDisplay::display
, geom_window
);
1474 geom_visible
= True
;
1479 sprintf(label
, "X: %4d x Y: %4d", x
, y
);
1481 XClearWindow(otk::OBDisplay::display
, geom_window
);
1483 resource
.wstyle
.font
->drawString(geom_window
,
1484 resource
.bevel_width
, resource
.bevel_width
,
1485 resource
.wstyle
.l_text_focus
,
1490 void BScreen::showGeometry(unsigned int gx
, unsigned int gy
) {
1491 if (! geom_visible
) {
1492 XMoveResizeWindow(otk::OBDisplay::display
, geom_window
,
1493 (getWidth() - geom_w
) / 2,
1494 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
1495 XMapWindow(otk::OBDisplay::display
, geom_window
);
1496 XRaiseWindow(otk::OBDisplay::display
, geom_window
);
1498 geom_visible
= True
;
1503 sprintf(label
, "W: %4d x H: %4d", gx
, gy
);
1505 XClearWindow(otk::OBDisplay::display
, geom_window
);
1507 resource
.wstyle
.font
->drawString(geom_window
,
1508 resource
.bevel_width
, resource
.bevel_width
,
1509 resource
.wstyle
.l_text_focus
,
1514 void BScreen::hideGeometry(void) {
1516 XUnmapWindow(otk::OBDisplay::display
, geom_window
);
1517 geom_visible
= False
;
1522 void BScreen::addStrut(Strut
*strut
) {
1523 strutList
.push_back(strut
);
1527 void BScreen::removeStrut(Strut
*strut
) {
1528 strutList
.remove(strut
);
1532 const otk::Rect
& BScreen::availableArea(void) const {
1534 return getRect(); // return the full screen
1540 const RectList
& BScreen::allAvailableAreas(void) const {
1541 assert(isXineramaActive());
1542 assert(xineramaUsableArea
.size() > 0);
1543 fprintf(stderr
, "1found x %d y %d w %d h %d\n",
1544 xineramaUsableArea
[0].x(), xineramaUsableArea
[0].y(),
1545 xineramaUsableArea
[0].width(), xineramaUsableArea
[0].height());
1546 return xineramaUsableArea
;
1551 void BScreen::updateAvailableArea(void) {
1552 otk::Rect old_area
= usableArea
;
1553 usableArea
= getRect(); // reset to full screen
1556 // reset to the full areas
1557 if (isXineramaActive())
1558 xineramaUsableArea
= getXineramaAreas();
1561 /* these values represent offsets from the screen edge
1562 * we look for the biggest offset on each edge and then apply them
1564 * do not be confused by the similarity to the names of Rect's members
1566 unsigned int current_left
= 0, current_right
= 0, current_top
= 0,
1569 StrutList::const_iterator it
= strutList
.begin(), end
= strutList
.end();
1571 for(; it
!= end
; ++it
) {
1573 if (strut
->left
> current_left
)
1574 current_left
= strut
->left
;
1575 if (strut
->top
> current_top
)
1576 current_top
= strut
->top
;
1577 if (strut
->right
> current_right
)
1578 current_right
= strut
->right
;
1579 if (strut
->bottom
> current_bottom
)
1580 current_bottom
= strut
->bottom
;
1583 usableArea
.setPos(current_left
, current_top
);
1584 usableArea
.setSize(usableArea
.width() - (current_left
+ current_right
),
1585 usableArea
.height() - (current_top
+ current_bottom
));
1588 if (isXineramaActive()) {
1589 // keep each of the ximerama-defined areas inside the strut
1590 RectList::iterator xit
, xend
= xineramaUsableArea
.end();
1591 for (xit
= xineramaUsableArea
.begin(); xit
!= xend
; ++xit
) {
1592 if (xit
->x() < usableArea
.x()) {
1593 xit
->setX(usableArea
.x());
1594 xit
->setWidth(xit
->width() - usableArea
.x());
1596 if (xit
->y() < usableArea
.y()) {
1597 xit
->setY(usableArea
.y());
1598 xit
->setHeight(xit
->height() - usableArea
.y());
1600 if (xit
->x() + xit
->width() > usableArea
.width())
1601 xit
->setWidth(usableArea
.width() - xit
->x());
1602 if (xit
->y() + xit
->height() > usableArea
.height())
1603 xit
->setHeight(usableArea
.height() - xit
->y());
1608 if (old_area
!= usableArea
) {
1609 BlackboxWindowList::iterator it
= windowList
.begin(),
1610 end
= windowList
.end();
1611 for (; it
!= end
; ++it
)
1612 if ((*it
)->isMaximized()) (*it
)->remaximize();
1619 Workspace
* BScreen::getWorkspace(unsigned int index
) const {
1620 assert(index
< workspacesList
.size());
1621 return workspacesList
[index
];
1625 void BScreen::buttonPressEvent(const XButtonEvent
*xbutton
) {
1626 if (xbutton
->button
== 1) {
1627 if (! isRootColormapInstalled())
1628 image_control
->installRootColormap();
1631 } else if ((xbutton
->button
== 4 && resource
.root_scroll
== NormalScroll
) ||
1632 (xbutton
->button
== 5 && resource
.root_scroll
== ReverseScroll
)) {
1633 if (getCurrentWorkspaceID() >= getWorkspaceCount() - 1)
1634 changeWorkspaceID(0);
1636 changeWorkspaceID(getCurrentWorkspaceID() + 1);
1638 } else if ((xbutton
->button
== 5 && resource
.root_scroll
== NormalScroll
) ||
1639 (xbutton
->button
== 4 && resource
.root_scroll
== ReverseScroll
)) {
1640 if (getCurrentWorkspaceID() == 0)
1641 changeWorkspaceID(getWorkspaceCount() - 1);
1643 changeWorkspaceID(getCurrentWorkspaceID() - 1);
1648 void BScreen::propertyNotifyEvent(const XPropertyEvent
*pe
) {
1649 if (pe
->atom
== xatom
->atom(otk::OBProperty::net_desktop_names
)) {
1650 // _NET_WM_DESKTOP_NAMES
1651 WorkspaceList::iterator it
= workspacesList
.begin();
1652 const WorkspaceList::iterator end
= workspacesList
.end();
1653 for (; it
!= end
; ++it
) {
1654 (*it
)->readName(); // re-read its name from the window property
1655 //workspacemenu->changeWorkspaceLabel((*it)->getID(), (*it)->getName());
1657 //workspacemenu->update();
1658 saveWorkspaceNames();
1663 void BScreen::toggleFocusModel(FocusModel model
) {
1664 std::for_each(windowList
.begin(), windowList
.end(),
1665 std::mem_fun(&BlackboxWindow::ungrabButtons
));
1667 if (model
== SloppyFocus
) {
1668 saveSloppyFocus(True
);
1670 // we're cheating here to save writing the config file 3 times
1671 resource
.auto_raise
= False
;
1672 resource
.click_raise
= False
;
1673 saveSloppyFocus(False
);
1676 std::for_each(windowList
.begin(), windowList
.end(),
1677 std::mem_fun(&BlackboxWindow::grabButtons
));
1680 void BScreen::readDatabaseMask(const string
&rname
, PixmapMask
&pixmapMask
,
1681 const Configuration
&style
) {
1683 int hx
, hy
; //ignored
1684 int ret
= BitmapOpenFailed
; //default to failure.
1686 if (style
.getValue(rname
, s
))
1688 if (s
[0] != '/' && s
[0] != '~')
1690 std::string xbmFile
= std::string("~/.openbox/buttons/") + s
;
1691 ret
= XReadBitmapFile(otk::OBDisplay::display
, getRootWindow(),
1692 expandTilde(xbmFile
).c_str(), &pixmapMask
.w
,
1693 &pixmapMask
.h
, &pixmapMask
.mask
, &hx
, &hy
);
1695 ret
= XReadBitmapFile(otk::OBDisplay::display
, getRootWindow(),
1696 expandTilde(s
).c_str(), &pixmapMask
.w
,
1697 &pixmapMask
.h
, &pixmapMask
.mask
, &hx
, &hy
);
1699 if (ret
== BitmapSuccess
)
1703 pixmapMask
.mask
= None
;
1704 pixmapMask
.w
= pixmapMask
.h
= 0;
1707 otk::BTexture
BScreen::readDatabaseTexture(const string
&rname
,
1708 const string
&default_color
,
1709 const Configuration
&style
,
1710 bool allowNoTexture
) {
1711 otk::BTexture texture
;
1714 if (style
.getValue(rname
, s
))
1715 texture
= otk::BTexture(s
);
1716 else if (allowNoTexture
) //no default
1717 texture
.setTexture(otk::BTexture::NoTexture
);
1719 texture
.setTexture(otk::BTexture::Solid
| otk::BTexture::Flat
);
1721 // associate this texture with this screen
1722 texture
.setScreen(getScreenNumber());
1723 texture
.setImageControl(image_control
);
1725 if (texture
.texture() != otk::BTexture::NoTexture
) {
1726 texture
.setColor(readDatabaseColor(rname
+ ".color", default_color
,
1728 texture
.setColorTo(readDatabaseColor(rname
+ ".colorTo", default_color
,
1730 texture
.setBorderColor(readDatabaseColor(rname
+ ".borderColor",
1731 default_color
, style
));
1738 otk::BColor
BScreen::readDatabaseColor(const string
&rname
,
1739 const string
&default_color
,
1740 const Configuration
&style
) {
1743 if (style
.getValue(rname
, s
))
1744 color
= otk::BColor(s
, getScreenNumber());
1746 color
= otk::BColor(default_color
, getScreenNumber());
1751 otk::BFont
*BScreen::readDatabaseFont(const string
&rbasename
,
1752 const Configuration
&style
) {
1758 if (style
.getValue(rbasename
+ "xft.font", s
) &&
1759 style
.getValue(rbasename
+ "xft.size", i
)) {
1762 bool italic
= False
;
1763 bool dropShadow
= False
;
1765 if (style
.getValue(rbasename
+ "xft.flags", s
)) {
1766 if (s
.find("bold") != string::npos
)
1768 if (s
.find("italic") != string::npos
)
1770 if (s
.find("shadow") != string::npos
)
1774 unsigned char offset
= 1;
1775 if (style
.getValue(rbasename
+ "xft.shadow.offset", s
)) {
1776 offset
= atoi(s
.c_str()); //doesn't detect errors
1777 if (offset
> CHAR_MAX
)
1781 unsigned char tint
= 0x40;
1782 if (style
.getValue(rbasename
+ "xft.shadow.tint", s
)) {
1783 tint
= atoi(s
.c_str());
1787 otk::BFont
*b
= new otk::BFont(getScreenNumber(), family
, i
, bold
, italic
,
1788 dropShadow
&& resource
.shadow_fonts
,
1789 offset
, tint
, resource
.aa_fonts
);
1795 exit(2); // can't continue without a font