1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // Screen.cc for Blackbox - an X11 Window manager
3 // Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
4 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
6 // Permission is hereby granted, free of charge, to any person obtaining a
7 // copy of this software and associated documentation files (the "Software"),
8 // to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 // and/or sell copies of the Software, and to permit persons to whom the
11 // Software is furnished to do so, subject to the following conditions:
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 // DEALINGS IN THE SOFTWARE.
25 #include "../config.h"
26 #endif // HAVE_CONFIG_H
29 #include <X11/Xatom.h>
30 #include <X11/keysym.h>
33 # include <X11/Xlib.h>
34 # include <X11/extensions/Xinerama.h>
39 #endif // HAVE_STDLIB_H
43 #endif // HAVE_STRING_H
47 #endif // HAVE_CTYPE_H
50 # include <sys/types.h>
52 #endif // HAVE_UNISTD_H
56 #endif // HAVE_DIRENT_H
60 #endif // HAVE_LOCALE_H
62 #ifdef HAVE_SYS_STAT_H
63 # include <sys/stat.h>
64 #endif // HAVE_SYS_STAT_H
68 #endif // HAVE_STDARG_H
79 #include "blackbox.hh"
80 #include "Clientmenu.hh"
83 #include "Iconmenu.hh"
87 #include "Rootmenu.hh"
91 #include "Workspace.hh"
92 #include "Workspacemenu.hh"
96 #ifndef FONT_ELEMENT_SIZE
97 #define FONT_ELEMENT_SIZE 50
98 #endif // FONT_ELEMENT_SIZE
101 static bool running
= True
;
103 static int anotherWMRunning(Display
*display
, XErrorEvent
*) {
104 fprintf(stderr
, i18n(ScreenSet
, ScreenAnotherWMRunning
,
105 "BScreen::BScreen: an error occured while querying the X server.\n"
106 " another window manager already running on display %s.\n"),
107 DisplayString(display
));
115 BScreen::BScreen(Blackbox
*bb
, unsigned int scrn
) : ScreenInfo(bb
, scrn
) {
117 screenstr
= "session.screen" + itostring(scrn
) + '.';
118 config
= blackbox
->getConfig();
119 xatom
= blackbox
->getXAtom();
121 event_mask
= ColormapChangeMask
| EnterWindowMask
| PropertyChangeMask
|
122 SubstructureRedirectMask
| ButtonPressMask
| ButtonReleaseMask
;
124 XErrorHandler old
= XSetErrorHandler((XErrorHandler
) anotherWMRunning
);
125 XSelectInput(getBaseDisplay()->getXDisplay(), getRootWindow(), event_mask
);
126 XSync(getBaseDisplay()->getXDisplay(), False
);
127 XSetErrorHandler((XErrorHandler
) old
);
130 if (! managed
) return;
132 fprintf(stderr
, i18n(ScreenSet
, ScreenManagingScreen
,
133 "BScreen::BScreen: managing screen %d "
134 "using visual 0x%lx, depth %d\n"),
135 getScreenNumber(), XVisualIDFromVisual(getVisual()),
140 resource
.mstyle
.t_font
= resource
.mstyle
.f_font
= resource
.tstyle
.font
=
141 resource
.wstyle
.font
= (BFont
*) 0;
145 xatom
->setSupported(this); // set-up netwm support
147 xatom
->setValue(getRootWindow(), XAtom::blackbox_pid
, XAtom::cardinal
,
148 (unsigned long) getpid());
149 #endif // HAVE_GETPID
150 unsigned long geometry
[] = { getWidth(),
152 xatom
->setValue(getRootWindow(), XAtom::net_desktop_geometry
,
153 XAtom::cardinal
, geometry
, 2);
154 unsigned long viewport
[] = {0,0};
155 xatom
->setValue(getRootWindow(), XAtom::net_desktop_viewport
,
156 XAtom::cardinal
, viewport
, 2);
159 XDefineCursor(blackbox
->getXDisplay(), getRootWindow(),
160 blackbox
->getSessionCursor());
162 updateAvailableArea();
165 new BImageControl(blackbox
, this, True
, blackbox
->getColorsPerChannel(),
166 blackbox
->getCacheLife(), blackbox
->getCacheMax());
167 image_control
->installRootColormap();
168 root_colormap_installed
= True
;
174 gcv
.foreground
= WhitePixel(blackbox
->getXDisplay(), getScreenNumber())
175 ^ BlackPixel(blackbox
->getXDisplay(), getScreenNumber());
176 gcv
.function
= GXxor
;
177 gcv
.subwindow_mode
= IncludeInferiors
;
178 opGC
= XCreateGC(blackbox
->getXDisplay(), getRootWindow(),
179 GCForeground
| GCFunction
| GCSubwindowMode
, &gcv
);
181 const char *s
= i18n(ScreenSet
, ScreenPositionLength
,
182 "0: 0000 x 0: 0000");
183 geom_w
= resource
.wstyle
.font
->measureString(s
) + resource
.bevel_width
* 2;
184 geom_h
= resource
.wstyle
.font
->height() + resource
.bevel_width
* 2;
186 XSetWindowAttributes attrib
;
187 unsigned long mask
= CWBorderPixel
| CWColormap
| CWSaveUnder
;
188 attrib
.border_pixel
= getBorderColor()->pixel();
189 attrib
.colormap
= getColormap();
190 attrib
.save_under
= True
;
192 geom_window
= XCreateWindow(blackbox
->getXDisplay(), getRootWindow(),
193 0, 0, geom_w
, geom_h
, resource
.border_width
,
194 getDepth(), InputOutput
, getVisual(),
196 geom_visible
= False
;
198 BTexture
* texture
= &(resource
.wstyle
.l_focus
);
199 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
200 if (geom_pixmap
== ParentRelative
) {
201 texture
= &(resource
.wstyle
.t_focus
);
202 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
205 XSetWindowBackground(blackbox
->getXDisplay(), geom_window
,
206 texture
->color().pixel());
208 XSetWindowBackgroundPixmap(blackbox
->getXDisplay(),
209 geom_window
, geom_pixmap
);
211 workspacemenu
= new Workspacemenu(this);
212 iconmenu
= new Iconmenu(this);
213 configmenu
= new Configmenu(this);
215 if (resource
.workspaces
> 0) {
216 for (unsigned int i
= 0; i
< resource
.workspaces
; ++i
) {
217 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
218 workspacesList
.push_back(wkspc
);
219 workspacemenu
->insertWorkspace(wkspc
);
220 workspacemenu
->update();
224 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
225 workspacesList
.push_back(wkspc
);
226 workspacemenu
->insertWorkspace(wkspc
);
227 workspacemenu
->update();
229 saveWorkspaceNames();
231 updateNetizenWorkspaceCount();
233 workspacemenu
->insert(i18n(IconSet
, IconIcons
, "Icons"), iconmenu
);
234 workspacemenu
->update();
236 current_workspace
= workspacesList
.front();
238 xatom
->setValue(getRootWindow(), XAtom::net_current_desktop
,
239 XAtom::cardinal
, 0); //first workspace
241 workspacemenu
->setItemSelected(2, True
);
243 toolbar
= new Toolbar(this);
245 slit
= new Slit(this);
249 raiseWindows(0, 0); // this also initializes the empty stacking list
252 updateClientList(); // initialize the client lists, which will be empty
253 updateAvailableArea();
255 changeWorkspaceID(0);
257 unsigned int i
, j
, nchild
;
258 Window r
, p
, *children
;
259 XQueryTree(blackbox
->getXDisplay(), getRootWindow(), &r
, &p
,
262 // preen the window list of all icon windows... for better dockapp support
263 for (i
= 0; i
< nchild
; i
++) {
264 if (children
[i
] == None
) continue;
266 XWMHints
*wmhints
= XGetWMHints(blackbox
->getXDisplay(),
270 if ((wmhints
->flags
& IconWindowHint
) &&
271 (wmhints
->icon_window
!= children
[i
])) {
272 for (j
= 0; j
< nchild
; j
++) {
273 if (children
[j
] == wmhints
->icon_window
) {
284 // manage shown windows
285 for (i
= 0; i
< nchild
; ++i
) {
286 if (children
[i
] == None
|| ! blackbox
->validateWindow(children
[i
]))
289 XWindowAttributes attrib
;
290 if (XGetWindowAttributes(blackbox
->getXDisplay(), children
[i
], &attrib
)) {
291 if (attrib
.override_redirect
) continue;
293 if (attrib
.map_state
!= IsUnmapped
) {
294 manageWindow(children
[i
]);
301 // call this again just in case a window we found updates the Strut list
302 updateAvailableArea();
306 BScreen::~BScreen(void) {
307 if (! managed
) return;
309 if (geom_pixmap
!= None
)
310 image_control
->removeImage(geom_pixmap
);
312 if (geom_window
!= None
)
313 XDestroyWindow(blackbox
->getXDisplay(), geom_window
);
315 std::for_each(workspacesList
.begin(), workspacesList
.end(),
318 std::for_each(iconList
.begin(), iconList
.end(), PointerAssassin());
320 std::for_each(netizenList
.begin(), netizenList
.end(), PointerAssassin());
322 while (! systrayWindowList
.empty())
323 removeSystrayWindow(systrayWindowList
[0]);
326 delete workspacemenu
;
331 delete image_control
;
333 if (resource
.wstyle
.font
)
334 delete resource
.wstyle
.font
;
335 if (resource
.mstyle
.t_font
)
336 delete resource
.mstyle
.t_font
;
337 if (resource
.mstyle
.f_font
)
338 delete resource
.mstyle
.f_font
;
339 if (resource
.tstyle
.font
)
340 delete resource
.tstyle
.font
;
343 if (resource
.wstyle
.close_button
.mask
!= None
)
344 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.close_button
.mask
);
345 if (resource
.wstyle
.max_button
.mask
!= None
)
346 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.max_button
.mask
);
347 if (resource
.wstyle
.icon_button
.mask
!= None
)
348 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.icon_button
.mask
);
349 if (resource
.wstyle
.stick_button
.mask
!= None
)
350 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.stick_button
.mask
);
352 if (resource
.tstyle
.left_button
.mask
!= None
)
353 XFreePixmap(blackbox
->getXDisplay(), resource
.tstyle
.left_button
.mask
);
354 if (resource
.tstyle
.right_button
.mask
!= None
)
355 XFreePixmap(blackbox
->getXDisplay(), resource
.tstyle
.right_button
.mask
);
357 if (resource
.mstyle
.bullet_image
.mask
!= None
)
358 XFreePixmap(blackbox
->getXDisplay(), resource
.mstyle
.bullet_image
.mask
);
359 if (resource
.mstyle
.tick_image
.mask
!= None
)
360 XFreePixmap(blackbox
->getXDisplay(), resource
.mstyle
.tick_image
.mask
);
362 resource
.wstyle
.max_button
.mask
= resource
.wstyle
.close_button
.mask
=
363 resource
.wstyle
.icon_button
.mask
=
364 resource
.wstyle
.stick_button
.mask
= None
;
365 resource
.tstyle
.left_button
.mask
= resource
.tstyle
.right_button
.mask
= None
;
366 resource
.mstyle
.bullet_image
.mask
= resource
.mstyle
.tick_image
.mask
= None
;
367 #endif // BITMAPBUTTONS
369 XFreeGC(blackbox
->getXDisplay(), opGC
);
373 void BScreen::saveSloppyFocus(bool s
) {
374 resource
.sloppy_focus
= s
;
377 if (resource
.sloppy_focus
) {
378 fmodel
= "SloppyFocus";
379 if (resource
.auto_raise
) fmodel
+= " AutoRaise";
380 if (resource
.click_raise
) fmodel
+= " ClickRaise";
382 fmodel
= "ClickToFocus";
384 config
->setValue(screenstr
+ "focusModel", fmodel
);
388 void BScreen::saveAutoRaise(bool a
) {
389 resource
.auto_raise
= a
;
390 saveSloppyFocus(resource
.sloppy_focus
);
394 void BScreen::saveClickRaise(bool c
) {
395 resource
.click_raise
= c
;
396 saveSloppyFocus(resource
.sloppy_focus
);
400 void BScreen::saveImageDither(bool d
) {
401 image_control
->setDither(d
);
402 config
->setValue(screenstr
+ "imageDither", doImageDither());
406 void BScreen::saveOpaqueMove(bool o
) {
407 resource
.opaque_move
= o
;
408 config
->setValue(screenstr
+ "opaqueMove", resource
.opaque_move
);
412 void BScreen::saveFullMax(bool f
) {
413 resource
.full_max
= f
;
414 config
->setValue(screenstr
+ "fullMaximization", resource
.full_max
);
418 void BScreen::saveFocusNew(bool f
) {
419 resource
.focus_new
= f
;
420 config
->setValue(screenstr
+ "focusNewWindows", resource
.focus_new
);
424 void BScreen::saveFocusLast(bool f
) {
425 resource
.focus_last
= f
;
426 config
->setValue(screenstr
+ "focusLastWindow", resource
.focus_last
);
430 void BScreen::saveAAFonts(bool f
) {
431 resource
.aa_fonts
= f
;
433 config
->setValue(screenstr
+ "antialiasFonts", resource
.aa_fonts
);
437 void BScreen::saveShadowFonts(bool f
) {
438 resource
.shadow_fonts
= f
;
440 config
->setValue(screenstr
+ "dropShadowFonts", resource
.shadow_fonts
);
444 void BScreen::saveHideToolbar(bool h
) {
445 resource
.hide_toolbar
= h
;
446 if (resource
.hide_toolbar
)
447 toolbar
->unmapToolbar();
449 toolbar
->mapToolbar();
450 config
->setValue(screenstr
+ "hideToolbar", resource
.hide_toolbar
);
454 void BScreen::saveWindowToEdgeSnap(int s
) {
455 resource
.snap_to_edges
= s
;
458 switch (resource
.snap_to_edges
) {
459 case WindowNoSnap
: snap
= "NoSnap"; break;
460 case WindowResistance
: snap
= "Resistance"; break;
461 case WindowSnap
: default: snap
= "Snap"; break;
463 config
->setValue(screenstr
+ "windowToEdgeSnap", snap
);
467 void BScreen::saveWindowToWindowSnap(int s
) {
468 resource
.snap_to_windows
= s
;
471 switch (resource
.snap_to_windows
) {
472 case WindowNoSnap
: snap
= "NoSnap"; break;
473 case WindowResistance
: snap
= "Resistance"; break;
474 case WindowSnap
: default: snap
= "Snap"; break;
476 config
->setValue(screenstr
+ "windowToWindowSnap", snap
);
480 void BScreen::saveResizeZones(unsigned int z
) {
481 resource
.resize_zones
= z
;
482 config
->setValue(screenstr
+ "resizeZones", resource
.resize_zones
);
486 void BScreen::saveWindowCornerSnap(bool s
) {
487 resource
.window_corner_snap
= s
;
488 config
->setValue(screenstr
+ "windowCornerSnap",
489 resource
.window_corner_snap
);
493 void BScreen::saveWorkspaces(unsigned int w
) {
494 resource
.workspaces
= w
;
495 config
->setValue(screenstr
+ "workspaces", resource
.workspaces
);
499 void BScreen::savePlacementPolicy(int p
) {
500 resource
.placement_policy
= p
;
501 const char *placement
;
502 switch (resource
.placement_policy
) {
503 case CascadePlacement
: placement
= "CascadePlacement"; break;
504 case UnderMousePlacement
: placement
= "UnderMousePlacement"; break;
505 case ClickMousePlacement
: placement
= "ClickMousePlacement"; break;
506 case ColSmartPlacement
: placement
= "ColSmartPlacement"; break;
507 case RowSmartPlacement
: default: placement
= "RowSmartPlacement"; break;
509 config
->setValue(screenstr
+ "windowPlacement", placement
);
513 void BScreen::saveResistanceSize(int s
) {
514 resource
.resistance_size
= s
;
515 config
->setValue(screenstr
+ "resistanceSize",
516 resource
.resistance_size
);
520 void BScreen::saveSnapThreshold(int t
) {
521 resource
.snap_threshold
= t
;
522 config
->setValue(screenstr
+ "edgeSnapThreshold",
523 resource
.snap_threshold
);
527 void BScreen::saveSnapOffset(int t
) {
528 resource
.snap_offset
= t
;
529 config
->setValue(screenstr
+ "edgeSnapOffset",
530 resource
.snap_offset
);
534 void BScreen::saveRowPlacementDirection(int d
) {
535 resource
.row_direction
= d
;
536 config
->setValue(screenstr
+ "rowPlacementDirection",
537 resource
.row_direction
== LeftRight
?
538 "LeftToRight" : "RightToLeft");
542 void BScreen::saveColPlacementDirection(int d
) {
543 resource
.col_direction
= d
;
544 config
->setValue(screenstr
+ "colPlacementDirection",
545 resource
.col_direction
== TopBottom
?
546 "TopToBottom" : "BottomToTop");
551 void BScreen::saveStrftimeFormat(const std::string
& format
) {
552 resource
.strftime_format
= format
;
553 config
->setValue(screenstr
+ "strftimeFormat", resource
.strftime_format
);
556 #else // !HAVE_STRFTIME
558 void BScreen::saveDateFormat(int f
) {
559 resource
.date_format
= f
;
560 config
->setValue(screenstr
+ "dateFormat",
561 resource
.date_format
== B_EuropeanDate
?
562 "European" : "American");
566 void BScreen::saveClock24Hour(bool c
) {
567 resource
.clock24hour
= c
;
568 config
->setValue(screenstr
+ "clockFormat", resource
.clock24hour
? 24 : 12);
570 #endif // HAVE_STRFTIME
573 void BScreen::saveWorkspaceNames() {
576 for (unsigned int i
= 0; i
< workspacesList
.size(); ++i
) {
577 names
+= workspacesList
[i
]->getName();
578 if (i
< workspacesList
.size() - 1)
582 config
->setValue(screenstr
+ "workspaceNames", names
);
586 void BScreen::savePlaceIgnoreShaded(bool i
) {
587 resource
.ignore_shaded
= i
;
588 config
->setValue(screenstr
+ "placementIgnoreShaded",
589 resource
.ignore_shaded
);
593 void BScreen::savePlaceIgnoreMaximized(bool i
) {
594 resource
.ignore_maximized
= i
;
595 config
->setValue(screenstr
+ "placementIgnoreMaximized",
596 resource
.ignore_maximized
);
600 void BScreen::saveAllowScrollLock(bool a
) {
601 resource
.allow_scroll_lock
= a
;
602 config
->setValue(screenstr
+ "disableBindingsWithScrollLock",
603 resource
.allow_scroll_lock
);
607 void BScreen::saveWorkspaceWarping(bool w
) {
608 resource
.workspace_warping
= w
;
609 config
->setValue(screenstr
+ "workspaceWarping",
610 resource
.workspace_warping
);
614 void BScreen::saveRootScrollDirection(int d
) {
615 resource
.root_scroll
= d
;
617 switch (resource
.root_scroll
) {
618 case NoScroll
: dir
= "None"; break;
619 case ReverseScroll
: dir
= "Reverse"; break;
620 case NormalScroll
: default: dir
= "Normal"; break;
622 config
->setValue(screenstr
+ "rootScrollDirection", dir
);
626 void BScreen::saveRootMenuButton(unsigned int b
) {
627 resource
.root_menu_button
= b
;
629 switch (resource
.root_menu_button
) {
630 case 0: but
= "None"; break;
631 case 1: but
= "Left"; break;
632 case 2: but
= "Middle"; break;
633 case 3: default: but
= "Right"; break;
635 config
->setValue(screenstr
+ "rootMenuButton", but
);
639 void BScreen::saveWorkspaceMenuButton(unsigned int b
) {
640 resource
.workspace_menu_button
= b
;
642 switch (resource
.workspace_menu_button
) {
643 case 0: but
= "None"; break;
644 case 1: but
= "Left"; break;
645 case 2: default: but
= "Middle"; break;
646 case 3: but
= "Right"; break;
648 config
->setValue(screenstr
+ "workspaceMenuButton", but
);
652 void BScreen::save_rc(void) {
653 saveSloppyFocus(resource
.sloppy_focus
);
654 saveAutoRaise(resource
.auto_raise
);
655 saveImageDither(doImageDither());
656 saveShadowFonts(resource
.shadow_fonts
);
657 saveAAFonts(resource
.aa_fonts
);
658 saveResizeZones(resource
.resize_zones
);
659 saveOpaqueMove(resource
.opaque_move
);
660 saveFullMax(resource
.full_max
);
661 saveFocusNew(resource
.focus_new
);
662 saveFocusLast(resource
.focus_last
);
663 saveHideToolbar(resource
.hide_toolbar
);
664 saveWindowToWindowSnap(resource
.snap_to_windows
);
665 saveWindowToEdgeSnap(resource
.snap_to_edges
);
666 saveWindowCornerSnap(resource
.window_corner_snap
);
667 saveWorkspaces(resource
.workspaces
);
668 savePlacementPolicy(resource
.placement_policy
);
669 saveSnapThreshold(resource
.snap_threshold
);
670 saveSnapOffset(resource
.snap_offset
);
671 saveResistanceSize(resource
.resistance_size
);
672 saveRowPlacementDirection(resource
.row_direction
);
673 saveColPlacementDirection(resource
.col_direction
);
675 saveStrftimeFormat(resource
.strftime_format
);
676 #else // !HAVE_STRFTIME
677 saveDateFormat(resource
.date_format
);
678 savwClock24Hour(resource
.clock24hour
);
679 #endif // HAVE_STRFTIME
680 savePlaceIgnoreShaded(resource
.ignore_shaded
);
681 savePlaceIgnoreMaximized(resource
.ignore_maximized
);
682 saveAllowScrollLock(resource
.allow_scroll_lock
);
683 saveWorkspaceWarping(resource
.workspace_warping
);
684 saveRootScrollDirection(resource
.root_scroll
);
685 saveRootMenuButton(resource
.root_menu_button
);
686 saveWorkspaceMenuButton(resource
.workspace_menu_button
);
693 void BScreen::load_rc(void) {
697 if (! config
->getValue(screenstr
+ "fullMaximization", resource
.full_max
))
698 resource
.full_max
= false;
700 if (! config
->getValue(screenstr
+ "focusNewWindows", resource
.focus_new
))
701 resource
.focus_new
= false;
703 if (! config
->getValue(screenstr
+ "focusLastWindow", resource
.focus_last
))
704 resource
.focus_last
= false;
706 if (! config
->getValue(screenstr
+ "workspaces", resource
.workspaces
))
707 resource
.workspaces
= 1;
709 if (! config
->getValue(screenstr
+ "opaqueMove", resource
.opaque_move
))
710 resource
.opaque_move
= false;
712 if (! config
->getValue(screenstr
+ "dropShadowFonts", resource
.shadow_fonts
))
713 resource
.shadow_fonts
= false;
715 if (! config
->getValue(screenstr
+ "antialiasFonts", resource
.aa_fonts
))
716 resource
.aa_fonts
= true;
718 if (! config
->getValue(screenstr
+ "resizeZones", resource
.resize_zones
) ||
719 (resource
.resize_zones
!= 1 && resource
.resize_zones
!= 2 &&
720 resource
.resize_zones
!= 4))
721 resource
.resize_zones
= 4;
723 if (! config
->getValue(screenstr
+ "hideToolbar", resource
.hide_toolbar
))
724 resource
.hide_toolbar
= false;
726 resource
.snap_to_windows
= WindowResistance
;
727 if (config
->getValue(screenstr
+ "windowToWindowSnap", s
)) {
729 resource
.snap_to_windows
= WindowNoSnap
;
730 else if (s
== "Snap")
731 resource
.snap_to_windows
= WindowSnap
;
734 resource
.snap_to_edges
= WindowResistance
;
735 if (config
->getValue(screenstr
+ "windowToEdgeSnap", s
)) {
737 resource
.snap_to_edges
= WindowNoSnap
;
738 else if (s
== "Snap")
739 resource
.snap_to_edges
= WindowSnap
;
742 if (! config
->getValue(screenstr
+ "windowCornerSnap",
743 resource
.window_corner_snap
))
744 resource
.window_corner_snap
= true;
746 if (! config
->getValue(screenstr
+ "imageDither", b
))
748 image_control
->setDither(b
);
750 if (! config
->getValue(screenstr
+ "edgeSnapOffset",
751 resource
.snap_offset
))
752 resource
.snap_offset
= 0;
753 if (resource
.snap_offset
> 50) // sanity check, setting this huge would
754 resource
.snap_offset
= 50; // seriously suck.
756 if (! config
->getValue(screenstr
+ "edgeSnapThreshold",
757 resource
.snap_threshold
))
758 resource
.snap_threshold
= 4;
760 if (! config
->getValue(screenstr
+ "resistanceSize",
761 resource
.resistance_size
))
762 resource
.resistance_size
= 18;
764 if (config
->getValue(screenstr
+ "rowPlacementDirection", s
) &&
766 resource
.row_direction
= RightLeft
;
768 resource
.row_direction
= LeftRight
;
770 if (config
->getValue(screenstr
+ "colPlacementDirection", s
) &&
772 resource
.col_direction
= BottomTop
;
774 resource
.col_direction
= TopBottom
;
776 if (config
->getValue(screenstr
+ "workspaceNames", s
)) {
777 XAtom::StringVect workspaceNames
;
779 string::const_iterator it
= s
.begin(), end
= s
.end();
781 string::const_iterator tmp
= it
; // current string.begin()
782 it
= std::find(tmp
, end
, ','); // look for comma between tmp and end
783 workspaceNames
.push_back(string(tmp
, it
)); // s[tmp:it]
789 xatom
->setValue(getRootWindow(), XAtom::net_desktop_names
, XAtom::utf8
,
793 resource
.sloppy_focus
= true;
794 resource
.auto_raise
= false;
795 resource
.click_raise
= false;
796 if (config
->getValue(screenstr
+ "focusModel", s
)) {
797 if (s
.find("ClickToFocus") != string::npos
) {
798 resource
.sloppy_focus
= false;
801 if (s
.find("AutoRaise") != string::npos
)
802 resource
.auto_raise
= true;
803 if (s
.find("ClickRaise") != string::npos
)
804 resource
.click_raise
= true;
808 if (config
->getValue(screenstr
+ "windowPlacement", s
)) {
809 if (s
== "CascadePlacement")
810 resource
.placement_policy
= CascadePlacement
;
811 else if (s
== "UnderMousePlacement")
812 resource
.placement_policy
= UnderMousePlacement
;
813 else if (s
== "ClickMousePlacement")
814 resource
.placement_policy
= ClickMousePlacement
;
815 else if (s
== "ColSmartPlacement")
816 resource
.placement_policy
= ColSmartPlacement
;
817 else //if (s == "RowSmartPlacement")
818 resource
.placement_policy
= RowSmartPlacement
;
820 resource
.placement_policy
= RowSmartPlacement
;
823 if (! config
->getValue(screenstr
+ "strftimeFormat",
824 resource
.strftime_format
))
825 resource
.strftime_format
= "%I:%M %p";
826 #else // !HAVE_STRFTIME
829 if (config
->getValue(screenstr
+ "dateFormat", s
) && s
== "European")
830 resource
.date_format
= B_EuropeanDate
;
832 resource
.date_format
= B_AmericanDate
;
834 if (! config
->getValue(screenstr
+ "clockFormat", l
))
836 resource
.clock24hour
= l
== 24;
837 #endif // HAVE_STRFTIME
839 if (! config
->getValue(screenstr
+ "placementIgnoreShaded",
840 resource
.ignore_shaded
))
841 resource
.ignore_shaded
= true;
843 if (! config
->getValue(screenstr
+ "placementIgnoreMaximized",
844 resource
.ignore_maximized
))
845 resource
.ignore_maximized
= true;
847 if (! config
->getValue(screenstr
+ "disableBindingsWithScrollLock",
848 resource
.allow_scroll_lock
))
849 resource
.allow_scroll_lock
= false;
851 if (! config
->getValue(screenstr
+ "workspaceWarping",
852 resource
.workspace_warping
))
853 resource
.workspace_warping
= false;
855 resource
.root_scroll
= NormalScroll
;
856 if (config
->getValue(screenstr
+ "rootScrollDirection", s
)) {
858 resource
.root_scroll
= NoScroll
;
859 else if (s
== "Reverse")
860 resource
.root_scroll
= ReverseScroll
;
863 resource
.root_menu_button
= 3;
864 if (config
->getValue(screenstr
+ "rootMenuButton", s
)) {
866 resource
.root_menu_button
= 0;
867 else if (s
== "Left")
868 resource
.root_menu_button
= 1;
869 else if (s
== "Middle")
870 resource
.root_menu_button
= 2;
873 resource
.workspace_menu_button
= 2;
874 if (config
->getValue(screenstr
+ "workspaceMenuButton", s
)) {
876 resource
.workspace_menu_button
= 0;
877 else if (s
== "Left")
878 resource
.workspace_menu_button
= 1;
879 else if (s
== "Right")
880 resource
.workspace_menu_button
= 3;
882 // cant both be the same
883 if (resource
.workspace_menu_button
== resource
.root_menu_button
)
884 resource
.workspace_menu_button
= 0;
888 void BScreen::changeWorkspaceCount(unsigned int new_count
) {
889 assert(new_count
> 0);
891 if (new_count
< workspacesList
.size()) {
893 for (unsigned int i
= workspacesList
.size(); i
> new_count
; --i
)
894 removeLastWorkspace();
895 // removeLast already sets the current workspace to the
896 // last available one.
897 } else if (new_count
> workspacesList
.size()) {
899 for(unsigned int i
= workspacesList
.size(); i
< new_count
; ++i
)
905 void BScreen::reconfigure(void) {
906 // don't reconfigure while saving the initial rc file, it's a waste and it
907 // breaks somethings (workspace names)
908 if (blackbox
->isStartup()) return;
915 // we need to do this explicitly, because just loading this value from the rc
917 changeWorkspaceCount(resource
.workspaces
);
920 gcv
.foreground
= WhitePixel(blackbox
->getXDisplay(),
922 gcv
.function
= GXinvert
;
923 gcv
.subwindow_mode
= IncludeInferiors
;
924 XChangeGC(blackbox
->getXDisplay(), opGC
,
925 GCForeground
| GCFunction
| GCSubwindowMode
, &gcv
);
927 const char *s
= i18n(ScreenSet
, ScreenPositionLength
,
928 "0: 0000 x 0: 0000");
930 geom_w
= resource
.wstyle
.font
->measureString(s
) + resource
.bevel_width
* 2;
931 geom_h
= resource
.wstyle
.font
->height() + resource
.bevel_width
* 2;
933 BTexture
* texture
= &(resource
.wstyle
.l_focus
);
934 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
935 if (geom_pixmap
== ParentRelative
) {
936 texture
= &(resource
.wstyle
.t_focus
);
937 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
940 XSetWindowBackground(blackbox
->getXDisplay(), geom_window
,
941 texture
->color().pixel());
943 XSetWindowBackgroundPixmap(blackbox
->getXDisplay(),
944 geom_window
, geom_pixmap
);
946 XSetWindowBorderWidth(blackbox
->getXDisplay(), geom_window
,
947 resource
.border_width
);
948 XSetWindowBorder(blackbox
->getXDisplay(), geom_window
,
949 resource
.border_color
.pixel());
951 workspacemenu
->reconfigure();
952 iconmenu
->reconfigure();
954 typedef std::vector
<int> SubList
;
955 SubList remember_subs
;
957 // save the current open menus
958 Basemenu
*menu
= rootmenu
;
960 while ((submenu
= menu
->getCurrentSubmenu()) >= 0) {
961 remember_subs
.push_back(submenu
);
962 menu
= menu
->find(submenu
)->submenu();
968 rootmenu
->reconfigure();
970 // reopen the saved menus
972 const SubList::iterator subs_end
= remember_subs
.end();
973 for (SubList::iterator it
= remember_subs
.begin(); it
!= subs_end
; ++it
) {
974 menu
->drawSubmenu(*it
);
975 menu
= menu
->find(*it
)->submenu();
980 configmenu
->reconfigure();
982 toolbar
->reconfigure();
986 std::for_each(workspacesList
.begin(), workspacesList
.end(),
987 std::mem_fun(&Workspace::reconfigure
));
989 BlackboxWindowList::iterator iit
= iconList
.begin();
990 for (; iit
!= iconList
.end(); ++iit
) {
991 BlackboxWindow
*bw
= *iit
;
992 if (bw
->validateClient())
996 image_control
->timeout();
1000 void BScreen::rereadMenu(void) {
1004 rootmenu
->reconfigure();
1008 void BScreen::LoadStyle(void) {
1009 Configuration
style(False
);
1011 const char *sfile
= blackbox
->getStyleFilename();
1012 if (sfile
!= NULL
) {
1013 style
.setFile(sfile
);
1014 if (! style
.load()) {
1015 style
.setFile(DEFAULTSTYLE
);
1017 style
.create(); // hardcoded default values will be used.
1021 // merge in the rc file
1022 style
.merge(config
->file(), True
);
1026 // load fonts/fontsets
1027 if (resource
.wstyle
.font
)
1028 delete resource
.wstyle
.font
;
1029 if (resource
.tstyle
.font
)
1030 delete resource
.tstyle
.font
;
1031 if (resource
.mstyle
.f_font
)
1032 delete resource
.mstyle
.f_font
;
1033 if (resource
.mstyle
.t_font
)
1034 delete resource
.mstyle
.t_font
;
1035 resource
.wstyle
.font
= resource
.tstyle
.font
= resource
.mstyle
.f_font
=
1036 resource
.mstyle
.t_font
= (BFont
*) 0;
1038 resource
.wstyle
.font
= readDatabaseFont("window.", style
);
1039 resource
.tstyle
.font
= readDatabaseFont("toolbar.", style
);
1040 resource
.mstyle
.t_font
= readDatabaseFont("menu.title.", style
);
1041 resource
.mstyle
.f_font
= readDatabaseFont("menu.frame.", style
);
1043 // load window config
1044 resource
.wstyle
.t_focus
=
1045 readDatabaseTexture("window.title.focus", "white", style
);
1046 resource
.wstyle
.t_unfocus
=
1047 readDatabaseTexture("window.title.unfocus", "black", style
);
1048 resource
.wstyle
.l_focus
=
1049 readDatabaseTexture("window.label.focus", "white", style
);
1050 resource
.wstyle
.l_unfocus
=
1051 readDatabaseTexture("window.label.unfocus", "black", style
);
1052 resource
.wstyle
.h_focus
=
1053 readDatabaseTexture("window.handle.focus", "white", style
);
1054 resource
.wstyle
.h_unfocus
=
1055 readDatabaseTexture("window.handle.unfocus", "black", style
);
1056 resource
.wstyle
.g_focus
=
1057 readDatabaseTexture("window.grip.focus", "white", style
);
1058 resource
.wstyle
.g_unfocus
=
1059 readDatabaseTexture("window.grip.unfocus", "black", style
);
1060 resource
.wstyle
.b_focus
=
1061 readDatabaseTexture("window.button.focus", "white", style
);
1062 resource
.wstyle
.b_unfocus
=
1063 readDatabaseTexture("window.button.unfocus", "black", style
);
1064 resource
.wstyle
.b_pressed
=
1065 readDatabaseTexture("window.button.pressed", "black", style
);
1067 #ifdef BITMAPBUTTONS
1068 if (resource
.wstyle
.close_button
.mask
!= None
)
1069 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.close_button
.mask
);
1070 if (resource
.wstyle
.max_button
.mask
!= None
)
1071 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.max_button
.mask
);
1072 if (resource
.wstyle
.icon_button
.mask
!= None
)
1073 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.icon_button
.mask
);
1074 if (resource
.wstyle
.stick_button
.mask
!= None
)
1075 XFreePixmap(blackbox
->getXDisplay(), resource
.wstyle
.stick_button
.mask
);
1077 resource
.wstyle
.close_button
.mask
= resource
.wstyle
.max_button
.mask
=
1078 resource
.wstyle
.icon_button
.mask
=
1079 resource
.wstyle
.icon_button
.mask
= None
;
1081 readDatabaseMask("window.button.close.mask", resource
.wstyle
.close_button
,
1083 readDatabaseMask("window.button.max.mask", resource
.wstyle
.max_button
,
1085 readDatabaseMask("window.button.icon.mask", resource
.wstyle
.icon_button
,
1087 readDatabaseMask("window.button.stick.mask", resource
.wstyle
.stick_button
,
1089 #endif // BITMAPBUTTONS
1091 // we create the window.frame texture by hand because it exists only to
1092 // make the code cleaner and is not actually used for display
1093 BColor color
= readDatabaseColor("window.frame.focusColor", "white", style
);
1094 resource
.wstyle
.f_focus
= BTexture("solid flat", getBaseDisplay(),
1095 getScreenNumber(), image_control
);
1096 resource
.wstyle
.f_focus
.setColor(color
);
1098 color
= readDatabaseColor("window.frame.unfocusColor", "white", style
);
1099 resource
.wstyle
.f_unfocus
= BTexture("solid flat", getBaseDisplay(),
1100 getScreenNumber(), image_control
);
1101 resource
.wstyle
.f_unfocus
.setColor(color
);
1103 resource
.wstyle
.l_text_focus
=
1104 readDatabaseColor("window.label.focus.textColor", "black", style
);
1105 resource
.wstyle
.l_text_unfocus
=
1106 readDatabaseColor("window.label.unfocus.textColor", "white", style
);
1107 resource
.wstyle
.b_pic_focus
=
1108 readDatabaseColor("window.button.focus.picColor", "black", style
);
1109 resource
.wstyle
.b_pic_unfocus
=
1110 readDatabaseColor("window.button.unfocus.picColor", "white", style
);
1112 resource
.wstyle
.justify
= LeftJustify
;
1113 if (style
.getValue("window.justify", s
)) {
1114 if (s
== "right" || s
== "Right")
1115 resource
.wstyle
.justify
= RightJustify
;
1116 else if (s
== "center" || s
== "Center")
1117 resource
.wstyle
.justify
= CenterJustify
;
1121 if (resource
.wstyle
.t_focus
.texture() == BTexture::Parent_Relative
)
1122 resource
.wstyle
.t_focus
= resource
.wstyle
.f_focus
;
1123 if (resource
.wstyle
.t_unfocus
.texture() == BTexture::Parent_Relative
)
1124 resource
.wstyle
.t_unfocus
= resource
.wstyle
.f_unfocus
;
1125 if (resource
.wstyle
.h_focus
.texture() == BTexture::Parent_Relative
)
1126 resource
.wstyle
.h_focus
= resource
.wstyle
.f_focus
;
1127 if (resource
.wstyle
.h_unfocus
.texture() == BTexture::Parent_Relative
)
1128 resource
.wstyle
.h_unfocus
= resource
.wstyle
.f_unfocus
;
1130 // load toolbar config
1131 #ifdef BITMAPBUTTONS
1132 if (resource
.tstyle
.left_button
.mask
!= None
)
1133 XFreePixmap(blackbox
->getXDisplay(), resource
.tstyle
.left_button
.mask
);
1134 if (resource
.tstyle
.right_button
.mask
!= None
)
1135 XFreePixmap(blackbox
->getXDisplay(), resource
.tstyle
.right_button
.mask
);
1136 #endif // BITMAPBUTTONS
1138 resource
.tstyle
.toolbar
=
1139 readDatabaseTexture("toolbar", "black", style
);
1140 resource
.tstyle
.label
=
1141 readDatabaseTexture("toolbar.label", "black", style
);
1142 resource
.tstyle
.window
=
1143 readDatabaseTexture("toolbar.windowLabel", "black", style
);
1144 resource
.tstyle
.button
=
1145 readDatabaseTexture("toolbar.button", "white", style
);
1146 resource
.tstyle
.pressed
=
1147 readDatabaseTexture("toolbar.button.pressed", "black", style
);
1148 resource
.tstyle
.clock
=
1149 readDatabaseTexture("toolbar.clock", "black", style
);
1150 resource
.tstyle
.l_text
=
1151 readDatabaseColor("toolbar.label.textColor", "white", style
);
1152 resource
.tstyle
.w_text
=
1153 readDatabaseColor("toolbar.windowLabel.textColor", "white", style
);
1154 resource
.tstyle
.c_text
=
1155 readDatabaseColor("toolbar.clock.textColor", "white", style
);
1156 resource
.tstyle
.b_pic
=
1157 readDatabaseColor("toolbar.button.picColor", "black", style
);
1159 #ifdef BITMAPBUTTONS
1160 readDatabaseMask("toolbar.button.left.mask", resource
.tstyle
.left_button
,
1162 readDatabaseMask("toolbar.button.right.mask", resource
.tstyle
.right_button
,
1164 #endif // BITMAPBUTTONS
1166 resource
.tstyle
.justify
= LeftJustify
;
1167 if (style
.getValue("toolbar.justify", s
)) {
1168 if (s
== "right" || s
== "Right")
1169 resource
.tstyle
.justify
= RightJustify
;
1170 else if (s
== "center" || s
== "Center")
1171 resource
.tstyle
.justify
= CenterJustify
;
1175 if (resource
.tstyle
.toolbar
.texture() == BTexture::Parent_Relative
) {
1176 resource
.tstyle
.toolbar
= BTexture("solid flat", getBaseDisplay(),
1177 getScreenNumber(), image_control
);
1178 resource
.tstyle
.toolbar
.setColor(BColor("black", getBaseDisplay(),
1179 getScreenNumber()));
1183 #ifdef BITMAPBUTTONS
1184 if (resource
.mstyle
.bullet_image
.mask
!= None
)
1185 XFreePixmap(blackbox
->getXDisplay(), resource
.mstyle
.bullet_image
.mask
);
1186 if (resource
.mstyle
.tick_image
.mask
!= None
)
1187 XFreePixmap(blackbox
->getXDisplay(), resource
.mstyle
.tick_image
.mask
);
1188 #endif // BITMAPBUTTONS
1190 resource
.mstyle
.title
=
1191 readDatabaseTexture("menu.title", "white", style
);
1192 resource
.mstyle
.frame
=
1193 readDatabaseTexture("menu.frame", "black", style
);
1194 resource
.mstyle
.hilite
=
1195 readDatabaseTexture("menu.hilite", "white", style
);
1196 resource
.mstyle
.t_text
=
1197 readDatabaseColor("menu.title.textColor", "black", style
);
1198 resource
.mstyle
.f_text
=
1199 readDatabaseColor("menu.frame.textColor", "white", style
);
1200 resource
.mstyle
.d_text
=
1201 readDatabaseColor("menu.frame.disableColor", "black", style
);
1202 resource
.mstyle
.h_text
=
1203 readDatabaseColor("menu.hilite.textColor", "black", style
);
1205 #ifdef BITMAPBUTTONS
1206 readDatabaseMask("menu.arrow.mask", resource
.mstyle
.bullet_image
, style
);
1207 readDatabaseMask("menu.selected.mask", resource
.mstyle
.tick_image
, style
);
1208 #endif // BITMAPBUTTONS
1210 resource
.mstyle
.t_justify
= LeftJustify
;
1211 if (style
.getValue("menu.title.justify", s
)) {
1212 if (s
== "right" || s
== "Right")
1213 resource
.mstyle
.t_justify
= RightJustify
;
1214 else if (s
== "center" || s
== "Center")
1215 resource
.mstyle
.t_justify
= CenterJustify
;
1218 resource
.mstyle
.f_justify
= LeftJustify
;
1219 if (style
.getValue("menu.frame.justify", s
)) {
1220 if (s
== "right" || s
== "Right")
1221 resource
.mstyle
.f_justify
= RightJustify
;
1222 else if (s
== "center" || s
== "Center")
1223 resource
.mstyle
.f_justify
= CenterJustify
;
1226 resource
.mstyle
.bullet
= Basemenu::Triangle
;
1227 if (style
.getValue("menu.bullet", s
)) {
1228 if (s
== "empty" || s
== "Empty")
1229 resource
.mstyle
.bullet
= Basemenu::Empty
;
1230 else if (s
== "square" || s
== "Square")
1231 resource
.mstyle
.bullet
= Basemenu::Square
;
1232 else if (s
== "diamond" || s
== "Diamond")
1233 resource
.mstyle
.bullet
= Basemenu::Diamond
;
1236 resource
.mstyle
.bullet_pos
= Basemenu::Left
;
1237 if (style
.getValue("menu.bullet.position", s
)) {
1238 if (s
== "right" || s
== "Right")
1239 resource
.mstyle
.bullet_pos
= Basemenu::Right
;
1243 if (resource
.mstyle
.frame
.texture() == BTexture::Parent_Relative
) {
1244 resource
.mstyle
.frame
= BTexture("solid flat", getBaseDisplay(),
1245 getScreenNumber(), image_control
);
1246 resource
.mstyle
.frame
.setColor(BColor("black", getBaseDisplay(),
1247 getScreenNumber()));
1250 resource
.border_color
=
1251 readDatabaseColor("borderColor", "black", style
);
1253 // load bevel, border and handle widths
1254 if (! style
.getValue("handleWidth", resource
.handle_width
) ||
1255 resource
.handle_width
> (getWidth() / 2) || resource
.handle_width
== 0)
1256 resource
.handle_width
= 6;
1258 if (! style
.getValue("borderWidth", resource
.border_width
))
1259 resource
.border_width
= 1;
1261 if (! style
.getValue("bevelWidth", resource
.bevel_width
) ||
1262 resource
.bevel_width
> (getWidth() / 2) || resource
.bevel_width
== 0)
1263 resource
.bevel_width
= 3;
1265 if (! style
.getValue("frameWidth", resource
.frame_width
) ||
1266 resource
.frame_width
> (getWidth() / 2))
1267 resource
.frame_width
= resource
.bevel_width
;
1269 if (style
.getValue("rootCommand", s
))
1270 bexec(s
, displayString());
1274 void BScreen::addIcon(BlackboxWindow
*w
) {
1277 w
->setWorkspace(BSENTINEL
);
1278 w
->setWindowNumber(iconList
.size());
1280 iconList
.push_back(w
);
1282 const char* title
= w
->getIconTitle();
1283 iconmenu
->insert(title
);
1288 void BScreen::removeIcon(BlackboxWindow
*w
) {
1293 iconmenu
->remove(w
->getWindowNumber());
1296 BlackboxWindowList::iterator it
= iconList
.begin(),
1297 end
= iconList
.end();
1298 for (int i
= 0; it
!= end
; ++it
)
1299 (*it
)->setWindowNumber(i
++);
1303 BlackboxWindow
*BScreen::getIcon(unsigned int index
) {
1304 if (index
< iconList
.size()) {
1305 BlackboxWindowList::iterator it
= iconList
.begin();
1306 while (index
-- > 0) // increment to index
1311 return (BlackboxWindow
*) 0;
1315 unsigned int BScreen::addWorkspace(void) {
1316 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
1317 workspacesList
.push_back(wkspc
);
1318 saveWorkspaces(getWorkspaceCount());
1319 saveWorkspaceNames();
1321 workspacemenu
->insertWorkspace(wkspc
);
1322 workspacemenu
->update();
1324 toolbar
->reconfigure();
1326 updateNetizenWorkspaceCount();
1328 return workspacesList
.size();
1332 unsigned int BScreen::removeLastWorkspace(void) {
1333 if (workspacesList
.size() == 1)
1336 Workspace
*wkspc
= workspacesList
.back();
1338 if (current_workspace
->getID() == wkspc
->getID())
1339 changeWorkspaceID(current_workspace
->getID() - 1);
1343 workspacemenu
->removeWorkspace(wkspc
);
1344 workspacemenu
->update();
1346 workspacesList
.pop_back();
1349 saveWorkspaces(getWorkspaceCount());
1350 saveWorkspaceNames();
1352 toolbar
->reconfigure();
1354 updateNetizenWorkspaceCount();
1356 return workspacesList
.size();
1360 void BScreen::changeWorkspaceID(unsigned int id
) {
1361 if (! current_workspace
|| id
== current_workspace
->getID()) return;
1363 BlackboxWindow
*focused
= blackbox
->getFocusedWindow();
1364 if (focused
&& focused
->getScreen() == this) {
1365 assert(focused
->isStuck() ||
1366 focused
->getWorkspaceNumber() == current_workspace
->getID());
1368 current_workspace
->setLastFocusedWindow(focused
);
1370 // if no window had focus, no need to store a last focus
1371 current_workspace
->setLastFocusedWindow((BlackboxWindow
*) 0);
1374 // when we switch workspaces, unfocus whatever was focused if it is going
1376 if (focused
&& ! focused
->isStuck())
1377 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1379 current_workspace
->hideAll();
1380 workspacemenu
->setItemSelected(current_workspace
->getID() + 2, False
);
1382 current_workspace
= getWorkspace(id
);
1384 xatom
->setValue(getRootWindow(), XAtom::net_current_desktop
,
1385 XAtom::cardinal
, id
);
1387 workspacemenu
->setItemSelected(current_workspace
->getID() + 2, True
);
1388 toolbar
->redrawWorkspaceLabel(True
);
1390 current_workspace
->showAll();
1395 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
1398 XSync(blackbox
->getXDisplay(), False
);
1400 // If sloppy focus and we can find the client window under the pointer,
1402 if (resource
.sloppy_focus
&&
1403 XQueryPointer(blackbox
->getXDisplay(), getRootWindow(), &r
, &c
,
1404 &rx
, &ry
, &x
, &y
, &m
) &&
1406 if ( (win
= blackbox
->searchWindow(c
)) )
1407 f
= win
->setInputFocus();
1410 // If that fails, and we're doing focus_last, try to focus the last window.
1411 if (! f
&& resource
.focus_last
&&
1412 (win
= current_workspace
->getLastFocusedWindow()))
1413 f
= win
->setInputFocus();
1416 if we found a focus target, then we set the focused window explicitly
1417 because it is possible to switch off this workspace before the x server
1418 generates the FocusIn event for the window. if that happens, openbox would
1419 lose track of what window was the 'LastFocused' window on the workspace.
1421 if we did not find a focus target, then set the current focused window to
1425 blackbox
->setFocusedWindow(win
);
1427 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1429 updateNetizenCurrentWorkspace();
1434 * Set the _NET_CLIENT_LIST root window property.
1436 void BScreen::updateClientList(void) {
1437 if (windowList
.size() > 0) {
1438 Window
*windows
= new Window
[windowList
.size()];
1439 Window
*win_it
= windows
;
1440 BlackboxWindowList::iterator it
= windowList
.begin();
1441 const BlackboxWindowList::iterator end
= windowList
.end();
1442 for (; it
!= end
; ++it
, ++win_it
)
1443 *win_it
= (*it
)->getClientWindow();
1444 xatom
->setValue(getRootWindow(), XAtom::net_client_list
, XAtom::window
,
1445 windows
, windowList
.size());
1448 xatom
->setValue(getRootWindow(), XAtom::net_client_list
, XAtom::window
,
1451 updateStackingList();
1456 * Set the _NET_CLIENT_LIST_STACKING root window property.
1458 void BScreen::updateStackingList(void) {
1460 BlackboxWindowList stack_order
;
1463 * Get the stacking order from all of the workspaces.
1464 * We start with the current workspace so that the sticky windows will be
1465 * in the right order on the current workspace.
1466 * XXX: Do we need to have sticky windows in the list once for each workspace?
1468 getCurrentWorkspace()->appendStackOrder(stack_order
);
1469 for (unsigned int i
= 0; i
< getWorkspaceCount(); ++i
)
1470 if (i
!= getCurrentWorkspaceID())
1471 getWorkspace(i
)->appendStackOrder(stack_order
);
1473 if (stack_order
.size() > 0) {
1474 // set the client list atoms
1475 Window
*windows
= new Window
[stack_order
.size()];
1476 Window
*win_it
= windows
;
1477 BlackboxWindowList::iterator it
= stack_order
.begin(),
1478 end
= stack_order
.end();
1479 for (; it
!= end
; ++it
, ++win_it
)
1480 *win_it
= (*it
)->getClientWindow();
1481 xatom
->setValue(getRootWindow(), XAtom::net_client_list_stacking
,
1482 XAtom::window
, windows
, stack_order
.size());
1485 xatom
->setValue(getRootWindow(), XAtom::net_client_list_stacking
,
1486 XAtom::window
, 0, 0);
1490 void BScreen::addSystrayWindow(Window window
) {
1491 XGrabServer(blackbox
->getXDisplay());
1493 XSelectInput(blackbox
->getXDisplay(), window
, StructureNotifyMask
);
1494 systrayWindowList
.push_back(window
);
1495 xatom
->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows
,
1497 &systrayWindowList
[0], systrayWindowList
.size());
1498 blackbox
->saveSystrayWindowSearch(window
, this);
1500 XUngrabServer(blackbox
->getXDisplay());
1504 void BScreen::removeSystrayWindow(Window window
) {
1505 XGrabServer(blackbox
->getXDisplay());
1507 WindowList::iterator it
= systrayWindowList
.begin();
1508 const WindowList::iterator end
= systrayWindowList
.end();
1509 for (; it
!= end
; ++it
)
1510 if (*it
== window
) {
1511 systrayWindowList
.erase(it
);
1512 xatom
->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows
,
1514 &systrayWindowList
[0], systrayWindowList
.size());
1515 blackbox
->removeSystrayWindowSearch(window
);
1516 XSelectInput(blackbox
->getXDisplay(), window
, NoEventMask
);
1520 assert(it
!= end
); // not a systray window
1522 XUngrabServer(blackbox
->getXDisplay());
1526 void BScreen::manageWindow(Window w
) {
1527 // is the window a KDE systray window?
1529 if (xatom
->getValue(w
, XAtom::kde_net_wm_system_tray_window_for
,
1530 XAtom::window
, systray
) && systray
!= None
) {
1531 addSystrayWindow(w
);
1535 // is the window a docking app
1536 XWMHints
*wmhint
= XGetWMHints(blackbox
->getXDisplay(), w
);
1537 if (wmhint
&& (wmhint
->flags
& StateHint
) &&
1538 wmhint
->initial_state
== WithdrawnState
) {
1543 new BlackboxWindow(blackbox
, w
, this);
1545 BlackboxWindow
*win
= blackbox
->searchWindow(w
);
1549 if (win
->isDesktop()) {
1550 desktopWindowList
.push_back(win
->getFrameWindow());
1551 } else { // if (win->isNormal()) {
1552 // don't list desktop windows as managed windows
1553 windowList
.push_back(win
);
1556 if (win
->isTopmost())
1557 specialWindowList
.push_back(win
->getFrameWindow());
1560 XMapRequestEvent mre
;
1562 if (blackbox
->isStartup() && win
->isNormal()) win
->restoreAttributes();
1563 win
->mapRequestEvent(&mre
);
1567 void BScreen::unmanageWindow(BlackboxWindow
*w
, bool remap
) {
1568 // is the window a KDE systray window?
1570 if (xatom
->getValue(w
->getClientWindow(),
1571 XAtom::kde_net_wm_system_tray_window_for
,
1572 XAtom::window
, systray
) && systray
!= None
) {
1573 removeSystrayWindow(w
->getClientWindow());
1579 // Remove the modality so that its parent won't try to re-focus the window
1580 if (w
->isModal()) w
->setModal(False
);
1582 if (w
->getWorkspaceNumber() != BSENTINEL
&&
1583 w
->getWindowNumber() != BSENTINEL
) {
1584 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1586 for (unsigned int i
= 0; i
< getNumberOfWorkspaces(); ++i
)
1587 if (i
!= w
->getWorkspaceNumber())
1588 getWorkspace(i
)->removeWindow(w
, True
);
1590 } else if (w
->isIconic())
1593 if (w
->isDesktop()) {
1594 WindowList::iterator it
= desktopWindowList
.begin();
1595 const WindowList::iterator end
= desktopWindowList
.end();
1596 for (; it
!= end
; ++it
)
1597 if (*it
== w
->getFrameWindow()) {
1598 desktopWindowList
.erase(it
);
1601 assert(it
!= end
); // the window wasnt a desktop window?
1602 } else { // if (w->isNormal()) {
1603 // we don't list desktop windows as managed windows
1604 windowList
.remove(w
);
1607 if (w
->isTopmost()) {
1608 WindowList::iterator it
= specialWindowList
.begin();
1609 const WindowList::iterator end
= specialWindowList
.end();
1610 for (; it
!= end
; ++it
)
1611 if (*it
== w
->getFrameWindow()) {
1612 specialWindowList
.erase(it
);
1615 assert(it
!= end
); // the window wasnt a special window?
1619 if (blackbox
->getFocusedWindow() == w
)
1620 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
1622 removeNetizen(w
->getClientWindow());
1625 some managed windows can also be window group controllers. when
1626 unmanaging such windows, we should also delete the window group.
1628 BWindowGroup
*group
= blackbox
->searchGroup(w
->getClientWindow());
1635 void BScreen::addNetizen(Netizen
*n
) {
1636 netizenList
.push_back(n
);
1638 n
->sendWorkspaceCount();
1639 n
->sendCurrentWorkspace();
1641 WorkspaceList::iterator it
= workspacesList
.begin();
1642 const WorkspaceList::iterator end
= workspacesList
.end();
1643 for (; it
!= end
; ++it
)
1644 (*it
)->sendWindowList(*n
);
1646 Window f
= ((blackbox
->getFocusedWindow()) ?
1647 blackbox
->getFocusedWindow()->getClientWindow() : None
);
1648 n
->sendWindowFocus(f
);
1652 void BScreen::removeNetizen(Window w
) {
1653 NetizenList::iterator it
= netizenList
.begin();
1654 for (; it
!= netizenList
.end(); ++it
) {
1655 if ((*it
)->getWindowID() == w
) {
1657 netizenList
.erase(it
);
1664 void BScreen::updateWorkArea(void) {
1665 if (workspacesList
.size() > 0) {
1666 unsigned long *dims
= new unsigned long[4 * workspacesList
.size()];
1667 for (unsigned int i
= 0, m
= workspacesList
.size(); i
< m
; ++i
) {
1668 // XXX: this could be different for each workspace
1669 const Rect
&area
= availableArea();
1670 dims
[(i
* 4) + 0] = area
.x();
1671 dims
[(i
* 4) + 1] = area
.y();
1672 dims
[(i
* 4) + 2] = area
.width();
1673 dims
[(i
* 4) + 3] = area
.height();
1675 xatom
->setValue(getRootWindow(), XAtom::net_workarea
, XAtom::cardinal
,
1676 dims
, 4 * workspacesList
.size());
1679 xatom
->setValue(getRootWindow(), XAtom::net_workarea
, XAtom::cardinal
,
1684 void BScreen::updateNetizenCurrentWorkspace(void) {
1685 std::for_each(netizenList
.begin(), netizenList
.end(),
1686 std::mem_fun(&Netizen::sendCurrentWorkspace
));
1690 void BScreen::updateNetizenWorkspaceCount(void) {
1691 xatom
->setValue(getRootWindow(), XAtom::net_number_of_desktops
,
1692 XAtom::cardinal
, workspacesList
.size());
1696 std::for_each(netizenList
.begin(), netizenList
.end(),
1697 std::mem_fun(&Netizen::sendWorkspaceCount
));
1701 void BScreen::updateNetizenWindowFocus(void) {
1702 Window f
= ((blackbox
->getFocusedWindow()) ?
1703 blackbox
->getFocusedWindow()->getClientWindow() : None
);
1705 xatom
->setValue(getRootWindow(), XAtom::net_active_window
,
1708 NetizenList::iterator it
= netizenList
.begin();
1709 for (; it
!= netizenList
.end(); ++it
)
1710 (*it
)->sendWindowFocus(f
);
1714 void BScreen::updateNetizenWindowAdd(Window w
, unsigned long p
) {
1715 NetizenList::iterator it
= netizenList
.begin();
1716 for (; it
!= netizenList
.end(); ++it
) {
1717 (*it
)->sendWindowAdd(w
, p
);
1722 void BScreen::updateNetizenWindowDel(Window w
) {
1723 NetizenList::iterator it
= netizenList
.begin();
1724 for (; it
!= netizenList
.end(); ++it
)
1725 (*it
)->sendWindowDel(w
);
1729 void BScreen::updateNetizenWindowRaise(Window w
) {
1730 NetizenList::iterator it
= netizenList
.begin();
1731 for (; it
!= netizenList
.end(); ++it
)
1732 (*it
)->sendWindowRaise(w
);
1736 void BScreen::updateNetizenWindowLower(Window w
) {
1737 NetizenList::iterator it
= netizenList
.begin();
1738 for (; it
!= netizenList
.end(); ++it
)
1739 (*it
)->sendWindowLower(w
);
1743 void BScreen::updateNetizenConfigNotify(XEvent
*e
) {
1744 NetizenList::iterator it
= netizenList
.begin();
1745 for (; it
!= netizenList
.end(); ++it
)
1746 (*it
)->sendConfigNotify(e
);
1750 void BScreen::raiseWindows(Window
*workspace_stack
, unsigned int num
) {
1751 // the 13 represents the number of blackbox windows such as menus
1757 Window
*session_stack
= new
1758 Window
[(num
+ workspacesList
.size() + rootmenuList
.size() +
1759 specialWindowList
.size() + bbwins
)];
1760 unsigned int i
= 0, k
= num
;
1762 XRaiseWindow(blackbox
->getXDisplay(), iconmenu
->getWindowID());
1763 *(session_stack
+ i
++) = iconmenu
->getWindowID();
1765 WorkspaceList::iterator wit
= workspacesList
.begin();
1766 const WorkspaceList::iterator w_end
= workspacesList
.end();
1767 for (; wit
!= w_end
; ++wit
)
1768 *(session_stack
+ i
++) = (*wit
)->getMenu()->getWindowID();
1770 *(session_stack
+ i
++) = workspacemenu
->getWindowID();
1772 *(session_stack
+ i
++) = configmenu
->getFocusmenu()->getWindowID();
1773 *(session_stack
+ i
++) = configmenu
->getPlacementmenu()->getWindowID();
1774 *(session_stack
+ i
++) = configmenu
->getWindowSnapmenu()->getWindowID();
1775 *(session_stack
+ i
++) = configmenu
->getEdgeSnapmenu()->getWindowID();
1777 *(session_stack
+ i
++) = configmenu
->getXineramamenu()->getWindowID();
1779 *(session_stack
+ i
++) = configmenu
->getWindowID();
1781 *(session_stack
+ i
++) = slit
->getMenu()->getDirectionmenu()->getWindowID();
1782 *(session_stack
+ i
++) = slit
->getMenu()->getPlacementmenu()->getWindowID();
1783 *(session_stack
+ i
++) = slit
->getMenu()->getWindowID();
1785 *(session_stack
+ i
++) =
1786 toolbar
->getMenu()->getPlacementmenu()->getWindowID();
1787 *(session_stack
+ i
++) = toolbar
->getMenu()->getWindowID();
1789 RootmenuList::iterator rit
= rootmenuList
.begin();
1790 for (; rit
!= rootmenuList
.end(); ++rit
)
1791 *(session_stack
+ i
++) = (*rit
)->getWindowID();
1792 *(session_stack
+ i
++) = rootmenu
->getWindowID();
1794 if (toolbar
->isOnTop())
1795 *(session_stack
+ i
++) = toolbar
->getWindowID();
1797 if (slit
->isOnTop())
1798 *(session_stack
+ i
++) = slit
->getWindowID();
1800 WindowList::iterator sit
, send
= specialWindowList
.end();
1801 for (sit
= specialWindowList
.begin(); sit
!= send
; ++sit
)
1802 *(session_stack
+ i
++) = *sit
;
1805 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
1807 XRestackWindows(blackbox
->getXDisplay(), session_stack
, i
);
1809 delete [] session_stack
;
1811 updateStackingList();
1815 void BScreen::lowerWindows(Window
*workspace_stack
, unsigned int num
) {
1816 assert(num
> 0); // this would cause trouble in the XRaiseWindow call
1818 Window
*session_stack
= new Window
[(num
+ desktopWindowList
.size())];
1819 unsigned int i
= 0, k
= num
;
1821 XLowerWindow(blackbox
->getXDisplay(), workspace_stack
[0]);
1824 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
1826 WindowList::iterator dit
= desktopWindowList
.begin();
1827 const WindowList::iterator d_end
= desktopWindowList
.end();
1828 for (; dit
!= d_end
; ++dit
)
1829 *(session_stack
+ i
++) = *dit
;
1831 XRestackWindows(blackbox
->getXDisplay(), session_stack
, i
);
1833 delete [] session_stack
;
1835 updateStackingList();
1839 void BScreen::reassociateWindow(BlackboxWindow
*w
, unsigned int wkspc_id
,
1840 bool ignore_sticky
) {
1843 if (wkspc_id
== BSENTINEL
)
1844 wkspc_id
= current_workspace
->getID();
1846 if (w
->getWorkspaceNumber() == wkspc_id
)
1849 if (w
->isIconic()) {
1851 getWorkspace(wkspc_id
)->addWindow(w
);
1853 for (unsigned int i
= 0; i
< getNumberOfWorkspaces(); ++i
)
1854 if (i
!= w
->getWorkspaceNumber())
1855 getWorkspace(i
)->addWindow(w
, True
);
1856 } else if (ignore_sticky
|| ! w
->isStuck()) {
1859 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1860 getWorkspace(wkspc_id
)->addWindow(w
);
1862 updateStackingList();
1866 void BScreen::propagateWindowName(const BlackboxWindow
*bw
) {
1867 if (bw
->isIconic()) {
1868 iconmenu
->changeItemLabel(bw
->getWindowNumber(), bw
->getIconTitle());
1872 Clientmenu
*clientmenu
= getWorkspace(bw
->getWorkspaceNumber())->getMenu();
1873 clientmenu
->changeItemLabel(bw
->getWindowNumber(), bw
->getTitle());
1874 clientmenu
->update();
1876 if (blackbox
->getFocusedWindow() == bw
)
1877 toolbar
->redrawWindowLabel(True
);
1882 void BScreen::nextFocus(void) {
1883 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1887 // if window is not on this screen, ignore it
1888 if (focused
->getScreen()->getScreenNumber() != getScreenNumber())
1889 focused
= (BlackboxWindow
*) 0;
1892 if (focused
&& current_workspace
->getCount() > 1) {
1893 // next is the next window to recieve focus, current is a place holder
1894 BlackboxWindow
*current
;
1897 next
= current_workspace
->getNextWindowInList(current
);
1898 } while(! next
->setInputFocus() && next
!= focused
);
1900 if (next
!= focused
)
1901 current_workspace
->raiseWindow(next
);
1902 } else if (current_workspace
->getCount() >= 1) {
1903 next
= current_workspace
->getTopWindowOnStack();
1905 current_workspace
->raiseWindow(next
);
1906 next
->setInputFocus();
1911 void BScreen::prevFocus(void) {
1912 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1916 // if window is not on this screen, ignore it
1917 if (focused
->getScreen()->getScreenNumber() != getScreenNumber())
1918 focused
= (BlackboxWindow
*) 0;
1921 if (focused
&& current_workspace
->getCount() > 1) {
1922 // next is the next window to recieve focus, current is a place holder
1923 BlackboxWindow
*current
;
1926 next
= current_workspace
->getPrevWindowInList(current
);
1927 } while(! next
->setInputFocus() && next
!= focused
);
1929 if (next
!= focused
)
1930 current_workspace
->raiseWindow(next
);
1931 } else if (current_workspace
->getCount() >= 1) {
1932 next
= current_workspace
->getTopWindowOnStack();
1934 current_workspace
->raiseWindow(next
);
1935 next
->setInputFocus();
1940 void BScreen::raiseFocus(void) {
1941 BlackboxWindow
*focused
= blackbox
->getFocusedWindow();
1945 // if on this Screen, raise it
1946 if (focused
->getScreen()->getScreenNumber() == getScreenNumber()) {
1947 Workspace
*workspace
= getWorkspace(focused
->getWorkspaceNumber());
1948 workspace
->raiseWindow(focused
);
1953 void BScreen::InitMenu(void) {
1955 rootmenuList
.clear();
1957 while (rootmenu
->getCount())
1958 rootmenu
->remove(0);
1960 rootmenu
= new Rootmenu(this);
1962 bool defaultMenu
= True
;
1964 FILE *menu_file
= (FILE *) 0;
1965 const char *menu_filename
= blackbox
->getMenuFilename();
1968 if (! (menu_file
= fopen(menu_filename
, "r")))
1969 perror(menu_filename
);
1970 if (! menu_file
) { // opening the menu file failed, try the default menu
1971 menu_filename
= DEFAULTMENU
;
1972 if (! (menu_file
= fopen(menu_filename
, "r")))
1973 perror(menu_filename
);
1977 if (feof(menu_file
)) {
1978 fprintf(stderr
, i18n(ScreenSet
, ScreenEmptyMenuFile
,
1979 "%s: Empty menu file"),
1982 char line
[1024], label
[1024];
1983 memset(line
, 0, 1024);
1984 memset(label
, 0, 1024);
1986 while (fgets(line
, 1024, menu_file
) && ! feof(menu_file
)) {
1990 int i
, key
= 0, index
= -1, len
= strlen(line
);
1992 for (i
= 0; i
< len
; i
++) {
1993 if (line
[i
] == '[') index
= 0;
1994 else if (line
[i
] == ']') break;
1995 else if (line
[i
] != ' ')
1997 key
+= tolower(line
[i
]);
2000 if (key
== 517) { // [begin]
2002 for (i
= index
; i
< len
; i
++) {
2003 if (line
[i
] == '(') index
= 0;
2004 else if (line
[i
] == ')') break;
2005 else if (index
++ >= 0) {
2006 if (line
[i
] == '\\' && i
< len
- 1) i
++;
2007 label
[index
- 1] = line
[i
];
2011 if (index
== -1) index
= 0;
2012 label
[index
] = '\0';
2014 rootmenu
->setLabel(label
);
2015 defaultMenu
= parseMenuFile(menu_file
, rootmenu
);
2017 blackbox
->addMenuTimestamp(menu_filename
);
2026 rootmenu
->setInternalMenu();
2027 rootmenu
->insert(i18n(ScreenSet
, Screenxterm
, "xterm"),
2029 i18n(ScreenSet
, Screenxterm
, "xterm"));
2030 rootmenu
->insert(i18n(ScreenSet
, ScreenRestart
, "Restart"),
2032 rootmenu
->insert(i18n(ScreenSet
, ScreenExit
, "Exit"),
2034 rootmenu
->setLabel(i18n(BasemenuSet
, BasemenuBlackboxMenu
,
2041 size_t string_within(char begin
, char end
,
2042 const char *input
, size_t start_at
, size_t length
,
2046 size_t i
= start_at
;
2047 for (; i
< length
; ++i
) {
2048 if (input
[i
] == begin
) {
2050 } else if (input
[i
] == end
) {
2053 if (input
[i
] == '\\' && i
< length
- 1) i
++;
2054 output
[index
++] = input
[i
];
2059 output
[index
] = '\0';
2067 bool BScreen::parseMenuFile(FILE *file
, Rootmenu
*menu
) {
2068 char line
[1024], keyword
[1024], label
[1024], command
[1024];
2071 while (! (done
|| feof(file
))) {
2072 memset(line
, 0, 1024);
2073 memset(label
, 0, 1024);
2074 memset(command
, 0, 1024);
2076 if (! fgets(line
, 1024, file
))
2079 if (line
[0] == '#') // comment, skip it
2082 size_t line_length
= strlen(line
);
2083 unsigned int key
= 0;
2085 // get the keyword enclosed in []'s
2086 size_t pos
= string_within('[', ']', line
, 0, line_length
, keyword
);
2088 if (keyword
[0] == '\0') { // no keyword, no menu entry
2091 size_t len
= strlen(keyword
);
2092 for (size_t i
= 0; i
< len
; ++i
) {
2093 if (keyword
[i
] != ' ')
2094 key
+= tolower(keyword
[i
]);
2098 // get the label enclosed in ()'s
2099 pos
= string_within('(', ')', line
, pos
, line_length
, label
);
2101 // get the command enclosed in {}'s
2102 pos
= string_within('{', '}', line
, pos
, line_length
, command
);
2113 menu
->insert(label
);
2118 if (! (*label
&& *command
)) {
2119 fprintf(stderr
, i18n(ScreenSet
, ScreenEXECError
,
2120 "BScreen::parseMenuFile: [exec] error, "
2121 "no menu label and/or command defined\n"));
2125 menu
->insert(label
, BScreen::Execute
, command
);
2131 fprintf(stderr
, i18n(ScreenSet
, ScreenEXITError
,
2132 "BScreen::parseMenuFile: [exit] error, "
2133 "no menu label defined\n"));
2137 menu
->insert(label
, BScreen::Exit
);
2141 case 561: { // style
2142 if (! (*label
&& *command
)) {
2144 i18n(ScreenSet
, ScreenSTYLEError
,
2145 "BScreen::parseMenuFile: [style] error, "
2146 "no menu label and/or filename defined\n"));
2150 string style
= expandTilde(command
);
2152 menu
->insert(label
, BScreen::SetStyle
, style
.c_str());
2158 fprintf(stderr
, i18n(ScreenSet
, ScreenCONFIGError
,
2159 "BScreen::parseMenufile: [config] error, "
2160 "no label defined"));
2164 menu
->insert(label
, configmenu
);
2168 case 740: { // include
2170 fprintf(stderr
, i18n(ScreenSet
, ScreenINCLUDEError
,
2171 "BScreen::parseMenuFile: [include] error, "
2172 "no filename defined\n"));
2176 string newfile
= expandTilde(label
);
2177 FILE *submenufile
= fopen(newfile
.c_str(), "r");
2179 if (! submenufile
) {
2180 perror(newfile
.c_str());
2185 if (fstat(fileno(submenufile
), &buf
) ||
2186 ! S_ISREG(buf
.st_mode
)) {
2188 i18n(ScreenSet
, ScreenINCLUDEErrorReg
,
2189 "BScreen::parseMenuFile: [include] error: "
2190 "'%s' is not a regular file\n"), newfile
.c_str());
2194 if (! feof(submenufile
)) {
2195 if (! parseMenuFile(submenufile
, menu
))
2196 blackbox
->addMenuTimestamp(newfile
);
2198 fclose(submenufile
);
2204 case 767: { // submenu
2206 fprintf(stderr
, i18n(ScreenSet
, ScreenSUBMENUError
,
2207 "BScreen::parseMenuFile: [submenu] error, "
2208 "no menu label defined\n"));
2212 Rootmenu
*submenu
= new Rootmenu(this);
2215 submenu
->setLabel(command
);
2217 submenu
->setLabel(label
);
2219 parseMenuFile(file
, submenu
);
2221 menu
->insert(label
, submenu
);
2222 rootmenuList
.push_back(submenu
);
2227 case 773: { // restart
2229 fprintf(stderr
, i18n(ScreenSet
, ScreenRESTARTError
,
2230 "BScreen::parseMenuFile: [restart] error, "
2231 "no menu label defined\n"));
2236 menu
->insert(label
, BScreen::RestartOther
, command
);
2238 menu
->insert(label
, BScreen::Restart
);
2243 case 845: { // reconfig
2246 i18n(ScreenSet
, ScreenRECONFIGError
,
2247 "BScreen::parseMenuFile: [reconfig] error, "
2248 "no menu label defined\n"));
2252 menu
->insert(label
, BScreen::Reconfigure
);
2257 case 995: // stylesdir
2258 case 1113: { // stylesmenu
2259 bool newmenu
= ((key
== 1113) ? True
: False
);
2261 if (! *label
|| (! *command
&& newmenu
)) {
2263 i18n(ScreenSet
, ScreenSTYLESDIRError
,
2264 "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
2265 " error, no directory defined\n"));
2269 char *directory
= ((newmenu
) ? command
: label
);
2271 string stylesdir
= expandTilde(directory
);
2273 struct stat statbuf
;
2275 if (stat(stylesdir
.c_str(), &statbuf
) == -1) {
2277 i18n(ScreenSet
, ScreenSTYLESDIRErrorNoExist
,
2278 "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
2279 " error, %s does not exist\n"), stylesdir
.c_str());
2282 if (! S_ISDIR(statbuf
.st_mode
)) {
2284 i18n(ScreenSet
, ScreenSTYLESDIRErrorNotDir
,
2285 "BScreen::parseMenuFile:"
2286 " [stylesdir/stylesmenu] error, %s is not a"
2287 " directory\n"), stylesdir
.c_str());
2291 Rootmenu
*stylesmenu
;
2294 stylesmenu
= new Rootmenu(this);
2298 DIR *d
= opendir(stylesdir
.c_str());
2300 std::vector
<string
> ls
;
2302 while((p
= readdir(d
)))
2303 ls
.push_back(p
->d_name
);
2307 std::sort(ls
.begin(), ls
.end());
2309 std::vector
<string
>::iterator it
= ls
.begin(),
2311 for (; it
!= end
; ++it
) {
2312 const string
& fname
= *it
;
2314 if (fname
[fname
.size()-1] == '~')
2317 string style
= stylesdir
;
2321 if (! stat(style
.c_str(), &statbuf
) && S_ISREG(statbuf
.st_mode
))
2322 stylesmenu
->insert(fname
, BScreen::SetStyle
, style
);
2325 stylesmenu
->update();
2328 stylesmenu
->setLabel(label
);
2329 menu
->insert(label
, stylesmenu
);
2330 rootmenuList
.push_back(stylesmenu
);
2333 blackbox
->addMenuTimestamp(stylesdir
);
2337 case 1090: { // workspaces
2340 i18n(ScreenSet
, ScreenWORKSPACESError
,
2341 "BScreen:parseMenuFile: [workspaces] error, "
2342 "no menu label defined\n"));
2346 menu
->insert(label
, workspacemenu
);
2352 return ((menu
->getCount() == 0) ? True
: False
);
2356 void BScreen::shutdown(void) {
2357 XSelectInput(blackbox
->getXDisplay(), getRootWindow(), NoEventMask
);
2358 XSync(blackbox
->getXDisplay(), False
);
2360 while(! windowList
.empty())
2361 unmanageWindow(windowList
.front(), True
);
2363 while(! desktopWindowList
.empty()) {
2364 BlackboxWindow
*win
= blackbox
->searchWindow(desktopWindowList
.front());
2366 unmanageWindow(win
, True
);
2373 void BScreen::showPosition(int x
, int y
) {
2374 if (! geom_visible
) {
2375 XMoveResizeWindow(blackbox
->getXDisplay(), geom_window
,
2376 (getWidth() - geom_w
) / 2,
2377 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
2378 XMapWindow(blackbox
->getXDisplay(), geom_window
);
2379 XRaiseWindow(blackbox
->getXDisplay(), geom_window
);
2381 geom_visible
= True
;
2386 sprintf(label
, i18n(ScreenSet
, ScreenPositionFormat
,
2387 "X: %4d x Y: %4d"), x
, y
);
2389 XClearWindow(blackbox
->getXDisplay(), geom_window
);
2391 resource
.wstyle
.font
->drawString(geom_window
,
2392 resource
.bevel_width
, resource
.bevel_width
,
2393 resource
.wstyle
.l_text_focus
,
2398 void BScreen::showGeometry(unsigned int gx
, unsigned int gy
) {
2399 if (! geom_visible
) {
2400 XMoveResizeWindow(blackbox
->getXDisplay(), geom_window
,
2401 (getWidth() - geom_w
) / 2,
2402 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
2403 XMapWindow(blackbox
->getXDisplay(), geom_window
);
2404 XRaiseWindow(blackbox
->getXDisplay(), geom_window
);
2406 geom_visible
= True
;
2411 sprintf(label
, i18n(ScreenSet
, ScreenGeometryFormat
,
2412 "W: %4d x H: %4d"), gx
, gy
);
2414 XClearWindow(blackbox
->getXDisplay(), geom_window
);
2416 resource
.wstyle
.font
->drawString(geom_window
,
2417 resource
.bevel_width
, resource
.bevel_width
,
2418 resource
.wstyle
.l_text_focus
,
2423 void BScreen::hideGeometry(void) {
2425 XUnmapWindow(blackbox
->getXDisplay(), geom_window
);
2426 geom_visible
= False
;
2431 void BScreen::addStrut(Strut
*strut
) {
2432 strutList
.push_back(strut
);
2436 void BScreen::removeStrut(Strut
*strut
) {
2437 strutList
.remove(strut
);
2441 const Rect
& BScreen::availableArea(void) const {
2443 return getRect(); // return the full screen
2449 const RectList
& BScreen::allAvailableAreas(void) const {
2450 assert(isXineramaActive());
2451 assert(xineramaUsableArea
.size() > 0);
2452 fprintf(stderr
, "1found x %d y %d w %d h %d\n",
2453 xineramaUsableArea
[0].x(), xineramaUsableArea
[0].y(),
2454 xineramaUsableArea
[0].width(), xineramaUsableArea
[0].height());
2455 return xineramaUsableArea
;
2460 void BScreen::updateAvailableArea(void) {
2461 Rect old_area
= usableArea
;
2462 usableArea
= getRect(); // reset to full screen
2465 // reset to the full areas
2466 if (isXineramaActive())
2467 xineramaUsableArea
= getXineramaAreas();
2470 /* these values represent offsets from the screen edge
2471 * we look for the biggest offset on each edge and then apply them
2473 * do not be confused by the similarity to the names of Rect's members
2475 unsigned int current_left
= 0, current_right
= 0, current_top
= 0,
2478 StrutList::const_iterator it
= strutList
.begin(), end
= strutList
.end();
2480 for(; it
!= end
; ++it
) {
2482 if (strut
->left
> current_left
)
2483 current_left
= strut
->left
;
2484 if (strut
->top
> current_top
)
2485 current_top
= strut
->top
;
2486 if (strut
->right
> current_right
)
2487 current_right
= strut
->right
;
2488 if (strut
->bottom
> current_bottom
)
2489 current_bottom
= strut
->bottom
;
2492 usableArea
.setPos(current_left
, current_top
);
2493 usableArea
.setSize(usableArea
.width() - (current_left
+ current_right
),
2494 usableArea
.height() - (current_top
+ current_bottom
));
2497 if (isXineramaActive()) {
2498 // keep each of the ximerama-defined areas inside the strut
2499 RectList::iterator xit
, xend
= xineramaUsableArea
.end();
2500 for (xit
= xineramaUsableArea
.begin(); xit
!= xend
; ++xit
) {
2501 if (xit
->x() < usableArea
.x()) {
2502 xit
->setX(usableArea
.x());
2503 xit
->setWidth(xit
->width() - usableArea
.x());
2505 if (xit
->y() < usableArea
.y()) {
2506 xit
->setY(usableArea
.y());
2507 xit
->setHeight(xit
->height() - usableArea
.y());
2509 if (xit
->x() + xit
->width() > usableArea
.width())
2510 xit
->setWidth(usableArea
.width() - xit
->x());
2511 if (xit
->y() + xit
->height() > usableArea
.height())
2512 xit
->setHeight(usableArea
.height() - xit
->y());
2517 if (old_area
!= usableArea
) {
2518 BlackboxWindowList::iterator it
= windowList
.begin(),
2519 end
= windowList
.end();
2520 for (; it
!= end
; ++it
)
2521 if ((*it
)->isMaximized()) (*it
)->remaximize();
2528 Workspace
* BScreen::getWorkspace(unsigned int index
) {
2529 assert(index
< workspacesList
.size());
2530 return workspacesList
[index
];
2534 void BScreen::buttonPressEvent(const XButtonEvent
*xbutton
) {
2535 if (xbutton
->button
== 1) {
2536 if (! isRootColormapInstalled())
2537 image_control
->installRootColormap();
2539 if (workspacemenu
->isVisible())
2540 workspacemenu
->hide();
2542 if (rootmenu
->isVisible())
2545 } else if ((xbutton
->button
== 4 && resource
.root_scroll
== NormalScroll
) ||
2546 (xbutton
->button
== 5 && resource
.root_scroll
== ReverseScroll
)) {
2547 if (getCurrentWorkspaceID() >= getWorkspaceCount() - 1)
2548 changeWorkspaceID(0);
2550 changeWorkspaceID(getCurrentWorkspaceID() + 1);
2552 } else if ((xbutton
->button
== 5 && resource
.root_scroll
== NormalScroll
) ||
2553 (xbutton
->button
== 4 && resource
.root_scroll
== ReverseScroll
)) {
2554 if (getCurrentWorkspaceID() == 0)
2555 changeWorkspaceID(getWorkspaceCount() - 1);
2557 changeWorkspaceID(getCurrentWorkspaceID() - 1);
2560 if (resource
.root_menu_button
> 0 &&
2561 xbutton
->button
== resource
.root_menu_button
)
2562 showRootMenu(xbutton
->x_root
, xbutton
->y_root
);
2563 else if (resource
.workspace_menu_button
> 0 &&
2564 xbutton
->button
== resource
.workspace_menu_button
)
2565 showWorkspaceMenu(xbutton
->x_root
, xbutton
->y_root
);
2569 void BScreen::showWorkspaceMenu(int x
, int y
) {
2570 int mx
= x
- (workspacemenu
->getWidth() / 2);
2571 int my
= y
- (workspacemenu
->getTitleHeight() / 2);
2576 if (mx
+ workspacemenu
->getWidth() > getWidth())
2577 mx
= getWidth() - workspacemenu
->getWidth() - getBorderWidth();
2579 if (my
+ workspacemenu
->getHeight() > getHeight())
2580 my
= getHeight() - workspacemenu
->getHeight() - getBorderWidth();
2582 workspacemenu
->move(mx
, my
);
2584 if (! workspacemenu
->isVisible()) {
2585 workspacemenu
->removeParent();
2586 workspacemenu
->show();
2591 void BScreen::showRootMenu(int x
, int y
) {
2592 int mx
= x
- (rootmenu
->getWidth() / 2);
2593 int my
= y
- (rootmenu
->getTitleHeight() / 2);
2598 if (mx
+ rootmenu
->getWidth() > getWidth())
2599 mx
= getWidth() - rootmenu
->getWidth() - getBorderWidth();
2601 if (my
+ rootmenu
->getHeight() > getHeight())
2602 my
= getHeight() - rootmenu
->getHeight() - getBorderWidth();
2604 rootmenu
->move(mx
, my
);
2606 if (! rootmenu
->isVisible()) {
2607 blackbox
->checkMenu();
2613 void BScreen::propertyNotifyEvent(const XPropertyEvent
*pe
) {
2614 if (pe
->atom
== xatom
->getAtom(XAtom::net_desktop_names
)) {
2615 // _NET_WM_DESKTOP_NAMES
2616 WorkspaceList::iterator it
= workspacesList
.begin();
2617 const WorkspaceList::iterator end
= workspacesList
.end();
2618 for (; it
!= end
; ++it
) {
2619 (*it
)->readName(); // re-read its name from the window property
2620 workspacemenu
->changeWorkspaceLabel((*it
)->getID(), (*it
)->getName());
2622 workspacemenu
->update();
2623 toolbar
->reconfigure();
2624 saveWorkspaceNames();
2629 void BScreen::toggleFocusModel(FocusModel model
) {
2630 std::for_each(windowList
.begin(), windowList
.end(),
2631 std::mem_fun(&BlackboxWindow::ungrabButtons
));
2633 if (model
== SloppyFocus
) {
2634 saveSloppyFocus(True
);
2636 // we're cheating here to save writing the config file 3 times
2637 resource
.auto_raise
= False
;
2638 resource
.click_raise
= False
;
2639 saveSloppyFocus(False
);
2642 std::for_each(windowList
.begin(), windowList
.end(),
2643 std::mem_fun(&BlackboxWindow::grabButtons
));
2646 #ifdef BITMAPBUTTONS
2647 void BScreen::readDatabaseMask(const string
&rname
, PixmapMask
&pixmapMask
,
2648 const Configuration
&style
) {
2650 int hx
, hy
; //ignored
2651 int ret
= BitmapOpenFailed
; //default to failure.
2653 if (style
.getValue(rname
, s
))
2655 if (s
[0] != '/' && s
[0] != '~')
2657 std::string xbmFile
= std::string("~/.openbox/buttons/") + s
;
2658 ret
= XReadBitmapFile(blackbox
->getXDisplay(), getRootWindow(),
2659 expandTilde(xbmFile
).c_str(), &pixmapMask
.w
,
2660 &pixmapMask
.h
, &pixmapMask
.mask
, &hx
, &hy
);
2662 ret
= XReadBitmapFile(blackbox
->getXDisplay(), getRootWindow(),
2663 expandTilde(s
).c_str(), &pixmapMask
.w
,
2664 &pixmapMask
.h
, &pixmapMask
.mask
, &hx
, &hy
);
2666 if (ret
== BitmapSuccess
)
2670 pixmapMask
.mask
= None
;
2671 pixmapMask
.w
= pixmapMask
.h
= 0;
2673 #endif // BITMAPSUCCESS
2675 BTexture
BScreen::readDatabaseTexture(const string
&rname
,
2676 const string
&default_color
,
2677 const Configuration
&style
) {
2681 if (style
.getValue(rname
, s
))
2682 texture
= BTexture(s
);
2684 texture
.setTexture(BTexture::Solid
| BTexture::Flat
);
2686 // associate this texture with this screen
2687 texture
.setDisplay(getBaseDisplay(), getScreenNumber());
2688 texture
.setImageControl(image_control
);
2690 texture
.setColor(readDatabaseColor(rname
+ ".color", default_color
, style
));
2691 texture
.setColorTo(readDatabaseColor(rname
+ ".colorTo", default_color
,
2693 texture
.setBorderColor(readDatabaseColor(rname
+ ".borderColor",
2694 default_color
, style
));
2700 BColor
BScreen::readDatabaseColor(const string
&rname
,
2701 const string
&default_color
,
2702 const Configuration
&style
) {
2705 if (style
.getValue(rname
, s
))
2706 color
= BColor(s
, getBaseDisplay(), getScreenNumber());
2708 color
= BColor(default_color
, getBaseDisplay(), getScreenNumber());
2713 BFont
*BScreen::readDatabaseFont(const string
&rbasename
,
2714 const Configuration
&style
) {
2721 if (style
.getValue(rbasename
+ "xft.font", s
) &&
2722 style
.getValue(rbasename
+ "xft.size", i
)) {
2725 bool italic
= False
;
2726 if (style
.getValue(rbasename
+ "xft.flags", s
)) {
2727 if (s
.find("bold") != string::npos
)
2729 if (s
.find("italic") != string::npos
)
2733 BFont
*b
= new BFont(blackbox
->getXDisplay(), this, family
, i
, bold
,
2734 italic
, resource
.shadow_fonts
, resource
.aa_fonts
);
2738 delete b
; // fall back to the normal X font stuff
2742 style
.getValue(rbasename
+ "font", s
);
2743 // if this fails, a blank string will be used, which will cause the fallback
2746 BFont
*b
= new BFont(blackbox
->getXDisplay(), this, s
);
2748 exit(2); // can't continue without a font