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
);
210 XSetWindowBackground(blackbox
->getXDisplay(), geom_window
,
211 texture
->color().pixel());
213 XSetWindowBackgroundPixmap(blackbox
->getXDisplay(),
214 geom_window
, geom_pixmap
);
216 workspacemenu
= new Workspacemenu(this);
217 iconmenu
= new Iconmenu(this);
218 configmenu
= new Configmenu(this);
220 Workspace
*wkspc
= (Workspace
*) 0;
221 if (resource
.workspaces
!= 0) {
222 for (unsigned int i
= 0; i
< resource
.workspaces
; ++i
) {
223 wkspc
= new Workspace(this, workspacesList
.size());
224 workspacesList
.push_back(wkspc
);
225 workspacemenu
->insert(wkspc
->getName(), wkspc
->getMenu());
228 wkspc
= new Workspace(this, workspacesList
.size());
229 workspacesList
.push_back(wkspc
);
230 workspacemenu
->insert(wkspc
->getName(), wkspc
->getMenu());
233 workspacemenu
->insert(i18n(IconSet
, IconIcons
, "Icons"), iconmenu
);
234 workspacemenu
->update();
236 current_workspace
= workspacesList
.front();
237 workspacemenu
->setItemSelected(2, True
);
239 toolbar
= new Toolbar(this);
241 slit
= new Slit(this);
248 updateAvailableArea();
250 changeWorkspaceID(0);
252 unsigned int i
, j
, nchild
;
253 Window r
, p
, *children
;
254 XQueryTree(blackbox
->getXDisplay(), getRootWindow(), &r
, &p
,
257 // preen the window list of all icon windows... for better dockapp support
258 for (i
= 0; i
< nchild
; i
++) {
259 if (children
[i
] == None
) continue;
261 XWMHints
*wmhints
= XGetWMHints(blackbox
->getXDisplay(),
265 if ((wmhints
->flags
& IconWindowHint
) &&
266 (wmhints
->icon_window
!= children
[i
])) {
267 for (j
= 0; j
< nchild
; j
++) {
268 if (children
[j
] == wmhints
->icon_window
) {
279 // manage shown windows
280 for (i
= 0; i
< nchild
; ++i
) {
281 if (children
[i
] == None
|| (! blackbox
->validateWindow(children
[i
])))
284 XWindowAttributes attrib
;
285 if (XGetWindowAttributes(blackbox
->getXDisplay(), children
[i
], &attrib
)) {
286 if (attrib
.override_redirect
) continue;
288 if (attrib
.map_state
!= IsUnmapped
) {
289 manageWindow(children
[i
]);
296 // call this again just in case a window we found updates the Strut list
297 updateAvailableArea();
301 BScreen::~BScreen(void) {
302 if (! managed
) return;
304 if (geom_pixmap
!= None
)
305 image_control
->removeImage(geom_pixmap
);
307 if (geom_window
!= None
)
308 XDestroyWindow(blackbox
->getXDisplay(), geom_window
);
310 std::for_each(workspacesList
.begin(), workspacesList
.end(),
313 std::for_each(iconList
.begin(), iconList
.end(), PointerAssassin());
315 std::for_each(netizenList
.begin(), netizenList
.end(), PointerAssassin());
318 delete workspacemenu
;
323 delete image_control
;
325 if (resource
.wstyle
.fontset
)
326 XFreeFontSet(blackbox
->getXDisplay(), resource
.wstyle
.fontset
);
327 if (resource
.mstyle
.t_fontset
)
328 XFreeFontSet(blackbox
->getXDisplay(), resource
.mstyle
.t_fontset
);
329 if (resource
.mstyle
.f_fontset
)
330 XFreeFontSet(blackbox
->getXDisplay(), resource
.mstyle
.f_fontset
);
331 if (resource
.tstyle
.fontset
)
332 XFreeFontSet(blackbox
->getXDisplay(), resource
.tstyle
.fontset
);
334 if (resource
.wstyle
.font
)
335 XFreeFont(blackbox
->getXDisplay(), resource
.wstyle
.font
);
336 if (resource
.mstyle
.t_font
)
337 XFreeFont(blackbox
->getXDisplay(), resource
.mstyle
.t_font
);
338 if (resource
.mstyle
.f_font
)
339 XFreeFont(blackbox
->getXDisplay(), resource
.mstyle
.f_font
);
340 if (resource
.tstyle
.font
)
341 XFreeFont(blackbox
->getXDisplay(), resource
.tstyle
.font
);
343 XFreeGC(blackbox
->getXDisplay(), opGC
);
347 void BScreen::removeWorkspaceNames(void) {
348 workspaceNames
.clear();
352 void BScreen::reconfigure(void) {
356 unsigned long gc_value_mask
= GCForeground
;
357 if (! i18n
.multibyte()) gc_value_mask
|= GCFont
;
359 gcv
.foreground
= WhitePixel(blackbox
->getXDisplay(),
361 gcv
.function
= GXinvert
;
362 gcv
.subwindow_mode
= IncludeInferiors
;
363 XChangeGC(blackbox
->getXDisplay(), opGC
,
364 GCForeground
| GCFunction
| GCSubwindowMode
, &gcv
);
366 const char *s
= i18n(ScreenSet
, ScreenPositionLength
,
367 "0: 0000 x 0: 0000");
370 if (i18n
.multibyte()) {
371 XRectangle ink
, logical
;
372 XmbTextExtents(resource
.wstyle
.fontset
, s
, l
, &ink
, &logical
);
373 geom_w
= logical
.width
;
375 geom_h
= resource
.wstyle
.fontset_extents
->max_ink_extent
.height
;
377 geom_w
= XTextWidth(resource
.wstyle
.font
, s
, l
);
379 geom_h
= resource
.wstyle
.font
->ascent
+ resource
.wstyle
.font
->descent
;
382 geom_w
+= (resource
.bevel_width
* 2);
383 geom_h
+= (resource
.bevel_width
* 2);
385 BTexture
* texture
= &(resource
.wstyle
.l_focus
);
386 geom_pixmap
= texture
->render(geom_w
, geom_h
, geom_pixmap
);
388 XSetWindowBackground(blackbox
->getXDisplay(), geom_window
,
389 texture
->color().pixel());
391 XSetWindowBackgroundPixmap(blackbox
->getXDisplay(),
392 geom_window
, geom_pixmap
);
394 XSetWindowBorderWidth(blackbox
->getXDisplay(), geom_window
,
395 resource
.border_width
);
396 XSetWindowBorder(blackbox
->getXDisplay(), geom_window
,
397 resource
.border_color
.pixel());
399 workspacemenu
->reconfigure();
400 iconmenu
->reconfigure();
402 int remember_sub
= rootmenu
->getCurrentSubmenu();
405 rootmenu
->reconfigure();
406 rootmenu
->drawSubmenu(remember_sub
);
408 configmenu
->reconfigure();
410 toolbar
->reconfigure();
414 std::for_each(workspacesList
.begin(), workspacesList
.end(),
415 std::mem_fun(&Workspace::reconfigure
));
417 BlackboxWindowList::iterator iit
= iconList
.begin();
418 for (; iit
!= iconList
.end(); ++iit
) {
419 BlackboxWindow
*bw
= *iit
;
420 if (bw
->validateClient())
424 image_control
->timeout();
428 void BScreen::rereadMenu(void) {
432 rootmenu
->reconfigure();
436 void BScreen::LoadStyle(void) {
437 resource
.stylerc
= XrmGetFileDatabase(blackbox
->getStyleFilename());
438 if (! resource
.stylerc
)
439 resource
.stylerc
= XrmGetFileDatabase(DEFAULTSTYLE
);
444 // load fonts/fontsets
445 if (resource
.wstyle
.fontset
)
446 XFreeFontSet(blackbox
->getXDisplay(), resource
.wstyle
.fontset
);
447 if (resource
.tstyle
.fontset
)
448 XFreeFontSet(blackbox
->getXDisplay(), resource
.tstyle
.fontset
);
449 if (resource
.mstyle
.f_fontset
)
450 XFreeFontSet(blackbox
->getXDisplay(), resource
.mstyle
.f_fontset
);
451 if (resource
.mstyle
.t_fontset
)
452 XFreeFontSet(blackbox
->getXDisplay(), resource
.mstyle
.t_fontset
);
453 resource
.wstyle
.fontset
= 0;
454 resource
.tstyle
.fontset
= 0;
455 resource
.mstyle
.f_fontset
= 0;
456 resource
.mstyle
.t_fontset
= 0;
457 if (resource
.wstyle
.font
)
458 XFreeFont(blackbox
->getXDisplay(), resource
.wstyle
.font
);
459 if (resource
.tstyle
.font
)
460 XFreeFont(blackbox
->getXDisplay(), resource
.tstyle
.font
);
461 if (resource
.mstyle
.f_font
)
462 XFreeFont(blackbox
->getXDisplay(), resource
.mstyle
.f_font
);
463 if (resource
.mstyle
.t_font
)
464 XFreeFont(blackbox
->getXDisplay(), resource
.mstyle
.t_font
);
465 resource
.wstyle
.font
= 0;
466 resource
.tstyle
.font
= 0;
467 resource
.mstyle
.f_font
= 0;
468 resource
.mstyle
.t_font
= 0;
470 if (i18n
.multibyte()) {
471 resource
.wstyle
.fontset
=
472 readDatabaseFontSet("window.font", "Window.Font");
473 resource
.tstyle
.fontset
=
474 readDatabaseFontSet("toolbar.font", "Toolbar.Font");
475 resource
.mstyle
.t_fontset
=
476 readDatabaseFontSet("menu.title.font", "Menu.Title.Font");
477 resource
.mstyle
.f_fontset
=
478 readDatabaseFontSet("menu.frame.font", "Menu.Frame.Font");
480 resource
.mstyle
.t_fontset_extents
=
481 XExtentsOfFontSet(resource
.mstyle
.t_fontset
);
482 resource
.mstyle
.f_fontset_extents
=
483 XExtentsOfFontSet(resource
.mstyle
.f_fontset
);
484 resource
.tstyle
.fontset_extents
=
485 XExtentsOfFontSet(resource
.tstyle
.fontset
);
486 resource
.wstyle
.fontset_extents
=
487 XExtentsOfFontSet(resource
.wstyle
.fontset
);
489 resource
.wstyle
.font
=
490 readDatabaseFont("window.font", "Window.Font");
491 resource
.tstyle
.font
=
492 readDatabaseFont("toolbar.font", "Toolbar.Font");
493 resource
.mstyle
.t_font
=
494 readDatabaseFont("menu.title.font", "Menu.Title.Font");
495 resource
.mstyle
.f_font
=
496 readDatabaseFont("menu.frame.font", "Menu.Frame.Font");
499 // load window config
500 resource
.wstyle
.t_focus
=
501 readDatabaseTexture("window.title.focus", "Window.Title.Focus", "white");
502 resource
.wstyle
.t_unfocus
=
503 readDatabaseTexture("window.title.unfocus",
504 "Window.Title.Unfocus", "black");
505 resource
.wstyle
.l_focus
=
506 readDatabaseTexture("window.label.focus", "Window.Label.Focus", "white" );
507 resource
.wstyle
.l_unfocus
=
508 readDatabaseTexture("window.label.unfocus", "Window.Label.Unfocus",
510 resource
.wstyle
.h_focus
=
511 readDatabaseTexture("window.handle.focus", "Window.Handle.Focus", "white");
512 resource
.wstyle
.h_unfocus
=
513 readDatabaseTexture("window.handle.unfocus",
514 "Window.Handle.Unfocus", "black");
515 resource
.wstyle
.g_focus
=
516 readDatabaseTexture("window.grip.focus", "Window.Grip.Focus", "white");
517 resource
.wstyle
.g_unfocus
=
518 readDatabaseTexture("window.grip.unfocus", "Window.Grip.Unfocus", "black");
519 resource
.wstyle
.b_focus
=
520 readDatabaseTexture("window.button.focus", "Window.Button.Focus", "white");
521 resource
.wstyle
.b_unfocus
=
522 readDatabaseTexture("window.button.unfocus",
523 "Window.Button.Unfocus", "black");
524 resource
.wstyle
.b_pressed
=
525 readDatabaseTexture("window.button.pressed",
526 "Window.Button.Pressed", "black");
527 resource
.wstyle
.f_focus
=
528 readDatabaseColor("window.frame.focusColor",
529 "Window.Frame.FocusColor", "white");
530 resource
.wstyle
.f_unfocus
=
531 readDatabaseColor("window.frame.unfocusColor",
532 "Window.Frame.UnfocusColor", "black");
533 resource
.wstyle
.l_text_focus
=
534 readDatabaseColor("window.label.focus.textColor",
535 "Window.Label.Focus.TextColor", "black");
536 resource
.wstyle
.l_text_unfocus
=
537 readDatabaseColor("window.label.unfocus.textColor",
538 "Window.Label.Unfocus.TextColor", "white");
539 resource
.wstyle
.b_pic_focus
=
540 readDatabaseColor("window.button.focus.picColor",
541 "Window.Button.Focus.PicColor", "black");
542 resource
.wstyle
.b_pic_unfocus
=
543 readDatabaseColor("window.button.unfocus.picColor",
544 "Window.Button.Unfocus.PicColor", "white");
546 resource
.wstyle
.justify
= LeftJustify
;
547 if (XrmGetResource(resource
.stylerc
, "window.justify", "Window.Justify",
548 &value_type
, &value
)) {
549 if (strstr(value
.addr
, "right") || strstr(value
.addr
, "Right"))
550 resource
.wstyle
.justify
= RightJustify
;
551 else if (strstr(value
.addr
, "center") || strstr(value
.addr
, "Center"))
552 resource
.wstyle
.justify
= CenterJustify
;
555 // load toolbar config
556 resource
.tstyle
.toolbar
=
557 readDatabaseTexture("toolbar", "Toolbar", "black");
558 resource
.tstyle
.label
=
559 readDatabaseTexture("toolbar.label", "Toolbar.Label", "black");
560 resource
.tstyle
.window
=
561 readDatabaseTexture("toolbar.windowLabel", "Toolbar.WindowLabel", "black");
562 resource
.tstyle
.button
=
563 readDatabaseTexture("toolbar.button", "Toolbar.Button", "white");
564 resource
.tstyle
.pressed
=
565 readDatabaseTexture("toolbar.button.pressed",
566 "Toolbar.Button.Pressed", "black");
567 resource
.tstyle
.clock
=
568 readDatabaseTexture("toolbar.clock", "Toolbar.Clock", "black");
569 resource
.tstyle
.l_text
=
570 readDatabaseColor("toolbar.label.textColor",
571 "Toolbar.Label.TextColor", "white");
572 resource
.tstyle
.w_text
=
573 readDatabaseColor("toolbar.windowLabel.textColor",
574 "Toolbar.WindowLabel.TextColor", "white");
575 resource
.tstyle
.c_text
=
576 readDatabaseColor("toolbar.clock.textColor",
577 "Toolbar.Clock.TextColor", "white");
578 resource
.tstyle
.b_pic
=
579 readDatabaseColor("toolbar.button.picColor",
580 "Toolbar.Button.PicColor", "black");
582 resource
.tstyle
.justify
= LeftJustify
;
583 if (XrmGetResource(resource
.stylerc
, "toolbar.justify",
584 "Toolbar.Justify", &value_type
, &value
)) {
585 if (strstr(value
.addr
, "right") || strstr(value
.addr
, "Right"))
586 resource
.tstyle
.justify
= RightJustify
;
587 else if (strstr(value
.addr
, "center") || strstr(value
.addr
, "Center"))
588 resource
.tstyle
.justify
= CenterJustify
;
592 resource
.mstyle
.title
=
593 readDatabaseTexture("menu.title", "Menu.Title", "white");
594 resource
.mstyle
.frame
=
595 readDatabaseTexture("menu.frame", "Menu.Frame", "black");
596 resource
.mstyle
.hilite
=
597 readDatabaseTexture("menu.hilite", "Menu.Hilite", "white");
598 resource
.mstyle
.t_text
=
599 readDatabaseColor("menu.title.textColor", "Menu.Title.TextColor", "black");
600 resource
.mstyle
.f_text
=
601 readDatabaseColor("menu.frame.textColor", "Menu.Frame.TextColor", "white");
602 resource
.mstyle
.d_text
=
603 readDatabaseColor("menu.frame.disableColor",
604 "Menu.Frame.DisableColor", "black");
605 resource
.mstyle
.h_text
=
606 readDatabaseColor("menu.hilite.textColor",
607 "Menu.Hilite.TextColor", "black");
609 resource
.mstyle
.t_justify
= LeftJustify
;
610 if (XrmGetResource(resource
.stylerc
, "menu.title.justify",
611 "Menu.Title.Justify",
612 &value_type
, &value
)) {
613 if (strstr(value
.addr
, "right") || strstr(value
.addr
, "Right"))
614 resource
.mstyle
.t_justify
= RightJustify
;
615 else if (strstr(value
.addr
, "center") || strstr(value
.addr
, "Center"))
616 resource
.mstyle
.t_justify
= CenterJustify
;
619 resource
.mstyle
.f_justify
= LeftJustify
;
620 if (XrmGetResource(resource
.stylerc
, "menu.frame.justify",
621 "Menu.Frame.Justify",
622 &value_type
, &value
)) {
623 if (strstr(value
.addr
, "right") || strstr(value
.addr
, "Right"))
624 resource
.mstyle
.f_justify
= RightJustify
;
625 else if (strstr(value
.addr
, "center") || strstr(value
.addr
, "Center"))
626 resource
.mstyle
.f_justify
= CenterJustify
;
629 resource
.mstyle
.bullet
= Basemenu::Triangle
;
630 if (XrmGetResource(resource
.stylerc
, "menu.bullet", "Menu.Bullet",
631 &value_type
, &value
)) {
632 if (! strncasecmp(value
.addr
, "empty", value
.size
))
633 resource
.mstyle
.bullet
= Basemenu::Empty
;
634 else if (! strncasecmp(value
.addr
, "square", value
.size
))
635 resource
.mstyle
.bullet
= Basemenu::Square
;
636 else if (! strncasecmp(value
.addr
, "diamond", value
.size
))
637 resource
.mstyle
.bullet
= Basemenu::Diamond
;
640 resource
.mstyle
.bullet_pos
= Basemenu::Left
;
641 if (XrmGetResource(resource
.stylerc
, "menu.bullet.position",
642 "Menu.Bullet.Position", &value_type
, &value
)) {
643 if (! strncasecmp(value
.addr
, "right", value
.size
))
644 resource
.mstyle
.bullet_pos
= Basemenu::Right
;
647 resource
.border_color
=
648 readDatabaseColor("borderColor", "BorderColor", "black");
650 unsigned int uint_value
;
652 // load bevel, border and handle widths
653 resource
.handle_width
= 6;
654 if (XrmGetResource(resource
.stylerc
, "handleWidth", "HandleWidth",
655 &value_type
, &value
) &&
656 sscanf(value
.addr
, "%u", &uint_value
) == 1 &&
657 uint_value
<= (getWidth() / 2) && uint_value
!= 0) {
658 resource
.handle_width
= uint_value
;
661 resource
.border_width
= 1;
662 if (XrmGetResource(resource
.stylerc
, "borderWidth", "BorderWidth",
663 &value_type
, &value
) &&
664 sscanf(value
.addr
, "%u", &uint_value
) == 1) {
665 resource
.border_width
= uint_value
;
668 resource
.bevel_width
= 3;
669 if (XrmGetResource(resource
.stylerc
, "bevelWidth", "BevelWidth",
670 &value_type
, &value
) &&
671 sscanf(value
.addr
, "%u", &uint_value
) == 1 &&
672 uint_value
<= (getWidth() / 2) && uint_value
!= 0) {
673 resource
.bevel_width
= uint_value
;
676 resource
.frame_width
= resource
.bevel_width
;
677 if (XrmGetResource(resource
.stylerc
, "frameWidth", "FrameWidth",
678 &value_type
, &value
) &&
679 sscanf(value
.addr
, "%u", &uint_value
) == 1 &&
680 uint_value
<= (getWidth() / 2)) {
681 resource
.frame_width
= uint_value
;
684 if (XrmGetResource(resource
.stylerc
, "rootCommand", "RootCommand",
685 &value_type
, &value
)) {
686 bexec(value
.addr
, displayString());
689 XrmDestroyDatabase(resource
.stylerc
);
693 void BScreen::addIcon(BlackboxWindow
*w
) {
696 w
->setWorkspace(BSENTINEL
);
697 w
->setWindowNumber(iconList
.size());
699 iconList
.push_back(w
);
701 const char* title
= w
->getIconTitle();
702 iconmenu
->insert(title
);
707 void BScreen::removeIcon(BlackboxWindow
*w
) {
712 iconmenu
->remove(w
->getWindowNumber());
715 BlackboxWindowList::iterator it
= iconList
.begin(),
716 end
= iconList
.end();
717 for (int i
= 0; it
!= end
; ++it
)
718 (*it
)->setWindowNumber(i
++);
722 BlackboxWindow
*BScreen::getIcon(unsigned int index
) {
723 if (index
< iconList
.size()) {
724 BlackboxWindowList::iterator it
= iconList
.begin();
725 for (; index
> 0; --index
, ++it
) ; /* increment to index */
729 return (BlackboxWindow
*) 0;
733 unsigned int BScreen::addWorkspace(void) {
734 Workspace
*wkspc
= new Workspace(this, workspacesList
.size());
735 workspacesList
.push_back(wkspc
);
737 workspacemenu
->insert(wkspc
->getName(), wkspc
->getMenu(),
739 workspacemenu
->update();
741 toolbar
->reconfigure();
743 updateNetizenWorkspaceCount();
745 return workspacesList
.size();
749 unsigned int BScreen::removeLastWorkspace(void) {
750 if (workspacesList
.size() == 1)
753 Workspace
*wkspc
= workspacesList
.back();
755 if (current_workspace
->getID() == wkspc
->getID())
756 changeWorkspaceID(current_workspace
->getID() - 1);
760 workspacemenu
->remove(wkspc
->getID() + 2);
761 workspacemenu
->update();
763 workspacesList
.pop_back();
766 toolbar
->reconfigure();
768 updateNetizenWorkspaceCount();
770 return workspacesList
.size();
774 void BScreen::changeWorkspaceID(unsigned int id
) {
775 if (! current_workspace
) return;
777 if (id
!= current_workspace
->getID()) {
778 current_workspace
->hideAll();
780 workspacemenu
->setItemSelected(current_workspace
->getID() + 2, False
);
782 if (blackbox
->getFocusedWindow() &&
783 blackbox
->getFocusedWindow()->getScreen() == this &&
784 (! blackbox
->getFocusedWindow()->isStuck())) {
785 current_workspace
->setLastFocusedWindow(blackbox
->getFocusedWindow());
786 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
789 current_workspace
= getWorkspace(id
);
791 workspacemenu
->setItemSelected(current_workspace
->getID() + 2, True
);
792 toolbar
->redrawWorkspaceLabel(True
);
794 current_workspace
->showAll();
796 if (resource
.focus_last
&& current_workspace
->getLastFocusedWindow()) {
797 XSync(blackbox
->getXDisplay(), False
);
798 current_workspace
->getLastFocusedWindow()->setInputFocus();
802 updateNetizenCurrentWorkspace();
806 void BScreen::manageWindow(Window w
) {
807 new BlackboxWindow(blackbox
, w
, this);
809 BlackboxWindow
*win
= blackbox
->searchWindow(w
);
813 windowList
.push_back(win
);
815 XMapRequestEvent mre
;
817 win
->restoreAttributes();
818 win
->mapRequestEvent(&mre
);
822 void BScreen::unmanageWindow(BlackboxWindow
*w
, bool remap
) {
825 if (w
->getWorkspaceNumber() != BSENTINEL
&&
826 w
->getWindowNumber() != BSENTINEL
)
827 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
828 else if (w
->isIconic())
831 windowList
.remove(w
);
833 if (blackbox
->getFocusedWindow() == w
)
834 blackbox
->setFocusedWindow((BlackboxWindow
*) 0);
836 removeNetizen(w
->getClientWindow());
842 void BScreen::addNetizen(Netizen
*n
) {
843 netizenList
.push_back(n
);
845 n
->sendWorkspaceCount();
846 n
->sendCurrentWorkspace();
848 WorkspaceList::iterator it
= workspacesList
.begin();
849 const WorkspaceList::iterator end
= workspacesList
.end();
850 for (; it
!= end
; ++it
)
851 (*it
)->sendWindowList(*n
);
853 Window f
= ((blackbox
->getFocusedWindow()) ?
854 blackbox
->getFocusedWindow()->getClientWindow() : None
);
855 n
->sendWindowFocus(f
);
859 void BScreen::removeNetizen(Window w
) {
860 NetizenList::iterator it
= netizenList
.begin();
861 for (; it
!= netizenList
.end(); ++it
) {
862 if ((*it
)->getWindowID() == w
) {
864 netizenList
.erase(it
);
871 void BScreen::updateNetizenCurrentWorkspace(void) {
872 std::for_each(netizenList
.begin(), netizenList
.end(),
873 std::mem_fun(&Netizen::sendCurrentWorkspace
));
877 void BScreen::updateNetizenWorkspaceCount(void) {
878 std::for_each(netizenList
.begin(), netizenList
.end(),
879 std::mem_fun(&Netizen::sendWorkspaceCount
));
883 void BScreen::updateNetizenWindowFocus(void) {
884 Window f
= ((blackbox
->getFocusedWindow()) ?
885 blackbox
->getFocusedWindow()->getClientWindow() : None
);
886 NetizenList::iterator it
= netizenList
.begin();
887 for (; it
!= netizenList
.end(); ++it
)
888 (*it
)->sendWindowFocus(f
);
892 void BScreen::updateNetizenWindowAdd(Window w
, unsigned long p
) {
893 NetizenList::iterator it
= netizenList
.begin();
894 for (; it
!= netizenList
.end(); ++it
) {
895 (*it
)->sendWindowAdd(w
, p
);
900 void BScreen::updateNetizenWindowDel(Window w
) {
901 NetizenList::iterator it
= netizenList
.begin();
902 for (; it
!= netizenList
.end(); ++it
)
903 (*it
)->sendWindowDel(w
);
907 void BScreen::updateNetizenWindowRaise(Window w
) {
908 NetizenList::iterator it
= netizenList
.begin();
909 for (; it
!= netizenList
.end(); ++it
)
910 (*it
)->sendWindowRaise(w
);
914 void BScreen::updateNetizenWindowLower(Window w
) {
915 NetizenList::iterator it
= netizenList
.begin();
916 for (; it
!= netizenList
.end(); ++it
)
917 (*it
)->sendWindowLower(w
);
921 void BScreen::updateNetizenConfigNotify(XEvent
*e
) {
922 NetizenList::iterator it
= netizenList
.begin();
923 for (; it
!= netizenList
.end(); ++it
)
924 (*it
)->sendConfigNotify(e
);
928 void BScreen::raiseWindows(Window
*workspace_stack
, unsigned int num
) {
930 Window
*session_stack
= new
931 Window
[(num
+ workspacesList
.size() + rootmenuList
.size() + 13)];
932 unsigned int i
= 0, k
= num
;
934 XRaiseWindow(blackbox
->getXDisplay(), iconmenu
->getWindowID());
935 *(session_stack
+ i
++) = iconmenu
->getWindowID();
937 WorkspaceList::iterator wit
= workspacesList
.begin();
938 const WorkspaceList::iterator w_end
= workspacesList
.end();
939 for (; wit
!= w_end
; ++wit
)
940 *(session_stack
+ i
++) = (*wit
)->getMenu()->getWindowID();
942 *(session_stack
+ i
++) = workspacemenu
->getWindowID();
944 *(session_stack
+ i
++) = configmenu
->getFocusmenu()->getWindowID();
945 *(session_stack
+ i
++) = configmenu
->getPlacementmenu()->getWindowID();
946 *(session_stack
+ i
++) = configmenu
->getWindowID();
948 *(session_stack
+ i
++) = slit
->getMenu()->getDirectionmenu()->getWindowID();
949 *(session_stack
+ i
++) = slit
->getMenu()->getPlacementmenu()->getWindowID();
950 *(session_stack
+ i
++) = slit
->getMenu()->getWindowID();
952 *(session_stack
+ i
++) =
953 toolbar
->getMenu()->getPlacementmenu()->getWindowID();
954 *(session_stack
+ i
++) = toolbar
->getMenu()->getWindowID();
956 RootmenuList::iterator rit
= rootmenuList
.begin();
957 for (; rit
!= rootmenuList
.end(); ++rit
)
958 *(session_stack
+ i
++) = (*rit
)->getWindowID();
959 *(session_stack
+ i
++) = rootmenu
->getWindowID();
961 if (toolbar
->isOnTop())
962 *(session_stack
+ i
++) = toolbar
->getWindowID();
965 *(session_stack
+ i
++) = slit
->getWindowID();
968 *(session_stack
+ i
++) = *(workspace_stack
+ k
);
970 XRestackWindows(blackbox
->getXDisplay(), session_stack
, i
);
972 delete [] session_stack
;
977 void BScreen::saveStrftimeFormat(const string
& format
) {
978 resource
.strftime_format
= format
;
980 #endif // HAVE_STRFTIME
983 void BScreen::addWorkspaceName(const string
& name
) {
984 workspaceNames
.push_back(name
);
989 * I would love to kill this function and the accompanying workspaceNames
990 * list. However, we have a chicken and egg situation. The names are read
991 * in during load_rc() which happens before the workspaces are created.
992 * The current solution is to read the names into a list, then use the list
993 * later for constructing the workspaces. It is only used during initial
996 const string
BScreen::getNameOfWorkspace(unsigned int id
) {
997 if (id
< workspaceNames
.size())
998 return workspaceNames
[id
];
1003 void BScreen::reassociateWindow(BlackboxWindow
*w
, unsigned int wkspc_id
,
1004 bool ignore_sticky
) {
1007 if (wkspc_id
== BSENTINEL
)
1008 wkspc_id
= current_workspace
->getID();
1010 if (w
->getWorkspaceNumber() == wkspc_id
)
1013 if (w
->isIconic()) {
1015 getWorkspace(wkspc_id
)->addWindow(w
);
1016 } else if (ignore_sticky
|| ! w
->isStuck()) {
1017 getWorkspace(w
->getWorkspaceNumber())->removeWindow(w
);
1018 getWorkspace(wkspc_id
)->addWindow(w
);
1023 void BScreen::propagateWindowName(const BlackboxWindow
*bw
) {
1024 if (bw
->isIconic()) {
1025 iconmenu
->changeItemLabel(bw
->getWindowNumber(), bw
->getIconTitle());
1029 Clientmenu
*clientmenu
= getWorkspace(bw
->getWorkspaceNumber())->getMenu();
1030 clientmenu
->changeItemLabel(bw
->getWindowNumber(), bw
->getTitle());
1031 clientmenu
->update();
1033 if (blackbox
->getFocusedWindow() == bw
)
1034 toolbar
->redrawWindowLabel(True
);
1039 void BScreen::nextFocus(void) {
1040 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1044 // if window is not on this screen, ignore it
1045 if (focused
->getScreen()->getScreenNumber() != getScreenNumber())
1046 focused
= (BlackboxWindow
*) 0;
1049 if (focused
&& current_workspace
->getCount() > 1) {
1050 // next is the next window to recieve focus, current is a place holder
1051 BlackboxWindow
*current
;
1054 next
= current_workspace
->getNextWindowInList(current
);
1055 } while(!next
->setInputFocus() && next
!= focused
);
1057 if (next
!= focused
)
1058 current_workspace
->raiseWindow(next
);
1059 } else if (current_workspace
->getCount() >= 1) {
1060 next
= current_workspace
->getTopWindowOnStack();
1062 current_workspace
->raiseWindow(next
);
1063 next
->setInputFocus();
1068 void BScreen::prevFocus(void) {
1069 BlackboxWindow
*focused
= blackbox
->getFocusedWindow(),
1073 // if window is not on this screen, ignore it
1074 if (focused
->getScreen()->getScreenNumber() != getScreenNumber())
1075 focused
= (BlackboxWindow
*) 0;
1078 if (focused
&& current_workspace
->getCount() > 1) {
1079 // next is the next window to recieve focus, current is a place holder
1080 BlackboxWindow
*current
;
1083 next
= current_workspace
->getPrevWindowInList(current
);
1084 } while(!next
->setInputFocus() && next
!= focused
);
1086 if (next
!= focused
)
1087 current_workspace
->raiseWindow(next
);
1088 } else if (current_workspace
->getCount() >= 1) {
1089 next
= current_workspace
->getTopWindowOnStack();
1091 current_workspace
->raiseWindow(next
);
1092 next
->setInputFocus();
1097 void BScreen::raiseFocus(void) {
1098 BlackboxWindow
*focused
= blackbox
->getFocusedWindow();
1102 // if on this Screen, raise it
1103 if (focused
->getScreen()->getScreenNumber() == getScreenNumber()) {
1104 Workspace
*workspace
= getWorkspace(focused
->getWorkspaceNumber());
1105 workspace
->raiseWindow(focused
);
1110 void BScreen::InitMenu(void) {
1112 rootmenuList
.clear();
1114 while (rootmenu
->getCount())
1115 rootmenu
->remove(0);
1117 rootmenu
= new Rootmenu(this);
1119 bool defaultMenu
= True
;
1121 FILE *menu_file
= (FILE *) 0;
1122 const char *menu_filename
= blackbox
->getMenuFilename();
1125 if (!(menu_file
= fopen(menu_filename
, "r")))
1126 perror(menu_filename
);
1127 if (!menu_file
) { // opening the menu file failed, try the default menu
1128 menu_filename
= DEFAULTMENU
;
1129 if (!(menu_file
= fopen(menu_filename
, "r")))
1130 perror(menu_filename
);
1134 if (feof(menu_file
)) {
1135 fprintf(stderr
, i18n(ScreenSet
, ScreenEmptyMenuFile
,
1136 "%s: Empty menu file"),
1139 char line
[1024], label
[1024];
1140 memset(line
, 0, 1024);
1141 memset(label
, 0, 1024);
1143 while (fgets(line
, 1024, menu_file
) && ! feof(menu_file
)) {
1144 if (line
[0] != '#') {
1145 int i
, key
= 0, index
= -1, len
= strlen(line
);
1147 for (i
= 0; i
< len
; i
++) {
1148 if (line
[i
] == '[') index
= 0;
1149 else if (line
[i
] == ']') break;
1150 else if (line
[i
] != ' ')
1152 key
+= tolower(line
[i
]);
1155 if (key
== 517) { // [begin]
1157 for (i
= index
; i
< len
; i
++) {
1158 if (line
[i
] == '(') index
= 0;
1159 else if (line
[i
] == ')') break;
1160 else if (index
++ >= 0) {
1161 if (line
[i
] == '\\' && i
< len
- 1) i
++;
1162 label
[index
- 1] = line
[i
];
1166 if (index
== -1) index
= 0;
1167 label
[index
] = '\0';
1169 rootmenu
->setLabel(label
);
1170 defaultMenu
= parseMenuFile(menu_file
, rootmenu
);
1172 blackbox
->addMenuTimestamp(menu_filename
);
1182 rootmenu
->setInternalMenu();
1183 rootmenu
->insert(i18n(ScreenSet
, Screenxterm
, "xterm"),
1185 i18n(ScreenSet
, Screenxterm
, "xterm"));
1186 rootmenu
->insert(i18n(ScreenSet
, ScreenRestart
, "Restart"),
1188 rootmenu
->insert(i18n(ScreenSet
, ScreenExit
, "Exit"),
1190 rootmenu
->setLabel(i18n(BasemenuSet
, BasemenuBlackboxMenu
,
1196 bool BScreen::parseMenuFile(FILE *file
, Rootmenu
*menu
) {
1197 char line
[1024], label
[1024], command
[1024];
1199 while (! feof(file
)) {
1200 memset(line
, 0, 1024);
1201 memset(label
, 0, 1024);
1202 memset(command
, 0, 1024);
1204 if (fgets(line
, 1024, file
)) {
1205 if (line
[0] != '#') {
1206 int i
, key
= 0, parse
= 0, index
= -1, line_length
= strlen(line
);
1208 // determine the keyword
1209 for (i
= 0; i
< line_length
; i
++) {
1210 if (line
[i
] == '[') parse
= 1;
1211 else if (line
[i
] == ']') break;
1212 else if (line
[i
] != ' ')
1214 key
+= tolower(line
[i
]);
1217 // get the label enclosed in ()'s
1220 for (i
= 0; i
< line_length
; i
++) {
1221 if (line
[i
] == '(') {
1224 } else if (line
[i
] == ')') break;
1225 else if (index
++ >= 0) {
1226 if (line
[i
] == '\\' && i
< line_length
- 1) i
++;
1227 label
[index
- 1] = line
[i
];
1232 label
[index
] = '\0';
1237 // get the command enclosed in {}'s
1240 for (i
= 0; i
< line_length
; i
++) {
1241 if (line
[i
] == '{') {
1244 } else if (line
[i
] == '}') break;
1245 else if (index
++ >= 0) {
1246 if (line
[i
] == '\\' && i
< line_length
- 1) i
++;
1247 command
[index
- 1] = line
[i
];
1252 command
[index
] = '\0';
1259 return ((menu
->getCount() == 0) ? True
: False
);
1266 menu
->insert(label
);
1271 if ((! *label
) && (! *command
)) {
1272 fprintf(stderr
, i18n(ScreenSet
, ScreenEXECError
,
1273 "BScreen::parseMenuFile: [exec] error, "
1274 "no menu label and/or command defined\n"));
1278 menu
->insert(label
, BScreen::Execute
, command
);
1284 fprintf(stderr
, i18n(ScreenSet
, ScreenEXITError
,
1285 "BScreen::parseMenuFile: [exit] error, "
1286 "no menu label defined\n"));
1290 menu
->insert(label
, BScreen::Exit
);
1296 if ((! *label
) || (! *command
)) {
1298 i18n(ScreenSet
, ScreenSTYLEError
,
1299 "BScreen::parseMenuFile: [style] error, "
1300 "no menu label and/or filename defined\n"));
1304 string style
= expandTilde(command
);
1306 menu
->insert(label
, BScreen::SetStyle
, style
.c_str());
1313 fprintf(stderr
, i18n(ScreenSet
, ScreenCONFIGError
,
1314 "BScreen::parseMenufile: [config] error, "
1315 "no label defined"));
1319 menu
->insert(label
, configmenu
);
1323 case 740: // include
1326 fprintf(stderr
, i18n(ScreenSet
, ScreenINCLUDEError
,
1327 "BScreen::parseMenuFile: [include] error, "
1328 "no filename defined\n"));
1332 string newfile
= expandTilde(label
);
1333 FILE *submenufile
= fopen(newfile
.c_str(), "r");
1337 if (fstat(fileno(submenufile
), &buf
) ||
1338 (! S_ISREG(buf
.st_mode
))) {
1340 i18n(ScreenSet
, ScreenINCLUDEErrorReg
,
1341 "BScreen::parseMenuFile: [include] error: "
1342 "'%s' is not a regular file\n"), newfile
.c_str());
1346 if (! feof(submenufile
)) {
1347 if (! parseMenuFile(submenufile
, menu
))
1348 blackbox
->addMenuTimestamp(newfile
);
1350 fclose(submenufile
);
1353 perror(newfile
.c_str());
1359 case 767: // submenu
1362 fprintf(stderr
, i18n(ScreenSet
, ScreenSUBMENUError
,
1363 "BScreen::parseMenuFile: [submenu] error, "
1364 "no menu label defined\n"));
1368 Rootmenu
*submenu
= new Rootmenu(this);
1371 submenu
->setLabel(command
);
1373 submenu
->setLabel(label
);
1375 parseMenuFile(file
, submenu
);
1377 menu
->insert(label
, submenu
);
1378 rootmenuList
.push_back(submenu
);
1383 case 773: // restart
1386 fprintf(stderr
, i18n(ScreenSet
, ScreenRESTARTError
,
1387 "BScreen::parseMenuFile: [restart] error, "
1388 "no menu label defined\n"));
1393 menu
->insert(label
, BScreen::RestartOther
, command
);
1395 menu
->insert(label
, BScreen::Restart
);
1400 case 845: // reconfig
1404 i18n(ScreenSet
, ScreenRECONFIGError
,
1405 "BScreen::parseMenuFile: [reconfig] error, "
1406 "no menu label defined\n"));
1410 menu
->insert(label
, BScreen::Reconfigure
);
1415 case 995: // stylesdir
1416 case 1113: // stylesmenu
1418 bool newmenu
= ((key
== 1113) ? True
: False
);
1420 if ((! *label
) || ((! *command
) && newmenu
)) {
1422 i18n(ScreenSet
, ScreenSTYLESDIRError
,
1423 "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
1424 " error, no directory defined\n"));
1428 char *directory
= ((newmenu
) ? command
: label
);
1430 string stylesdir
= expandTilde(directory
);
1432 struct stat statbuf
;
1434 if (! stat(stylesdir
.c_str(), &statbuf
)) {
1435 if (S_ISDIR(statbuf
.st_mode
)) {
1436 Rootmenu
*stylesmenu
;
1439 stylesmenu
= new Rootmenu(this);
1443 DIR *d
= opendir(stylesdir
.c_str());
1445 std::vector
<string
> ls
;
1447 while((p
= readdir(d
)))
1448 ls
.push_back(p
->d_name
);
1452 std::sort(ls
.begin(), ls
.end());
1454 std::vector
<string
>::iterator it
= ls
.begin(),
1456 for (; it
!= end
; ++it
) {
1457 const string
& fname
= *it
;
1459 if (fname
[fname
.size()-1] == '~')
1462 string style
= stylesdir
;
1466 if ((! stat(style
.c_str(), &statbuf
)) &&
1467 S_ISREG(statbuf
.st_mode
))
1468 stylesmenu
->insert(fname
, BScreen::SetStyle
, style
);
1471 stylesmenu
->update();
1474 stylesmenu
->setLabel(label
);
1475 menu
->insert(label
, stylesmenu
);
1476 rootmenuList
.push_back(stylesmenu
);
1479 blackbox
->addMenuTimestamp(stylesdir
);
1482 i18n(ScreenSet
, ScreenSTYLESDIRErrorNotDir
,
1483 "BScreen::parseMenuFile:"
1484 " [stylesdir/stylesmenu] error, %s is not a"
1485 " directory\n"), stylesdir
.c_str());
1489 i18n(ScreenSet
, ScreenSTYLESDIRErrorNoExist
,
1490 "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
1491 " error, %s does not exist\n"), stylesdir
.c_str());
1496 case 1090: // workspaces
1500 i18n(ScreenSet
, ScreenWORKSPACESError
,
1501 "BScreen:parseMenuFile: [workspaces] error, "
1502 "no menu label defined\n"));
1506 menu
->insert(label
, workspacemenu
);
1515 return ((menu
->getCount() == 0) ? True
: False
);
1519 void BScreen::shutdown(void) {
1520 XSelectInput(blackbox
->getXDisplay(), getRootWindow(), NoEventMask
);
1521 XSync(blackbox
->getXDisplay(), False
);
1523 while(! windowList
.empty())
1524 unmanageWindow(windowList
.front(), True
);
1530 void BScreen::showPosition(int x
, int y
) {
1531 if (! geom_visible
) {
1532 XMoveResizeWindow(blackbox
->getXDisplay(), geom_window
,
1533 (getWidth() - geom_w
) / 2,
1534 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
1535 XMapWindow(blackbox
->getXDisplay(), geom_window
);
1536 XRaiseWindow(blackbox
->getXDisplay(), geom_window
);
1538 geom_visible
= True
;
1543 sprintf(label
, i18n(ScreenSet
, ScreenPositionFormat
,
1544 "X: %4d x Y: %4d"), x
, y
);
1546 XClearWindow(blackbox
->getXDisplay(), geom_window
);
1548 BPen
pen(resource
.wstyle
.l_text_focus
, resource
.wstyle
.font
);
1549 if (i18n
.multibyte()) {
1550 XmbDrawString(blackbox
->getXDisplay(), geom_window
,
1551 resource
.wstyle
.fontset
, pen
.gc(),
1552 resource
.bevel_width
, resource
.bevel_width
-
1553 resource
.wstyle
.fontset_extents
->max_ink_extent
.y
,
1554 label
, strlen(label
));
1556 XDrawString(blackbox
->getXDisplay(), geom_window
,
1557 pen
.gc(), resource
.bevel_width
,
1558 resource
.wstyle
.font
->ascent
+ resource
.bevel_width
,
1559 label
, strlen(label
));
1564 void BScreen::showGeometry(unsigned int gx
, unsigned int gy
) {
1565 if (! geom_visible
) {
1566 XMoveResizeWindow(blackbox
->getXDisplay(), geom_window
,
1567 (getWidth() - geom_w
) / 2,
1568 (getHeight() - geom_h
) / 2, geom_w
, geom_h
);
1569 XMapWindow(blackbox
->getXDisplay(), geom_window
);
1570 XRaiseWindow(blackbox
->getXDisplay(), geom_window
);
1572 geom_visible
= True
;
1577 sprintf(label
, i18n(ScreenSet
, ScreenGeometryFormat
,
1578 "W: %4d x H: %4d"), gx
, gy
);
1580 XClearWindow(blackbox
->getXDisplay(), geom_window
);
1582 BPen
pen(resource
.wstyle
.l_text_focus
, resource
.wstyle
.font
);
1583 if (i18n
.multibyte()) {
1584 XmbDrawString(blackbox
->getXDisplay(), geom_window
,
1585 resource
.wstyle
.fontset
, pen
.gc(),
1586 resource
.bevel_width
, resource
.bevel_width
-
1587 resource
.wstyle
.fontset_extents
->max_ink_extent
.y
,
1588 label
, strlen(label
));
1590 XDrawString(blackbox
->getXDisplay(), geom_window
,
1591 pen
.gc(), resource
.bevel_width
,
1592 resource
.wstyle
.font
->ascent
+
1593 resource
.bevel_width
, label
, strlen(label
));
1598 void BScreen::hideGeometry(void) {
1600 XUnmapWindow(blackbox
->getXDisplay(), geom_window
);
1601 geom_visible
= False
;
1606 void BScreen::addStrut(Strut
*strut
) {
1607 strutList
.push_back(strut
);
1611 void BScreen::removeStrut(Strut
*strut
) {
1612 strutList
.remove(strut
);
1616 const Rect
& BScreen::availableArea(void) const {
1618 return getRect(); // return the full screen
1623 void BScreen::updateAvailableArea(void) {
1624 Rect old_area
= usableArea
;
1625 usableArea
= getRect(); // reset to full screen
1627 /* these values represent offsets from the screen edge
1628 * we look for the biggest offset on each edge and then apply them
1630 * do not be confused by the similarity to the names of Rect's members
1632 unsigned int current_left
= 0, current_right
= 0, current_top
= 0,
1635 StrutList::const_iterator it
= strutList
.begin(), end
= strutList
.end();
1637 for(; it
!= end
; ++it
) {
1639 if (strut
->left
> current_left
)
1640 current_left
= strut
->left
;
1641 if (strut
->top
> current_top
)
1642 current_top
= strut
->top
;
1643 if (strut
->right
> current_right
)
1644 current_right
= strut
->right
;
1645 if (strut
->bottom
> current_bottom
)
1646 current_bottom
= strut
->bottom
;
1649 usableArea
.setPos(current_left
, current_top
);
1650 usableArea
.setSize(usableArea
.width() - (current_left
+ current_right
),
1651 usableArea
.height() - (current_top
+ current_bottom
));
1653 if (old_area
!= usableArea
) {
1654 BlackboxWindowList::iterator it
= windowList
.begin(),
1655 end
= windowList
.end();
1656 for (; it
!= end
; ++it
)
1657 if ((*it
)->isMaximized()) (*it
)->remaximize();
1662 Workspace
* BScreen::getWorkspace(unsigned int index
) {
1663 assert(index
< workspacesList
.size());
1664 return workspacesList
[index
];
1668 void BScreen::buttonPressEvent(XButtonEvent
*xbutton
) {
1669 if (xbutton
->button
== 1) {
1670 if (! isRootColormapInstalled())
1671 image_control
->installRootColormap();
1673 if (workspacemenu
->isVisible())
1674 workspacemenu
->hide();
1676 if (rootmenu
->isVisible())
1678 } else if (xbutton
->button
== 2) {
1679 int mx
= xbutton
->x_root
- (workspacemenu
->getWidth() / 2);
1680 int my
= xbutton
->y_root
- (workspacemenu
->getTitleHeight() / 2);
1685 if (mx
+ workspacemenu
->getWidth() > getWidth())
1686 mx
= getWidth() - workspacemenu
->getWidth() - getBorderWidth();
1688 if (my
+ workspacemenu
->getHeight() > getHeight())
1689 my
= getHeight() - workspacemenu
->getHeight() - getBorderWidth();
1691 workspacemenu
->move(mx
, my
);
1693 if (! workspacemenu
->isVisible()) {
1694 workspacemenu
->removeParent();
1695 workspacemenu
->show();
1697 } else if (xbutton
->button
== 3) {
1698 int mx
= xbutton
->x_root
- (rootmenu
->getWidth() / 2);
1699 int my
= xbutton
->y_root
- (rootmenu
->getTitleHeight() / 2);
1704 if (mx
+ rootmenu
->getWidth() > getWidth())
1705 mx
= getWidth() - rootmenu
->getWidth() - getBorderWidth();
1707 if (my
+ rootmenu
->getHeight() > getHeight())
1708 my
= getHeight() - rootmenu
->getHeight() - getBorderWidth();
1710 rootmenu
->move(mx
, my
);
1712 if (! rootmenu
->isVisible()) {
1713 blackbox
->checkMenu();
1720 void BScreen::toggleFocusModel(FocusModel model
) {
1721 if (model
== SloppyFocus
) {
1722 saveSloppyFocus(True
);
1724 saveSloppyFocus(False
);
1725 saveAutoRaise(False
);
1726 saveClickRaise(False
);
1733 void BScreen::updateFocusModel()
1735 std::for_each(workspacesList
.begin(), workspacesList
.end(),
1736 std::mem_fun(&Workspace::updateFocusModel
));
1740 BTexture
BScreen::readDatabaseTexture(const string
&rname
,
1741 const string
&rclass
,
1742 const string
&default_color
) {
1747 if (XrmGetResource(resource
.stylerc
, rname
.c_str(), rclass
.c_str(),
1748 &value_type
, &value
))
1749 texture
= BTexture(value
.addr
);
1751 texture
.setTexture(BTexture::Solid
| BTexture::Flat
);
1753 // associate this texture with this screen
1754 texture
.setDisplay(getBaseDisplay(), getScreenNumber());
1755 texture
.setImageControl(image_control
);
1757 if (texture
.texture() & BTexture::Solid
) {
1758 texture
.setColor(readDatabaseColor(rname
+ ".color",
1761 texture
.setColorTo(readDatabaseColor(rname
+ ".colorTo",
1762 rclass
+ ".ColorTo",
1764 } else if (texture
.texture() & BTexture::Gradient
) {
1765 texture
.setColor(readDatabaseColor(rname
+ ".color",
1768 texture
.setColorTo(readDatabaseColor(rname
+ ".colorTo",
1769 rclass
+ ".ColorTo",
1777 BColor
BScreen::readDatabaseColor(const string
&rname
, const string
&rclass
,
1778 const string
&default_color
) {
1782 if (XrmGetResource(resource
.stylerc
, rname
.c_str(), rclass
.c_str(),
1783 &value_type
, &value
))
1784 color
= BColor(value
.addr
, getBaseDisplay(), getScreenNumber());
1786 color
= BColor(default_color
, getBaseDisplay(), getScreenNumber());
1791 XFontSet
BScreen::readDatabaseFontSet(const string
&rname
,
1792 const string
&rclass
) {
1793 char *defaultFont
= "fixed";
1795 bool load_default
= True
;
1798 XFontSet fontset
= 0;
1799 if (XrmGetResource(resource
.stylerc
, rname
.c_str(), rclass
.c_str(),
1800 &value_type
, &value
) &&
1801 (fontset
= createFontSet(value
.addr
))) {
1802 load_default
= False
;
1806 fontset
= createFontSet(defaultFont
);
1810 i18n(ScreenSet
, ScreenDefaultFontLoadFail
,
1811 "BScreen::setCurrentStyle(): couldn't load default font.\n"));
1820 XFontStruct
*BScreen::readDatabaseFont(const string
&rname
,
1821 const string
&rclass
) {
1822 char *defaultFont
= "fixed";
1824 bool load_default
= False
;
1827 XFontStruct
*font
= 0;
1828 if (XrmGetResource(resource
.stylerc
, rname
.c_str(), rclass
.c_str(),
1829 &value_type
, &value
)) {
1830 if ((font
= XLoadQueryFont(blackbox
->getXDisplay(), value
.addr
)) == NULL
) {
1832 i18n(ScreenSet
, ScreenFontLoadFail
,
1833 "BScreen::setCurrentStyle(): couldn't load font '%s'\n"),
1836 load_default
= True
;
1839 load_default
= True
;
1843 font
= XLoadQueryFont(blackbox
->getXDisplay(), defaultFont
);
1846 i18n(ScreenSet
, ScreenDefaultFontLoadFail
,
1847 "BScreen::setCurrentStyle(): couldn't load default font.\n"));
1856 #ifndef HAVE_STRCASESTR
1857 static const char * strcasestr(const char *str
, const char *ptn
) {
1858 const char *s2
, *p2
;
1859 for(; *str
; str
++) {
1860 for(s2
=str
,p2
=ptn
; ; s2
++,p2
++) {
1861 if (!*p2
) return str
;
1862 if (toupper(*s2
) != toupper(*p2
)) break;
1867 #endif // HAVE_STRCASESTR
1870 static const char *getFontElement(const char *pattern
, char *buf
,
1876 va_start(va
, bufsiz
);
1878 buf
[bufsiz
-2] = '*';
1879 while((v
= va_arg(va
, char *)) != NULL
) {
1880 p
= strcasestr(pattern
, v
);
1882 strncpy(buf
, p
+1, bufsiz
-2);
1883 p2
= strchr(buf
, '-');
1890 strncpy(buf
, "*", bufsiz
);
1895 static const char *getFontSize(const char *pattern
, int *size
) {
1897 const char *p2
=NULL
;
1900 for (p
=pattern
; 1; p
++) {
1902 if (p2
!=NULL
&& n
>1 && n
<72) {
1903 *size
= n
; return p2
+1;
1905 *size
= 16; return NULL
;
1907 } else if (*p
=='-') {
1908 if (n
>1 && n
<72 && p2
!=NULL
) {
1913 } else if (*p
>='0' && *p
<='9' && p2
!=NULL
) {
1923 XFontSet
BScreen::createFontSet(const string
&fontname
) {
1925 char **missing
, *def
= "-";
1926 int nmissing
, pixel_size
= 0, buf_size
= 0;
1927 char weight
[FONT_ELEMENT_SIZE
], slant
[FONT_ELEMENT_SIZE
];
1929 fs
= XCreateFontSet(blackbox
->getXDisplay(),
1930 fontname
.c_str(), &missing
, &nmissing
, &def
);
1931 if (fs
&& (! nmissing
))
1934 const char *nfontname
= fontname
.c_str();
1935 #ifdef HAVE_SETLOCALE
1937 if (nmissing
) XFreeStringList(missing
);
1939 setlocale(LC_CTYPE
, "C");
1940 fs
= XCreateFontSet(blackbox
->getXDisplay(), fontname
.c_str(),
1941 &missing
, &nmissing
, &def
);
1942 setlocale(LC_CTYPE
, "");
1944 #endif // HAVE_SETLOCALE
1947 XFontStruct
**fontstructs
;
1949 XFontsOfFontSet(fs
, &fontstructs
, &fontnames
);
1950 nfontname
= fontnames
[0];
1953 getFontElement(nfontname
, weight
, FONT_ELEMENT_SIZE
,
1954 "-medium-", "-bold-", "-demibold-", "-regular-", NULL
);
1955 getFontElement(nfontname
, slant
, FONT_ELEMENT_SIZE
,
1956 "-r-", "-i-", "-o-", "-ri-", "-ro-", NULL
);
1957 getFontSize(nfontname
, &pixel_size
);
1959 if (! strcmp(weight
, "*"))
1960 strncpy(weight
, "medium", FONT_ELEMENT_SIZE
);
1961 if (! strcmp(slant
, "*"))
1962 strncpy(slant
, "r", FONT_ELEMENT_SIZE
);
1965 else if (pixel_size
> 97)
1968 buf_size
= strlen(nfontname
) + (FONT_ELEMENT_SIZE
* 2) + 64;
1969 char *pattern2
= new char[buf_size
];
1972 "-*-*-%s-%s-*-*-%d-*-*-*-*-*-*-*,"
1973 "-*-*-*-*-*-*-%d-*-*-*-*-*-*-*,*",
1974 nfontname
, weight
, slant
, pixel_size
, pixel_size
);
1975 nfontname
= pattern2
;
1978 XFreeStringList(missing
);
1980 XFreeFontSet(blackbox
->getXDisplay(), fs
);
1982 fs
= XCreateFontSet(blackbox
->getXDisplay(), nfontname
, &missing
,