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>
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
76 #include "blackbox.hh"
77 #include "Clientmenu.hh"
79 #include "Iconmenu.hh"
83 #include "Rootmenu.hh"
87 #include "Workspace.hh"
88 #include "Workspacemenu.hh"
90 #ifndef FONT_ELEMENT_SIZE
91 #define FONT_ELEMENT_SIZE 50
92 #endif // FONT_ELEMENT_SIZE
95 static bool running
= True
;
97 static int anotherWMRunning(Display
*display
, XErrorEvent
*) {
98 fprintf(stderr
, i18n(ScreenSet
, ScreenAnotherWMRunning
,
99 "BScreen::BScreen: an error occured while querying the X server.\n"
100 " another window manager already running on display %s.\n"),
101 DisplayString(display
));
109 BScreen::BScreen(Blackbox
*bb
, unsigned int scrn
) : ScreenInfo(bb
, scrn
) {
112 event_mask
= ColormapChangeMask
| EnterWindowMask
| PropertyChangeMask
|
113 SubstructureRedirectMask
| ButtonPressMask
| ButtonReleaseMask
;
115 XErrorHandler old
= XSetErrorHandler((XErrorHandler
) anotherWMRunning
);
116 XSelectInput(getBaseDisplay()->getXDisplay(), getRootWindow(), event_mask
);
117 XSync(getBaseDisplay()->getXDisplay(), False
);
118 XSetErrorHandler((XErrorHandler
) old
);
121 if (! managed
) return;
123 fprintf(stderr
, i18n(ScreenSet
, ScreenManagingScreen
,
124 "BScreen::BScreen: managing screen %d "
125 "using visual 0x%lx, depth %d\n"),
126 getScreenNumber(), XVisualIDFromVisual(getVisual()),
130 resource
.stylerc
= 0;
132 resource
.mstyle
.t_fontset
= resource
.mstyle
.f_fontset
=
133 resource
.tstyle
.fontset
= resource
.wstyle
.fontset
= (XFontSet
) 0;
134 resource
.mstyle
.t_font
= resource
.mstyle
.f_font
= resource
.tstyle
.font
=
135 resource
.wstyle
.font
= (XFontStruct
*) 0;
138 pid_t bpid
= getpid();
140 XChangeProperty(blackbox
->getXDisplay(), getRootWindow(),
141 blackbox
->getBlackboxPidAtom(), XA_CARDINAL
,
142 sizeof(pid_t
) * 8, PropModeReplace
,
143 (unsigned char *) &bpid
, 1);
144 #endif // HAVE_GETPID
146 XDefineCursor(blackbox
->getXDisplay(), getRootWindow(),
147 blackbox
->getSessionCursor());
149 // start off full screen, top left.
150 usableArea
.setSize(getWidth(), getHeight());
153 new BImageControl(blackbox
, this, True
, blackbox
->getColorsPerChannel(),
154 blackbox
->getCacheLife(), blackbox
->getCacheMax());
155 image_control
->installRootColormap();
156 root_colormap_installed
= True
;
158 blackbox
->load_rc(this);
160 image_control
->setDither(resource
.image_dither
);
165 unsigned long gc_value_mask
= GCForeground
;
166 if (! i18n
.multibyte()) gc_value_mask
|= GCFont
;
168 gcv
.foreground
= WhitePixel(blackbox
->getXDisplay(), getScreenNumber())
169 ^ BlackPixel(blackbox
->getXDisplay(), getScreenNumber());
170 gcv
.function
= GXxor
;
171 gcv
.subwindow_mode
= IncludeInferiors
;
172 opGC
= XCreateGC(blackbox
->getXDisplay(), getRootWindow(),
173 GCForeground
| GCFunction
| GCSubwindowMode
, &gcv
);
175 const char *s
= i18n(ScreenSet
, ScreenPositionLength
,
176 "0: 0000 x 0: 0000");
179 if (i18n
.multibyte()) {
180 XRectangle ink
, logical
;
181 XmbTextExtents(resource
.wstyle
.fontset
, s
, l
, &ink
, &logical
);
182 geom_w
= logical
.width
;
184 geom_h
= resource
.wstyle
.fontset_extents
->max_ink_extent
.height
;
186 geom_h
= resource
.wstyle
.font
->ascent
+
187 resource
.wstyle
.font
->descent
;
189 geom_w
= XTextWidth(resource
.wstyle
.font
, s
, l
);
192 geom_w
+= (resource
.bevel_width
* 2);
193 geom_h
+= (resource
.bevel_width
* 2);
195 XSetWindowAttributes attrib
;
196 unsigned long mask
= CWBorderPixel
| CWColormap
| CWSaveUnder
;
197 attrib
.border_pixel
= getBorderColor()->pixel();
198 attrib
.colormap
= getColormap();
199 attrib
.save_under
= True
;
201 geom_window
= XCreateWindow(blackbox
->getXDisplay(), getRootWindow(),
202 0, 0, geom_w
, geom_h
, resource
.border_width
,
203 getDepth(), InputOutput
, getVisual(),
205 geom_visible
= False
;
207 BTexture
* texture
= &(resource
.wstyle
.l_focus
);
208 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
209 if (geom_pixmap
== ParentRelative
) {
210 texture
= &(resource
.wstyle
.t_focus
);
211 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
214 XSetWindowBackground(blackbox
->getXDisplay(), geom_window
,
215 texture
->color().pixel());
217 XSetWindowBackgroundPixmap(blackbox
->getXDisplay(),
218 geom_window
, geom_pixmap
);
220 workspacemenu
= new Workspacemenu(this);
221 iconmenu
= new Iconmenu(this);
222 configmenu
= new Configmenu(this);
224 Workspace
*wkspc
= (Workspace
*) 0;
225 if (resource
.workspaces
!= 0) {
226 for (unsigned int i
= 0; i
< resource
.workspaces
; ++i
) {
227 wkspc
= new Workspace(this, workspacesList
.size());
228 workspacesList
.push_back(wkspc
);
229 workspacemenu
->insert(wkspc
->getName(), wkspc
->getMenu());
232 wkspc
= new Workspace(this, workspacesList
.size());
233 workspacesList
.push_back(wkspc
);
234 workspacemenu
->insert(wkspc
->getName(), wkspc
->getMenu());
237 workspacemenu
->insert(i18n(IconSet
, IconIcons
, "Icons"), iconmenu
);
238 workspacemenu
->update();
240 current_workspace
= workspacesList
.front();
241 workspacemenu
->setItemSelected(2, True
);
243 toolbar
= new Toolbar(this);
245 slit
= new Slit(this);
252 updateAvailableArea();
254 changeWorkspaceID(0);
256 unsigned int i
, j
, nchild
;
257 Window r
, p
, *children
;
258 XQueryTree(blackbox
->getXDisplay(), getRootWindow(), &r
, &p
,
261 // preen the window list of all icon windows... for better dockapp support
262 for (i
= 0; i
< nchild
; i
++) {
263 if (children
[i
] == None
) continue;
265 XWMHints
*wmhints
= XGetWMHints(blackbox
->getXDisplay(),
269 if ((wmhints
->flags
& IconWindowHint
) &&
270 (wmhints
->icon_window
!= children
[i
])) {
271 for (j
= 0; j
< nchild
; j
++) {
272 if (children
[j
] == wmhints
->icon_window
) {
283 // manage shown windows
284 for (i
= 0; i
< nchild
; ++i
) {
285 if (children
[i
] == None
|| (! blackbox
->validateWindow(children
[i
])))
288 XWindowAttributes attrib
;
289 if (XGetWindowAttributes(blackbox
->getXDisplay(), children
[i
], &attrib
)) {
290 if (attrib
.override_redirect
) continue;
292 if (attrib
.map_state
!= IsUnmapped
) {
293 manageWindow(children
[i
]);
300 // call this again just in case a window we found updates the Strut list
301 updateAvailableArea();
305 BScreen::~BScreen(void) {
306 if (! managed
) return;
308 if (geom_pixmap
!= None
)
309 image_control
->removeImage(geom_pixmap
);
311 if (geom_window
!= None
)
312 XDestroyWindow(blackbox
->getXDisplay(), geom_window
);
314 std::for_each(workspacesList
.begin(), workspacesList
.end(),
317 std::for_each(iconList
.begin(), iconList
.end(), PointerAssassin());
319 std::for_each(netizenList
.begin(), netizenList
.end(), PointerAssassin());
322 delete workspacemenu
;
327 delete image_control
;
329 if (resource
.wstyle
.fontset
)
330 XFreeFontSet(blackbox
->getXDisplay(), resource
.wstyle
.fontset
);
331 if (resource
.mstyle
.t_fontset
)
332 XFreeFontSet(blackbox
->getXDisplay(), resource
.mstyle
.t_fontset
);
333 if (resource
.mstyle
.f_fontset
)
334 XFreeFontSet(blackbox
->getXDisplay(), resource
.mstyle
.f_fontset
);
335 if (resource
.tstyle
.fontset
)
336 XFreeFontSet(blackbox
->getXDisplay(), resource
.tstyle
.fontset
);
338 if (resource
.wstyle
.font
)
339 XFreeFont(blackbox
->getXDisplay(), resource
.wstyle
.font
);
340 if (resource
.mstyle
.t_font
)
341 XFreeFont(blackbox
->getXDisplay(), resource
.mstyle
.t_font
);
342 if (resource
.mstyle
.f_font
)
343 XFreeFont(blackbox
->getXDisplay(), resource
.mstyle
.f_font
);
344 if (resource
.tstyle
.font
)
345 XFreeFont(blackbox
->getXDisplay(), resource
.tstyle
.font
);
347 XFreeGC(blackbox
->getXDisplay(), opGC
);
351 void BScreen::removeWorkspaceNames(void) {
352 workspaceNames
.clear();
356 void BScreen::reconfigure(void) {
360 unsigned long gc_value_mask
= GCForeground
;
361 if (! i18n
.multibyte()) gc_value_mask
|= GCFont
;
363 gcv
.foreground
= WhitePixel(blackbox
->getXDisplay(),
365 gcv
.function
= GXinvert
;
366 gcv
.subwindow_mode
= IncludeInferiors
;
367 XChangeGC(blackbox
->getXDisplay(), opGC
,
368 GCForeground
| GCFunction
| GCSubwindowMode
, &gcv
);
370 const char *s
= i18n(ScreenSet
, ScreenPositionLength
,
371 "0: 0000 x 0: 0000");
374 if (i18n
.multibyte()) {
375 XRectangle ink
, logical
;
376 XmbTextExtents(resource
.wstyle
.fontset
, s
, l
, &ink
, &logical
);
377 geom_w
= logical
.width
;
379 geom_h
= resource
.wstyle
.fontset_extents
->max_ink_extent
.height
;
381 geom_w
= XTextWidth(resource
.wstyle
.font
, s
, l
);
383 geom_h
= resource
.wstyle
.font
->ascent
+ resource
.wstyle
.font
->descent
;
386 geom_w
+= (resource
.bevel_width
* 2);
387 geom_h
+= (resource
.bevel_width
* 2);
389 BTexture
* texture
= &(resource
.wstyle
.l_focus
);
390 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
391 if (geom_pixmap
== ParentRelative
) {
392 texture
= &(resource
.wstyle
.t_focus
);
393 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
396 XSetWindowBackground(blackbox
->getXDisplay(), geom_window
,
397 texture
->color().pixel());
399 XSetWindowBackgroundPixmap(blackbox
->getXDisplay(),
400 geom_window
, geom_pixmap
);
402 XSetWindowBorderWidth(blackbox
->getXDisplay(), geom_window
,
403 resource
.border_width
);
404 XSetWindowBorder(blackbox
->getXDisplay(), geom_window
,
405 resource
.border_color
.pixel());
407 workspacemenu
->reconfigure();
408 iconmenu
->reconfigure();
410 int remember_sub
= rootmenu
->getCurrentSubmenu();
413 rootmenu
->reconfigure();
414 rootmenu
->drawSubmenu(remember_sub
);
416 configmenu
->reconfigure();
418 toolbar
->reconfigure();
422 std::for_each(workspacesList
.begin(), workspacesList
.end(),
423 std::mem_fun(&Workspace::reconfigure
));
425 BlackboxWindowList::iterator iit
= iconList
.begin();
426 for (; iit
!= iconList
.end(); ++iit
) {
427 BlackboxWindow
*bw
= *iit
;
428 if (bw
->validateClient())
432 image_control
->timeout();
436 void BScreen::rereadMenu(void) {
440 rootmenu
->reconfigure();
444 void BScreen::LoadStyle(void) {
445 resource
.stylerc
= XrmGetFileDatabase(blackbox
->getStyleFilename());
446 if (! resource
.stylerc
)
447 resource
.stylerc
= XrmGetFileDatabase(DEFAULTSTYLE
);
452 // load fonts/fontsets
453 if (resource
.wstyle
.fontset
)
454 XFreeFontSet(blackbox
->getXDisplay(), resource
.wstyle
.fontset
);
455 if (resource
.tstyle
.fontset
)
456 XFreeFontSet(blackbox
->getXDisplay(), resource
.tstyle
.fontset
);
457 if (resource
.mstyle
.f_fontset
)
458 XFreeFontSet(blackbox
->getXDisplay(), resource
.mstyle
.f_fontset
);
459 if (resource
.mstyle
.t_fontset
)
460 XFreeFontSet(blackbox
->getXDisplay(), resource
.mstyle
.t_fontset
);
461 resource
.wstyle
.fontset
= 0;
462 resource
.tstyle
.fontset
= 0;
463 resource
.mstyle
.f_fontset
= 0;
464 resource
.mstyle
.t_fontset
= 0;
465 if (resource
.wstyle
.font
)
466 XFreeFont(blackbox
->getXDisplay(), resource
.wstyle
.font
);
467 if (resource
.tstyle
.font
)
468 XFreeFont(blackbox
->getXDisplay(), resource
.tstyle
.font
);
469 if (resource
.mstyle
.f_font
)
470 XFreeFont(blackbox
->getXDisplay(), resource
.mstyle
.f_font
);
471 if (resource
.mstyle
.t_font
)
472 XFreeFont(blackbox
->getXDisplay(), resource
.mstyle
.t_font
);
473 resource
.wstyle
.font
= 0;
474 resource
.tstyle
.font
= 0;
475 resource
.mstyle
.f_font
= 0;
476 resource
.mstyle
.t_font
= 0;
478 if (i18n
.multibyte()) {
479 resource
.wstyle
.fontset
=
480 readDatabaseFontSet("window.font", "Window.Font");
481 resource
.tstyle
.fontset
=
482 readDatabaseFontSet("toolbar.font", "Toolbar.Font");
483 resource
.mstyle
.t_fontset
=
484 readDatabaseFontSet("menu.title.font", "Menu.Title.Font");
485 resource
.mstyle
.f_fontset
=
486 readDatabaseFontSet("menu.frame.font", "Menu.Frame.Font");
488 resource
.mstyle
.t_fontset_extents
=
489 XExtentsOfFontSet(resource
.mstyle
.t_fontset
);
490 resource
.mstyle
.f_fontset_extents
=
491 XExtentsOfFontSet(resource
.mstyle
.f_fontset
);
492 resource
.tstyle
.fontset_extents
=
493 XExtentsOfFontSet(resource
.tstyle
.fontset
);
494 resource
.wstyle
.fontset_extents
=
495 XExtentsOfFontSet(resource
.wstyle
.fontset
);
497 resource
.wstyle
.font
=
498 readDatabaseFont("window.font", "Window.Font");
499 resource
.tstyle
.font
=
500 readDatabaseFont("toolbar.font", "Toolbar.Font");
501 resource
.mstyle
.t_font
=
502 readDatabaseFont("menu.title.font", "Menu.Title.Font");
503 resource
.mstyle
.f_font
=
504 readDatabaseFont("menu.frame.font", "Menu.Frame.Font");
507 // load window config
508 resource
.wstyle
.t_focus
=
509 readDatabaseTexture("window.title.focus", "Window.Title.Focus", "white");
510 resource
.wstyle
.t_unfocus
=
511 readDatabaseTexture("window.title.unfocus",
512 "Window.Title.Unfocus", "black");
513 resource
.wstyle
.l_focus
=
514 readDatabaseTexture("window.label.focus", "Window.Label.Focus", "white" );
515 resource
.wstyle
.l_unfocus
=
516 readDatabaseTexture("window.label.unfocus", "Window.Label.Unfocus",
518 resource
.wstyle
.h_focus
=
519 readDatabaseTexture("window.handle.focus", "Window.Handle.Focus", "white");
520 resource
.wstyle
.h_unfocus
=
521 readDatabaseTexture("window.handle.unfocus",
522 "Window.Handle.Unfocus", "black");
523 resource
.wstyle
.g_focus
=
524 readDatabaseTexture("window.grip.focus", "Window.Grip.Focus", "white");
525 resource
.wstyle
.g_unfocus
=
526 readDatabaseTexture("window.grip.unfocus", "Window.Grip.Unfocus", "black");
527 resource
.wstyle
.b_focus
=
528 readDatabaseTexture("window.button.focus", "Window.Button.Focus", "white");
529 resource
.wstyle
.b_unfocus
=
530 readDatabaseTexture("window.button.unfocus",
531 "Window.Button.Unfocus", "black");
532 resource
.wstyle
.b_pressed
=
533 readDatabaseTexture("window.button.pressed",
534 "Window.Button.Pressed", "black");
535 resource
.wstyle
.f_focus
=
536 readDatabaseColor("window.frame.focusColor",
537 "Window.Frame.FocusColor", "white");
538 resource
.wstyle
.f_unfocus
=
539 readDatabaseColor("window.frame.unfocusColor",
540 "Window.Frame.UnfocusColor", "black");
541 resource
.wstyle
.l_text_focus
=
542 readDatabaseColor("window.label.focus.textColor",
543 "Window.Label.Focus.TextColor", "black");
544 resource
.wstyle
.l_text_unfocus
=
545 readDatabaseColor("window.label.unfocus.textColor",
546 "Window.Label.Unfocus.TextColor", "white");
547 resource
.wstyle
.b_pic_focus
=
548 readDatabaseColor("window.button.focus.picColor",
549 "Window.Button.Focus.PicColor", "black");
550 resource
.wstyle
.b_pic_unfocus
=
551 readDatabaseColor("window.button.unfocus.picColor",
552 "Window.Button.Unfocus.PicColor", "white");
554 resource
.wstyle
.justify
= LeftJustify
;
555 if (XrmGetResource(resource
.stylerc
, "window.justify", "Window.Justify",
556 &value_type
, &value
)) {
557 if (strstr(value
.addr
, "right") || strstr(value
.addr
, "Right"))
558 resource
.wstyle
.justify
= RightJustify
;
559 else if (strstr(value
.addr
, "center") || strstr(value
.addr
, "Center"))
560 resource
.wstyle
.justify
= CenterJustify
;
563 // load toolbar config
564 resource
.tstyle
.toolbar
=
565 readDatabaseTexture("toolbar", "Toolbar", "black");
566 resource
.tstyle
.label
=
567 readDatabaseTexture("toolbar.label", "Toolbar.Label", "black");
568 resource
.tstyle
.window
=
569 readDatabaseTexture("toolbar.windowLabel", "Toolbar.WindowLabel", "black");
570 resource
.tstyle
.button
=
571 readDatabaseTexture("toolbar.button", "Toolbar.Button", "white");
572 resource
.tstyle
.pressed
=
573 readDatabaseTexture("toolbar.button.pressed",
574 "Toolbar.Button.Pressed", "black");
575 resource
.tstyle
.clock
=
576 readDatabaseTexture("toolbar.clock", "Toolbar.Clock", "black");
577 resource
.tstyle
.l_text
=
578 readDatabaseColor("toolbar.label.textColor",
579 "Toolbar.Label.TextColor", "white");
580 resource
.tstyle
.w_text
=
581 readDatabaseColor("toolbar.windowLabel.textColor",
582 "Toolbar.WindowLabel.TextColor", "white");
583 resource
.tstyle
.c_text
=
584 readDatabaseColor("toolbar.clock.textColor",
585 "Toolbar.Clock.TextColor", "white");
586 resource
.tstyle
.b_pic
=
587 readDatabaseColor("toolbar.button.picColor",
588 "Toolbar.Button.PicColor", "black");
590 resource
.tstyle
.justify
= LeftJustify
;
591 if (XrmGetResource(resource
.stylerc
, "toolbar.justify",
592 "Toolbar.Justify", &value_type
, &value
)) {
593 if (strstr(value
.addr
, "right") || strstr(value
.addr
, "Right"))
594 resource
.tstyle
.justify
= RightJustify
;
595 else if (strstr(value
.addr
, "center") || strstr(value
.addr
, "Center"))
596 resource
.tstyle
.justify
= CenterJustify
;
600 resource
.mstyle
.title
=
601 readDatabaseTexture("menu.title", "Menu.Title", "white");
602 resource
.mstyle
.frame
=
603 readDatabaseTexture("menu.frame", "Menu.Frame", "black");
604 resource
.mstyle
.hilite
=
605 readDatabaseTexture("menu.hilite", "Menu.Hilite", "white");
606 resource
.mstyle
.t_text
=
607 readDatabaseColor("menu.title.textColor", "Menu.Title.TextColor", "black");
608 resource
.mstyle
.f_text
=
609 readDatabaseColor("menu.frame.textColor", "Menu.Frame.TextColor", "white");
610 resource
.mstyle
.d_text
=
611 readDatabaseColor("menu.frame.disableColor",
612 "Menu.Frame.DisableColor", "black");
613 resource
.mstyle
.h_text
=
614 readDatabaseColor("menu.hilite.textColor",
615 "Menu.Hilite.TextColor", "black");
617 resource
.mstyle
.t_justify
= LeftJustify
;
618 if (XrmGetResource(resource
.stylerc
, "menu.title.justify",
619 "Menu.Title.Justify",
620 &value_type
, &value
)) {
621 if (strstr(value
.addr
, "right") || strstr(value
.addr
, "Right"))
622 resource
.mstyle
.t_justify
= RightJustify
;
623 else if (strstr(value
.addr
, "center") || strstr(value
.addr
, "Center"))
624 resource
.mstyle
.t_justify
= CenterJustify
;
627 resource
.mstyle
.f_justify
= LeftJustify
;
628 if (XrmGetResource(resource
.stylerc
, "menu.frame.justify",
629 "Menu.Frame.Justify",
630 &value_type
, &value
)) {
631 if (strstr(value
.addr
, "right") || strstr(value
.addr
, "Right"))
632 resource
.mstyle
.f_justify
= RightJustify
;
633 else if (strstr(value
.addr
, "center") || strstr(value
.addr
, "Center"))
634 resource
.mstyle
.f_justify
= CenterJustify
;
637 resource
.mstyle
.bullet
= Basemenu::Triangle
;
638 if (XrmGetResource(resource
.stylerc
, "menu.bullet", "Menu.Bullet",
639 &value_type
, &value
)) {
640 if (! strncasecmp(value
.addr
, "empty", value
.size
))
641 resource
.mstyle
.bullet
= Basemenu::Empty
;
642 else if (! strncasecmp(value
.addr
, "square", value
.size
))
643 resource
.mstyle
.bullet
= Basemenu::Square
;
644 else if (! strncasecmp(value
.addr
, "diamond", value
.size
))
645 resource
.mstyle
.bullet
= Basemenu::Diamond
;
648 resource
.mstyle
.bullet_pos
= Basemenu::Left
;
649 if (XrmGetResource(resource
.stylerc
, "menu.bullet.position",
650 "Menu.Bullet.Position", &value_type
, &value
)) {
651 if (! strncasecmp(value
.addr
, "right", value
.size
))
652 resource
.mstyle
.bullet_pos
= Basemenu::Right
;
655 resource
.border_color
=
656 readDatabaseColor("borderColor", "BorderColor", "black");
658 unsigned int uint_value
;
660 // load bevel, border and handle widths
661 resource
.handle_width
= 6;
662 if (XrmGetResource(resource
.stylerc
, "handleWidth", "HandleWidth",
663 &value_type
, &value
) &&
664 sscanf(value
.addr
, "%u", &uint_value
) == 1 &&
665 uint_value
<= (getWidth() / 2) && uint_value
!= 0) {
666 resource
.handle_width
= uint_value
;
669 resource
.border_width
= 1;
670 if (XrmGetResource(resource
.stylerc
, "borderWidth", "BorderWidth",
671 &value_type
, &value
) &&
672 sscanf(value
.addr
, "%u", &uint_value
) == 1) {
673 resource
.border_width
= uint_value
;
676 resource
.bevel_width
= 3;
677 if (XrmGetResource(resource
.stylerc
, "bevelWidth", "BevelWidth",
678 &value_type
, &value
) &&
679 sscanf(value
.addr
, "%u", &uint_value
) == 1 &&
680 uint_value
<= (getWidth() / 2) && uint_value
!= 0) {
681 resource
.bevel_width
= uint_value
;
684 resource
.frame_width
= resource
.bevel_width
;
685 if (XrmGetResource(resource
.stylerc
, "frameWidth", "FrameWidth",
686 &value_type
, &value
) &&
687 sscanf(value
.addr
, "%u", &uint_value
) == 1 &&
688 uint_value
<= (getWidth() / 2)) {
689 resource
.frame_width
= uint_value
;
692 if (XrmGetResource(resource
.stylerc
, "rootCommand", "RootCommand",
693 &value_type
, &value
)) {
694 bexec(value
.addr
, displayString());
697 XrmDestroyDatabase(resource
.stylerc
);
701 void BScreen::addIcon(BlackboxWindow
*w
) {
704 w
->setWorkspace(BSENTINEL
);
705 w
->setWindowNumber(iconList
.size());
707 iconList
.push_back(w
);
709 const char* title
= w
->getIconTitle();
710 iconmenu
->insert(title
);
715 void BScreen::removeIcon(BlackboxWindow
*w
) {
720 iconmenu
->remove(w
->getWindowNumber());
723 BlackboxWindowList::iterator it
= iconList
.begin(),
724 end
= iconList
.end();
725 for (int i
= 0; it
!= end
; ++it
)
726 (*it
)->setWindowNumber(i
++);
730 BlackboxWindow
*BScreen::getIcon(unsigned int index
) {
731 if (index
< iconList
.size()) {
732 BlackboxWindowList::iterator it
= iconList
.begin();
733 for (; index
> 0; --index
, ++it
) ; /* increment to index */
737 return (BlackboxWindow
*) 0;
741 unsigned int BScreen::addWorkspace(void) {
742 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
743 workspacesList
.push_back(wkspc
);
745 workspacemenu
->insert(wkspc
->getName(), wkspc
->getMenu(),
747 workspacemenu
->update();
749 toolbar
->reconfigure();
751 updateNetizenWorkspaceCount();
753 return workspacesList
.size();
757 unsigned int BScreen::removeLastWorkspace(void) {
758 if (workspacesList
.size() == 1)
761 Workspace
*wkspc
= workspacesList
.back();
763 if (current_workspace
->getID() == wkspc
->getID())
764 changeWorkspaceID(current_workspace
->getID() - 1);
768 workspacemenu
->remove(wkspc
->getID() + 2);
769 workspacemenu
->update();
771 workspacesList
.pop_back();
774 toolbar
->reconfigure();
776 updateNetizenWorkspaceCount();
778 return workspacesList
.size();
782 void BScreen::changeWorkspaceID(unsigned int id
) {
783 if (! current_workspace
) return;
785 if (id
!= current_workspace
->getID()) {
786 current_workspace
->hideAll();
788 workspacemenu
->setItemSelected(current_workspace
->getID() + 2, False
);
790 if (blackbox
->getFocusedWindow() &&
791 blackbox
->getFocusedWindow()->getScreen() == this &&
792 (! blackbox
->getFocusedWindow()->isStuck())) {
793 current_workspace
->setLastFocusedWindow(blackbox
->getFocusedWindow());
794 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
797 current_workspace
= getWorkspace(id
);
799 workspacemenu
->setItemSelected(current_workspace
->getID() + 2, True
);
800 toolbar
->redrawWorkspaceLabel(True
);
802 current_workspace
->showAll();
804 if (resource
.focus_last
&& current_workspace
->getLastFocusedWindow()) {
805 XSync(blackbox
->getXDisplay(), False
);
806 current_workspace
->getLastFocusedWindow()->setInputFocus();
810 updateNetizenCurrentWorkspace();
814 void BScreen::manageWindow(Window w
) {
815 new BlackboxWindow(blackbox
, w
, this);
817 BlackboxWindow
*win
= blackbox
->searchWindow(w
);
821 windowList
.push_back(win
);
823 XMapRequestEvent mre
;
825 win
->restoreAttributes();
826 win
->mapRequestEvent(&mre
);
830 void BScreen::unmanageWindow(BlackboxWindow
*w
, bool remap
) {
833 if (w
->getWorkspaceNumber() != BSENTINEL
&&
834 w
->getWindowNumber() != BSENTINEL
)
835 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
836 else if (w
->isIconic())
839 windowList
.remove(w
);
841 if (blackbox
->getFocusedWindow() == w
)
842 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
844 removeNetizen(w
->getClientWindow());
850 void BScreen::addNetizen(Netizen
*n
) {
851 netizenList
.push_back(n
);
853 n
->sendWorkspaceCount();
854 n
->sendCurrentWorkspace();
856 WorkspaceList::iterator it
= workspacesList
.begin();
857 const WorkspaceList::iterator end
= workspacesList
.end();
858 for (; it
!= end
; ++it
)
859 (*it
)->sendWindowList(*n
);
861 Window f
= ((blackbox
->getFocusedWindow()) ?
862 blackbox
->getFocusedWindow()->getClientWindow() : None
);
863 n
->sendWindowFocus(f
);
867 void BScreen::removeNetizen(Window w
) {
868 NetizenList::iterator it
= netizenList
.begin();
869 for (; it
!= netizenList
.end(); ++it
) {
870 if ((*it
)->getWindowID() == w
) {
872 netizenList
.erase(it
);
879 void BScreen::updateNetizenCurrentWorkspace(void) {
880 std::for_each(netizenList
.begin(), netizenList
.end(),
881 std::mem_fun(&Netizen::sendCurrentWorkspace
));
885 void BScreen::updateNetizenWorkspaceCount(void) {
886 std::for_each(netizenList
.begin(), netizenList
.end(),
887 std::mem_fun(&Netizen::sendWorkspaceCount
));
891 void BScreen::updateNetizenWindowFocus(void) {
892 Window f
= ((blackbox
->getFocusedWindow()) ?
893 blackbox
->getFocusedWindow()->getClientWindow() : None
);
894 NetizenList::iterator it
= netizenList
.begin();
895 for (; it
!= netizenList
.end(); ++it
)
896 (*it
)->sendWindowFocus(f
);
900 void BScreen::updateNetizenWindowAdd(Window w
, unsigned long p
) {
901 NetizenList::iterator it
= netizenList
.begin();
902 for (; it
!= netizenList
.end(); ++it
) {
903 (*it
)->sendWindowAdd(w
, p
);
908 void BScreen::updateNetizenWindowDel(Window w
) {
909 NetizenList::iterator it
= netizenList
.begin();
910 for (; it
!= netizenList
.end(); ++it
)
911 (*it
)->sendWindowDel(w
);
915 void BScreen::updateNetizenWindowRaise(Window w
) {
916 NetizenList::iterator it
= netizenList
.begin();
917 for (; it
!= netizenList
.end(); ++it
)
918 (*it
)->sendWindowRaise(w
);
922 void BScreen::updateNetizenWindowLower(Window w
) {
923 NetizenList::iterator it
= netizenList
.begin();
924 for (; it
!= netizenList
.end(); ++it
)
925 (*it
)->sendWindowLower(w
);
929 void BScreen::updateNetizenConfigNotify(XEvent
*e
) {
930 NetizenList::iterator it
= netizenList
.begin();
931 for (; it
!= netizenList
.end(); ++it
)
932 (*it
)->sendConfigNotify(e
);
936 void BScreen::raiseWindows(Window
*workspace_stack
, unsigned int num
) {
938 Window
*session_stack
= new
939 Window
[(num
+ workspacesList
.size() + rootmenuList
.size() + 13)];
940 unsigned int i
= 0, k
= num
;
942 XRaiseWindow(blackbox
->getXDisplay(), iconmenu
->getWindowID());
943 *(session_stack
+ i
++) = iconmenu
->getWindowID();
945 WorkspaceList::iterator wit
= workspacesList
.begin();
946 const WorkspaceList::iterator w_end
= workspacesList
.end();
947 for (; wit
!= w_end
; ++wit
)
948 *(session_stack
+ i
++) = (*wit
)->getMenu()->getWindowID();
950 *(session_stack
+ i
++) = workspacemenu
->getWindowID();
952 *(session_stack
+ i
++) = configmenu
->getFocusmenu()->getWindowID();
953 *(session_stack
+ i
++) = configmenu
->getPlacementmenu()->getWindowID();
954 *(session_stack
+ i
++) = configmenu
->getWindowID();
956 *(session_stack
+ i
++) = slit
->getMenu()->getDirectionmenu()->getWindowID();
957 *(session_stack
+ i
++) = slit
->getMenu()->getPlacementmenu()->getWindowID();
958 *(session_stack
+ i
++) = slit
->getMenu()->getWindowID();
960 *(session_stack
+ i
++) =
961 toolbar
->getMenu()->getPlacementmenu()->getWindowID();
962 *(session_stack
+ i
++) = toolbar
->getMenu()->getWindowID();
964 RootmenuList::iterator rit
= rootmenuList
.begin();
965 for (; rit
!= rootmenuList
.end(); ++rit
)
966 *(session_stack
+ i
++) = (*rit
)->getWindowID();
967 *(session_stack
+ i
++) = rootmenu
->getWindowID();
969 if (toolbar
->isOnTop())
970 *(session_stack
+ i
++) = toolbar
->getWindowID();
973 *(session_stack
+ i
++) = slit
->getWindowID();
976 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
978 XRestackWindows(blackbox
->getXDisplay(), session_stack
, i
);
980 delete [] session_stack
;
985 void BScreen::saveStrftimeFormat(const string
& format
) {
986 resource
.strftime_format
= format
;
988 #endif // HAVE_STRFTIME
991 void BScreen::addWorkspaceName(const string
& name
) {
992 workspaceNames
.push_back(name
);
997 * I would love to kill this function and the accompanying workspaceNames
998 * list. However, we have a chicken and egg situation. The names are read
999 * in during load_rc() which happens before the workspaces are created.
1000 * The current solution is to read the names into a list, then use the list
1001 * later for constructing the workspaces. It is only used during initial
1004 const string
BScreen::getNameOfWorkspace(unsigned int id
) {
1005 if (id
< workspaceNames
.size())
1006 return workspaceNames
[id
];
1011 void BScreen::reassociateWindow(BlackboxWindow
*w
, unsigned int wkspc_id
,
1012 bool ignore_sticky
) {
1015 if (wkspc_id
== BSENTINEL
)
1016 wkspc_id
= current_workspace
->getID();
1018 if (w
->getWorkspaceNumber() == wkspc_id
)
1021 if (w
->isIconic()) {
1023 getWorkspace(wkspc_id
)->addWindow(w
);
1024 } else if (ignore_sticky
|| ! w
->isStuck()) {
1025 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1026 getWorkspace(wkspc_id
)->addWindow(w
);
1031 void BScreen::propagateWindowName(const BlackboxWindow
*bw
) {
1032 if (bw
->isIconic()) {
1033 iconmenu
->changeItemLabel(bw
->getWindowNumber(), bw
->getIconTitle());
1037 Clientmenu
*clientmenu
= getWorkspace(bw
->getWorkspaceNumber())->getMenu();
1038 clientmenu
->changeItemLabel(bw
->getWindowNumber(), bw
->getTitle());
1039 clientmenu
->update();
1041 if (blackbox
->getFocusedWindow() == bw
)
1042 toolbar
->redrawWindowLabel(True
);
1047 void BScreen::nextFocus(void) {
1048 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1052 // if window is not on this screen, ignore it
1053 if (focused
->getScreen()->getScreenNumber() != getScreenNumber())
1054 focused
= (BlackboxWindow
*) 0;
1057 if (focused
&& current_workspace
->getCount() > 1) {
1058 // next is the next window to recieve focus, current is a place holder
1059 BlackboxWindow
*current
;
1062 next
= current_workspace
->getNextWindowInList(current
);
1063 } while(!next
->setInputFocus() && next
!= focused
);
1065 if (next
!= focused
)
1066 current_workspace
->raiseWindow(next
);
1067 } else if (current_workspace
->getCount() >= 1) {
1068 next
= current_workspace
->getTopWindowOnStack();
1070 current_workspace
->raiseWindow(next
);
1071 next
->setInputFocus();
1076 void BScreen::prevFocus(void) {
1077 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1081 // if window is not on this screen, ignore it
1082 if (focused
->getScreen()->getScreenNumber() != getScreenNumber())
1083 focused
= (BlackboxWindow
*) 0;
1086 if (focused
&& current_workspace
->getCount() > 1) {
1087 // next is the next window to recieve focus, current is a place holder
1088 BlackboxWindow
*current
;
1091 next
= current_workspace
->getPrevWindowInList(current
);
1092 } while(!next
->setInputFocus() && next
!= focused
);
1094 if (next
!= focused
)
1095 current_workspace
->raiseWindow(next
);
1096 } else if (current_workspace
->getCount() >= 1) {
1097 next
= current_workspace
->getTopWindowOnStack();
1099 current_workspace
->raiseWindow(next
);
1100 next
->setInputFocus();
1105 void BScreen::raiseFocus(void) {
1106 BlackboxWindow
*focused
= blackbox
->getFocusedWindow();
1110 // if on this Screen, raise it
1111 if (focused
->getScreen()->getScreenNumber() == getScreenNumber()) {
1112 Workspace
*workspace
= getWorkspace(focused
->getWorkspaceNumber());
1113 workspace
->raiseWindow(focused
);
1118 void BScreen::InitMenu(void) {
1120 rootmenuList
.clear();
1122 while (rootmenu
->getCount())
1123 rootmenu
->remove(0);
1125 rootmenu
= new Rootmenu(this);
1127 bool defaultMenu
= True
;
1129 FILE *menu_file
= (FILE *) 0;
1130 const char *menu_filename
= blackbox
->getMenuFilename();
1133 if (!(menu_file
= fopen(menu_filename
, "r")))
1134 perror(menu_filename
);
1135 if (!menu_file
) { // opening the menu file failed, try the default menu
1136 menu_filename
= DEFAULTMENU
;
1137 if (!(menu_file
= fopen(menu_filename
, "r")))
1138 perror(menu_filename
);
1142 if (feof(menu_file
)) {
1143 fprintf(stderr
, i18n(ScreenSet
, ScreenEmptyMenuFile
,
1144 "%s: Empty menu file"),
1147 char line
[1024], label
[1024];
1148 memset(line
, 0, 1024);
1149 memset(label
, 0, 1024);
1151 while (fgets(line
, 1024, menu_file
) && ! feof(menu_file
)) {
1152 if (line
[0] != '#') {
1153 int i
, key
= 0, index
= -1, len
= strlen(line
);
1155 for (i
= 0; i
< len
; i
++) {
1156 if (line
[i
] == '[') index
= 0;
1157 else if (line
[i
] == ']') break;
1158 else if (line
[i
] != ' ')
1160 key
+= tolower(line
[i
]);
1163 if (key
== 517) { // [begin]
1165 for (i
= index
; i
< len
; i
++) {
1166 if (line
[i
] == '(') index
= 0;
1167 else if (line
[i
] == ')') break;
1168 else if (index
++ >= 0) {
1169 if (line
[i
] == '\\' && i
< len
- 1) i
++;
1170 label
[index
- 1] = line
[i
];
1174 if (index
== -1) index
= 0;
1175 label
[index
] = '\0';
1177 rootmenu
->setLabel(label
);
1178 defaultMenu
= parseMenuFile(menu_file
, rootmenu
);
1180 blackbox
->addMenuTimestamp(menu_filename
);
1190 rootmenu
->setInternalMenu();
1191 rootmenu
->insert(i18n(ScreenSet
, Screenxterm
, "xterm"),
1193 i18n(ScreenSet
, Screenxterm
, "xterm"));
1194 rootmenu
->insert(i18n(ScreenSet
, ScreenRestart
, "Restart"),
1196 rootmenu
->insert(i18n(ScreenSet
, ScreenExit
, "Exit"),
1198 rootmenu
->setLabel(i18n(BasemenuSet
, BasemenuBlackboxMenu
,
1204 bool BScreen::parseMenuFile(FILE *file
, Rootmenu
*menu
) {
1205 char line
[1024], label
[1024], command
[1024];
1207 while (! feof(file
)) {
1208 memset(line
, 0, 1024);
1209 memset(label
, 0, 1024);
1210 memset(command
, 0, 1024);
1212 if (fgets(line
, 1024, file
)) {
1213 if (line
[0] != '#') {
1214 int i
, key
= 0, parse
= 0, index
= -1, line_length
= strlen(line
);
1216 // determine the keyword
1217 for (i
= 0; i
< line_length
; i
++) {
1218 if (line
[i
] == '[') parse
= 1;
1219 else if (line
[i
] == ']') break;
1220 else if (line
[i
] != ' ')
1222 key
+= tolower(line
[i
]);
1225 // get the label enclosed in ()'s
1228 for (i
= 0; i
< line_length
; i
++) {
1229 if (line
[i
] == '(') {
1232 } else if (line
[i
] == ')') break;
1233 else if (index
++ >= 0) {
1234 if (line
[i
] == '\\' && i
< line_length
- 1) i
++;
1235 label
[index
- 1] = line
[i
];
1240 label
[index
] = '\0';
1245 // get the command enclosed in {}'s
1248 for (i
= 0; i
< line_length
; i
++) {
1249 if (line
[i
] == '{') {
1252 } else if (line
[i
] == '}') break;
1253 else if (index
++ >= 0) {
1254 if (line
[i
] == '\\' && i
< line_length
- 1) i
++;
1255 command
[index
- 1] = line
[i
];
1260 command
[index
] = '\0';
1267 return ((menu
->getCount() == 0) ? True
: False
);
1274 menu
->insert(label
);
1279 if ((! *label
) && (! *command
)) {
1280 fprintf(stderr
, i18n(ScreenSet
, ScreenEXECError
,
1281 "BScreen::parseMenuFile: [exec] error, "
1282 "no menu label and/or command defined\n"));
1286 menu
->insert(label
, BScreen::Execute
, command
);
1292 fprintf(stderr
, i18n(ScreenSet
, ScreenEXITError
,
1293 "BScreen::parseMenuFile: [exit] error, "
1294 "no menu label defined\n"));
1298 menu
->insert(label
, BScreen::Exit
);
1304 if ((! *label
) || (! *command
)) {
1306 i18n(ScreenSet
, ScreenSTYLEError
,
1307 "BScreen::parseMenuFile: [style] error, "
1308 "no menu label and/or filename defined\n"));
1312 string style
= expandTilde(command
);
1314 menu
->insert(label
, BScreen::SetStyle
, style
.c_str());
1321 fprintf(stderr
, i18n(ScreenSet
, ScreenCONFIGError
,
1322 "BScreen::parseMenufile: [config] error, "
1323 "no label defined"));
1327 menu
->insert(label
, configmenu
);
1331 case 740: // include
1334 fprintf(stderr
, i18n(ScreenSet
, ScreenINCLUDEError
,
1335 "BScreen::parseMenuFile: [include] error, "
1336 "no filename defined\n"));
1340 string newfile
= expandTilde(label
);
1341 FILE *submenufile
= fopen(newfile
.c_str(), "r");
1345 if (fstat(fileno(submenufile
), &buf
) ||
1346 (! S_ISREG(buf
.st_mode
))) {
1348 i18n(ScreenSet
, ScreenINCLUDEErrorReg
,
1349 "BScreen::parseMenuFile: [include] error: "
1350 "'%s' is not a regular file\n"), newfile
.c_str());
1354 if (! feof(submenufile
)) {
1355 if (! parseMenuFile(submenufile
, menu
))
1356 blackbox
->addMenuTimestamp(newfile
);
1358 fclose(submenufile
);
1361 perror(newfile
.c_str());
1367 case 767: // submenu
1370 fprintf(stderr
, i18n(ScreenSet
, ScreenSUBMENUError
,
1371 "BScreen::parseMenuFile: [submenu] error, "
1372 "no menu label defined\n"));
1376 Rootmenu
*submenu
= new Rootmenu(this);
1379 submenu
->setLabel(command
);
1381 submenu
->setLabel(label
);
1383 parseMenuFile(file
, submenu
);
1385 menu
->insert(label
, submenu
);
1386 rootmenuList
.push_back(submenu
);
1391 case 773: // restart
1394 fprintf(stderr
, i18n(ScreenSet
, ScreenRESTARTError
,
1395 "BScreen::parseMenuFile: [restart] error, "
1396 "no menu label defined\n"));
1401 menu
->insert(label
, BScreen::RestartOther
, command
);
1403 menu
->insert(label
, BScreen::Restart
);
1408 case 845: // reconfig
1412 i18n(ScreenSet
, ScreenRECONFIGError
,
1413 "BScreen::parseMenuFile: [reconfig] error, "
1414 "no menu label defined\n"));
1418 menu
->insert(label
, BScreen::Reconfigure
);
1423 case 995: // stylesdir
1424 case 1113: // stylesmenu
1426 bool newmenu
= ((key
== 1113) ? True
: False
);
1428 if ((! *label
) || ((! *command
) && newmenu
)) {
1430 i18n(ScreenSet
, ScreenSTYLESDIRError
,
1431 "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
1432 " error, no directory defined\n"));
1436 char *directory
= ((newmenu
) ? command
: label
);
1438 string stylesdir
= expandTilde(directory
);
1440 struct stat statbuf
;
1442 if (! stat(stylesdir
.c_str(), &statbuf
)) {
1443 if (S_ISDIR(statbuf
.st_mode
)) {
1444 Rootmenu
*stylesmenu
;
1447 stylesmenu
= new Rootmenu(this);
1451 DIR *d
= opendir(stylesdir
.c_str());
1453 std::vector
<string
> ls
;
1455 while((p
= readdir(d
)))
1456 ls
.push_back(p
->d_name
);
1460 std::sort(ls
.begin(), ls
.end());
1462 std::vector
<string
>::iterator it
= ls
.begin(),
1464 for (; it
!= end
; ++it
) {
1465 const string
& fname
= *it
;
1467 if (fname
[fname
.size()-1] == '~')
1470 string style
= stylesdir
;
1474 if ((! stat(style
.c_str(), &statbuf
)) &&
1475 S_ISREG(statbuf
.st_mode
))
1476 stylesmenu
->insert(fname
, BScreen::SetStyle
, style
);
1479 stylesmenu
->update();
1482 stylesmenu
->setLabel(label
);
1483 menu
->insert(label
, stylesmenu
);
1484 rootmenuList
.push_back(stylesmenu
);
1487 blackbox
->addMenuTimestamp(stylesdir
);
1490 i18n(ScreenSet
, ScreenSTYLESDIRErrorNotDir
,
1491 "BScreen::parseMenuFile:"
1492 " [stylesdir/stylesmenu] error, %s is not a"
1493 " directory\n"), stylesdir
.c_str());
1497 i18n(ScreenSet
, ScreenSTYLESDIRErrorNoExist
,
1498 "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
1499 " error, %s does not exist\n"), stylesdir
.c_str());
1504 case 1090: // workspaces
1508 i18n(ScreenSet
, ScreenWORKSPACESError
,
1509 "BScreen:parseMenuFile: [workspaces] error, "
1510 "no menu label defined\n"));
1514 menu
->insert(label
, workspacemenu
);
1523 return ((menu
->getCount() == 0) ? True
: False
);
1527 void BScreen::shutdown(void) {
1528 XSelectInput(blackbox
->getXDisplay(), getRootWindow(), NoEventMask
);
1529 XSync(blackbox
->getXDisplay(), False
);
1531 while(! windowList
.empty())
1532 unmanageWindow(windowList
.front(), True
);
1538 void BScreen::showPosition(int x
, int y
) {
1539 if (! geom_visible
) {
1540 XMoveResizeWindow(blackbox
->getXDisplay(), geom_window
,
1541 (getWidth() - geom_w
) / 2,
1542 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
1543 XMapWindow(blackbox
->getXDisplay(), geom_window
);
1544 XRaiseWindow(blackbox
->getXDisplay(), geom_window
);
1546 geom_visible
= True
;
1551 sprintf(label
, i18n(ScreenSet
, ScreenPositionFormat
,
1552 "X: %4d x Y: %4d"), x
, y
);
1554 XClearWindow(blackbox
->getXDisplay(), geom_window
);
1556 BPen
pen(resource
.wstyle
.l_text_focus
, resource
.wstyle
.font
);
1557 if (i18n
.multibyte()) {
1558 XmbDrawString(blackbox
->getXDisplay(), geom_window
,
1559 resource
.wstyle
.fontset
, pen
.gc(),
1560 resource
.bevel_width
, resource
.bevel_width
-
1561 resource
.wstyle
.fontset_extents
->max_ink_extent
.y
,
1562 label
, strlen(label
));
1564 XDrawString(blackbox
->getXDisplay(), geom_window
,
1565 pen
.gc(), resource
.bevel_width
,
1566 resource
.wstyle
.font
->ascent
+ resource
.bevel_width
,
1567 label
, strlen(label
));
1572 void BScreen::showGeometry(unsigned int gx
, unsigned int gy
) {
1573 if (! geom_visible
) {
1574 XMoveResizeWindow(blackbox
->getXDisplay(), geom_window
,
1575 (getWidth() - geom_w
) / 2,
1576 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
1577 XMapWindow(blackbox
->getXDisplay(), geom_window
);
1578 XRaiseWindow(blackbox
->getXDisplay(), geom_window
);
1580 geom_visible
= True
;
1585 sprintf(label
, i18n(ScreenSet
, ScreenGeometryFormat
,
1586 "W: %4d x H: %4d"), gx
, gy
);
1588 XClearWindow(blackbox
->getXDisplay(), geom_window
);
1590 BPen
pen(resource
.wstyle
.l_text_focus
, resource
.wstyle
.font
);
1591 if (i18n
.multibyte()) {
1592 XmbDrawString(blackbox
->getXDisplay(), geom_window
,
1593 resource
.wstyle
.fontset
, pen
.gc(),
1594 resource
.bevel_width
, resource
.bevel_width
-
1595 resource
.wstyle
.fontset_extents
->max_ink_extent
.y
,
1596 label
, strlen(label
));
1598 XDrawString(blackbox
->getXDisplay(), geom_window
,
1599 pen
.gc(), resource
.bevel_width
,
1600 resource
.wstyle
.font
->ascent
+
1601 resource
.bevel_width
, label
, strlen(label
));
1606 void BScreen::hideGeometry(void) {
1608 XUnmapWindow(blackbox
->getXDisplay(), geom_window
);
1609 geom_visible
= False
;
1614 void BScreen::addStrut(Strut
*strut
) {
1615 strutList
.push_back(strut
);
1619 void BScreen::removeStrut(Strut
*strut
) {
1620 strutList
.remove(strut
);
1624 const Rect
& BScreen::availableArea(void) const {
1626 return getRect(); // return the full screen
1631 void BScreen::updateAvailableArea(void) {
1632 Rect old_area
= usableArea
;
1633 usableArea
= getRect(); // reset to full screen
1635 /* these values represent offsets from the screen edge
1636 * we look for the biggest offset on each edge and then apply them
1638 * do not be confused by the similarity to the names of Rect's members
1640 unsigned int current_left
= 0, current_right
= 0, current_top
= 0,
1643 StrutList::const_iterator it
= strutList
.begin(), end
= strutList
.end();
1645 for(; it
!= end
; ++it
) {
1647 if (strut
->left
> current_left
)
1648 current_left
= strut
->left
;
1649 if (strut
->top
> current_top
)
1650 current_top
= strut
->top
;
1651 if (strut
->right
> current_right
)
1652 current_right
= strut
->right
;
1653 if (strut
->bottom
> current_bottom
)
1654 current_bottom
= strut
->bottom
;
1657 usableArea
.setPos(current_left
, current_top
);
1658 usableArea
.setSize(usableArea
.width() - (current_left
+ current_right
),
1659 usableArea
.height() - (current_top
+ current_bottom
));
1661 if (old_area
!= usableArea
) {
1662 BlackboxWindowList::iterator it
= windowList
.begin(),
1663 end
= windowList
.end();
1664 for (; it
!= end
; ++it
)
1665 if ((*it
)->isMaximized()) (*it
)->remaximize();
1670 Workspace
* BScreen::getWorkspace(unsigned int index
) {
1671 assert(index
< workspacesList
.size());
1672 return workspacesList
[index
];
1676 void BScreen::buttonPressEvent(XButtonEvent
*xbutton
) {
1677 if (xbutton
->button
== 1) {
1678 if (! isRootColormapInstalled())
1679 image_control
->installRootColormap();
1681 if (workspacemenu
->isVisible())
1682 workspacemenu
->hide();
1684 if (rootmenu
->isVisible())
1686 } else if (xbutton
->button
== 2) {
1687 int mx
= xbutton
->x_root
- (workspacemenu
->getWidth() / 2);
1688 int my
= xbutton
->y_root
- (workspacemenu
->getTitleHeight() / 2);
1693 if (mx
+ workspacemenu
->getWidth() > getWidth())
1694 mx
= getWidth() - workspacemenu
->getWidth() - getBorderWidth();
1696 if (my
+ workspacemenu
->getHeight() > getHeight())
1697 my
= getHeight() - workspacemenu
->getHeight() - getBorderWidth();
1699 workspacemenu
->move(mx
, my
);
1701 if (! workspacemenu
->isVisible()) {
1702 workspacemenu
->removeParent();
1703 workspacemenu
->show();
1705 } else if (xbutton
->button
== 3) {
1706 int mx
= xbutton
->x_root
- (rootmenu
->getWidth() / 2);
1707 int my
= xbutton
->y_root
- (rootmenu
->getTitleHeight() / 2);
1712 if (mx
+ rootmenu
->getWidth() > getWidth())
1713 mx
= getWidth() - rootmenu
->getWidth() - getBorderWidth();
1715 if (my
+ rootmenu
->getHeight() > getHeight())
1716 my
= getHeight() - rootmenu
->getHeight() - getBorderWidth();
1718 rootmenu
->move(mx
, my
);
1720 if (! rootmenu
->isVisible()) {
1721 blackbox
->checkMenu();
1728 void BScreen::toggleFocusModel(FocusModel model
) {
1729 if (model
== SloppyFocus
) {
1730 saveSloppyFocus(True
);
1732 saveSloppyFocus(False
);
1733 saveAutoRaise(False
);
1734 saveClickRaise(False
);
1741 void BScreen::updateFocusModel()
1743 std::for_each(workspacesList
.begin(), workspacesList
.end(),
1744 std::mem_fun(&Workspace::updateFocusModel
));
1748 BTexture
BScreen::readDatabaseTexture(const string
&rname
,
1749 const string
&rclass
,
1750 const string
&default_color
) {
1755 if (XrmGetResource(resource
.stylerc
, rname
.c_str(), rclass
.c_str(),
1756 &value_type
, &value
))
1757 texture
= BTexture(value
.addr
);
1759 texture
.setTexture(BTexture::Solid
| BTexture::Flat
);
1761 // associate this texture with this screen
1762 texture
.setDisplay(getBaseDisplay(), getScreenNumber());
1763 texture
.setImageControl(image_control
);
1765 if (texture
.texture() & BTexture::Solid
) {
1766 texture
.setColor(readDatabaseColor(rname
+ ".color",
1769 texture
.setColorTo(readDatabaseColor(rname
+ ".colorTo",
1770 rclass
+ ".ColorTo",
1772 } else if (texture
.texture() & BTexture::Gradient
) {
1773 texture
.setColor(readDatabaseColor(rname
+ ".color",
1776 texture
.setColorTo(readDatabaseColor(rname
+ ".colorTo",
1777 rclass
+ ".ColorTo",
1785 BColor
BScreen::readDatabaseColor(const string
&rname
, const string
&rclass
,
1786 const string
&default_color
) {
1790 if (XrmGetResource(resource
.stylerc
, rname
.c_str(), rclass
.c_str(),
1791 &value_type
, &value
))
1792 color
= BColor(value
.addr
, getBaseDisplay(), getScreenNumber());
1794 color
= BColor(default_color
, getBaseDisplay(), getScreenNumber());
1799 XFontSet
BScreen::readDatabaseFontSet(const string
&rname
,
1800 const string
&rclass
) {
1801 char *defaultFont
= "fixed";
1803 bool load_default
= True
;
1806 XFontSet fontset
= 0;
1807 if (XrmGetResource(resource
.stylerc
, rname
.c_str(), rclass
.c_str(),
1808 &value_type
, &value
) &&
1809 (fontset
= createFontSet(value
.addr
))) {
1810 load_default
= False
;
1814 fontset
= createFontSet(defaultFont
);
1818 i18n(ScreenSet
, ScreenDefaultFontLoadFail
,
1819 "BScreen::setCurrentStyle(): couldn't load default font.\n"));
1828 XFontStruct
*BScreen::readDatabaseFont(const string
&rname
,
1829 const string
&rclass
) {
1830 char *defaultFont
= "fixed";
1832 bool load_default
= False
;
1835 XFontStruct
*font
= 0;
1836 if (XrmGetResource(resource
.stylerc
, rname
.c_str(), rclass
.c_str(),
1837 &value_type
, &value
)) {
1838 if ((font
= XLoadQueryFont(blackbox
->getXDisplay(), value
.addr
)) == NULL
) {
1840 i18n(ScreenSet
, ScreenFontLoadFail
,
1841 "BScreen::setCurrentStyle(): couldn't load font '%s'\n"),
1844 load_default
= True
;
1847 load_default
= True
;
1851 font
= XLoadQueryFont(blackbox
->getXDisplay(), defaultFont
);
1854 i18n(ScreenSet
, ScreenDefaultFontLoadFail
,
1855 "BScreen::setCurrentStyle(): couldn't load default font.\n"));
1864 #ifndef HAVE_STRCASESTR
1865 static const char * strcasestr(const char *str
, const char *ptn
) {
1866 const char *s2
, *p2
;
1867 for(; *str
; str
++) {
1868 for(s2
=str
,p2
=ptn
; ; s2
++,p2
++) {
1869 if (!*p2
) return str
;
1870 if (toupper(*s2
) != toupper(*p2
)) break;
1875 #endif // HAVE_STRCASESTR
1878 static const char *getFontElement(const char *pattern
, char *buf
,
1884 va_start(va
, bufsiz
);
1886 buf
[bufsiz
-2] = '*';
1887 while((v
= va_arg(va
, char *)) != NULL
) {
1888 p
= strcasestr(pattern
, v
);
1890 strncpy(buf
, p
+1, bufsiz
-2);
1891 p2
= strchr(buf
, '-');
1898 strncpy(buf
, "*", bufsiz
);
1903 static const char *getFontSize(const char *pattern
, int *size
) {
1905 const char *p2
=NULL
;
1908 for (p
=pattern
; 1; p
++) {
1910 if (p2
!=NULL
&& n
>1 && n
<72) {
1911 *size
= n
; return p2
+1;
1913 *size
= 16; return NULL
;
1915 } else if (*p
=='-') {
1916 if (n
>1 && n
<72 && p2
!=NULL
) {
1921 } else if (*p
>='0' && *p
<='9' && p2
!=NULL
) {
1931 XFontSet
BScreen::createFontSet(const string
&fontname
) {
1933 char **missing
, *def
= "-";
1934 int nmissing
, pixel_size
= 0, buf_size
= 0;
1935 char weight
[FONT_ELEMENT_SIZE
], slant
[FONT_ELEMENT_SIZE
];
1937 fs
= XCreateFontSet(blackbox
->getXDisplay(),
1938 fontname
.c_str(), &missing
, &nmissing
, &def
);
1939 if (fs
&& (! nmissing
))
1942 const char *nfontname
= fontname
.c_str();
1943 #ifdef HAVE_SETLOCALE
1945 if (nmissing
) XFreeStringList(missing
);
1947 setlocale(LC_CTYPE
, "C");
1948 fs
= XCreateFontSet(blackbox
->getXDisplay(), fontname
.c_str(),
1949 &missing
, &nmissing
, &def
);
1950 setlocale(LC_CTYPE
, "");
1952 #endif // HAVE_SETLOCALE
1955 XFontStruct
**fontstructs
;
1957 XFontsOfFontSet(fs
, &fontstructs
, &fontnames
);
1958 nfontname
= fontnames
[0];
1961 getFontElement(nfontname
, weight
, FONT_ELEMENT_SIZE
,
1962 "-medium-", "-bold-", "-demibold-", "-regular-", NULL
);
1963 getFontElement(nfontname
, slant
, FONT_ELEMENT_SIZE
,
1964 "-r-", "-i-", "-o-", "-ri-", "-ro-", NULL
);
1965 getFontSize(nfontname
, &pixel_size
);
1967 if (! strcmp(weight
, "*"))
1968 strncpy(weight
, "medium", FONT_ELEMENT_SIZE
);
1969 if (! strcmp(slant
, "*"))
1970 strncpy(slant
, "r", FONT_ELEMENT_SIZE
);
1973 else if (pixel_size
> 97)
1976 buf_size
= strlen(nfontname
) + (FONT_ELEMENT_SIZE
* 2) + 64;
1977 char *pattern2
= new char[buf_size
];
1980 "-*-*-%s-%s-*-*-%d-*-*-*-*-*-*-*,"
1981 "-*-*-*-*-*-*-%d-*-*-*-*-*-*-*,*",
1982 nfontname
, weight
, slant
, pixel_size
, pixel_size
);
1983 nfontname
= pattern2
;
1986 XFreeStringList(missing
);
1988 XFreeFontSet(blackbox
->getXDisplay(), fs
);
1990 fs
= XCreateFontSet(blackbox
->getXDisplay(), nfontname
, &missing
,