1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // Screen.cc for Blackbox - an X11 Window manager
3 // Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
4 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
6 // Permission is hereby granted, free of charge, to any person obtaining a
7 // copy of this software and associated documentation files (the "Software"),
8 // to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 // and/or sell copies of the Software, and to permit persons to whom the
11 // Software is furnished to do so, subject to the following conditions:
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 // DEALINGS IN THE SOFTWARE.
25 #include "../config.h"
26 #endif // HAVE_CONFIG_H
29 #include <X11/Xatom.h>
30 #include <X11/keysym.h>
33 # include <X11/Xlib.h>
34 # include <X11/extensions/Xinerama.h>
39 #endif // HAVE_STDLIB_H
43 #endif // HAVE_STRING_H
47 #endif // HAVE_CTYPE_H
50 # include <sys/types.h>
52 #endif // HAVE_UNISTD_H
56 #endif // HAVE_DIRENT_H
60 #endif // HAVE_LOCALE_H
62 #ifdef HAVE_SYS_STAT_H
63 # include <sys/stat.h>
64 #endif // HAVE_SYS_STAT_H
68 #endif // HAVE_STDARG_H
79 #include "blackbox.hh"
80 #include "Clientmenu.hh"
83 #include "Iconmenu.hh"
87 #include "Rootmenu.hh"
91 #include "Workspace.hh"
92 #include "Workspacemenu.hh"
96 #ifndef FONT_ELEMENT_SIZE
97 #define FONT_ELEMENT_SIZE 50
98 #endif // FONT_ELEMENT_SIZE
101 static bool running = True;
103 static int anotherWMRunning(Display *display, XErrorEvent *) {
104 fprintf(stderr, i18n(ScreenSet, ScreenAnotherWMRunning,
105 "BScreen::BScreen: an error occured while querying the X server.\n"
106 " another window manager already running on display %s.\n"),
107 DisplayString(display));
115 BScreen::BScreen(Blackbox *bb, unsigned int scrn) : ScreenInfo(bb, scrn) {
117 screenstr = "session.screen" + itostring(scrn) + '.';
118 config = blackbox->getConfig();
119 xatom = blackbox->getXAtom();
121 event_mask = ColormapChangeMask | EnterWindowMask | PropertyChangeMask |
122 SubstructureRedirectMask | ButtonPressMask | ButtonReleaseMask;
124 XErrorHandler old = XSetErrorHandler((XErrorHandler) anotherWMRunning);
125 XSelectInput(getBaseDisplay()->getXDisplay(), getRootWindow(), event_mask);
126 XSync(getBaseDisplay()->getXDisplay(), False);
127 XSetErrorHandler((XErrorHandler) old);
130 if (! managed) return;
132 fprintf(stderr, i18n(ScreenSet, ScreenManagingScreen,
133 "BScreen::BScreen: managing screen %d "
134 "using visual 0x%lx, depth %d\n"),
135 getScreenNumber(), XVisualIDFromVisual(getVisual()),
140 resource.mstyle.t_font = resource.mstyle.f_font = resource.tstyle.font =
141 resource.wstyle.font = (BFont *) 0;
145 xatom->setSupported(this); // set-up netwm support
147 xatom->setValue(getRootWindow(), XAtom::blackbox_pid, XAtom::cardinal,
148 (unsigned long) getpid());
149 #endif // HAVE_GETPID
150 unsigned long geometry[] = { getWidth(),
152 xatom->setValue(getRootWindow(), XAtom::net_desktop_geometry,
153 XAtom::cardinal, geometry, 2);
154 unsigned long viewport[] = {0,0};
155 xatom->setValue(getRootWindow(), XAtom::net_desktop_viewport,
156 XAtom::cardinal, viewport, 2);
159 XDefineCursor(blackbox->getXDisplay(), getRootWindow(),
160 blackbox->getSessionCursor());
162 updateAvailableArea();
165 new BImageControl(blackbox, this, True, blackbox->getColorsPerChannel(),
166 blackbox->getCacheLife(), blackbox->getCacheMax());
167 image_control->installRootColormap();
168 root_colormap_installed = True;
174 gcv.foreground = WhitePixel(blackbox->getXDisplay(), getScreenNumber())
175 ^ BlackPixel(blackbox->getXDisplay(), getScreenNumber());
176 gcv.function = GXxor;
177 gcv.subwindow_mode = IncludeInferiors;
178 opGC = XCreateGC(blackbox->getXDisplay(), getRootWindow(),
179 GCForeground | GCFunction | GCSubwindowMode, &gcv);
181 const char *s = i18n(ScreenSet, ScreenPositionLength,
182 "0: 0000 x 0: 0000");
183 geom_w = resource.wstyle.font->measureString(s) + resource.bevel_width * 2;
184 geom_h = resource.wstyle.font->height() + resource.bevel_width * 2;
186 XSetWindowAttributes attrib;
187 unsigned long mask = CWBorderPixel | CWColormap | CWSaveUnder;
188 attrib.border_pixel = getBorderColor()->pixel();
189 attrib.colormap = getColormap();
190 attrib.save_under = True;
192 geom_window = XCreateWindow(blackbox->getXDisplay(), getRootWindow(),
193 0, 0, geom_w, geom_h, resource.border_width,
194 getDepth(), InputOutput, getVisual(),
196 geom_visible = False;
198 BTexture* texture = &(resource.wstyle.l_focus);
199 geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap);
200 if (geom_pixmap == ParentRelative) {
201 texture = &(resource.wstyle.t_focus);
202 geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap);
205 XSetWindowBackground(blackbox->getXDisplay(), geom_window,
206 texture->color().pixel());
208 XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
209 geom_window, geom_pixmap);
211 workspacemenu = new Workspacemenu(this);
212 iconmenu = new Iconmenu(this);
213 configmenu = new Configmenu(this);
215 if (resource.workspaces > 0) {
216 for (unsigned int i = 0; i < resource.workspaces; ++i) {
217 Workspace *wkspc = new Workspace(this, workspacesList.size());
218 workspacesList.push_back(wkspc);
219 workspacemenu->insertWorkspace(wkspc);
220 workspacemenu->update();
224 Workspace *wkspc = new Workspace(this, workspacesList.size());
225 workspacesList.push_back(wkspc);
226 workspacemenu->insertWorkspace(wkspc);
227 workspacemenu->update();
229 saveWorkspaceNames();
231 updateNetizenWorkspaceCount();
233 workspacemenu->insert(i18n(IconSet, IconIcons, "Icons"), iconmenu);
234 workspacemenu->update();
236 current_workspace = workspacesList.front();
238 xatom->setValue(getRootWindow(), XAtom::net_current_desktop,
239 XAtom::cardinal, 0); //first workspace
241 workspacemenu->setItemSelected(2, True);
243 toolbar = new Toolbar(this);
245 slit = new Slit(this);
249 raiseWindows(0, 0); // this also initializes the empty stacking list
252 updateClientList(); // initialize the client lists, which will be empty
253 updateAvailableArea();
255 changeWorkspaceID(0);
257 unsigned int i, j, nchild;
258 Window r, p, *children;
259 XQueryTree(blackbox->getXDisplay(), getRootWindow(), &r, &p,
262 // preen the window list of all icon windows... for better dockapp support
263 for (i = 0; i < nchild; i++) {
264 if (children[i] == None) continue;
266 XWMHints *wmhints = XGetWMHints(blackbox->getXDisplay(),
270 if ((wmhints->flags & IconWindowHint) &&
271 (wmhints->icon_window != children[i])) {
272 for (j = 0; j < nchild; j++) {
273 if (children[j] == wmhints->icon_window) {
284 // manage shown windows
285 for (i = 0; i < nchild; ++i) {
286 if (children[i] == None || ! blackbox->validateWindow(children[i]))
289 XWindowAttributes attrib;
290 if (XGetWindowAttributes(blackbox->getXDisplay(), children[i], &attrib)) {
291 if (attrib.override_redirect) continue;
293 if (attrib.map_state != IsUnmapped) {
294 manageWindow(children[i]);
301 // call this again just in case a window we found updates the Strut list
302 updateAvailableArea();
306 BScreen::~BScreen(void) {
307 if (! managed) return;
309 if (geom_pixmap != None)
310 image_control->removeImage(geom_pixmap);
312 if (geom_window != None)
313 XDestroyWindow(blackbox->getXDisplay(), geom_window);
315 std::for_each(workspacesList.begin(), workspacesList.end(),
318 std::for_each(iconList.begin(), iconList.end(), PointerAssassin());
320 std::for_each(netizenList.begin(), netizenList.end(), PointerAssassin());
322 while (! systrayWindowList.empty())
323 removeSystrayWindow(systrayWindowList[0]);
326 delete workspacemenu;
331 delete image_control;
333 if (resource.wstyle.font)
334 delete resource.wstyle.font;
335 if (resource.mstyle.t_font)
336 delete resource.mstyle.t_font;
337 if (resource.mstyle.f_font)
338 delete resource.mstyle.f_font;
339 if (resource.tstyle.font)
340 delete resource.tstyle.font;
343 if (resource.wstyle.close_button.mask != None)
344 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.close_button.mask);
345 if (resource.wstyle.max_button.mask != None)
346 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.max_button.mask);
347 if (resource.wstyle.icon_button.mask != None)
348 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.icon_button.mask);
349 if (resource.wstyle.stick_button.mask != None)
350 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.stick_button.mask);
352 if (resource.tstyle.left_button.mask != None)
353 XFreePixmap(blackbox->getXDisplay(), resource.tstyle.left_button.mask);
354 if (resource.tstyle.right_button.mask != None)
355 XFreePixmap(blackbox->getXDisplay(), resource.tstyle.right_button.mask);
357 if (resource.mstyle.bullet_image.mask != None)
358 XFreePixmap(blackbox->getXDisplay(), resource.mstyle.bullet_image.mask);
359 if (resource.mstyle.tick_image.mask != None)
360 XFreePixmap(blackbox->getXDisplay(), resource.mstyle.tick_image.mask);
362 resource.wstyle.max_button.mask = resource.wstyle.close_button.mask =
363 resource.wstyle.icon_button.mask =
364 resource.wstyle.stick_button.mask = None;
365 resource.tstyle.left_button.mask = resource.tstyle.right_button.mask = None;
366 resource.mstyle.bullet_image.mask = resource.mstyle.tick_image.mask = None;
367 #endif // BITMAPBUTTONS
369 XFreeGC(blackbox->getXDisplay(), opGC);
373 void BScreen::saveSloppyFocus(bool s) {
374 resource.sloppy_focus = s;
377 if (resource.sloppy_focus) {
378 fmodel = "SloppyFocus";
379 if (resource.auto_raise) fmodel += " AutoRaise";
380 if (resource.click_raise) fmodel += " ClickRaise";
382 fmodel = "ClickToFocus";
384 config->setValue(screenstr + "focusModel", fmodel);
388 void BScreen::saveAutoRaise(bool a) {
389 resource.auto_raise = a;
390 saveSloppyFocus(resource.sloppy_focus);
394 void BScreen::saveClickRaise(bool c) {
395 resource.click_raise = c;
396 saveSloppyFocus(resource.sloppy_focus);
400 void BScreen::saveImageDither(bool d) {
401 image_control->setDither(d);
402 config->setValue(screenstr + "imageDither", doImageDither());
406 void BScreen::saveOpaqueMove(bool o) {
407 resource.opaque_move = o;
408 config->setValue(screenstr + "opaqueMove", resource.opaque_move);
411 void BScreen::saveRaiseOnMove(bool r) {
412 resource.raise_on_move = r;
413 config->setValue(screenstr + "raiseOnAltMove", resource.raise_on_move);
417 void BScreen::saveFullMax(bool f) {
418 resource.full_max = f;
419 config->setValue(screenstr + "fullMaximization", resource.full_max);
423 void BScreen::saveFocusNew(bool f) {
424 resource.focus_new = f;
425 config->setValue(screenstr + "focusNewWindows", resource.focus_new);
429 void BScreen::saveFocusLast(bool f) {
430 resource.focus_last = f;
431 config->setValue(screenstr + "focusLastWindow", resource.focus_last);
435 void BScreen::saveAAFonts(bool f) {
436 resource.aa_fonts = f;
437 config->setValue(screenstr + "antialiasFonts", resource.aa_fonts);
442 void BScreen::saveShadowFonts(bool f) {
443 resource.shadow_fonts = f;
444 config->setValue(screenstr + "dropShadowFonts", resource.shadow_fonts);
449 void BScreen::saveHideToolbar(bool h) {
450 resource.hide_toolbar = h;
451 if (resource.hide_toolbar)
452 toolbar->unmapToolbar();
454 toolbar->mapToolbar();
455 config->setValue(screenstr + "hideToolbar", resource.hide_toolbar);
459 void BScreen::saveWindowToEdgeSnap(int s) {
460 resource.snap_to_edges = s;
463 switch (resource.snap_to_edges) {
464 case WindowNoSnap: snap = "NoSnap"; break;
465 case WindowResistance: snap = "Resistance"; break;
466 case WindowSnap: default: snap = "Snap"; break;
468 config->setValue(screenstr + "windowToEdgeSnap", snap);
472 void BScreen::saveWindowToWindowSnap(int s) {
473 resource.snap_to_windows = s;
476 switch (resource.snap_to_windows) {
477 case WindowNoSnap: snap = "NoSnap"; break;
478 case WindowResistance: snap = "Resistance"; break;
479 case WindowSnap: default: snap = "Snap"; break;
481 config->setValue(screenstr + "windowToWindowSnap", snap);
485 void BScreen::saveResizeZones(unsigned int z) {
486 resource.resize_zones = z;
487 config->setValue(screenstr + "resizeZones", resource.resize_zones);
491 void BScreen::saveWindowCornerSnap(bool s) {
492 resource.window_corner_snap = s;
493 config->setValue(screenstr + "windowCornerSnap",
494 resource.window_corner_snap);
498 void BScreen::saveWorkspaces(unsigned int w) {
499 resource.workspaces = w;
500 config->setValue(screenstr + "workspaces", resource.workspaces);
504 void BScreen::savePlacementPolicy(int p) {
505 resource.placement_policy = p;
506 const char *placement;
507 switch (resource.placement_policy) {
508 case CascadePlacement: placement = "CascadePlacement"; break;
509 case UnderMousePlacement: placement = "UnderMousePlacement"; break;
510 case ClickMousePlacement: placement = "ClickMousePlacement"; break;
511 case ColSmartPlacement: placement = "ColSmartPlacement"; break;
512 case RowSmartPlacement: default: placement = "RowSmartPlacement"; break;
514 config->setValue(screenstr + "windowPlacement", placement);
518 void BScreen::saveResistanceSize(int s) {
519 resource.resistance_size = s;
520 config->setValue(screenstr + "resistanceSize",
521 resource.resistance_size);
525 void BScreen::saveSnapThreshold(int t) {
526 resource.snap_threshold = t;
527 config->setValue(screenstr + "edgeSnapThreshold",
528 resource.snap_threshold);
532 void BScreen::saveSnapOffset(int t) {
533 resource.snap_offset = t;
534 config->setValue(screenstr + "edgeSnapOffset",
535 resource.snap_offset);
539 void BScreen::saveRowPlacementDirection(int d) {
540 resource.row_direction = d;
541 config->setValue(screenstr + "rowPlacementDirection",
542 resource.row_direction == LeftRight ?
543 "LeftToRight" : "RightToLeft");
547 void BScreen::saveColPlacementDirection(int d) {
548 resource.col_direction = d;
549 config->setValue(screenstr + "colPlacementDirection",
550 resource.col_direction == TopBottom ?
551 "TopToBottom" : "BottomToTop");
556 void BScreen::saveStrftimeFormat(const std::string& format) {
557 resource.strftime_format = format;
558 config->setValue(screenstr + "strftimeFormat", resource.strftime_format);
561 #else // !HAVE_STRFTIME
563 void BScreen::saveDateFormat(int f) {
564 resource.date_format = f;
565 config->setValue(screenstr + "dateFormat",
566 resource.date_format == B_EuropeanDate ?
567 "European" : "American");
571 void BScreen::saveClock24Hour(bool c) {
572 resource.clock24hour = c;
573 config->setValue(screenstr + "clockFormat", resource.clock24hour ? 24 : 12);
575 #endif // HAVE_STRFTIME
578 void BScreen::saveWorkspaceNames() {
581 for (unsigned int i = 0; i < workspacesList.size(); ++i) {
582 names += workspacesList[i]->getName();
583 if (i < workspacesList.size() - 1)
587 config->setValue(screenstr + "workspaceNames", names);
591 void BScreen::savePlaceIgnoreShaded(bool i) {
592 resource.ignore_shaded = i;
593 config->setValue(screenstr + "placementIgnoreShaded",
594 resource.ignore_shaded);
598 void BScreen::savePlaceIgnoreMaximized(bool i) {
599 resource.ignore_maximized = i;
600 config->setValue(screenstr + "placementIgnoreMaximized",
601 resource.ignore_maximized);
605 void BScreen::saveAllowScrollLock(bool a) {
606 resource.allow_scroll_lock = a;
607 config->setValue(screenstr + "disableBindingsWithScrollLock",
608 resource.allow_scroll_lock);
612 void BScreen::saveWorkspaceWarping(bool w) {
613 resource.workspace_warping = w;
614 config->setValue(screenstr + "workspaceWarping",
615 resource.workspace_warping);
619 void BScreen::saveRootScrollDirection(int d) {
620 resource.root_scroll = d;
622 switch (resource.root_scroll) {
623 case NoScroll: dir = "None"; break;
624 case ReverseScroll: dir = "Reverse"; break;
625 case NormalScroll: default: dir = "Normal"; break;
627 config->setValue(screenstr + "rootScrollDirection", dir);
631 void BScreen::saveRootMenuButton(unsigned int b) {
632 resource.root_menu_button = b;
634 switch (resource.root_menu_button) {
635 case 0: but = "None"; break;
636 case 1: but = "Left"; break;
637 case 2: but = "Middle"; break;
638 case 3: default: but = "Right"; break;
640 config->setValue(screenstr + "rootMenuButton", but);
644 void BScreen::saveWorkspaceMenuButton(unsigned int b) {
645 resource.workspace_menu_button = b;
647 switch (resource.workspace_menu_button) {
648 case 0: but = "None"; break;
649 case 1: but = "Left"; break;
650 case 2: default: but = "Middle"; break;
651 case 3: but = "Right"; break;
653 config->setValue(screenstr + "workspaceMenuButton", but);
657 void BScreen::save_rc(void) {
658 saveSloppyFocus(resource.sloppy_focus);
659 saveAutoRaise(resource.auto_raise);
660 saveImageDither(doImageDither());
661 saveShadowFonts(resource.shadow_fonts);
662 saveAAFonts(resource.aa_fonts);
663 saveResizeZones(resource.resize_zones);
664 saveOpaqueMove(resource.opaque_move);
665 saveRaiseOnMove(resource.raise_on_move);
666 saveFullMax(resource.full_max);
667 saveFocusNew(resource.focus_new);
668 saveFocusLast(resource.focus_last);
669 saveHideToolbar(resource.hide_toolbar);
670 saveWindowToWindowSnap(resource.snap_to_windows);
671 saveWindowToEdgeSnap(resource.snap_to_edges);
672 saveWindowCornerSnap(resource.window_corner_snap);
673 saveWorkspaces(resource.workspaces);
674 savePlacementPolicy(resource.placement_policy);
675 saveSnapThreshold(resource.snap_threshold);
676 saveSnapOffset(resource.snap_offset);
677 saveResistanceSize(resource.resistance_size);
678 saveRowPlacementDirection(resource.row_direction);
679 saveColPlacementDirection(resource.col_direction);
681 saveStrftimeFormat(resource.strftime_format);
682 #else // !HAVE_STRFTIME
683 saveDateFormat(resource.date_format);
684 savwClock24Hour(resource.clock24hour);
685 #endif // HAVE_STRFTIME
686 savePlaceIgnoreShaded(resource.ignore_shaded);
687 savePlaceIgnoreMaximized(resource.ignore_maximized);
688 saveAllowScrollLock(resource.allow_scroll_lock);
689 saveWorkspaceWarping(resource.workspace_warping);
690 saveRootScrollDirection(resource.root_scroll);
691 saveRootMenuButton(resource.root_menu_button);
692 saveWorkspaceMenuButton(resource.workspace_menu_button);
699 void BScreen::load_rc(void) {
703 if (! config->getValue(screenstr + "fullMaximization", resource.full_max))
704 resource.full_max = false;
706 if (! config->getValue(screenstr + "focusNewWindows", resource.focus_new))
707 resource.focus_new = false;
709 if (! config->getValue(screenstr + "focusLastWindow", resource.focus_last))
710 resource.focus_last = false;
712 if (! config->getValue(screenstr + "workspaces", resource.workspaces))
713 resource.workspaces = 1;
715 if (! config->getValue(screenstr + "opaqueMove", resource.opaque_move))
716 resource.opaque_move = false;
718 if (! config->getValue(screenstr + "raiseOnAltMove", resource.raise_on_move))
719 resource.raise_on_move = true;
721 if (! config->getValue(screenstr + "antialiasFonts", resource.aa_fonts))
722 resource.aa_fonts = true;
724 if (! resource.aa_fonts ||
725 ! config->getValue(screenstr + "dropShadowFonts", resource.shadow_fonts))
726 resource.shadow_fonts = false;
728 if (! config->getValue(screenstr + "resizeZones", resource.resize_zones) ||
729 (resource.resize_zones != 1 && resource.resize_zones != 2 &&
730 resource.resize_zones != 4))
731 resource.resize_zones = 4;
733 if (! config->getValue(screenstr + "hideToolbar", resource.hide_toolbar))
734 resource.hide_toolbar = false;
736 resource.snap_to_windows = WindowResistance;
737 if (config->getValue(screenstr + "windowToWindowSnap", s)) {
739 resource.snap_to_windows = WindowNoSnap;
740 else if (s == "Snap")
741 resource.snap_to_windows = WindowSnap;
744 resource.snap_to_edges = WindowResistance;
745 if (config->getValue(screenstr + "windowToEdgeSnap", s)) {
747 resource.snap_to_edges = WindowNoSnap;
748 else if (s == "Snap")
749 resource.snap_to_edges = WindowSnap;
752 if (! config->getValue(screenstr + "windowCornerSnap",
753 resource.window_corner_snap))
754 resource.window_corner_snap = true;
756 if (! config->getValue(screenstr + "imageDither", b))
758 image_control->setDither(b);
760 if (! config->getValue(screenstr + "edgeSnapOffset",
761 resource.snap_offset))
762 resource.snap_offset = 0;
763 if (resource.snap_offset > 50) // sanity check, setting this huge would
764 resource.snap_offset = 50; // seriously suck.
766 if (! config->getValue(screenstr + "edgeSnapThreshold",
767 resource.snap_threshold))
768 resource.snap_threshold = 4;
770 if (! config->getValue(screenstr + "resistanceSize",
771 resource.resistance_size))
772 resource.resistance_size = 18;
774 if (config->getValue(screenstr + "rowPlacementDirection", s) &&
776 resource.row_direction = RightLeft;
778 resource.row_direction = LeftRight;
780 if (config->getValue(screenstr + "colPlacementDirection", s) &&
782 resource.col_direction = BottomTop;
784 resource.col_direction = TopBottom;
786 if (config->getValue(screenstr + "workspaceNames", s)) {
787 XAtom::StringVect workspaceNames;
789 string::const_iterator it = s.begin(), end = s.end();
791 string::const_iterator tmp = it; // current string.begin()
792 it = std::find(tmp, end, ','); // look for comma between tmp and end
793 workspaceNames.push_back(string(tmp, it)); // s[tmp:it]
799 xatom->setValue(getRootWindow(), XAtom::net_desktop_names, XAtom::utf8,
803 resource.sloppy_focus = true;
804 resource.auto_raise = false;
805 resource.click_raise = false;
806 if (config->getValue(screenstr + "focusModel", s)) {
807 if (s.find("ClickToFocus") != string::npos) {
808 resource.sloppy_focus = false;
811 if (s.find("AutoRaise") != string::npos)
812 resource.auto_raise = true;
813 if (s.find("ClickRaise") != string::npos)
814 resource.click_raise = true;
818 if (config->getValue(screenstr + "windowPlacement", s)) {
819 if (s == "CascadePlacement")
820 resource.placement_policy = CascadePlacement;
821 else if (s == "UnderMousePlacement")
822 resource.placement_policy = UnderMousePlacement;
823 else if (s == "ClickMousePlacement")
824 resource.placement_policy = ClickMousePlacement;
825 else if (s == "ColSmartPlacement")
826 resource.placement_policy = ColSmartPlacement;
827 else //if (s == "RowSmartPlacement")
828 resource.placement_policy = RowSmartPlacement;
830 resource.placement_policy = RowSmartPlacement;
833 if (! config->getValue(screenstr + "strftimeFormat",
834 resource.strftime_format))
835 resource.strftime_format = "%I:%M %p";
836 #else // !HAVE_STRFTIME
839 if (config->getValue(screenstr + "dateFormat", s) && s == "European")
840 resource.date_format = B_EuropeanDate;
842 resource.date_format = B_AmericanDate;
844 if (! config->getValue(screenstr + "clockFormat", l))
846 resource.clock24hour = l == 24;
847 #endif // HAVE_STRFTIME
849 if (! config->getValue(screenstr + "placementIgnoreShaded",
850 resource.ignore_shaded))
851 resource.ignore_shaded = true;
853 if (! config->getValue(screenstr + "placementIgnoreMaximized",
854 resource.ignore_maximized))
855 resource.ignore_maximized = true;
857 if (! config->getValue(screenstr + "disableBindingsWithScrollLock",
858 resource.allow_scroll_lock))
859 resource.allow_scroll_lock = false;
861 if (! config->getValue(screenstr + "workspaceWarping",
862 resource.workspace_warping))
863 resource.workspace_warping = false;
865 resource.root_scroll = NormalScroll;
866 if (config->getValue(screenstr + "rootScrollDirection", s)) {
868 resource.root_scroll = NoScroll;
869 else if (s == "Reverse")
870 resource.root_scroll = ReverseScroll;
873 resource.root_menu_button = 3;
874 if (config->getValue(screenstr + "rootMenuButton", s)) {
876 resource.root_menu_button = 0;
877 else if (s == "Left")
878 resource.root_menu_button = 1;
879 else if (s == "Middle")
880 resource.root_menu_button = 2;
883 resource.workspace_menu_button = 2;
884 if (config->getValue(screenstr + "workspaceMenuButton", s)) {
886 resource.workspace_menu_button = 0;
887 else if (s == "Left")
888 resource.workspace_menu_button = 1;
889 else if (s == "Right")
890 resource.workspace_menu_button = 3;
892 // cant both be the same
893 if (resource.workspace_menu_button == resource.root_menu_button)
894 resource.workspace_menu_button = 0;
898 void BScreen::changeWorkspaceCount(unsigned int new_count) {
899 assert(new_count > 0);
901 if (new_count < workspacesList.size()) {
903 for (unsigned int i = workspacesList.size(); i > new_count; --i)
904 removeLastWorkspace();
905 // removeLast already sets the current workspace to the
906 // last available one.
907 } else if (new_count > workspacesList.size()) {
909 for(unsigned int i = workspacesList.size(); i < new_count; ++i)
915 void BScreen::reconfigure(void) {
916 // don't reconfigure while saving the initial rc file, it's a waste and it
917 // breaks somethings (workspace names)
918 if (blackbox->isStartup()) return;
925 // we need to do this explicitly, because just loading this value from the rc
927 changeWorkspaceCount(resource.workspaces);
930 gcv.foreground = WhitePixel(blackbox->getXDisplay(),
932 gcv.function = GXinvert;
933 gcv.subwindow_mode = IncludeInferiors;
934 XChangeGC(blackbox->getXDisplay(), opGC,
935 GCForeground | GCFunction | GCSubwindowMode, &gcv);
937 const char *s = i18n(ScreenSet, ScreenPositionLength,
938 "0: 0000 x 0: 0000");
940 geom_w = resource.wstyle.font->measureString(s) + resource.bevel_width * 2;
941 geom_h = resource.wstyle.font->height() + resource.bevel_width * 2;
943 BTexture* texture = &(resource.wstyle.l_focus);
944 geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap);
945 if (geom_pixmap == ParentRelative) {
946 texture = &(resource.wstyle.t_focus);
947 geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap);
950 XSetWindowBackground(blackbox->getXDisplay(), geom_window,
951 texture->color().pixel());
953 XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
954 geom_window, geom_pixmap);
956 XSetWindowBorderWidth(blackbox->getXDisplay(), geom_window,
957 resource.border_width);
958 XSetWindowBorder(blackbox->getXDisplay(), geom_window,
959 resource.border_color.pixel());
961 workspacemenu->reconfigure();
962 iconmenu->reconfigure();
964 typedef std::vector<int> SubList;
965 SubList remember_subs;
967 // save the current open menus
968 Basemenu *menu = rootmenu;
970 while ((submenu = menu->getCurrentSubmenu()) >= 0) {
971 remember_subs.push_back(submenu);
972 menu = menu->find(submenu)->submenu();
978 rootmenu->reconfigure();
980 // reopen the saved menus
982 const SubList::iterator subs_end = remember_subs.end();
983 for (SubList::iterator it = remember_subs.begin(); it != subs_end; ++it) {
984 menu->drawSubmenu(*it);
985 menu = menu->find(*it)->submenu();
990 configmenu->reconfigure();
992 toolbar->reconfigure();
996 std::for_each(workspacesList.begin(), workspacesList.end(),
997 std::mem_fun(&Workspace::reconfigure));
999 BlackboxWindowList::iterator iit = iconList.begin();
1000 for (; iit != iconList.end(); ++iit) {
1001 BlackboxWindow *bw = *iit;
1002 if (bw->validateClient())
1006 image_control->timeout();
1010 void BScreen::rereadMenu(void) {
1014 rootmenu->reconfigure();
1018 void BScreen::LoadStyle(void) {
1019 Configuration style(False);
1021 const char *sfile = blackbox->getStyleFilename();
1022 if (sfile != NULL) {
1023 style.setFile(sfile);
1024 if (! style.load()) {
1025 style.setFile(DEFAULTSTYLE);
1027 style.create(); // hardcoded default values will be used.
1031 // merge in the rc file
1032 style.merge(config->file(), True);
1036 // load fonts/fontsets
1037 if (resource.wstyle.font)
1038 delete resource.wstyle.font;
1039 if (resource.tstyle.font)
1040 delete resource.tstyle.font;
1041 if (resource.mstyle.f_font)
1042 delete resource.mstyle.f_font;
1043 if (resource.mstyle.t_font)
1044 delete resource.mstyle.t_font;
1045 resource.wstyle.font = resource.tstyle.font = resource.mstyle.f_font =
1046 resource.mstyle.t_font = (BFont *) 0;
1048 resource.wstyle.font = readDatabaseFont("window.", style);
1049 resource.tstyle.font = readDatabaseFont("toolbar.", style);
1050 resource.mstyle.t_font = readDatabaseFont("menu.title.", style);
1051 resource.mstyle.f_font = readDatabaseFont("menu.frame.", style);
1053 // load window config
1054 resource.wstyle.t_focus =
1055 readDatabaseTexture("window.title.focus", "white", style);
1056 resource.wstyle.t_unfocus =
1057 readDatabaseTexture("window.title.unfocus", "black", style);
1058 resource.wstyle.l_focus =
1059 readDatabaseTexture("window.label.focus", "white", style);
1060 resource.wstyle.l_unfocus =
1061 readDatabaseTexture("window.label.unfocus", "black", style);
1062 resource.wstyle.h_focus =
1063 readDatabaseTexture("window.handle.focus", "white", style);
1064 resource.wstyle.h_unfocus =
1065 readDatabaseTexture("window.handle.unfocus", "black", style);
1066 resource.wstyle.g_focus =
1067 readDatabaseTexture("window.grip.focus", "white", style);
1068 resource.wstyle.g_unfocus =
1069 readDatabaseTexture("window.grip.unfocus", "black", style);
1070 resource.wstyle.b_focus =
1071 readDatabaseTexture("window.button.focus", "white", style);
1072 resource.wstyle.b_unfocus =
1073 readDatabaseTexture("window.button.unfocus", "black", style);
1074 resource.wstyle.b_pressed =
1075 readDatabaseTexture("window.button.pressed", "black", style);
1077 //if neither of these can be found, we will use the previous resource
1078 resource.wstyle.b_pressed_focus =
1079 readDatabaseTexture("window.button.pressed.focus", "black", style, true);
1080 resource.wstyle.b_pressed_unfocus =
1081 readDatabaseTexture("window.button.pressed.unfocus", "black", style, true);
1083 #ifdef BITMAPBUTTONS
1084 if (resource.wstyle.close_button.mask != None)
1085 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.close_button.mask);
1086 if (resource.wstyle.max_button.mask != None)
1087 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.max_button.mask);
1088 if (resource.wstyle.icon_button.mask != None)
1089 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.icon_button.mask);
1090 if (resource.wstyle.stick_button.mask != None)
1091 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.stick_button.mask);
1093 resource.wstyle.close_button.mask = resource.wstyle.max_button.mask =
1094 resource.wstyle.icon_button.mask =
1095 resource.wstyle.icon_button.mask = None;
1097 readDatabaseMask("window.button.close.mask", resource.wstyle.close_button,
1099 readDatabaseMask("window.button.max.mask", resource.wstyle.max_button,
1101 readDatabaseMask("window.button.icon.mask", resource.wstyle.icon_button,
1103 readDatabaseMask("window.button.stick.mask", resource.wstyle.stick_button,
1105 #endif // BITMAPBUTTONS
1107 // we create the window.frame texture by hand because it exists only to
1108 // make the code cleaner and is not actually used for display
1109 BColor color = readDatabaseColor("window.frame.focusColor", "white", style);
1110 resource.wstyle.f_focus = BTexture("solid flat", getBaseDisplay(),
1111 getScreenNumber(), image_control);
1112 resource.wstyle.f_focus.setColor(color);
1114 color = readDatabaseColor("window.frame.unfocusColor", "white", style);
1115 resource.wstyle.f_unfocus = BTexture("solid flat", getBaseDisplay(),
1116 getScreenNumber(), image_control);
1117 resource.wstyle.f_unfocus.setColor(color);
1119 resource.wstyle.l_text_focus =
1120 readDatabaseColor("window.label.focus.textColor", "black", style);
1121 resource.wstyle.l_text_unfocus =
1122 readDatabaseColor("window.label.unfocus.textColor", "white", style);
1123 resource.wstyle.b_pic_focus =
1124 readDatabaseColor("window.button.focus.picColor", "black", style);
1125 resource.wstyle.b_pic_unfocus =
1126 readDatabaseColor("window.button.unfocus.picColor", "white", style);
1128 resource.wstyle.justify = LeftJustify;
1129 if (style.getValue("window.justify", s)) {
1130 if (s == "right" || s == "Right")
1131 resource.wstyle.justify = RightJustify;
1132 else if (s == "center" || s == "Center")
1133 resource.wstyle.justify = CenterJustify;
1137 if (resource.wstyle.t_focus.texture() == BTexture::Parent_Relative)
1138 resource.wstyle.t_focus = resource.wstyle.f_focus;
1139 if (resource.wstyle.t_unfocus.texture() == BTexture::Parent_Relative)
1140 resource.wstyle.t_unfocus = resource.wstyle.f_unfocus;
1141 if (resource.wstyle.h_focus.texture() == BTexture::Parent_Relative)
1142 resource.wstyle.h_focus = resource.wstyle.f_focus;
1143 if (resource.wstyle.h_unfocus.texture() == BTexture::Parent_Relative)
1144 resource.wstyle.h_unfocus = resource.wstyle.f_unfocus;
1146 // load toolbar config
1147 #ifdef BITMAPBUTTONS
1148 if (resource.tstyle.left_button.mask != None)
1149 XFreePixmap(blackbox->getXDisplay(), resource.tstyle.left_button.mask);
1150 if (resource.tstyle.right_button.mask != None)
1151 XFreePixmap(blackbox->getXDisplay(), resource.tstyle.right_button.mask);
1152 #endif // BITMAPBUTTONS
1154 resource.tstyle.toolbar =
1155 readDatabaseTexture("toolbar", "black", style);
1156 resource.tstyle.label =
1157 readDatabaseTexture("toolbar.label", "black", style);
1158 resource.tstyle.window =
1159 readDatabaseTexture("toolbar.windowLabel", "black", style);
1160 resource.tstyle.button =
1161 readDatabaseTexture("toolbar.button", "white", style);
1162 resource.tstyle.pressed =
1163 readDatabaseTexture("toolbar.button.pressed", "black", style);
1164 resource.tstyle.clock =
1165 readDatabaseTexture("toolbar.clock", "black", style);
1166 resource.tstyle.l_text =
1167 readDatabaseColor("toolbar.label.textColor", "white", style);
1168 resource.tstyle.w_text =
1169 readDatabaseColor("toolbar.windowLabel.textColor", "white", style);
1170 resource.tstyle.c_text =
1171 readDatabaseColor("toolbar.clock.textColor", "white", style);
1172 resource.tstyle.b_pic =
1173 readDatabaseColor("toolbar.button.picColor", "black", style);
1175 #ifdef BITMAPBUTTONS
1176 readDatabaseMask("toolbar.button.left.mask", resource.tstyle.left_button,
1178 readDatabaseMask("toolbar.button.right.mask", resource.tstyle.right_button,
1180 #endif // BITMAPBUTTONS
1182 resource.tstyle.justify = LeftJustify;
1183 if (style.getValue("toolbar.justify", s)) {
1184 if (s == "right" || s == "Right")
1185 resource.tstyle.justify = RightJustify;
1186 else if (s == "center" || s == "Center")
1187 resource.tstyle.justify = CenterJustify;
1191 if (resource.tstyle.toolbar.texture() == BTexture::Parent_Relative) {
1192 resource.tstyle.toolbar = BTexture("solid flat", getBaseDisplay(),
1193 getScreenNumber(), image_control);
1194 resource.tstyle.toolbar.setColor(BColor("black", getBaseDisplay(),
1195 getScreenNumber()));
1199 #ifdef BITMAPBUTTONS
1200 if (resource.mstyle.bullet_image.mask != None)
1201 XFreePixmap(blackbox->getXDisplay(), resource.mstyle.bullet_image.mask);
1202 if (resource.mstyle.tick_image.mask != None)
1203 XFreePixmap(blackbox->getXDisplay(), resource.mstyle.tick_image.mask);
1204 #endif // BITMAPBUTTONS
1206 resource.mstyle.title =
1207 readDatabaseTexture("menu.title", "white", style);
1208 resource.mstyle.frame =
1209 readDatabaseTexture("menu.frame", "black", style);
1210 resource.mstyle.hilite =
1211 readDatabaseTexture("menu.hilite", "white", style);
1212 resource.mstyle.t_text =
1213 readDatabaseColor("menu.title.textColor", "black", style);
1214 resource.mstyle.f_text =
1215 readDatabaseColor("menu.frame.textColor", "white", style);
1216 resource.mstyle.d_text =
1217 readDatabaseColor("menu.frame.disableColor", "black", style);
1218 resource.mstyle.h_text =
1219 readDatabaseColor("menu.hilite.textColor", "black", style);
1221 #ifdef BITMAPBUTTONS
1222 readDatabaseMask("menu.arrow.mask", resource.mstyle.bullet_image, style);
1223 readDatabaseMask("menu.selected.mask", resource.mstyle.tick_image, style);
1224 #endif // BITMAPBUTTONS
1226 resource.mstyle.t_justify = LeftJustify;
1227 if (style.getValue("menu.title.justify", s)) {
1228 if (s == "right" || s == "Right")
1229 resource.mstyle.t_justify = RightJustify;
1230 else if (s == "center" || s == "Center")
1231 resource.mstyle.t_justify = CenterJustify;
1234 resource.mstyle.f_justify = LeftJustify;
1235 if (style.getValue("menu.frame.justify", s)) {
1236 if (s == "right" || s == "Right")
1237 resource.mstyle.f_justify = RightJustify;
1238 else if (s == "center" || s == "Center")
1239 resource.mstyle.f_justify = CenterJustify;
1242 resource.mstyle.bullet = Basemenu::Triangle;
1243 if (style.getValue("menu.bullet", s)) {
1244 if (s == "empty" || s == "Empty")
1245 resource.mstyle.bullet = Basemenu::Empty;
1246 else if (s == "square" || s == "Square")
1247 resource.mstyle.bullet = Basemenu::Square;
1248 else if (s == "diamond" || s == "Diamond")
1249 resource.mstyle.bullet = Basemenu::Diamond;
1252 resource.mstyle.bullet_pos = Basemenu::Left;
1253 if (style.getValue("menu.bullet.position", s)) {
1254 if (s == "right" || s == "Right")
1255 resource.mstyle.bullet_pos = Basemenu::Right;
1259 if (resource.mstyle.frame.texture() == BTexture::Parent_Relative) {
1260 resource.mstyle.frame = BTexture("solid flat", getBaseDisplay(),
1261 getScreenNumber(), image_control);
1262 resource.mstyle.frame.setColor(BColor("black", getBaseDisplay(),
1263 getScreenNumber()));
1266 resource.border_color =
1267 readDatabaseColor("borderColor", "black", style);
1269 // load bevel, border and handle widths
1270 if (! style.getValue("handleWidth", resource.handle_width) ||
1271 resource.handle_width > (getWidth() / 2) || resource.handle_width == 0)
1272 resource.handle_width = 6;
1274 if (! style.getValue("borderWidth", resource.border_width))
1275 resource.border_width = 1;
1277 if (! style.getValue("bevelWidth", resource.bevel_width) ||
1278 resource.bevel_width > (getWidth() / 2) || resource.bevel_width == 0)
1279 resource.bevel_width = 3;
1281 if (! style.getValue("frameWidth", resource.frame_width) ||
1282 resource.frame_width > (getWidth() / 2))
1283 resource.frame_width = resource.bevel_width;
1285 if (style.getValue("rootCommand", s))
1286 bexec(s, displayString());
1290 void BScreen::addIcon(BlackboxWindow *w) {
1293 w->setWorkspace(BSENTINEL);
1294 w->setWindowNumber(iconList.size());
1296 iconList.push_back(w);
1298 const char* title = w->getIconTitle();
1299 iconmenu->insert(title);
1304 void BScreen::removeIcon(BlackboxWindow *w) {
1309 iconmenu->remove(w->getWindowNumber());
1312 BlackboxWindowList::iterator it = iconList.begin(),
1313 end = iconList.end();
1314 for (int i = 0; it != end; ++it)
1315 (*it)->setWindowNumber(i++);
1319 BlackboxWindow *BScreen::getIcon(unsigned int index) {
1320 if (index < iconList.size()) {
1321 BlackboxWindowList::iterator it = iconList.begin();
1322 while (index-- > 0) // increment to index
1327 return (BlackboxWindow *) 0;
1331 unsigned int BScreen::addWorkspace(void) {
1332 Workspace *wkspc = new Workspace(this, workspacesList.size());
1333 workspacesList.push_back(wkspc);
1334 saveWorkspaces(getWorkspaceCount());
1335 saveWorkspaceNames();
1337 workspacemenu->insertWorkspace(wkspc);
1338 workspacemenu->update();
1340 toolbar->reconfigure();
1342 updateNetizenWorkspaceCount();
1344 return workspacesList.size();
1348 unsigned int BScreen::removeLastWorkspace(void) {
1349 if (workspacesList.size() == 1)
1352 Workspace *wkspc = workspacesList.back();
1354 if (current_workspace->getID() == wkspc->getID())
1355 changeWorkspaceID(current_workspace->getID() - 1);
1359 workspacemenu->removeWorkspace(wkspc);
1360 workspacemenu->update();
1362 workspacesList.pop_back();
1365 saveWorkspaces(getWorkspaceCount());
1366 saveWorkspaceNames();
1368 toolbar->reconfigure();
1370 updateNetizenWorkspaceCount();
1372 return workspacesList.size();
1376 void BScreen::changeWorkspaceID(unsigned int id) {
1377 if (! current_workspace || id == current_workspace->getID()) return;
1379 BlackboxWindow *focused = blackbox->getFocusedWindow();
1380 if (focused && focused->getScreen() == this) {
1381 assert(focused->isStuck() ||
1382 focused->getWorkspaceNumber() == current_workspace->getID());
1384 current_workspace->setLastFocusedWindow(focused);
1386 // if no window had focus, no need to store a last focus
1387 current_workspace->setLastFocusedWindow((BlackboxWindow *) 0);
1390 // when we switch workspaces, unfocus whatever was focused if it is going
1392 if (focused && ! focused->isStuck())
1393 blackbox->setFocusedWindow((BlackboxWindow *) 0);
1395 current_workspace->hideAll();
1396 workspacemenu->setItemSelected(current_workspace->getID() + 2, False);
1398 current_workspace = getWorkspace(id);
1400 xatom->setValue(getRootWindow(), XAtom::net_current_desktop,
1401 XAtom::cardinal, id);
1403 workspacemenu->setItemSelected(current_workspace->getID() + 2, True);
1404 toolbar->redrawWorkspaceLabel(True);
1406 current_workspace->showAll();
1411 BlackboxWindow *win = (BlackboxWindow *) 0;
1414 XSync(blackbox->getXDisplay(), False);
1416 // If sloppy focus and we can find the client window under the pointer,
1418 if (resource.sloppy_focus &&
1419 XQueryPointer(blackbox->getXDisplay(), getRootWindow(), &r, &c,
1420 &rx, &ry, &x, &y, &m) &&
1422 if ( (win = blackbox->searchWindow(c)) )
1423 f = win->setInputFocus();
1426 // If that fails, and we're doing focus_last, try to focus the last window.
1427 if (! f && resource.focus_last &&
1428 (win = current_workspace->getLastFocusedWindow()))
1429 f = win->setInputFocus();
1432 if we found a focus target, then we set the focused window explicitly
1433 because it is possible to switch off this workspace before the x server
1434 generates the FocusIn event for the window. if that happens, openbox would
1435 lose track of what window was the 'LastFocused' window on the workspace.
1437 if we did not find a focus target, then set the current focused window to
1441 blackbox->setFocusedWindow(win);
1443 blackbox->setFocusedWindow((BlackboxWindow *) 0);
1445 updateNetizenCurrentWorkspace();
1450 * Set the _NET_CLIENT_LIST root window property.
1452 void BScreen::updateClientList(void) {
1453 if (windowList.size() > 0) {
1454 Window *windows = new Window[windowList.size()];
1455 Window *win_it = windows;
1456 BlackboxWindowList::iterator it = windowList.begin();
1457 const BlackboxWindowList::iterator end = windowList.end();
1458 for (; it != end; ++it, ++win_it)
1459 *win_it = (*it)->getClientWindow();
1460 xatom->setValue(getRootWindow(), XAtom::net_client_list, XAtom::window,
1461 windows, windowList.size());
1464 xatom->setValue(getRootWindow(), XAtom::net_client_list, XAtom::window,
1467 updateStackingList();
1472 * Set the _NET_CLIENT_LIST_STACKING root window property.
1474 void BScreen::updateStackingList(void) {
1476 BlackboxWindowList stack_order;
1479 * Get the stacking order from all of the workspaces.
1480 * We start with the current workspace so that the sticky windows will be
1481 * in the right order on the current workspace.
1482 * XXX: Do we need to have sticky windows in the list once for each workspace?
1484 getCurrentWorkspace()->appendStackOrder(stack_order);
1485 for (unsigned int i = 0; i < getWorkspaceCount(); ++i)
1486 if (i != getCurrentWorkspaceID())
1487 getWorkspace(i)->appendStackOrder(stack_order);
1489 if (stack_order.size() > 0) {
1490 // set the client list atoms
1491 Window *windows = new Window[stack_order.size()];
1492 Window *win_it = windows;
1493 BlackboxWindowList::iterator it = stack_order.begin(),
1494 end = stack_order.end();
1495 for (; it != end; ++it, ++win_it)
1496 *win_it = (*it)->getClientWindow();
1497 xatom->setValue(getRootWindow(), XAtom::net_client_list_stacking,
1498 XAtom::window, windows, stack_order.size());
1501 xatom->setValue(getRootWindow(), XAtom::net_client_list_stacking,
1502 XAtom::window, 0, 0);
1506 void BScreen::addSystrayWindow(Window window) {
1507 XGrabServer(blackbox->getXDisplay());
1509 XSelectInput(blackbox->getXDisplay(), window, StructureNotifyMask);
1510 systrayWindowList.push_back(window);
1511 xatom->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows,
1513 &systrayWindowList[0], systrayWindowList.size());
1514 blackbox->saveSystrayWindowSearch(window, this);
1516 XUngrabServer(blackbox->getXDisplay());
1520 void BScreen::removeSystrayWindow(Window window) {
1521 XGrabServer(blackbox->getXDisplay());
1523 WindowList::iterator it = systrayWindowList.begin();
1524 const WindowList::iterator end = systrayWindowList.end();
1525 for (; it != end; ++it)
1526 if (*it == window) {
1527 systrayWindowList.erase(it);
1528 xatom->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows,
1530 &systrayWindowList[0], systrayWindowList.size());
1531 blackbox->removeSystrayWindowSearch(window);
1532 XSelectInput(blackbox->getXDisplay(), window, NoEventMask);
1536 assert(it != end); // not a systray window
1538 XUngrabServer(blackbox->getXDisplay());
1542 void BScreen::manageWindow(Window w) {
1543 // is the window a KDE systray window?
1545 if (xatom->getValue(w, XAtom::kde_net_wm_system_tray_window_for,
1546 XAtom::window, systray) && systray != None) {
1547 addSystrayWindow(w);
1551 // is the window a docking app
1552 XWMHints *wmhint = XGetWMHints(blackbox->getXDisplay(), w);
1553 if (wmhint && (wmhint->flags & StateHint) &&
1554 wmhint->initial_state == WithdrawnState) {
1559 new BlackboxWindow(blackbox, w, this);
1561 BlackboxWindow *win = blackbox->searchWindow(w);
1565 if (win->isDesktop()) {
1566 desktopWindowList.push_back(win->getFrameWindow());
1567 } else { // if (win->isNormal()) {
1568 // don't list desktop windows as managed windows
1569 windowList.push_back(win);
1572 if (win->isTopmost())
1573 specialWindowList.push_back(win->getFrameWindow());
1576 XMapRequestEvent mre;
1578 if (blackbox->isStartup() && win->isNormal()) win->restoreAttributes();
1579 win->mapRequestEvent(&mre);
1583 void BScreen::unmanageWindow(BlackboxWindow *w, bool remap) {
1584 // is the window a KDE systray window?
1586 if (xatom->getValue(w->getClientWindow(),
1587 XAtom::kde_net_wm_system_tray_window_for,
1588 XAtom::window, systray) && systray != None) {
1589 removeSystrayWindow(w->getClientWindow());
1595 // Remove the modality so that its parent won't try to re-focus the window
1596 if (w->isModal()) w->setModal(False);
1598 if (w->getWorkspaceNumber() != BSENTINEL &&
1599 w->getWindowNumber() != BSENTINEL) {
1600 getWorkspace(w->getWorkspaceNumber())->removeWindow(w);
1602 for (unsigned int i = 0; i < getNumberOfWorkspaces(); ++i)
1603 if (i != w->getWorkspaceNumber())
1604 getWorkspace(i)->removeWindow(w, True);
1606 } else if (w->isIconic())
1609 if (w->isDesktop()) {
1610 WindowList::iterator it = desktopWindowList.begin();
1611 const WindowList::iterator end = desktopWindowList.end();
1612 for (; it != end; ++it)
1613 if (*it == w->getFrameWindow()) {
1614 desktopWindowList.erase(it);
1617 assert(it != end); // the window wasnt a desktop window?
1618 } else { // if (w->isNormal()) {
1619 // we don't list desktop windows as managed windows
1620 windowList.remove(w);
1623 if (w->isTopmost()) {
1624 WindowList::iterator it = specialWindowList.begin();
1625 const WindowList::iterator end = specialWindowList.end();
1626 for (; it != end; ++it)
1627 if (*it == w->getFrameWindow()) {
1628 specialWindowList.erase(it);
1631 assert(it != end); // the window wasnt a special window?
1635 if (blackbox->getFocusedWindow() == w)
1636 blackbox->setFocusedWindow((BlackboxWindow *) 0);
1638 removeNetizen(w->getClientWindow());
1641 some managed windows can also be window group controllers. when
1642 unmanaging such windows, we should also delete the window group.
1644 BWindowGroup *group = blackbox->searchGroup(w->getClientWindow());
1651 void BScreen::addNetizen(Netizen *n) {
1652 netizenList.push_back(n);
1654 n->sendWorkspaceCount();
1655 n->sendCurrentWorkspace();
1657 WorkspaceList::iterator it = workspacesList.begin();
1658 const WorkspaceList::iterator end = workspacesList.end();
1659 for (; it != end; ++it)
1660 (*it)->sendWindowList(*n);
1662 Window f = ((blackbox->getFocusedWindow()) ?
1663 blackbox->getFocusedWindow()->getClientWindow() : None);
1664 n->sendWindowFocus(f);
1668 void BScreen::removeNetizen(Window w) {
1669 NetizenList::iterator it = netizenList.begin();
1670 for (; it != netizenList.end(); ++it) {
1671 if ((*it)->getWindowID() == w) {
1673 netizenList.erase(it);
1680 void BScreen::updateWorkArea(void) {
1681 if (workspacesList.size() > 0) {
1682 unsigned long *dims = new unsigned long[4 * workspacesList.size()];
1683 for (unsigned int i = 0, m = workspacesList.size(); i < m; ++i) {
1684 // XXX: this could be different for each workspace
1685 const Rect &area = availableArea();
1686 dims[(i * 4) + 0] = area.x();
1687 dims[(i * 4) + 1] = area.y();
1688 dims[(i * 4) + 2] = area.width();
1689 dims[(i * 4) + 3] = area.height();
1691 xatom->setValue(getRootWindow(), XAtom::net_workarea, XAtom::cardinal,
1692 dims, 4 * workspacesList.size());
1695 xatom->setValue(getRootWindow(), XAtom::net_workarea, XAtom::cardinal,
1700 void BScreen::updateNetizenCurrentWorkspace(void) {
1701 std::for_each(netizenList.begin(), netizenList.end(),
1702 std::mem_fun(&Netizen::sendCurrentWorkspace));
1706 void BScreen::updateNetizenWorkspaceCount(void) {
1707 xatom->setValue(getRootWindow(), XAtom::net_number_of_desktops,
1708 XAtom::cardinal, workspacesList.size());
1712 std::for_each(netizenList.begin(), netizenList.end(),
1713 std::mem_fun(&Netizen::sendWorkspaceCount));
1717 void BScreen::updateNetizenWindowFocus(void) {
1718 Window f = ((blackbox->getFocusedWindow()) ?
1719 blackbox->getFocusedWindow()->getClientWindow() : None);
1721 xatom->setValue(getRootWindow(), XAtom::net_active_window,
1724 NetizenList::iterator it = netizenList.begin();
1725 for (; it != netizenList.end(); ++it)
1726 (*it)->sendWindowFocus(f);
1730 void BScreen::updateNetizenWindowAdd(Window w, unsigned long p) {
1731 NetizenList::iterator it = netizenList.begin();
1732 for (; it != netizenList.end(); ++it) {
1733 (*it)->sendWindowAdd(w, p);
1738 void BScreen::updateNetizenWindowDel(Window w) {
1739 NetizenList::iterator it = netizenList.begin();
1740 for (; it != netizenList.end(); ++it)
1741 (*it)->sendWindowDel(w);
1745 void BScreen::updateNetizenWindowRaise(Window w) {
1746 NetizenList::iterator it = netizenList.begin();
1747 for (; it != netizenList.end(); ++it)
1748 (*it)->sendWindowRaise(w);
1752 void BScreen::updateNetizenWindowLower(Window w) {
1753 NetizenList::iterator it = netizenList.begin();
1754 for (; it != netizenList.end(); ++it)
1755 (*it)->sendWindowLower(w);
1759 void BScreen::updateNetizenConfigNotify(XEvent *e) {
1760 NetizenList::iterator it = netizenList.begin();
1761 for (; it != netizenList.end(); ++it)
1762 (*it)->sendConfigNotify(e);
1766 void BScreen::raiseWindows(Window *workspace_stack, unsigned int num) {
1767 // the 13 represents the number of blackbox windows such as menus
1776 Window *session_stack = new
1777 Window[(num + workspacesList.size() + rootmenuList.size() +
1778 specialWindowList.size() + bbwins)];
1779 unsigned int i = 0, k = num;
1781 XRaiseWindow(blackbox->getXDisplay(), iconmenu->getWindowID());
1782 *(session_stack + i++) = iconmenu->getWindowID();
1784 WorkspaceList::iterator wit = workspacesList.begin();
1785 const WorkspaceList::iterator w_end = workspacesList.end();
1786 for (; wit != w_end; ++wit)
1787 *(session_stack + i++) = (*wit)->getMenu()->getWindowID();
1789 *(session_stack + i++) = workspacemenu->getWindowID();
1791 *(session_stack + i++) = configmenu->getFocusmenu()->getWindowID();
1792 *(session_stack + i++) = configmenu->getPlacementmenu()->getWindowID();
1793 *(session_stack + i++) = configmenu->getWindowSnapmenu()->getWindowID();
1794 *(session_stack + i++) = configmenu->getEdgeSnapmenu()->getWindowID();
1796 *(session_stack + i++) = configmenu->getXineramamenu()->getWindowID();
1799 *(session_stack + i++) = configmenu->getXftmenu()->getWindowID();
1801 *(session_stack + i++) = configmenu->getWindowID();
1803 *(session_stack + i++) = slit->getMenu()->getDirectionmenu()->getWindowID();
1804 *(session_stack + i++) = slit->getMenu()->getPlacementmenu()->getWindowID();
1805 *(session_stack + i++) = slit->getMenu()->getWindowID();
1807 *(session_stack + i++) =
1808 toolbar->getMenu()->getPlacementmenu()->getWindowID();
1809 *(session_stack + i++) = toolbar->getMenu()->getWindowID();
1811 RootmenuList::iterator rit = rootmenuList.begin();
1812 for (; rit != rootmenuList.end(); ++rit)
1813 *(session_stack + i++) = (*rit)->getWindowID();
1814 *(session_stack + i++) = rootmenu->getWindowID();
1816 if (toolbar->isOnTop())
1817 *(session_stack + i++) = toolbar->getWindowID();
1819 if (slit->isOnTop())
1820 *(session_stack + i++) = slit->getWindowID();
1822 WindowList::iterator sit, send = specialWindowList.end();
1823 for (sit = specialWindowList.begin(); sit != send; ++sit)
1824 *(session_stack + i++) = *sit;
1827 *(session_stack + i++) = *(workspace_stack + k);
1829 XRestackWindows(blackbox->getXDisplay(), session_stack, i);
1831 delete [] session_stack;
1833 updateStackingList();
1837 void BScreen::lowerWindows(Window *workspace_stack, unsigned int num) {
1838 assert(num > 0); // this would cause trouble in the XRaiseWindow call
1840 Window *session_stack = new Window[(num + desktopWindowList.size())];
1841 unsigned int i = 0, k = num;
1843 XLowerWindow(blackbox->getXDisplay(), workspace_stack[0]);
1846 *(session_stack + i++) = *(workspace_stack + k);
1848 WindowList::iterator dit = desktopWindowList.begin();
1849 const WindowList::iterator d_end = desktopWindowList.end();
1850 for (; dit != d_end; ++dit)
1851 *(session_stack + i++) = *dit;
1853 XRestackWindows(blackbox->getXDisplay(), session_stack, i);
1855 delete [] session_stack;
1857 updateStackingList();
1861 void BScreen::reassociateWindow(BlackboxWindow *w, unsigned int wkspc_id,
1862 bool ignore_sticky) {
1865 if (wkspc_id == BSENTINEL)
1866 wkspc_id = current_workspace->getID();
1868 if (w->getWorkspaceNumber() == wkspc_id)
1871 if (w->isIconic()) {
1873 getWorkspace(wkspc_id)->addWindow(w);
1875 for (unsigned int i = 0; i < getNumberOfWorkspaces(); ++i)
1876 if (i != w->getWorkspaceNumber())
1877 getWorkspace(i)->addWindow(w, True);
1878 } else if (ignore_sticky || ! w->isStuck()) {
1881 getWorkspace(w->getWorkspaceNumber())->removeWindow(w);
1882 getWorkspace(wkspc_id)->addWindow(w);
1884 updateStackingList();
1888 void BScreen::propagateWindowName(const BlackboxWindow *bw) {
1889 if (bw->isIconic()) {
1890 iconmenu->changeItemLabel(bw->getWindowNumber(), bw->getIconTitle());
1893 Clientmenu *clientmenu = getWorkspace(bw->getWorkspaceNumber())->getMenu();
1894 clientmenu->changeItemLabel(bw->getWindowNumber(), bw->getTitle());
1895 clientmenu->update();
1897 if (blackbox->getFocusedWindow() == bw)
1898 toolbar->redrawWindowLabel(True);
1903 void BScreen::nextFocus(void) const {
1904 BlackboxWindow *focused = blackbox->getFocusedWindow(),
1908 focused->getScreen()->getScreenNumber() == getScreenNumber() &&
1909 current_workspace->getCount() > 1) {
1911 next = current_workspace->getNextWindowInList(next);
1912 } while (next != focused && ! next->setInputFocus());
1914 if (next != focused)
1915 current_workspace->raiseWindow(next);
1916 } else if (current_workspace->getCount() > 0) {
1917 next = current_workspace->getTopWindowOnStack();
1918 next->setInputFocus();
1919 current_workspace->raiseWindow(next);
1924 void BScreen::prevFocus(void) const {
1925 BlackboxWindow *focused = blackbox->getFocusedWindow(),
1929 focused->getScreen()->getScreenNumber() == getScreenNumber() &&
1930 current_workspace->getCount() > 1) {
1932 next = current_workspace->getPrevWindowInList(next);
1933 } while (next != focused && ! next->setInputFocus());
1935 if (next != focused)
1936 current_workspace->raiseWindow(next);
1937 } else if (current_workspace->getCount() > 0) {
1938 next = current_workspace->getTopWindowOnStack();
1939 next->setInputFocus();
1940 current_workspace->raiseWindow(next);
1945 void BScreen::raiseFocus(void) const {
1946 BlackboxWindow *focused = blackbox->getFocusedWindow();
1950 // if on this Screen, raise it
1951 if (focused->getScreen()->getScreenNumber() == getScreenNumber()) {
1952 Workspace *workspace = getWorkspace(focused->getWorkspaceNumber());
1953 workspace->raiseWindow(focused);
1958 void BScreen::InitMenu(void) {
1960 rootmenuList.clear();
1962 while (rootmenu->getCount())
1963 rootmenu->remove(0);
1965 rootmenu = new Rootmenu(this);
1967 bool defaultMenu = True;
1969 FILE *menu_file = (FILE *) 0;
1970 const char *menu_filename = blackbox->getMenuFilename();
1973 if (! (menu_file = fopen(menu_filename, "r")))
1974 perror(menu_filename);
1975 if (! menu_file) { // opening the menu file failed, try the default menu
1976 menu_filename = DEFAULTMENU;
1977 if (! (menu_file = fopen(menu_filename, "r")))
1978 perror(menu_filename);
1982 if (feof(menu_file)) {
1983 fprintf(stderr, i18n(ScreenSet, ScreenEmptyMenuFile,
1984 "%s: Empty menu file"),
1987 char line[1024], label[1024];
1988 memset(line, 0, 1024);
1989 memset(label, 0, 1024);
1991 while (fgets(line, 1024, menu_file) && ! feof(menu_file)) {
1995 int i, key = 0, index = -1, len = strlen(line);
1997 for (i = 0; i < len; i++) {
1998 if (line[i] == '[') index = 0;
1999 else if (line[i] == ']') break;
2000 else if (line[i] != ' ')
2002 key += tolower(line[i]);
2005 if (key == 517) { // [begin]
2007 for (i = index; i < len; i++) {
2008 if (line[i] == '(') index = 0;
2009 else if (line[i] == ')') break;
2010 else if (index++ >= 0) {
2011 if (line[i] == '\\' && i < len - 1) i++;
2012 label[index - 1] = line[i];
2016 if (index == -1) index = 0;
2017 label[index] = '\0';
2019 rootmenu->setLabel(label);
2020 defaultMenu = parseMenuFile(menu_file, rootmenu);
2022 blackbox->addMenuTimestamp(menu_filename);
2031 rootmenu->setInternalMenu();
2032 rootmenu->insert(i18n(ScreenSet, Screenxterm, "xterm"),
2034 i18n(ScreenSet, Screenxterm, "xterm"));
2035 rootmenu->insert(i18n(ScreenSet, ScreenRestart, "Restart"),
2037 rootmenu->insert(i18n(ScreenSet, ScreenExit, "Exit"),
2039 rootmenu->setLabel(i18n(BasemenuSet, BasemenuBlackboxMenu,
2046 size_t string_within(char begin, char end,
2047 const char *input, size_t start_at, size_t length,
2051 size_t i = start_at;
2052 for (; i < length; ++i) {
2053 if (input[i] == begin) {
2055 } else if (input[i] == end) {
2058 if (input[i] == '\\' && i < length - 1) i++;
2059 output[index++] = input[i];
2064 output[index] = '\0';
2072 bool BScreen::parseMenuFile(FILE *file, Rootmenu *menu) {
2073 char line[1024], keyword[1024], label[1024], command[1024];
2076 while (! (done || feof(file))) {
2077 memset(line, 0, 1024);
2078 memset(label, 0, 1024);
2079 memset(command, 0, 1024);
2081 if (! fgets(line, 1024, file))
2084 if (line[0] == '#') // comment, skip it
2087 size_t line_length = strlen(line);
2088 unsigned int key = 0;
2090 // get the keyword enclosed in []'s
2091 size_t pos = string_within('[', ']', line, 0, line_length, keyword);
2093 if (keyword[0] == '\0') { // no keyword, no menu entry
2096 size_t len = strlen(keyword);
2097 for (size_t i = 0; i < len; ++i) {
2098 if (keyword[i] != ' ')
2099 key += tolower(keyword[i]);
2103 // get the label enclosed in ()'s
2104 pos = string_within('(', ')', line, pos, line_length, label);
2106 // get the command enclosed in {}'s
2107 pos = string_within('{', '}', line, pos, line_length, command);
2118 menu->insert(label);
2123 if (! (*label && *command)) {
2124 fprintf(stderr, i18n(ScreenSet, ScreenEXECError,
2125 "BScreen::parseMenuFile: [exec] error, "
2126 "no menu label and/or command defined\n"));
2130 menu->insert(label, BScreen::Execute, command);
2136 fprintf(stderr, i18n(ScreenSet, ScreenEXITError,
2137 "BScreen::parseMenuFile: [exit] error, "
2138 "no menu label defined\n"));
2142 menu->insert(label, BScreen::Exit);
2146 case 561: { // style
2147 if (! (*label && *command)) {
2149 i18n(ScreenSet, ScreenSTYLEError,
2150 "BScreen::parseMenuFile: [style] error, "
2151 "no menu label and/or filename defined\n"));
2155 string style = expandTilde(command);
2157 menu->insert(label, BScreen::SetStyle, style.c_str());
2163 fprintf(stderr, i18n(ScreenSet, ScreenCONFIGError,
2164 "BScreen::parseMenufile: [config] error, "
2165 "no label defined"));
2169 menu->insert(label, configmenu);
2173 case 740: { // include
2175 fprintf(stderr, i18n(ScreenSet, ScreenINCLUDEError,
2176 "BScreen::parseMenuFile: [include] error, "
2177 "no filename defined\n"));
2181 string newfile = expandTilde(label);
2182 FILE *submenufile = fopen(newfile.c_str(), "r");
2184 if (! submenufile) {
2185 perror(newfile.c_str());
2190 if (fstat(fileno(submenufile), &buf) ||
2191 ! S_ISREG(buf.st_mode)) {
2193 i18n(ScreenSet, ScreenINCLUDEErrorReg,
2194 "BScreen::parseMenuFile: [include] error: "
2195 "'%s' is not a regular file\n"), newfile.c_str());
2199 if (! feof(submenufile)) {
2200 if (! parseMenuFile(submenufile, menu))
2201 blackbox->addMenuTimestamp(newfile);
2203 fclose(submenufile);
2209 case 767: { // submenu
2211 fprintf(stderr, i18n(ScreenSet, ScreenSUBMENUError,
2212 "BScreen::parseMenuFile: [submenu] error, "
2213 "no menu label defined\n"));
2217 Rootmenu *submenu = new Rootmenu(this);
2220 submenu->setLabel(command);
2222 submenu->setLabel(label);
2224 parseMenuFile(file, submenu);
2226 menu->insert(label, submenu);
2227 rootmenuList.push_back(submenu);
2232 case 773: { // restart
2234 fprintf(stderr, i18n(ScreenSet, ScreenRESTARTError,
2235 "BScreen::parseMenuFile: [restart] error, "
2236 "no menu label defined\n"));
2241 menu->insert(label, BScreen::RestartOther, command);
2243 menu->insert(label, BScreen::Restart);
2248 case 845: { // reconfig
2251 i18n(ScreenSet, ScreenRECONFIGError,
2252 "BScreen::parseMenuFile: [reconfig] error, "
2253 "no menu label defined\n"));
2257 menu->insert(label, BScreen::Reconfigure);
2262 case 995: // stylesdir
2263 case 1113: { // stylesmenu
2264 bool newmenu = ((key == 1113) ? True : False);
2266 if (! *label || (! *command && newmenu)) {
2268 i18n(ScreenSet, ScreenSTYLESDIRError,
2269 "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
2270 " error, no directory defined\n"));
2274 char *directory = ((newmenu) ? command : label);
2276 string stylesdir = expandTilde(directory);
2278 struct stat statbuf;
2280 if (stat(stylesdir.c_str(), &statbuf) == -1) {
2282 i18n(ScreenSet, ScreenSTYLESDIRErrorNoExist,
2283 "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
2284 " error, %s does not exist\n"), stylesdir.c_str());
2287 if (! S_ISDIR(statbuf.st_mode)) {
2289 i18n(ScreenSet, ScreenSTYLESDIRErrorNotDir,
2290 "BScreen::parseMenuFile:"
2291 " [stylesdir/stylesmenu] error, %s is not a"
2292 " directory\n"), stylesdir.c_str());
2296 Rootmenu *stylesmenu;
2299 stylesmenu = new Rootmenu(this);
2303 DIR *d = opendir(stylesdir.c_str());
2305 std::vector<string> ls;
2307 while((p = readdir(d)))
2308 ls.push_back(p->d_name);
2312 std::sort(ls.begin(), ls.end());
2314 std::vector<string>::iterator it = ls.begin(),
2316 for (; it != end; ++it) {
2317 const string& fname = *it;
2319 //ignore backups and dot files
2320 if (fname[fname.size()-1] == '~' || fname[0] == '.')
2323 string style = stylesdir;
2327 if (! stat(style.c_str(), &statbuf) && S_ISREG(statbuf.st_mode))
2328 stylesmenu->insert(fname, BScreen::SetStyle, style);
2331 stylesmenu->update();
2334 stylesmenu->setLabel(label);
2335 menu->insert(label, stylesmenu);
2336 rootmenuList.push_back(stylesmenu);
2339 blackbox->addMenuTimestamp(stylesdir);
2343 case 1090: { // workspaces
2346 i18n(ScreenSet, ScreenWORKSPACESError,
2347 "BScreen:parseMenuFile: [workspaces] error, "
2348 "no menu label defined\n"));
2352 menu->insert(label, workspacemenu);
2358 return ((menu->getCount() == 0) ? True : False);
2362 void BScreen::shutdown(void) {
2363 XSelectInput(blackbox->getXDisplay(), getRootWindow(), NoEventMask);
2364 XSync(blackbox->getXDisplay(), False);
2366 while(! windowList.empty())
2367 unmanageWindow(windowList.front(), True);
2369 while(! desktopWindowList.empty()) {
2370 BlackboxWindow *win = blackbox->searchWindow(desktopWindowList.front());
2372 unmanageWindow(win, True);
2379 void BScreen::showPosition(int x, int y) {
2380 if (! geom_visible) {
2381 XMoveResizeWindow(blackbox->getXDisplay(), geom_window,
2382 (getWidth() - geom_w) / 2,
2383 (getHeight() - geom_h) / 2, geom_w, geom_h);
2384 XMapWindow(blackbox->getXDisplay(), geom_window);
2385 XRaiseWindow(blackbox->getXDisplay(), geom_window);
2387 geom_visible = True;
2392 sprintf(label, i18n(ScreenSet, ScreenPositionFormat,
2393 "X: %4d x Y: %4d"), x, y);
2395 XClearWindow(blackbox->getXDisplay(), geom_window);
2397 resource.wstyle.font->drawString(geom_window,
2398 resource.bevel_width, resource.bevel_width,
2399 resource.wstyle.l_text_focus,
2404 void BScreen::showGeometry(unsigned int gx, unsigned int gy) {
2405 if (! geom_visible) {
2406 XMoveResizeWindow(blackbox->getXDisplay(), geom_window,
2407 (getWidth() - geom_w) / 2,
2408 (getHeight() - geom_h) / 2, geom_w, geom_h);
2409 XMapWindow(blackbox->getXDisplay(), geom_window);
2410 XRaiseWindow(blackbox->getXDisplay(), geom_window);
2412 geom_visible = True;
2417 sprintf(label, i18n(ScreenSet, ScreenGeometryFormat,
2418 "W: %4d x H: %4d"), gx, gy);
2420 XClearWindow(blackbox->getXDisplay(), geom_window);
2422 resource.wstyle.font->drawString(geom_window,
2423 resource.bevel_width, resource.bevel_width,
2424 resource.wstyle.l_text_focus,
2429 void BScreen::hideGeometry(void) {
2431 XUnmapWindow(blackbox->getXDisplay(), geom_window);
2432 geom_visible = False;
2437 void BScreen::addStrut(Strut *strut) {
2438 strutList.push_back(strut);
2442 void BScreen::removeStrut(Strut *strut) {
2443 strutList.remove(strut);
2447 const Rect& BScreen::availableArea(void) const {
2449 return getRect(); // return the full screen
2455 const RectList& BScreen::allAvailableAreas(void) const {
2456 assert(isXineramaActive());
2457 assert(xineramaUsableArea.size() > 0);
2458 fprintf(stderr, "1found x %d y %d w %d h %d\n",
2459 xineramaUsableArea[0].x(), xineramaUsableArea[0].y(),
2460 xineramaUsableArea[0].width(), xineramaUsableArea[0].height());
2461 return xineramaUsableArea;
2466 void BScreen::updateAvailableArea(void) {
2467 Rect old_area = usableArea;
2468 usableArea = getRect(); // reset to full screen
2471 // reset to the full areas
2472 if (isXineramaActive())
2473 xineramaUsableArea = getXineramaAreas();
2476 /* these values represent offsets from the screen edge
2477 * we look for the biggest offset on each edge and then apply them
2479 * do not be confused by the similarity to the names of Rect's members
2481 unsigned int current_left = 0, current_right = 0, current_top = 0,
2484 StrutList::const_iterator it = strutList.begin(), end = strutList.end();
2486 for(; it != end; ++it) {
2488 if (strut->left > current_left)
2489 current_left = strut->left;
2490 if (strut->top > current_top)
2491 current_top = strut->top;
2492 if (strut->right > current_right)
2493 current_right = strut->right;
2494 if (strut->bottom > current_bottom)
2495 current_bottom = strut->bottom;
2498 usableArea.setPos(current_left, current_top);
2499 usableArea.setSize(usableArea.width() - (current_left + current_right),
2500 usableArea.height() - (current_top + current_bottom));
2503 if (isXineramaActive()) {
2504 // keep each of the ximerama-defined areas inside the strut
2505 RectList::iterator xit, xend = xineramaUsableArea.end();
2506 for (xit = xineramaUsableArea.begin(); xit != xend; ++xit) {
2507 if (xit->x() < usableArea.x()) {
2508 xit->setX(usableArea.x());
2509 xit->setWidth(xit->width() - usableArea.x());
2511 if (xit->y() < usableArea.y()) {
2512 xit->setY(usableArea.y());
2513 xit->setHeight(xit->height() - usableArea.y());
2515 if (xit->x() + xit->width() > usableArea.width())
2516 xit->setWidth(usableArea.width() - xit->x());
2517 if (xit->y() + xit->height() > usableArea.height())
2518 xit->setHeight(usableArea.height() - xit->y());
2523 if (old_area != usableArea) {
2524 BlackboxWindowList::iterator it = windowList.begin(),
2525 end = windowList.end();
2526 for (; it != end; ++it)
2527 if ((*it)->isMaximized()) (*it)->remaximize();
2534 Workspace* BScreen::getWorkspace(unsigned int index) const {
2535 assert(index < workspacesList.size());
2536 return workspacesList[index];
2540 void BScreen::buttonPressEvent(const XButtonEvent *xbutton) {
2541 if (xbutton->button == 1) {
2542 if (! isRootColormapInstalled())
2543 image_control->installRootColormap();
2545 if (workspacemenu->isVisible())
2546 workspacemenu->hide();
2548 if (rootmenu->isVisible())
2551 } else if ((xbutton->button == 4 && resource.root_scroll == NormalScroll) ||
2552 (xbutton->button == 5 && resource.root_scroll == ReverseScroll)) {
2553 if (getCurrentWorkspaceID() >= getWorkspaceCount() - 1)
2554 changeWorkspaceID(0);
2556 changeWorkspaceID(getCurrentWorkspaceID() + 1);
2558 } else if ((xbutton->button == 5 && resource.root_scroll == NormalScroll) ||
2559 (xbutton->button == 4 && resource.root_scroll == ReverseScroll)) {
2560 if (getCurrentWorkspaceID() == 0)
2561 changeWorkspaceID(getWorkspaceCount() - 1);
2563 changeWorkspaceID(getCurrentWorkspaceID() - 1);
2566 if (resource.root_menu_button > 0 &&
2567 xbutton->button == resource.root_menu_button)
2568 showRootMenu(xbutton->x_root, xbutton->y_root);
2569 else if (resource.workspace_menu_button > 0 &&
2570 xbutton->button == resource.workspace_menu_button)
2571 showWorkspaceMenu(xbutton->x_root, xbutton->y_root);
2575 void BScreen::showWorkspaceMenu(int x, int y) {
2576 int mx = x - (workspacemenu->getWidth() / 2);
2577 int my = y - (workspacemenu->getTitleHeight() / 2);
2582 if (mx + workspacemenu->getWidth() > getWidth())
2583 mx = getWidth() - workspacemenu->getWidth() - getBorderWidth();
2585 if (my + workspacemenu->getHeight() > getHeight())
2586 my = getHeight() - workspacemenu->getHeight() - getBorderWidth();
2588 workspacemenu->move(mx, my);
2590 if (! workspacemenu->isVisible()) {
2591 workspacemenu->removeParent();
2592 workspacemenu->show();
2597 void BScreen::showRootMenu(int x, int y) {
2598 int mx = x - (rootmenu->getWidth() / 2);
2599 int my = y - (rootmenu->getTitleHeight() / 2);
2604 if (mx + rootmenu->getWidth() > getWidth())
2605 mx = getWidth() - rootmenu->getWidth() - getBorderWidth();
2607 if (my + rootmenu->getHeight() > getHeight())
2608 my = getHeight() - rootmenu->getHeight() - getBorderWidth();
2610 rootmenu->move(mx, my);
2612 if (! rootmenu->isVisible()) {
2613 blackbox->checkMenu();
2619 void BScreen::propertyNotifyEvent(const XPropertyEvent *pe) {
2620 if (pe->atom == xatom->getAtom(XAtom::net_desktop_names)) {
2621 // _NET_WM_DESKTOP_NAMES
2622 WorkspaceList::iterator it = workspacesList.begin();
2623 const WorkspaceList::iterator end = workspacesList.end();
2624 for (; it != end; ++it) {
2625 (*it)->readName(); // re-read its name from the window property
2626 workspacemenu->changeWorkspaceLabel((*it)->getID(), (*it)->getName());
2628 workspacemenu->update();
2629 toolbar->reconfigure();
2630 saveWorkspaceNames();
2635 void BScreen::toggleFocusModel(FocusModel model) {
2636 std::for_each(windowList.begin(), windowList.end(),
2637 std::mem_fun(&BlackboxWindow::ungrabButtons));
2639 if (model == SloppyFocus) {
2640 saveSloppyFocus(True);
2642 // we're cheating here to save writing the config file 3 times
2643 resource.auto_raise = False;
2644 resource.click_raise = False;
2645 saveSloppyFocus(False);
2648 std::for_each(windowList.begin(), windowList.end(),
2649 std::mem_fun(&BlackboxWindow::grabButtons));
2652 #ifdef BITMAPBUTTONS
2653 void BScreen::readDatabaseMask(const string &rname, PixmapMask &pixmapMask,
2654 const Configuration &style) {
2656 int hx, hy; //ignored
2657 int ret = BitmapOpenFailed; //default to failure.
2659 if (style.getValue(rname, s))
2661 if (s[0] != '/' && s[0] != '~')
2663 std::string xbmFile;
2664 xbmFile = "~/.openbox/buttons/" + s;
2665 ret = XReadBitmapFile(blackbox->getXDisplay(), getRootWindow(),
2666 expandTilde(xbmFile).c_str(), &pixmapMask.w,
2667 &pixmapMask.h, &pixmapMask.mask, &hx, &hy);
2668 if (ret != BitmapSuccess) {
2669 xbmFile = std::string(BUTTONSDIR) + "/" + s;
2670 ret = XReadBitmapFile(blackbox->getXDisplay(), getRootWindow(),
2671 expandTilde(xbmFile).c_str(), &pixmapMask.w,
2672 &pixmapMask.h, &pixmapMask.mask, &hx, &hy);
2675 ret = XReadBitmapFile(blackbox->getXDisplay(), getRootWindow(),
2676 expandTilde(s).c_str(), &pixmapMask.w,
2677 &pixmapMask.h, &pixmapMask.mask, &hx, &hy);
2679 if (ret == BitmapSuccess)
2683 pixmapMask.mask = None;
2684 pixmapMask.w = pixmapMask.h = 0;
2686 #endif // BITMAPSUCCESS
2688 BTexture BScreen::readDatabaseTexture(const string &rname,
2689 const string &default_color,
2690 const Configuration &style,
2691 bool allowNoTexture) {
2695 if (style.getValue(rname, s))
2696 texture = BTexture(s);
2697 else if (allowNoTexture) //no default
2698 texture.setTexture(BTexture::NoTexture);
2700 texture.setTexture(BTexture::Solid | BTexture::Flat);
2702 // associate this texture with this screen
2703 texture.setDisplay(getBaseDisplay(), getScreenNumber());
2704 texture.setImageControl(image_control);
2706 if (texture.texture() != BTexture::NoTexture) {
2707 texture.setColor(readDatabaseColor(rname + ".color", default_color,
2709 texture.setColorTo(readDatabaseColor(rname + ".colorTo", default_color,
2711 texture.setBorderColor(readDatabaseColor(rname + ".borderColor",
2712 default_color, style));
2719 BColor BScreen::readDatabaseColor(const string &rname,
2720 const string &default_color,
2721 const Configuration &style) {
2724 if (style.getValue(rname, s))
2725 color = BColor(s, getBaseDisplay(), getScreenNumber());
2727 color = BColor(default_color, getBaseDisplay(), getScreenNumber());
2732 BFont *BScreen::readDatabaseFont(const string &rbasename,
2733 const Configuration &style) {
2740 if (style.getValue(rbasename + "xft.font", s) &&
2741 style.getValue(rbasename + "xft.size", i)) {
2744 bool italic = False;
2745 bool dropShadow = False;
2747 if (style.getValue(rbasename + "xft.flags", s)) {
2748 if (s.find("bold") != string::npos)
2750 if (s.find("italic") != string::npos)
2752 if (s.find("shadow") != string::npos)
2756 unsigned char offset = 1;
2757 if (style.getValue(rbasename + "xft.shadow.offset", s)) {
2758 offset = atoi(s.c_str()); //doesn't detect errors
2759 if (offset > CHAR_MAX)
2764 if (style.getValue(rbasename + "xft.shadow.tint", s)) {
2765 tint = atoi(s.c_str());
2768 if (tint > 100) tint = 100;
2769 else if (tint < -100) tint = -100;
2771 BFont *b = new BFont(blackbox->getXDisplay(), this, family, i, bold,
2772 italic, dropShadow && resource.shadow_fonts, offset,
2773 tint, resource.aa_fonts);
2777 delete b; // fall back to the normal X font stuff
2781 style.getValue(rbasename + "font", s);
2782 // if this fails, a blank string will be used, which will cause the fallback
2785 BFont *b = new BFont(blackbox->getXDisplay(), this, s);
2787 exit(2); // can't continue without a font