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
,
117 otk::OBProperty::Atom_Cardinal
,
118 (unsigned long) getpid());
119 #endif // HAVE_GETPID
120 unsigned long geometry
[] = { getWidth(),
122 xatom
->set(getRootWindow(), otk::OBProperty::net_desktop_geometry
,
123 otk::OBProperty::Atom_Cardinal
, geometry
, 2);
124 unsigned long viewport
[] = {0,0};
125 xatom
->set(getRootWindow(), otk::OBProperty::net_desktop_viewport
,
126 otk::OBProperty::Atom_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
->set(getRootWindow(), otk::OBProperty::net_current_desktop
,
198 otk::OBProperty::Atom_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 otk::OBProperty::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
->set(getRootWindow(), otk::OBProperty::net_desktop_names
,
646 otk::OBProperty::utf8
, workspaceNames
);
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
->set(getRootWindow(), otk::OBProperty::net_current_desktop
,
1018 otk::OBProperty::Atom_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
->set(getRootWindow(), otk::OBProperty::net_client_list
,
1073 otk::OBProperty::Atom_Window
, windows
, windowList
.size());
1076 xatom
->set(getRootWindow(), otk::OBProperty::net_client_list
,
1077 otk::OBProperty::Atom_Window
, 0, 0);
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
->set(getRootWindow(), otk::OBProperty::net_client_list_stacking
,
1110 otk::OBProperty::Atom_Window
, windows
, stack_order
.size());
1113 xatom
->set(getRootWindow(), otk::OBProperty::net_client_list_stacking
,
1114 otk::OBProperty::Atom_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
->set(getRootWindow(), otk::OBProperty::kde_net_system_tray_windows
,
1124 otk::OBProperty::Atom_Window
,
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
->set(getRootWindow(),
1141 otk::OBProperty::kde_net_system_tray_windows
,
1142 otk::OBProperty::Atom_Window
,
1143 &systrayWindowList
[0], systrayWindowList
.size());
1144 blackbox
->removeSystrayWindowSearch(window
);
1145 XSelectInput(otk::OBDisplay::display
, window
, NoEventMask
);
1149 assert(it
!= end
); // not a systray window
1151 XUngrabServer(otk::OBDisplay::display
);
1155 void BScreen::manageWindow(Window w
) {
1156 // is the window a KDE systray window?
1158 if (xatom
->get(w
, otk::OBProperty::kde_net_wm_system_tray_window_for
,
1159 otk::OBProperty::Atom_Window
, &systray
) &&
1162 addSystrayWindow(w
);
1166 // is the window a docking app
1167 XWMHints
*wmhint
= XGetWMHints(otk::OBDisplay::display
, w
);
1168 if (wmhint
&& (wmhint
->flags
& StateHint
) &&
1169 wmhint
->initial_state
== WithdrawnState
) {
1170 //slit->addClient(w);
1174 new BlackboxWindow(blackbox
, w
, this);
1176 BlackboxWindow
*win
= blackbox
->searchWindow(w
);
1180 if (win
->isDesktop()) {
1181 desktopWindowList
.push_back(win
->getFrameWindow());
1182 } else { // if (win->isNormal()) {
1183 // don't list desktop windows as managed windows
1184 windowList
.push_back(win
);
1187 if (win
->isTopmost())
1188 specialWindowList
.push_back(win
->getFrameWindow());
1191 XMapRequestEvent mre
;
1193 if (blackbox
->state() == Openbox::State_Starting
&&
1195 win
->restoreAttributes();
1196 win
->mapRequestEvent(&mre
);
1200 void BScreen::unmanageWindow(BlackboxWindow
*w
, bool remap
) {
1201 // is the window a KDE systray window?
1203 if (xatom
->get(w
->getClientWindow(),
1204 otk::OBProperty::kde_net_wm_system_tray_window_for
,
1205 otk::OBProperty::Atom_Window
, &systray
) &&
1208 removeSystrayWindow(w
->getClientWindow());
1214 // Remove the modality so that its parent won't try to re-focus the window
1215 if (w
->isModal()) w
->setModal(False
);
1217 if (w
->getWorkspaceNumber() != BSENTINEL
&&
1218 w
->getWindowNumber() != BSENTINEL
) {
1219 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1221 for (unsigned int i
= 0; i
< getNumberOfWorkspaces(); ++i
)
1222 if (i
!= w
->getWorkspaceNumber())
1223 getWorkspace(i
)->removeWindow(w
, True
);
1225 } else if (w
->isIconic())
1228 if (w
->isDesktop()) {
1229 WindowList::iterator it
= desktopWindowList
.begin();
1230 const WindowList::iterator end
= desktopWindowList
.end();
1231 for (; it
!= end
; ++it
)
1232 if (*it
== w
->getFrameWindow()) {
1233 desktopWindowList
.erase(it
);
1236 assert(it
!= end
); // the window wasnt a desktop window?
1237 } else { // if (w->isNormal()) {
1238 // we don't list desktop windows as managed windows
1239 windowList
.remove(w
);
1242 if (w
->isTopmost()) {
1243 WindowList::iterator it
= specialWindowList
.begin();
1244 const WindowList::iterator end
= specialWindowList
.end();
1245 for (; it
!= end
; ++it
)
1246 if (*it
== w
->getFrameWindow()) {
1247 specialWindowList
.erase(it
);
1250 assert(it
!= end
); // the window wasnt a special window?
1254 if (blackbox
->getFocusedWindow() == w
)
1255 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1258 some managed windows can also be window group controllers. when
1259 unmanaging such windows, we should also delete the window group.
1261 BWindowGroup
*group
= blackbox
->searchGroup(w
->getClientWindow());
1268 void BScreen::updateWorkArea(void) {
1269 if (workspacesList
.size() > 0) {
1270 unsigned long *dims
= new unsigned long[4 * workspacesList
.size()];
1271 for (unsigned int i
= 0, m
= workspacesList
.size(); i
< m
; ++i
) {
1272 // XXX: this could be different for each workspace
1273 const otk::Rect
&area
= availableArea();
1274 dims
[(i
* 4) + 0] = area
.x();
1275 dims
[(i
* 4) + 1] = area
.y();
1276 dims
[(i
* 4) + 2] = area
.width();
1277 dims
[(i
* 4) + 3] = area
.height();
1279 xatom
->set(getRootWindow(), otk::OBProperty::net_workarea
,
1280 otk::OBProperty::Atom_Cardinal
,
1281 dims
, 4 * workspacesList
.size());
1284 xatom
->set(getRootWindow(), otk::OBProperty::net_workarea
,
1285 otk::OBProperty::Atom_Cardinal
, 0, 0);
1289 void BScreen::updateNetizenWorkspaceCount(void) {
1290 xatom
->set(getRootWindow(), otk::OBProperty::net_number_of_desktops
,
1291 otk::OBProperty::Atom_Cardinal
, workspacesList
.size());
1297 void BScreen::updateNetizenWindowFocus(void) {
1298 Window f
= ((blackbox
->getFocusedWindow()) ?
1299 blackbox
->getFocusedWindow()->getClientWindow() : None
);
1301 xatom
->set(getRootWindow(), otk::OBProperty::net_active_window
,
1302 otk::OBProperty::Atom_Window
, f
);
1306 void BScreen::raiseWindows(Window
*workspace_stack
, unsigned int num
) {
1307 // the 13 represents the number of blackbox windows such as menus
1313 Window
*session_stack
= new
1314 Window
[(num
+ specialWindowList
.size() + bbwins
)];
1315 unsigned int i
= 0, k
= num
;
1317 WindowList::iterator sit
, send
= specialWindowList
.end();
1318 for (sit
= specialWindowList
.begin(); sit
!= send
; ++sit
)
1319 *(session_stack
+ i
++) = *sit
;
1322 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
1324 XRestackWindows(otk::OBDisplay::display
, session_stack
, i
);
1326 delete [] session_stack
;
1328 updateStackingList();
1332 void BScreen::lowerWindows(Window
*workspace_stack
, unsigned int num
) {
1333 assert(num
> 0); // this would cause trouble in the XRaiseWindow call
1335 Window
*session_stack
= new Window
[(num
+ desktopWindowList
.size())];
1336 unsigned int i
= 0, k
= num
;
1338 XLowerWindow(otk::OBDisplay::display
, workspace_stack
[0]);
1341 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
1343 WindowList::iterator dit
= desktopWindowList
.begin();
1344 const WindowList::iterator d_end
= desktopWindowList
.end();
1345 for (; dit
!= d_end
; ++dit
)
1346 *(session_stack
+ i
++) = *dit
;
1348 XRestackWindows(otk::OBDisplay::display
, session_stack
, i
);
1350 delete [] session_stack
;
1352 updateStackingList();
1356 void BScreen::reassociateWindow(BlackboxWindow
*w
, unsigned int wkspc_id
,
1357 bool ignore_sticky
) {
1360 if (wkspc_id
== BSENTINEL
)
1361 wkspc_id
= current_workspace
->getID();
1363 if (w
->getWorkspaceNumber() == wkspc_id
)
1366 if (w
->isIconic()) {
1368 getWorkspace(wkspc_id
)->addWindow(w
);
1370 for (unsigned int i
= 0; i
< getNumberOfWorkspaces(); ++i
)
1371 if (i
!= w
->getWorkspaceNumber())
1372 getWorkspace(i
)->addWindow(w
, True
);
1373 } else if (ignore_sticky
|| ! w
->isStuck()) {
1376 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1377 getWorkspace(wkspc_id
)->addWindow(w
);
1379 updateStackingList();
1383 void BScreen::propagateWindowName(const BlackboxWindow
*bw
) {
1384 if (bw
->isIconic()) {
1390 void BScreen::nextFocus(void) const {
1391 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1395 focused
->getScreen()->getScreenNumber() == getScreenNumber() &&
1396 current_workspace
->getCount() > 1) {
1398 next
= current_workspace
->getNextWindowInList(next
);
1399 } while (next
!= focused
&& ! next
->setInputFocus());
1401 if (next
!= focused
)
1402 current_workspace
->raiseWindow(next
);
1403 } else if (current_workspace
->getCount() > 0) {
1404 next
= current_workspace
->getTopWindowOnStack();
1405 next
->setInputFocus();
1406 current_workspace
->raiseWindow(next
);
1411 void BScreen::prevFocus(void) const {
1412 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1416 // if window is not on this screen, ignore it
1417 if (focused
->getScreen()->getScreenNumber() != getScreenNumber())
1418 focused
= (BlackboxWindow
*) 0;
1422 focused
->getScreen()->getScreenNumber() == getScreenNumber() &&
1423 current_workspace
->getCount() > 1) {
1424 // next is the next window to receive focus, current is a place holder
1426 next
= current_workspace
->getPrevWindowInList(next
);
1427 } while (next
!= focused
&& ! next
->setInputFocus());
1429 if (next
!= focused
)
1430 current_workspace
->raiseWindow(next
);
1431 } else if (current_workspace
->getCount() > 0) {
1432 next
= current_workspace
->getTopWindowOnStack();
1433 next
->setInputFocus();
1434 current_workspace
->raiseWindow(next
);
1439 void BScreen::raiseFocus(void) const {
1440 BlackboxWindow
*focused
= blackbox
->getFocusedWindow();
1444 // if on this Screen, raise it
1445 if (focused
->getScreen()->getScreenNumber() == getScreenNumber()) {
1446 Workspace
*workspace
= getWorkspace(focused
->getWorkspaceNumber());
1447 workspace
->raiseWindow(focused
);
1452 void BScreen::shutdown(void) {
1453 XSelectInput(otk::OBDisplay::display
, getRootWindow(), NoEventMask
);
1454 XSync(otk::OBDisplay::display
, False
);
1456 while(! windowList
.empty())
1457 unmanageWindow(windowList
.front(), True
);
1459 while(! desktopWindowList
.empty()) {
1460 BlackboxWindow
*win
= blackbox
->searchWindow(desktopWindowList
.front());
1462 unmanageWindow(win
, True
);
1467 void BScreen::showPosition(int x
, int y
) {
1468 if (! geom_visible
) {
1469 XMoveResizeWindow(otk::OBDisplay::display
, geom_window
,
1470 (getWidth() - geom_w
) / 2,
1471 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
1472 XMapWindow(otk::OBDisplay::display
, geom_window
);
1473 XRaiseWindow(otk::OBDisplay::display
, geom_window
);
1475 geom_visible
= True
;
1480 sprintf(label
, "X: %4d x Y: %4d", x
, y
);
1482 XClearWindow(otk::OBDisplay::display
, geom_window
);
1484 resource
.wstyle
.font
->drawString(geom_window
,
1485 resource
.bevel_width
, resource
.bevel_width
,
1486 resource
.wstyle
.l_text_focus
,
1491 void BScreen::showGeometry(unsigned int gx
, unsigned int gy
) {
1492 if (! geom_visible
) {
1493 XMoveResizeWindow(otk::OBDisplay::display
, geom_window
,
1494 (getWidth() - geom_w
) / 2,
1495 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
1496 XMapWindow(otk::OBDisplay::display
, geom_window
);
1497 XRaiseWindow(otk::OBDisplay::display
, geom_window
);
1499 geom_visible
= True
;
1504 sprintf(label
, "W: %4d x H: %4d", gx
, gy
);
1506 XClearWindow(otk::OBDisplay::display
, geom_window
);
1508 resource
.wstyle
.font
->drawString(geom_window
,
1509 resource
.bevel_width
, resource
.bevel_width
,
1510 resource
.wstyle
.l_text_focus
,
1515 void BScreen::hideGeometry(void) {
1517 XUnmapWindow(otk::OBDisplay::display
, geom_window
);
1518 geom_visible
= False
;
1523 void BScreen::addStrut(otk::Strut
*strut
) {
1524 strutList
.push_back(strut
);
1528 void BScreen::removeStrut(otk::Strut
*strut
) {
1529 strutList
.remove(strut
);
1533 const otk::Rect
& BScreen::availableArea(void) const {
1535 return getRect(); // return the full screen
1541 const RectList
& BScreen::allAvailableAreas(void) const {
1542 assert(isXineramaActive());
1543 assert(xineramaUsableArea
.size() > 0);
1544 fprintf(stderr
, "1found x %d y %d w %d h %d\n",
1545 xineramaUsableArea
[0].x(), xineramaUsableArea
[0].y(),
1546 xineramaUsableArea
[0].width(), xineramaUsableArea
[0].height());
1547 return xineramaUsableArea
;
1552 void BScreen::updateAvailableArea(void) {
1553 otk::Rect old_area
= usableArea
;
1554 usableArea
= getRect(); // reset to full screen
1557 // reset to the full areas
1558 if (isXineramaActive())
1559 xineramaUsableArea
= getXineramaAreas();
1562 /* these values represent offsets from the screen edge
1563 * we look for the biggest offset on each edge and then apply them
1565 * do not be confused by the similarity to the names of Rect's members
1567 unsigned int current_left
= 0, current_right
= 0, current_top
= 0,
1570 StrutList::const_iterator it
= strutList
.begin(), end
= strutList
.end();
1572 for(; it
!= end
; ++it
) {
1573 otk::Strut
*strut
= *it
;
1574 if (strut
->left
> current_left
)
1575 current_left
= strut
->left
;
1576 if (strut
->top
> current_top
)
1577 current_top
= strut
->top
;
1578 if (strut
->right
> current_right
)
1579 current_right
= strut
->right
;
1580 if (strut
->bottom
> current_bottom
)
1581 current_bottom
= strut
->bottom
;
1584 usableArea
.setPos(current_left
, current_top
);
1585 usableArea
.setSize(usableArea
.width() - (current_left
+ current_right
),
1586 usableArea
.height() - (current_top
+ current_bottom
));
1589 if (isXineramaActive()) {
1590 // keep each of the ximerama-defined areas inside the strut
1591 RectList::iterator xit
, xend
= xineramaUsableArea
.end();
1592 for (xit
= xineramaUsableArea
.begin(); xit
!= xend
; ++xit
) {
1593 if (xit
->x() < usableArea
.x()) {
1594 xit
->setX(usableArea
.x());
1595 xit
->setWidth(xit
->width() - usableArea
.x());
1597 if (xit
->y() < usableArea
.y()) {
1598 xit
->setY(usableArea
.y());
1599 xit
->setHeight(xit
->height() - usableArea
.y());
1601 if (xit
->x() + xit
->width() > usableArea
.width())
1602 xit
->setWidth(usableArea
.width() - xit
->x());
1603 if (xit
->y() + xit
->height() > usableArea
.height())
1604 xit
->setHeight(usableArea
.height() - xit
->y());
1609 if (old_area
!= usableArea
) {
1610 BlackboxWindowList::iterator it
= windowList
.begin(),
1611 end
= windowList
.end();
1612 for (; it
!= end
; ++it
)
1613 if ((*it
)->isMaximized()) (*it
)->remaximize();
1620 Workspace
* BScreen::getWorkspace(unsigned int index
) const {
1621 assert(index
< workspacesList
.size());
1622 return workspacesList
[index
];
1626 void BScreen::buttonPressEvent(const XButtonEvent
*xbutton
) {
1627 if (xbutton
->button
== 1) {
1628 if (! isRootColormapInstalled())
1629 image_control
->installRootColormap();
1632 } else if ((xbutton
->button
== 4 && resource
.root_scroll
== NormalScroll
) ||
1633 (xbutton
->button
== 5 && resource
.root_scroll
== ReverseScroll
)) {
1634 if (getCurrentWorkspaceID() >= getWorkspaceCount() - 1)
1635 changeWorkspaceID(0);
1637 changeWorkspaceID(getCurrentWorkspaceID() + 1);
1639 } else if ((xbutton
->button
== 5 && resource
.root_scroll
== NormalScroll
) ||
1640 (xbutton
->button
== 4 && resource
.root_scroll
== ReverseScroll
)) {
1641 if (getCurrentWorkspaceID() == 0)
1642 changeWorkspaceID(getWorkspaceCount() - 1);
1644 changeWorkspaceID(getCurrentWorkspaceID() - 1);
1649 void BScreen::propertyNotifyEvent(const XPropertyEvent
*pe
) {
1650 if (pe
->atom
== xatom
->atom(otk::OBProperty::net_desktop_names
)) {
1651 // _NET_WM_DESKTOP_NAMES
1652 WorkspaceList::iterator it
= workspacesList
.begin();
1653 const WorkspaceList::iterator end
= workspacesList
.end();
1654 for (; it
!= end
; ++it
) {
1655 (*it
)->readName(); // re-read its name from the window property
1656 //workspacemenu->changeWorkspaceLabel((*it)->getID(), (*it)->getName());
1658 //workspacemenu->update();
1659 saveWorkspaceNames();
1664 void BScreen::toggleFocusModel(FocusModel model
) {
1665 std::for_each(windowList
.begin(), windowList
.end(),
1666 std::mem_fun(&BlackboxWindow::ungrabButtons
));
1668 if (model
== SloppyFocus
) {
1669 saveSloppyFocus(True
);
1671 // we're cheating here to save writing the config file 3 times
1672 resource
.auto_raise
= False
;
1673 resource
.click_raise
= False
;
1674 saveSloppyFocus(False
);
1677 std::for_each(windowList
.begin(), windowList
.end(),
1678 std::mem_fun(&BlackboxWindow::grabButtons
));
1681 void BScreen::readDatabaseMask(const string
&rname
, PixmapMask
&pixmapMask
,
1682 const Configuration
&style
) {
1684 int hx
, hy
; //ignored
1685 int ret
= BitmapOpenFailed
; //default to failure.
1687 if (style
.getValue(rname
, s
))
1689 if (s
[0] != '/' && s
[0] != '~')
1691 std::string xbmFile
= std::string("~/.openbox/buttons/") + s
;
1692 ret
= XReadBitmapFile(otk::OBDisplay::display
, getRootWindow(),
1693 expandTilde(xbmFile
).c_str(), &pixmapMask
.w
,
1694 &pixmapMask
.h
, &pixmapMask
.mask
, &hx
, &hy
);
1696 ret
= XReadBitmapFile(otk::OBDisplay::display
, getRootWindow(),
1697 expandTilde(s
).c_str(), &pixmapMask
.w
,
1698 &pixmapMask
.h
, &pixmapMask
.mask
, &hx
, &hy
);
1700 if (ret
== BitmapSuccess
)
1704 pixmapMask
.mask
= None
;
1705 pixmapMask
.w
= pixmapMask
.h
= 0;
1708 otk::BTexture
BScreen::readDatabaseTexture(const string
&rname
,
1709 const string
&default_color
,
1710 const Configuration
&style
,
1711 bool allowNoTexture
) {
1712 otk::BTexture texture
;
1715 if (style
.getValue(rname
, s
))
1716 texture
= otk::BTexture(s
);
1717 else if (allowNoTexture
) //no default
1718 texture
.setTexture(otk::BTexture::NoTexture
);
1720 texture
.setTexture(otk::BTexture::Solid
| otk::BTexture::Flat
);
1722 // associate this texture with this screen
1723 texture
.setScreen(getScreenNumber());
1724 texture
.setImageControl(image_control
);
1726 if (texture
.texture() != otk::BTexture::NoTexture
) {
1727 texture
.setColor(readDatabaseColor(rname
+ ".color", default_color
,
1729 texture
.setColorTo(readDatabaseColor(rname
+ ".colorTo", default_color
,
1731 texture
.setBorderColor(readDatabaseColor(rname
+ ".borderColor",
1732 default_color
, style
));
1739 otk::BColor
BScreen::readDatabaseColor(const string
&rname
,
1740 const string
&default_color
,
1741 const Configuration
&style
) {
1744 if (style
.getValue(rname
, s
))
1745 color
= otk::BColor(s
, getScreenNumber());
1747 color
= otk::BColor(default_color
, getScreenNumber());
1752 otk::BFont
*BScreen::readDatabaseFont(const string
&rbasename
,
1753 const Configuration
&style
) {
1759 if (style
.getValue(rbasename
+ "xft.font", s
) &&
1760 style
.getValue(rbasename
+ "xft.size", i
)) {
1763 bool italic
= False
;
1764 bool dropShadow
= False
;
1766 if (style
.getValue(rbasename
+ "xft.flags", s
)) {
1767 if (s
.find("bold") != string::npos
)
1769 if (s
.find("italic") != string::npos
)
1771 if (s
.find("shadow") != string::npos
)
1775 unsigned char offset
= 1;
1776 if (style
.getValue(rbasename
+ "xft.shadow.offset", s
)) {
1777 offset
= atoi(s
.c_str()); //doesn't detect errors
1778 if (offset
> CHAR_MAX
)
1782 unsigned char tint
= 0x40;
1783 if (style
.getValue(rbasename
+ "xft.shadow.tint", s
)) {
1784 tint
= atoi(s
.c_str());
1788 otk::BFont
*b
= new otk::BFont(getScreenNumber(), family
, i
, bold
, italic
,
1789 dropShadow
&& resource
.shadow_fonts
,
1790 offset
, tint
, resource
.aa_fonts
);
1796 exit(2); // can't continue without a font