]> Dogcows Code - chaz/openbox/blob - src/Screen.cc
merged bitmap buttons
[chaz/openbox] / src / Screen.cc
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)
5 //
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:
12 //
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
15 //
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.
23
24 #ifdef HAVE_CONFIG_H
25 #include "../config.h"
26 #endif // HAVE_CONFIG_H
27
28 extern "C" {
29 #include <X11/Xatom.h>
30 #include <X11/keysym.h>
31
32 #ifdef XINERAMA
33 # include <X11/Xlib.h>
34 # include <X11/extensions/Xinerama.h>
35 #endif // XINERAMA
36
37 #ifdef HAVE_STDLIB_H
38 # include <stdlib.h>
39 #endif // HAVE_STDLIB_H
40
41 #ifdef HAVE_STRING_H
42 # include <string.h>
43 #endif // HAVE_STRING_H
44
45 #ifdef HAVE_CTYPE_H
46 # include <ctype.h>
47 #endif // HAVE_CTYPE_H
48
49 #ifdef HAVE_UNISTD_H
50 # include <sys/types.h>
51 # include <unistd.h>
52 #endif // HAVE_UNISTD_H
53
54 #ifdef HAVE_DIRENT_H
55 # include <dirent.h>
56 #endif // HAVE_DIRENT_H
57
58 #ifdef HAVE_LOCALE_H
59 # include <locale.h>
60 #endif // HAVE_LOCALE_H
61
62 #ifdef HAVE_SYS_STAT_H
63 # include <sys/stat.h>
64 #endif // HAVE_SYS_STAT_H
65
66 #ifdef HAVE_STDARG_H
67 # include <stdarg.h>
68 #endif // HAVE_STDARG_H
69 }
70
71 #include <assert.h>
72
73 #include <algorithm>
74 #include <functional>
75 #include <string>
76 using std::string;
77
78 #include "i18n.hh"
79 #include "blackbox.hh"
80 #include "Clientmenu.hh"
81 #include "Font.hh"
82 #include "GCCache.hh"
83 #include "Iconmenu.hh"
84 #include "Image.hh"
85 #include "Screen.hh"
86 #include "Slit.hh"
87 #include "Rootmenu.hh"
88 #include "Toolbar.hh"
89 #include "Util.hh"
90 #include "Window.hh"
91 #include "Workspace.hh"
92 #include "Workspacemenu.hh"
93 #include "Util.hh"
94 #include "XAtom.hh"
95
96 #ifndef FONT_ELEMENT_SIZE
97 #define FONT_ELEMENT_SIZE 50
98 #endif // FONT_ELEMENT_SIZE
99
100
101 static bool running = True;
102
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));
108
109 running = False;
110
111 return(-1);
112 }
113
114
115 BScreen::BScreen(Blackbox *bb, unsigned int scrn) : ScreenInfo(bb, scrn) {
116 blackbox = bb;
117 screenstr = "session.screen" + itostring(scrn) + '.';
118 config = blackbox->getConfig();
119 xatom = blackbox->getXAtom();
120
121 event_mask = ColormapChangeMask | EnterWindowMask | PropertyChangeMask |
122 SubstructureRedirectMask | ButtonPressMask | ButtonReleaseMask;
123
124 XErrorHandler old = XSetErrorHandler((XErrorHandler) anotherWMRunning);
125 XSelectInput(getBaseDisplay()->getXDisplay(), getRootWindow(), event_mask);
126 XSync(getBaseDisplay()->getXDisplay(), False);
127 XSetErrorHandler((XErrorHandler) old);
128
129 managed = running;
130 if (! managed) return;
131
132 fprintf(stderr, i18n(ScreenSet, ScreenManagingScreen,
133 "BScreen::BScreen: managing screen %d "
134 "using visual 0x%lx, depth %d\n"),
135 getScreenNumber(), XVisualIDFromVisual(getVisual()),
136 getDepth());
137
138 rootmenu = 0;
139
140 resource.mstyle.t_font = resource.mstyle.f_font = resource.tstyle.font =
141 resource.wstyle.font = (BFont *) 0;
142
143 geom_pixmap = None;
144
145 xatom->setSupported(this); // set-up netwm support
146 #ifdef HAVE_GETPID
147 xatom->setValue(getRootWindow(), XAtom::blackbox_pid, XAtom::cardinal,
148 (unsigned long) getpid());
149 #endif // HAVE_GETPID
150 unsigned long geometry[] = { getWidth(),
151 getHeight()};
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);
157
158
159 XDefineCursor(blackbox->getXDisplay(), getRootWindow(),
160 blackbox->getSessionCursor());
161
162 updateAvailableArea();
163
164 image_control =
165 new BImageControl(blackbox, this, True, blackbox->getColorsPerChannel(),
166 blackbox->getCacheLife(), blackbox->getCacheMax());
167 image_control->installRootColormap();
168 root_colormap_installed = True;
169
170 load_rc();
171 LoadStyle();
172
173 XGCValues gcv;
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);
180
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;
185
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;
191
192 geom_window = XCreateWindow(blackbox->getXDisplay(), getRootWindow(),
193 0, 0, geom_w, geom_h, resource.border_width,
194 getDepth(), InputOutput, getVisual(),
195 mask, &attrib);
196 geom_visible = False;
197
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);
203 }
204 if (! geom_pixmap)
205 XSetWindowBackground(blackbox->getXDisplay(), geom_window,
206 texture->color().pixel());
207 else
208 XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
209 geom_window, geom_pixmap);
210
211 workspacemenu = new Workspacemenu(this);
212 iconmenu = new Iconmenu(this);
213 configmenu = new Configmenu(this);
214
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();
221
222 }
223 } else {
224 Workspace *wkspc = new Workspace(this, workspacesList.size());
225 workspacesList.push_back(wkspc);
226 workspacemenu->insertWorkspace(wkspc);
227 workspacemenu->update();
228 }
229 saveWorkspaceNames();
230
231 updateNetizenWorkspaceCount();
232
233 workspacemenu->insert(i18n(IconSet, IconIcons, "Icons"), iconmenu);
234 workspacemenu->update();
235
236 current_workspace = workspacesList.front();
237
238 xatom->setValue(getRootWindow(), XAtom::net_current_desktop,
239 XAtom::cardinal, 0); //first workspace
240
241 workspacemenu->setItemSelected(2, True);
242
243 toolbar = new Toolbar(this);
244
245 slit = new Slit(this);
246
247 InitMenu();
248
249 raiseWindows(0, 0); // this also initializes the empty stacking list
250 rootmenu->update();
251
252 updateClientList(); // initialize the client lists, which will be empty
253 updateAvailableArea();
254
255 changeWorkspaceID(0);
256
257 unsigned int i, j, nchild;
258 Window r, p, *children;
259 XQueryTree(blackbox->getXDisplay(), getRootWindow(), &r, &p,
260 &children, &nchild);
261
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;
265
266 XWMHints *wmhints = XGetWMHints(blackbox->getXDisplay(),
267 children[i]);
268
269 if (wmhints) {
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) {
274 children[j] = None;
275 break;
276 }
277 }
278 }
279
280 XFree(wmhints);
281 }
282 }
283
284 // manage shown windows
285 for (i = 0; i < nchild; ++i) {
286 if (children[i] == None || ! blackbox->validateWindow(children[i]))
287 continue;
288
289 XWindowAttributes attrib;
290 if (XGetWindowAttributes(blackbox->getXDisplay(), children[i], &attrib)) {
291 if (attrib.override_redirect) continue;
292
293 if (attrib.map_state != IsUnmapped) {
294 manageWindow(children[i]);
295 }
296 }
297 }
298
299 XFree(children);
300
301 // call this again just in case a window we found updates the Strut list
302 updateAvailableArea();
303 }
304
305
306 BScreen::~BScreen(void) {
307 if (! managed) return;
308
309 if (geom_pixmap != None)
310 image_control->removeImage(geom_pixmap);
311
312 if (geom_window != None)
313 XDestroyWindow(blackbox->getXDisplay(), geom_window);
314
315 std::for_each(workspacesList.begin(), workspacesList.end(),
316 PointerAssassin());
317
318 std::for_each(iconList.begin(), iconList.end(), PointerAssassin());
319
320 std::for_each(netizenList.begin(), netizenList.end(), PointerAssassin());
321
322 while (! systrayWindowList.empty())
323 removeSystrayWindow(systrayWindowList[0]);
324
325 delete rootmenu;
326 delete workspacemenu;
327 delete iconmenu;
328 delete configmenu;
329 delete slit;
330 delete toolbar;
331 delete image_control;
332
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;
341
342 if (resource.wstyle.close_button.mask != None)
343 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.close_button.mask);
344 if (resource.wstyle.max_button.mask != None)
345 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.max_button.mask);
346 if (resource.wstyle.icon_button.mask != None)
347 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.icon_button.mask);
348 if (resource.wstyle.stick_button.mask != None)
349 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.stick_button.mask);
350
351 if (resource.tstyle.left_button.mask != None)
352 XFreePixmap(blackbox->getXDisplay(), resource.tstyle.left_button.mask);
353 if (resource.tstyle.right_button.mask != None)
354 XFreePixmap(blackbox->getXDisplay(), resource.tstyle.right_button.mask);
355
356 if (resource.mstyle.bullet_image.mask != None)
357 XFreePixmap(blackbox->getXDisplay(), resource.mstyle.bullet_image.mask);
358 if (resource.mstyle.tick_image.mask != None)
359 XFreePixmap(blackbox->getXDisplay(), resource.mstyle.tick_image.mask);
360
361 resource.wstyle.max_button.mask = resource.wstyle.close_button.mask =
362 resource.wstyle.icon_button.mask =
363 resource.wstyle.stick_button.mask = None;
364 resource.tstyle.left_button.mask = resource.tstyle.right_button.mask = None;
365 resource.mstyle.bullet_image.mask = resource.mstyle.tick_image.mask = None;
366
367 XFreeGC(blackbox->getXDisplay(), opGC);
368 }
369
370
371 void BScreen::saveSloppyFocus(bool s) {
372 resource.sloppy_focus = s;
373
374 string fmodel;
375 if (resource.sloppy_focus) {
376 fmodel = "SloppyFocus";
377 if (resource.auto_raise) fmodel += " AutoRaise";
378 if (resource.click_raise) fmodel += " ClickRaise";
379 } else {
380 fmodel = "ClickToFocus";
381 }
382 config->setValue(screenstr + "focusModel", fmodel);
383 }
384
385
386 void BScreen::saveAutoRaise(bool a) {
387 resource.auto_raise = a;
388 saveSloppyFocus(resource.sloppy_focus);
389 }
390
391
392 void BScreen::saveClickRaise(bool c) {
393 resource.click_raise = c;
394 saveSloppyFocus(resource.sloppy_focus);
395 }
396
397
398 void BScreen::saveImageDither(bool d) {
399 image_control->setDither(d);
400 config->setValue(screenstr + "imageDither", doImageDither());
401 }
402
403
404 void BScreen::saveOpaqueMove(bool o) {
405 resource.opaque_move = o;
406 config->setValue(screenstr + "opaqueMove", resource.opaque_move);
407 }
408
409
410 void BScreen::saveFullMax(bool f) {
411 resource.full_max = f;
412 config->setValue(screenstr + "fullMaximization", resource.full_max);
413 }
414
415
416 void BScreen::saveFocusNew(bool f) {
417 resource.focus_new = f;
418 config->setValue(screenstr + "focusNewWindows", resource.focus_new);
419 }
420
421
422 void BScreen::saveFocusLast(bool f) {
423 resource.focus_last = f;
424 config->setValue(screenstr + "focusLastWindow", resource.focus_last);
425 }
426
427
428 void BScreen::saveAAFonts(bool f) {
429 resource.aa_fonts = f;
430 reconfigure();
431 config->setValue(screenstr + "antialiasFonts", resource.aa_fonts);
432 }
433
434
435 void BScreen::saveShadowFonts(bool f) {
436 resource.shadow_fonts = f;
437 reconfigure();
438 config->setValue(screenstr + "dropShadowFonts", resource.shadow_fonts);
439 }
440
441
442 void BScreen::saveHideToolbar(bool h) {
443 resource.hide_toolbar = h;
444 if (resource.hide_toolbar)
445 toolbar->unmapToolbar();
446 else
447 toolbar->mapToolbar();
448 config->setValue(screenstr + "hideToolbar", resource.hide_toolbar);
449 }
450
451
452 void BScreen::saveWindowToEdgeSnap(int s) {
453 resource.snap_to_edges = s;
454
455 const char *snap;
456 switch (resource.snap_to_edges) {
457 case WindowNoSnap: snap = "NoSnap"; break;
458 case WindowResistance: snap = "Resistance"; break;
459 case WindowSnap: default: snap = "Snap"; break;
460 }
461 config->setValue(screenstr + "windowToEdgeSnap", snap);
462 }
463
464
465 void BScreen::saveWindowToWindowSnap(int s) {
466 resource.snap_to_windows = s;
467
468 const char *snap;
469 switch (resource.snap_to_windows) {
470 case WindowNoSnap: snap = "NoSnap"; break;
471 case WindowResistance: snap = "Resistance"; break;
472 case WindowSnap: default: snap = "Snap"; break;
473 }
474 config->setValue(screenstr + "windowToWindowSnap", snap);
475 }
476
477
478 void BScreen::saveResizeZones(unsigned int z) {
479 resource.resize_zones = z;
480 config->setValue(screenstr + "resizeZones", resource.resize_zones);
481 }
482
483
484 void BScreen::saveWindowCornerSnap(bool s) {
485 resource.window_corner_snap = s;
486 config->setValue(screenstr + "windowCornerSnap",
487 resource.window_corner_snap);
488 }
489
490
491 void BScreen::saveWorkspaces(unsigned int w) {
492 resource.workspaces = w;
493 config->setValue(screenstr + "workspaces", resource.workspaces);
494 }
495
496
497 void BScreen::savePlacementPolicy(int p) {
498 resource.placement_policy = p;
499 const char *placement;
500 switch (resource.placement_policy) {
501 case CascadePlacement: placement = "CascadePlacement"; break;
502 case UnderMousePlacement: placement = "UnderMousePlacement"; break;
503 case ClickMousePlacement: placement = "ClickMousePlacement"; break;
504 case ColSmartPlacement: placement = "ColSmartPlacement"; break;
505 case RowSmartPlacement: default: placement = "RowSmartPlacement"; break;
506 }
507 config->setValue(screenstr + "windowPlacement", placement);
508 }
509
510
511 void BScreen::saveResistanceSize(int s) {
512 resource.resistance_size = s;
513 config->setValue(screenstr + "resistanceSize",
514 resource.resistance_size);
515 }
516
517
518 void BScreen::saveSnapThreshold(int t) {
519 resource.snap_threshold = t;
520 config->setValue(screenstr + "edgeSnapThreshold",
521 resource.snap_threshold);
522 }
523
524
525 void BScreen::saveSnapOffset(int t) {
526 resource.snap_offset = t;
527 config->setValue(screenstr + "edgeSnapOffset",
528 resource.snap_offset);
529 }
530
531
532 void BScreen::saveRowPlacementDirection(int d) {
533 resource.row_direction = d;
534 config->setValue(screenstr + "rowPlacementDirection",
535 resource.row_direction == LeftRight ?
536 "LeftToRight" : "RightToLeft");
537 }
538
539
540 void BScreen::saveColPlacementDirection(int d) {
541 resource.col_direction = d;
542 config->setValue(screenstr + "colPlacementDirection",
543 resource.col_direction == TopBottom ?
544 "TopToBottom" : "BottomToTop");
545 }
546
547
548 #ifdef HAVE_STRFTIME
549 void BScreen::saveStrftimeFormat(const std::string& format) {
550 resource.strftime_format = format;
551 config->setValue(screenstr + "strftimeFormat", resource.strftime_format);
552 }
553
554 #else // !HAVE_STRFTIME
555
556 void BScreen::saveDateFormat(int f) {
557 resource.date_format = f;
558 config->setValue(screenstr + "dateFormat",
559 resource.date_format == B_EuropeanDate ?
560 "European" : "American");
561 }
562
563
564 void BScreen::saveClock24Hour(bool c) {
565 resource.clock24hour = c;
566 config->setValue(screenstr + "clockFormat", resource.clock24hour ? 24 : 12);
567 }
568 #endif // HAVE_STRFTIME
569
570
571 void BScreen::saveWorkspaceNames() {
572 string names;
573
574 for (unsigned int i = 0; i < workspacesList.size(); ++i) {
575 names += workspacesList[i]->getName();
576 if (i < workspacesList.size() - 1)
577 names += ',';
578 }
579
580 config->setValue(screenstr + "workspaceNames", names);
581 }
582
583
584 void BScreen::savePlaceIgnoreShaded(bool i) {
585 resource.ignore_shaded = i;
586 config->setValue(screenstr + "placementIgnoreShaded",
587 resource.ignore_shaded);
588 }
589
590
591 void BScreen::savePlaceIgnoreMaximized(bool i) {
592 resource.ignore_maximized = i;
593 config->setValue(screenstr + "placementIgnoreMaximized",
594 resource.ignore_maximized);
595 }
596
597
598 void BScreen::saveAllowScrollLock(bool a) {
599 resource.allow_scroll_lock = a;
600 config->setValue(screenstr + "disableBindingsWithScrollLock",
601 resource.allow_scroll_lock);
602 }
603
604
605 void BScreen::saveWorkspaceWarping(bool w) {
606 resource.workspace_warping = w;
607 config->setValue(screenstr + "workspaceWarping",
608 resource.workspace_warping);
609 }
610
611
612 void BScreen::saveRootScrollDirection(int d) {
613 resource.root_scroll = d;
614 const char *dir;
615 switch (resource.root_scroll) {
616 case NoScroll: dir = "None"; break;
617 case ReverseScroll: dir = "Reverse"; break;
618 case NormalScroll: default: dir = "Normal"; break;
619 }
620 config->setValue(screenstr + "rootScrollDirection", dir);
621 }
622
623
624 void BScreen::saveRootMenuButton(unsigned int b) {
625 resource.root_menu_button = b;
626 const char *but;
627 switch (resource.root_menu_button) {
628 case 0: but = "None"; break;
629 case 1: but = "Left"; break;
630 case 2: but = "Middle"; break;
631 case 3: default: but = "Right"; break;
632 }
633 config->setValue(screenstr + "rootMenuButton", but);
634 }
635
636
637 void BScreen::saveWorkspaceMenuButton(unsigned int b) {
638 resource.workspace_menu_button = b;
639 const char *but;
640 switch (resource.workspace_menu_button) {
641 case 0: but = "None"; break;
642 case 1: but = "Left"; break;
643 case 2: default: but = "Middle"; break;
644 case 3: but = "Right"; break;
645 }
646 config->setValue(screenstr + "workspaceMenuButton", but);
647 }
648
649
650 void BScreen::save_rc(void) {
651 saveSloppyFocus(resource.sloppy_focus);
652 saveAutoRaise(resource.auto_raise);
653 saveImageDither(doImageDither());
654 saveShadowFonts(resource.shadow_fonts);
655 saveAAFonts(resource.aa_fonts);
656 saveResizeZones(resource.resize_zones);
657 saveOpaqueMove(resource.opaque_move);
658 saveFullMax(resource.full_max);
659 saveFocusNew(resource.focus_new);
660 saveFocusLast(resource.focus_last);
661 saveHideToolbar(resource.hide_toolbar);
662 saveWindowToWindowSnap(resource.snap_to_windows);
663 saveWindowToEdgeSnap(resource.snap_to_edges);
664 saveWindowCornerSnap(resource.window_corner_snap);
665 saveWorkspaces(resource.workspaces);
666 savePlacementPolicy(resource.placement_policy);
667 saveSnapThreshold(resource.snap_threshold);
668 saveSnapOffset(resource.snap_offset);
669 saveResistanceSize(resource.resistance_size);
670 saveRowPlacementDirection(resource.row_direction);
671 saveColPlacementDirection(resource.col_direction);
672 #ifdef HAVE_STRFTIME
673 saveStrftimeFormat(resource.strftime_format);
674 #else // !HAVE_STRFTIME
675 saveDateFormat(resource.date_format);
676 savwClock24Hour(resource.clock24hour);
677 #endif // HAVE_STRFTIME
678 savePlaceIgnoreShaded(resource.ignore_shaded);
679 savePlaceIgnoreMaximized(resource.ignore_maximized);
680 saveAllowScrollLock(resource.allow_scroll_lock);
681 saveWorkspaceWarping(resource.workspace_warping);
682 saveRootScrollDirection(resource.root_scroll);
683 saveRootMenuButton(resource.root_menu_button);
684 saveWorkspaceMenuButton(resource.workspace_menu_button);
685
686 toolbar->save_rc();
687 slit->save_rc();
688 }
689
690
691 void BScreen::load_rc(void) {
692 std::string s;
693 bool b;
694
695 if (! config->getValue(screenstr + "fullMaximization", resource.full_max))
696 resource.full_max = false;
697
698 if (! config->getValue(screenstr + "focusNewWindows", resource.focus_new))
699 resource.focus_new = false;
700
701 if (! config->getValue(screenstr + "focusLastWindow", resource.focus_last))
702 resource.focus_last = false;
703
704 if (! config->getValue(screenstr + "workspaces", resource.workspaces))
705 resource.workspaces = 1;
706
707 if (! config->getValue(screenstr + "opaqueMove", resource.opaque_move))
708 resource.opaque_move = false;
709
710 if (! config->getValue(screenstr + "dropShadowFonts", resource.shadow_fonts))
711 resource.shadow_fonts = false;
712
713 if (! config->getValue(screenstr + "antialiasFonts", resource.aa_fonts))
714 resource.aa_fonts = true;
715
716 if (! config->getValue(screenstr + "resizeZones", resource.resize_zones) ||
717 (resource.resize_zones != 1 && resource.resize_zones != 2 &&
718 resource.resize_zones != 4))
719 resource.resize_zones = 4;
720
721 if (! config->getValue(screenstr + "hideToolbar", resource.hide_toolbar))
722 resource.hide_toolbar = false;
723
724 resource.snap_to_windows = WindowResistance;
725 if (config->getValue(screenstr + "windowToWindowSnap", s)) {
726 if (s == "NoSnap")
727 resource.snap_to_windows = WindowNoSnap;
728 else if (s == "Snap")
729 resource.snap_to_windows = WindowSnap;
730 }
731
732 resource.snap_to_edges = WindowResistance;
733 if (config->getValue(screenstr + "windowToEdgeSnap", s)) {
734 if (s == "NoSnap")
735 resource.snap_to_edges = WindowNoSnap;
736 else if (s == "Snap")
737 resource.snap_to_edges = WindowSnap;
738 }
739
740 if (! config->getValue(screenstr + "windowCornerSnap",
741 resource.window_corner_snap))
742 resource.window_corner_snap = true;
743
744 if (! config->getValue(screenstr + "imageDither", b))
745 b = true;
746 image_control->setDither(b);
747
748 if (! config->getValue(screenstr + "edgeSnapOffset",
749 resource.snap_offset))
750 resource.snap_offset = 0;
751 if (resource.snap_offset > 50) // sanity check, setting this huge would
752 resource.snap_offset = 50; // seriously suck.
753
754 if (! config->getValue(screenstr + "edgeSnapThreshold",
755 resource.snap_threshold))
756 resource.snap_threshold = 4;
757
758 if (! config->getValue(screenstr + "resistanceSize",
759 resource.resistance_size))
760 resource.resistance_size = 18;
761
762 if (config->getValue(screenstr + "rowPlacementDirection", s) &&
763 s == "RightToLeft")
764 resource.row_direction = RightLeft;
765 else
766 resource.row_direction = LeftRight;
767
768 if (config->getValue(screenstr + "colPlacementDirection", s) &&
769 s == "BottomToTop")
770 resource.col_direction = BottomTop;
771 else
772 resource.col_direction = TopBottom;
773
774 if (config->getValue(screenstr + "workspaceNames", s)) {
775 XAtom::StringVect workspaceNames;
776
777 string::const_iterator it = s.begin(), end = s.end();
778 while(1) {
779 string::const_iterator tmp = it; // current string.begin()
780 it = std::find(tmp, end, ','); // look for comma between tmp and end
781 workspaceNames.push_back(string(tmp, it)); // s[tmp:it]
782 if (it == end)
783 break;
784 ++it;
785 }
786
787 xatom->setValue(getRootWindow(), XAtom::net_desktop_names, XAtom::utf8,
788 workspaceNames);
789 }
790
791 resource.sloppy_focus = true;
792 resource.auto_raise = false;
793 resource.click_raise = false;
794 if (config->getValue(screenstr + "focusModel", s)) {
795 if (s.find("ClickToFocus") != string::npos) {
796 resource.sloppy_focus = false;
797 } else {
798 // must be sloppy
799 if (s.find("AutoRaise") != string::npos)
800 resource.auto_raise = true;
801 if (s.find("ClickRaise") != string::npos)
802 resource.click_raise = true;
803 }
804 }
805
806 if (config->getValue(screenstr + "windowPlacement", s)) {
807 if (s == "CascadePlacement")
808 resource.placement_policy = CascadePlacement;
809 else if (s == "UnderMousePlacement")
810 resource.placement_policy = UnderMousePlacement;
811 else if (s == "ClickMousePlacement")
812 resource.placement_policy = ClickMousePlacement;
813 else if (s == "ColSmartPlacement")
814 resource.placement_policy = ColSmartPlacement;
815 else //if (s == "RowSmartPlacement")
816 resource.placement_policy = RowSmartPlacement;
817 } else
818 resource.placement_policy = RowSmartPlacement;
819
820 #ifdef HAVE_STRFTIME
821 if (! config->getValue(screenstr + "strftimeFormat",
822 resource.strftime_format))
823 resource.strftime_format = "%I:%M %p";
824 #else // !HAVE_STRFTIME
825 long l;
826
827 if (config->getValue(screenstr + "dateFormat", s) && s == "European")
828 resource.date_format = B_EuropeanDate;
829 else
830 resource.date_format = B_AmericanDate;
831
832 if (! config->getValue(screenstr + "clockFormat", l))
833 l = 12;
834 resource.clock24hour = l == 24;
835 #endif // HAVE_STRFTIME
836
837 if (! config->getValue(screenstr + "placementIgnoreShaded",
838 resource.ignore_shaded))
839 resource.ignore_shaded = true;
840
841 if (! config->getValue(screenstr + "placementIgnoreMaximized",
842 resource.ignore_maximized))
843 resource.ignore_maximized = true;
844
845 if (! config->getValue(screenstr + "disableBindingsWithScrollLock",
846 resource.allow_scroll_lock))
847 resource.allow_scroll_lock = false;
848
849 if (! config->getValue(screenstr + "workspaceWarping",
850 resource.workspace_warping))
851 resource.workspace_warping = false;
852
853 resource.root_scroll = NormalScroll;
854 if (config->getValue(screenstr + "rootScrollDirection", s)) {
855 if (s == "None")
856 resource.root_scroll = NoScroll;
857 else if (s == "Reverse")
858 resource.root_scroll = ReverseScroll;
859 }
860
861 resource.root_menu_button = 3;
862 if (config->getValue(screenstr + "rootMenuButton", s)) {
863 if (s == "None")
864 resource.root_menu_button = 0;
865 else if (s == "Left")
866 resource.root_menu_button = 1;
867 else if (s == "Middle")
868 resource.root_menu_button = 2;
869 }
870
871 resource.workspace_menu_button = 2;
872 if (config->getValue(screenstr + "workspaceMenuButton", s)) {
873 if (s == "None")
874 resource.workspace_menu_button = 0;
875 else if (s == "Left")
876 resource.workspace_menu_button = 1;
877 else if (s == "Right")
878 resource.workspace_menu_button = 3;
879 }
880 // cant both be the same
881 if (resource.workspace_menu_button == resource.root_menu_button)
882 resource.workspace_menu_button = 0;
883 }
884
885
886 void BScreen::changeWorkspaceCount(unsigned int new_count) {
887 assert(new_count > 0);
888
889 if (new_count < workspacesList.size()) {
890 // shrink
891 for (unsigned int i = workspacesList.size(); i > new_count; --i)
892 removeLastWorkspace();
893 // removeLast already sets the current workspace to the
894 // last available one.
895 } else if (new_count > workspacesList.size()) {
896 // grow
897 for(unsigned int i = workspacesList.size(); i < new_count; ++i)
898 addWorkspace();
899 }
900 }
901
902
903 void BScreen::reconfigure(void) {
904 // don't reconfigure while saving the initial rc file, it's a waste and it
905 // breaks somethings (workspace names)
906 if (blackbox->isStartup()) return;
907
908 load_rc();
909 toolbar->load_rc();
910 slit->load_rc();
911 LoadStyle();
912
913 // we need to do this explicitly, because just loading this value from the rc
914 // does nothing
915 changeWorkspaceCount(resource.workspaces);
916
917 XGCValues gcv;
918 gcv.foreground = WhitePixel(blackbox->getXDisplay(),
919 getScreenNumber());
920 gcv.function = GXinvert;
921 gcv.subwindow_mode = IncludeInferiors;
922 XChangeGC(blackbox->getXDisplay(), opGC,
923 GCForeground | GCFunction | GCSubwindowMode, &gcv);
924
925 const char *s = i18n(ScreenSet, ScreenPositionLength,
926 "0: 0000 x 0: 0000");
927
928 geom_w = resource.wstyle.font->measureString(s) + resource.bevel_width * 2;
929 geom_h = resource.wstyle.font->height() + resource.bevel_width * 2;
930
931 BTexture* texture = &(resource.wstyle.l_focus);
932 geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap);
933 if (geom_pixmap == ParentRelative) {
934 texture = &(resource.wstyle.t_focus);
935 geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap);
936 }
937 if (! geom_pixmap)
938 XSetWindowBackground(blackbox->getXDisplay(), geom_window,
939 texture->color().pixel());
940 else
941 XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
942 geom_window, geom_pixmap);
943
944 XSetWindowBorderWidth(blackbox->getXDisplay(), geom_window,
945 resource.border_width);
946 XSetWindowBorder(blackbox->getXDisplay(), geom_window,
947 resource.border_color.pixel());
948
949 workspacemenu->reconfigure();
950 iconmenu->reconfigure();
951
952 typedef std::vector<int> SubList;
953 SubList remember_subs;
954
955 // save the current open menus
956 Basemenu *menu = rootmenu;
957 int submenu;
958 while ((submenu = menu->getCurrentSubmenu()) >= 0) {
959 remember_subs.push_back(submenu);
960 menu = menu->find(submenu)->submenu();
961 assert(menu);
962 }
963
964 InitMenu();
965 raiseWindows(0, 0);
966 rootmenu->reconfigure();
967
968 // reopen the saved menus
969 menu = rootmenu;
970 const SubList::iterator subs_end = remember_subs.end();
971 for (SubList::iterator it = remember_subs.begin(); it != subs_end; ++it) {
972 menu->drawSubmenu(*it);
973 menu = menu->find(*it)->submenu();
974 if (! menu)
975 break;
976 }
977
978 configmenu->reconfigure();
979
980 toolbar->reconfigure();
981
982 slit->reconfigure();
983
984 std::for_each(workspacesList.begin(), workspacesList.end(),
985 std::mem_fun(&Workspace::reconfigure));
986
987 BlackboxWindowList::iterator iit = iconList.begin();
988 for (; iit != iconList.end(); ++iit) {
989 BlackboxWindow *bw = *iit;
990 if (bw->validateClient())
991 bw->reconfigure();
992 }
993
994 image_control->timeout();
995 }
996
997
998 void BScreen::rereadMenu(void) {
999 InitMenu();
1000 raiseWindows(0, 0);
1001
1002 rootmenu->reconfigure();
1003 }
1004
1005
1006 void BScreen::LoadStyle(void) {
1007 Configuration style(False);
1008
1009 const char *sfile = blackbox->getStyleFilename();
1010 if (sfile != NULL) {
1011 style.setFile(sfile);
1012 if (! style.load()) {
1013 style.setFile(DEFAULTSTYLE);
1014 if (! style.load())
1015 style.create(); // hardcoded default values will be used.
1016 }
1017 }
1018
1019 // merge in the rc file
1020 style.merge(config->file(), True);
1021
1022 string s;
1023
1024 // load fonts/fontsets
1025 if (resource.wstyle.font)
1026 delete resource.wstyle.font;
1027 if (resource.tstyle.font)
1028 delete resource.tstyle.font;
1029 if (resource.mstyle.f_font)
1030 delete resource.mstyle.f_font;
1031 if (resource.mstyle.t_font)
1032 delete resource.mstyle.t_font;
1033 resource.wstyle.font = resource.tstyle.font = resource.mstyle.f_font =
1034 resource.mstyle.t_font = (BFont *) 0;
1035
1036 resource.wstyle.font = readDatabaseFont("window.", style);
1037 resource.tstyle.font = readDatabaseFont("toolbar.", style);
1038 resource.mstyle.t_font = readDatabaseFont("menu.title.", style);
1039 resource.mstyle.f_font = readDatabaseFont("menu.frame.", style);
1040
1041 // load window config
1042 resource.wstyle.t_focus =
1043 readDatabaseTexture("window.title.focus", "white", style);
1044 resource.wstyle.t_unfocus =
1045 readDatabaseTexture("window.title.unfocus", "black", style);
1046 resource.wstyle.l_focus =
1047 readDatabaseTexture("window.label.focus", "white", style);
1048 resource.wstyle.l_unfocus =
1049 readDatabaseTexture("window.label.unfocus", "black", style);
1050 resource.wstyle.h_focus =
1051 readDatabaseTexture("window.handle.focus", "white", style);
1052 resource.wstyle.h_unfocus =
1053 readDatabaseTexture("window.handle.unfocus", "black", style);
1054 resource.wstyle.g_focus =
1055 readDatabaseTexture("window.grip.focus", "white", style);
1056 resource.wstyle.g_unfocus =
1057 readDatabaseTexture("window.grip.unfocus", "black", style);
1058 resource.wstyle.b_focus =
1059 readDatabaseTexture("window.button.focus", "white", style);
1060 resource.wstyle.b_unfocus =
1061 readDatabaseTexture("window.button.unfocus", "black", style);
1062 resource.wstyle.b_pressed =
1063 readDatabaseTexture("window.button.pressed", "black", style);
1064
1065 if (resource.wstyle.close_button.mask != None)
1066 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.close_button.mask);
1067 if (resource.wstyle.max_button.mask != None)
1068 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.max_button.mask);
1069 if (resource.wstyle.icon_button.mask != None)
1070 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.icon_button.mask);
1071 if (resource.wstyle.stick_button.mask != None)
1072 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.stick_button.mask);
1073
1074 resource.wstyle.close_button.mask = resource.wstyle.max_button.mask =
1075 resource.wstyle.icon_button.mask =
1076 resource.wstyle.icon_button.mask = None;
1077
1078 readDatabaseMask("window.button.close_mask", resource.wstyle.close_button,
1079 style);
1080 readDatabaseMask("window.button.max_mask", resource.wstyle.max_button,
1081 style);
1082 readDatabaseMask("window.button.icon_mask", resource.wstyle.icon_button,
1083 style);
1084 readDatabaseMask("window.button.stick_mask", resource.wstyle.stick_button,
1085 style);
1086
1087 // we create the window.frame texture by hand because it exists only to
1088 // make the code cleaner and is not actually used for display
1089 BColor color = readDatabaseColor("window.frame.focusColor", "white", style);
1090 resource.wstyle.f_focus = BTexture("solid flat", getBaseDisplay(),
1091 getScreenNumber(), image_control);
1092 resource.wstyle.f_focus.setColor(color);
1093
1094 color = readDatabaseColor("window.frame.unfocusColor", "white", style);
1095 resource.wstyle.f_unfocus = BTexture("solid flat", getBaseDisplay(),
1096 getScreenNumber(), image_control);
1097 resource.wstyle.f_unfocus.setColor(color);
1098
1099 resource.wstyle.l_text_focus =
1100 readDatabaseColor("window.label.focus.textColor", "black", style);
1101 resource.wstyle.l_text_unfocus =
1102 readDatabaseColor("window.label.unfocus.textColor", "white", style);
1103 resource.wstyle.b_pic_focus =
1104 readDatabaseColor("window.button.focus.picColor", "black", style);
1105 resource.wstyle.b_pic_unfocus =
1106 readDatabaseColor("window.button.unfocus.picColor", "white", style);
1107
1108 resource.wstyle.justify = LeftJustify;
1109 if (style.getValue("window.justify", s)) {
1110 if (s == "right" || s == "Right")
1111 resource.wstyle.justify = RightJustify;
1112 else if (s == "center" || s == "Center")
1113 resource.wstyle.justify = CenterJustify;
1114 }
1115
1116 // sanity checks
1117 if (resource.wstyle.t_focus.texture() == BTexture::Parent_Relative)
1118 resource.wstyle.t_focus = resource.wstyle.f_focus;
1119 if (resource.wstyle.t_unfocus.texture() == BTexture::Parent_Relative)
1120 resource.wstyle.t_unfocus = resource.wstyle.f_unfocus;
1121 if (resource.wstyle.h_focus.texture() == BTexture::Parent_Relative)
1122 resource.wstyle.h_focus = resource.wstyle.f_focus;
1123 if (resource.wstyle.h_unfocus.texture() == BTexture::Parent_Relative)
1124 resource.wstyle.h_unfocus = resource.wstyle.f_unfocus;
1125
1126 // load toolbar config
1127 if (resource.tstyle.left_button.mask != None)
1128 XFreePixmap(blackbox->getXDisplay(), resource.tstyle.left_button.mask);
1129 if (resource.tstyle.right_button.mask != None)
1130 XFreePixmap(blackbox->getXDisplay(), resource.tstyle.right_button.mask);
1131
1132 resource.tstyle.toolbar =
1133 readDatabaseTexture("toolbar", "black", style);
1134 resource.tstyle.label =
1135 readDatabaseTexture("toolbar.label", "black", style);
1136 resource.tstyle.window =
1137 readDatabaseTexture("toolbar.windowLabel", "black", style);
1138 resource.tstyle.button =
1139 readDatabaseTexture("toolbar.button", "white", style);
1140 resource.tstyle.pressed =
1141 readDatabaseTexture("toolbar.button.pressed", "black", style);
1142 resource.tstyle.clock =
1143 readDatabaseTexture("toolbar.clock", "black", style);
1144 resource.tstyle.l_text =
1145 readDatabaseColor("toolbar.label.textColor", "white", style);
1146 resource.tstyle.w_text =
1147 readDatabaseColor("toolbar.windowLabel.textColor", "white", style);
1148 resource.tstyle.c_text =
1149 readDatabaseColor("toolbar.clock.textColor", "white", style);
1150 resource.tstyle.b_pic =
1151 readDatabaseColor("toolbar.button.picColor", "black", style);
1152 readDatabaseMask("toolbar.button.left_mask", resource.tstyle.left_button,
1153 style);
1154 readDatabaseMask("toolbar.button.right_mask", resource.tstyle.right_button,
1155 style);
1156
1157 resource.tstyle.justify = LeftJustify;
1158 if (style.getValue("toolbar.justify", s)) {
1159 if (s == "right" || s == "Right")
1160 resource.tstyle.justify = RightJustify;
1161 else if (s == "center" || s == "Center")
1162 resource.tstyle.justify = CenterJustify;
1163 }
1164
1165 // sanity checks
1166 if (resource.tstyle.toolbar.texture() == BTexture::Parent_Relative) {
1167 resource.tstyle.toolbar = BTexture("solid flat", getBaseDisplay(),
1168 getScreenNumber(), image_control);
1169 resource.tstyle.toolbar.setColor(BColor("black", getBaseDisplay(),
1170 getScreenNumber()));
1171 }
1172
1173 // load menu config
1174 if (resource.mstyle.bullet_image.mask != None)
1175 XFreePixmap(blackbox->getXDisplay(), resource.mstyle.bullet_image.mask);
1176 if (resource.mstyle.tick_image.mask != None)
1177 XFreePixmap(blackbox->getXDisplay(), resource.mstyle.tick_image.mask);
1178
1179 resource.mstyle.title =
1180 readDatabaseTexture("menu.title", "white", style);
1181 resource.mstyle.frame =
1182 readDatabaseTexture("menu.frame", "black", style);
1183 resource.mstyle.hilite =
1184 readDatabaseTexture("menu.hilite", "white", style);
1185 resource.mstyle.t_text =
1186 readDatabaseColor("menu.title.textColor", "black", style);
1187 resource.mstyle.f_text =
1188 readDatabaseColor("menu.frame.textColor", "white", style);
1189 resource.mstyle.d_text =
1190 readDatabaseColor("menu.frame.disableColor", "black", style);
1191 resource.mstyle.h_text =
1192 readDatabaseColor("menu.hilite.textColor", "black", style);
1193 readDatabaseMask("menu.bullet.mask", resource.mstyle.bullet_image, style);
1194 readDatabaseMask("menu.selected.mask", resource.mstyle.tick_image, style);
1195
1196 resource.mstyle.t_justify = LeftJustify;
1197 if (style.getValue("menu.title.justify", s)) {
1198 if (s == "right" || s == "Right")
1199 resource.mstyle.t_justify = RightJustify;
1200 else if (s == "center" || s == "Center")
1201 resource.mstyle.t_justify = CenterJustify;
1202 }
1203
1204 resource.mstyle.f_justify = LeftJustify;
1205 if (style.getValue("menu.frame.justify", s)) {
1206 if (s == "right" || s == "Right")
1207 resource.mstyle.f_justify = RightJustify;
1208 else if (s == "center" || s == "Center")
1209 resource.mstyle.f_justify = CenterJustify;
1210 }
1211
1212 resource.mstyle.bullet = Basemenu::Triangle;
1213 if (style.getValue("menu.bullet", s)) {
1214 if (s == "empty" || s == "Empty")
1215 resource.mstyle.bullet = Basemenu::Empty;
1216 else if (s == "square" || s == "Square")
1217 resource.mstyle.bullet = Basemenu::Square;
1218 else if (s == "diamond" || s == "Diamond")
1219 resource.mstyle.bullet = Basemenu::Diamond;
1220 }
1221
1222 resource.mstyle.bullet_pos = Basemenu::Left;
1223 if (style.getValue("menu.bullet.position", s)) {
1224 if (s == "right" || s == "Right")
1225 resource.mstyle.bullet_pos = Basemenu::Right;
1226 }
1227
1228 // sanity checks
1229 if (resource.mstyle.frame.texture() == BTexture::Parent_Relative) {
1230 resource.mstyle.frame = BTexture("solid flat", getBaseDisplay(),
1231 getScreenNumber(), image_control);
1232 resource.mstyle.frame.setColor(BColor("black", getBaseDisplay(),
1233 getScreenNumber()));
1234 }
1235
1236 resource.border_color =
1237 readDatabaseColor("borderColor", "black", style);
1238
1239 // load bevel, border and handle widths
1240 if (! style.getValue("handleWidth", resource.handle_width) ||
1241 resource.handle_width > (getWidth() / 2) || resource.handle_width == 0)
1242 resource.handle_width = 6;
1243
1244 if (! style.getValue("borderWidth", resource.border_width))
1245 resource.border_width = 1;
1246
1247 if (! style.getValue("bevelWidth", resource.bevel_width) ||
1248 resource.bevel_width > (getWidth() / 2) || resource.bevel_width == 0)
1249 resource.bevel_width = 3;
1250
1251 if (! style.getValue("frameWidth", resource.frame_width) ||
1252 resource.frame_width > (getWidth() / 2))
1253 resource.frame_width = resource.bevel_width;
1254
1255 if (style.getValue("rootCommand", s))
1256 bexec(s, displayString());
1257 }
1258
1259
1260 void BScreen::addIcon(BlackboxWindow *w) {
1261 if (! w) return;
1262
1263 w->setWorkspace(BSENTINEL);
1264 w->setWindowNumber(iconList.size());
1265
1266 iconList.push_back(w);
1267
1268 const char* title = w->getIconTitle();
1269 iconmenu->insert(title);
1270 iconmenu->update();
1271 }
1272
1273
1274 void BScreen::removeIcon(BlackboxWindow *w) {
1275 if (! w) return;
1276
1277 iconList.remove(w);
1278
1279 iconmenu->remove(w->getWindowNumber());
1280 iconmenu->update();
1281
1282 BlackboxWindowList::iterator it = iconList.begin(),
1283 end = iconList.end();
1284 for (int i = 0; it != end; ++it)
1285 (*it)->setWindowNumber(i++);
1286 }
1287
1288
1289 BlackboxWindow *BScreen::getIcon(unsigned int index) {
1290 if (index < iconList.size()) {
1291 BlackboxWindowList::iterator it = iconList.begin();
1292 while (index-- > 0) // increment to index
1293 ++it;
1294 return *it;
1295 }
1296
1297 return (BlackboxWindow *) 0;
1298 }
1299
1300
1301 unsigned int BScreen::addWorkspace(void) {
1302 Workspace *wkspc = new Workspace(this, workspacesList.size());
1303 workspacesList.push_back(wkspc);
1304 saveWorkspaces(getWorkspaceCount());
1305 saveWorkspaceNames();
1306
1307 workspacemenu->insertWorkspace(wkspc);
1308 workspacemenu->update();
1309
1310 toolbar->reconfigure();
1311
1312 updateNetizenWorkspaceCount();
1313
1314 return workspacesList.size();
1315 }
1316
1317
1318 unsigned int BScreen::removeLastWorkspace(void) {
1319 if (workspacesList.size() == 1)
1320 return 1;
1321
1322 Workspace *wkspc = workspacesList.back();
1323
1324 if (current_workspace->getID() == wkspc->getID())
1325 changeWorkspaceID(current_workspace->getID() - 1);
1326
1327 wkspc->removeAll();
1328
1329 workspacemenu->removeWorkspace(wkspc);
1330 workspacemenu->update();
1331
1332 workspacesList.pop_back();
1333 delete wkspc;
1334
1335 saveWorkspaces(getWorkspaceCount());
1336 saveWorkspaceNames();
1337
1338 toolbar->reconfigure();
1339
1340 updateNetizenWorkspaceCount();
1341
1342 return workspacesList.size();
1343 }
1344
1345
1346 void BScreen::changeWorkspaceID(unsigned int id) {
1347 if (! current_workspace || id == current_workspace->getID()) return;
1348
1349 BlackboxWindow *focused = blackbox->getFocusedWindow();
1350 if (focused && focused->getScreen() == this) {
1351 assert(focused->isStuck() ||
1352 focused->getWorkspaceNumber() == current_workspace->getID());
1353
1354 current_workspace->setLastFocusedWindow(focused);
1355 } else {
1356 // if no window had focus, no need to store a last focus
1357 current_workspace->setLastFocusedWindow((BlackboxWindow *) 0);
1358 }
1359
1360 // when we switch workspaces, unfocus whatever was focused if it is going
1361 // to be unmapped
1362 if (focused && ! focused->isStuck())
1363 blackbox->setFocusedWindow((BlackboxWindow *) 0);
1364
1365 current_workspace->hideAll();
1366 workspacemenu->setItemSelected(current_workspace->getID() + 2, False);
1367
1368 current_workspace = getWorkspace(id);
1369
1370 xatom->setValue(getRootWindow(), XAtom::net_current_desktop,
1371 XAtom::cardinal, id);
1372
1373 workspacemenu->setItemSelected(current_workspace->getID() + 2, True);
1374 toolbar->redrawWorkspaceLabel(True);
1375
1376 current_workspace->showAll();
1377
1378 int x, y, rx, ry;
1379 Window c, r;
1380 unsigned int m;
1381 BlackboxWindow *win = (BlackboxWindow *) 0;
1382 bool f = False;
1383
1384 XSync(blackbox->getXDisplay(), False);
1385
1386 // If sloppy focus and we can find the client window under the pointer,
1387 // try to focus it.
1388 if (resource.sloppy_focus &&
1389 XQueryPointer(blackbox->getXDisplay(), getRootWindow(), &r, &c,
1390 &rx, &ry, &x, &y, &m) &&
1391 c != None) {
1392 if ( (win = blackbox->searchWindow(c)) )
1393 f = win->setInputFocus();
1394 }
1395
1396 // If that fails, and we're doing focus_last, try to focus the last window.
1397 if (! f && resource.focus_last &&
1398 (win = current_workspace->getLastFocusedWindow()))
1399 f = win->setInputFocus();
1400
1401 /*
1402 if we found a focus target, then we set the focused window explicitly
1403 because it is possible to switch off this workspace before the x server
1404 generates the FocusIn event for the window. if that happens, openbox would
1405 lose track of what window was the 'LastFocused' window on the workspace.
1406
1407 if we did not find a focus target, then set the current focused window to
1408 nothing.
1409 */
1410 if (f)
1411 blackbox->setFocusedWindow(win);
1412 else
1413 blackbox->setFocusedWindow((BlackboxWindow *) 0);
1414
1415 updateNetizenCurrentWorkspace();
1416 }
1417
1418
1419 /*
1420 * Set the _NET_CLIENT_LIST root window property.
1421 */
1422 void BScreen::updateClientList(void) {
1423 if (windowList.size() > 0) {
1424 Window *windows = new Window[windowList.size()];
1425 Window *win_it = windows;
1426 BlackboxWindowList::iterator it = windowList.begin();
1427 const BlackboxWindowList::iterator end = windowList.end();
1428 for (; it != end; ++it, ++win_it)
1429 *win_it = (*it)->getClientWindow();
1430 xatom->setValue(getRootWindow(), XAtom::net_client_list, XAtom::window,
1431 windows, windowList.size());
1432 delete [] windows;
1433 } else
1434 xatom->setValue(getRootWindow(), XAtom::net_client_list, XAtom::window,
1435 0, 0);
1436
1437 updateStackingList();
1438 }
1439
1440
1441 /*
1442 * Set the _NET_CLIENT_LIST_STACKING root window property.
1443 */
1444 void BScreen::updateStackingList(void) {
1445
1446 BlackboxWindowList stack_order;
1447
1448 /*
1449 * Get the stacking order from all of the workspaces.
1450 * We start with the current workspace so that the sticky windows will be
1451 * in the right order on the current workspace.
1452 * XXX: Do we need to have sticky windows in the list once for each workspace?
1453 */
1454 getCurrentWorkspace()->appendStackOrder(stack_order);
1455 for (unsigned int i = 0; i < getWorkspaceCount(); ++i)
1456 if (i != getCurrentWorkspaceID())
1457 getWorkspace(i)->appendStackOrder(stack_order);
1458
1459 if (stack_order.size() > 0) {
1460 // set the client list atoms
1461 Window *windows = new Window[stack_order.size()];
1462 Window *win_it = windows;
1463 BlackboxWindowList::iterator it = stack_order.begin(),
1464 end = stack_order.end();
1465 for (; it != end; ++it, ++win_it)
1466 *win_it = (*it)->getClientWindow();
1467 xatom->setValue(getRootWindow(), XAtom::net_client_list_stacking,
1468 XAtom::window, windows, stack_order.size());
1469 delete [] windows;
1470 } else
1471 xatom->setValue(getRootWindow(), XAtom::net_client_list_stacking,
1472 XAtom::window, 0, 0);
1473 }
1474
1475
1476 void BScreen::addSystrayWindow(Window window) {
1477 XGrabServer(blackbox->getXDisplay());
1478
1479 XSelectInput(blackbox->getXDisplay(), window, StructureNotifyMask);
1480 systrayWindowList.push_back(window);
1481 xatom->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows,
1482 XAtom::window,
1483 &systrayWindowList[0], systrayWindowList.size());
1484 blackbox->saveSystrayWindowSearch(window, this);
1485
1486 XUngrabServer(blackbox->getXDisplay());
1487 }
1488
1489
1490 void BScreen::removeSystrayWindow(Window window) {
1491 XGrabServer(blackbox->getXDisplay());
1492
1493 WindowList::iterator it = systrayWindowList.begin();
1494 const WindowList::iterator end = systrayWindowList.end();
1495 for (; it != end; ++it)
1496 if (*it == window) {
1497 systrayWindowList.erase(it);
1498 xatom->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows,
1499 XAtom::window,
1500 &systrayWindowList[0], systrayWindowList.size());
1501 blackbox->removeSystrayWindowSearch(window);
1502 XSelectInput(blackbox->getXDisplay(), window, NoEventMask);
1503 break;
1504 }
1505
1506 assert(it != end); // not a systray window
1507
1508 XUngrabServer(blackbox->getXDisplay());
1509 }
1510
1511
1512 void BScreen::manageWindow(Window w) {
1513 // is the window a KDE systray window?
1514 Window systray;
1515 if (xatom->getValue(w, XAtom::kde_net_wm_system_tray_window_for,
1516 XAtom::window, systray) && systray != None) {
1517 addSystrayWindow(w);
1518 return;
1519 }
1520
1521 // is the window a docking app
1522 XWMHints *wmhint = XGetWMHints(blackbox->getXDisplay(), w);
1523 if (wmhint && (wmhint->flags & StateHint) &&
1524 wmhint->initial_state == WithdrawnState) {
1525 slit->addClient(w);
1526 return;
1527 }
1528
1529 new BlackboxWindow(blackbox, w, this);
1530
1531 BlackboxWindow *win = blackbox->searchWindow(w);
1532 if (! win)
1533 return;
1534
1535 if (win->isDesktop()) {
1536 desktopWindowList.push_back(win->getFrameWindow());
1537 } else { // if (win->isNormal()) {
1538 // don't list desktop windows as managed windows
1539 windowList.push_back(win);
1540 updateClientList();
1541
1542 if (win->isTopmost())
1543 specialWindowList.push_back(win->getFrameWindow());
1544 }
1545
1546 XMapRequestEvent mre;
1547 mre.window = w;
1548 if (blackbox->isStartup() && win->isNormal()) win->restoreAttributes();
1549 win->mapRequestEvent(&mre);
1550 }
1551
1552
1553 void BScreen::unmanageWindow(BlackboxWindow *w, bool remap) {
1554 // is the window a KDE systray window?
1555 Window systray;
1556 if (xatom->getValue(w->getClientWindow(),
1557 XAtom::kde_net_wm_system_tray_window_for,
1558 XAtom::window, systray) && systray != None) {
1559 removeSystrayWindow(w->getClientWindow());
1560 return;
1561 }
1562
1563 w->restore(remap);
1564
1565 // Remove the modality so that its parent won't try to re-focus the window
1566 if (w->isModal()) w->setModal(False);
1567
1568 if (w->getWorkspaceNumber() != BSENTINEL &&
1569 w->getWindowNumber() != BSENTINEL) {
1570 getWorkspace(w->getWorkspaceNumber())->removeWindow(w);
1571 if (w->isStuck()) {
1572 for (unsigned int i = 0; i < getNumberOfWorkspaces(); ++i)
1573 if (i != w->getWorkspaceNumber())
1574 getWorkspace(i)->removeWindow(w, True);
1575 }
1576 } else if (w->isIconic())
1577 removeIcon(w);
1578
1579 if (w->isDesktop()) {
1580 WindowList::iterator it = desktopWindowList.begin();
1581 const WindowList::iterator end = desktopWindowList.end();
1582 for (; it != end; ++it)
1583 if (*it == w->getFrameWindow()) {
1584 desktopWindowList.erase(it);
1585 break;
1586 }
1587 assert(it != end); // the window wasnt a desktop window?
1588 } else { // if (w->isNormal()) {
1589 // we don't list desktop windows as managed windows
1590 windowList.remove(w);
1591 updateClientList();
1592
1593 if (w->isTopmost()) {
1594 WindowList::iterator it = specialWindowList.begin();
1595 const WindowList::iterator end = specialWindowList.end();
1596 for (; it != end; ++it)
1597 if (*it == w->getFrameWindow()) {
1598 specialWindowList.erase(it);
1599 break;
1600 }
1601 assert(it != end); // the window wasnt a special window?
1602 }
1603 }
1604
1605 if (blackbox->getFocusedWindow() == w)
1606 blackbox->setFocusedWindow((BlackboxWindow *) 0);
1607
1608 removeNetizen(w->getClientWindow());
1609
1610 /*
1611 some managed windows can also be window group controllers. when
1612 unmanaging such windows, we should also delete the window group.
1613 */
1614 BWindowGroup *group = blackbox->searchGroup(w->getClientWindow());
1615 delete group;
1616
1617 delete w;
1618 }
1619
1620
1621 void BScreen::addNetizen(Netizen *n) {
1622 netizenList.push_back(n);
1623
1624 n->sendWorkspaceCount();
1625 n->sendCurrentWorkspace();
1626
1627 WorkspaceList::iterator it = workspacesList.begin();
1628 const WorkspaceList::iterator end = workspacesList.end();
1629 for (; it != end; ++it)
1630 (*it)->sendWindowList(*n);
1631
1632 Window f = ((blackbox->getFocusedWindow()) ?
1633 blackbox->getFocusedWindow()->getClientWindow() : None);
1634 n->sendWindowFocus(f);
1635 }
1636
1637
1638 void BScreen::removeNetizen(Window w) {
1639 NetizenList::iterator it = netizenList.begin();
1640 for (; it != netizenList.end(); ++it) {
1641 if ((*it)->getWindowID() == w) {
1642 delete *it;
1643 netizenList.erase(it);
1644 break;
1645 }
1646 }
1647 }
1648
1649
1650 void BScreen::updateWorkArea(void) {
1651 if (workspacesList.size() > 0) {
1652 unsigned long *dims = new unsigned long[4 * workspacesList.size()];
1653 for (unsigned int i = 0, m = workspacesList.size(); i < m; ++i) {
1654 // XXX: this could be different for each workspace
1655 const Rect &area = availableArea();
1656 dims[(i * 4) + 0] = area.x();
1657 dims[(i * 4) + 1] = area.y();
1658 dims[(i * 4) + 2] = area.width();
1659 dims[(i * 4) + 3] = area.height();
1660 }
1661 xatom->setValue(getRootWindow(), XAtom::net_workarea, XAtom::cardinal,
1662 dims, 4 * workspacesList.size());
1663 delete [] dims;
1664 } else
1665 xatom->setValue(getRootWindow(), XAtom::net_workarea, XAtom::cardinal,
1666 0, 0);
1667 }
1668
1669
1670 void BScreen::updateNetizenCurrentWorkspace(void) {
1671 std::for_each(netizenList.begin(), netizenList.end(),
1672 std::mem_fun(&Netizen::sendCurrentWorkspace));
1673 }
1674
1675
1676 void BScreen::updateNetizenWorkspaceCount(void) {
1677 xatom->setValue(getRootWindow(), XAtom::net_number_of_desktops,
1678 XAtom::cardinal, workspacesList.size());
1679
1680 updateWorkArea();
1681
1682 std::for_each(netizenList.begin(), netizenList.end(),
1683 std::mem_fun(&Netizen::sendWorkspaceCount));
1684 }
1685
1686
1687 void BScreen::updateNetizenWindowFocus(void) {
1688 Window f = ((blackbox->getFocusedWindow()) ?
1689 blackbox->getFocusedWindow()->getClientWindow() : None);
1690
1691 xatom->setValue(getRootWindow(), XAtom::net_active_window,
1692 XAtom::window, f);
1693
1694 NetizenList::iterator it = netizenList.begin();
1695 for (; it != netizenList.end(); ++it)
1696 (*it)->sendWindowFocus(f);
1697 }
1698
1699
1700 void BScreen::updateNetizenWindowAdd(Window w, unsigned long p) {
1701 NetizenList::iterator it = netizenList.begin();
1702 for (; it != netizenList.end(); ++it) {
1703 (*it)->sendWindowAdd(w, p);
1704 }
1705 }
1706
1707
1708 void BScreen::updateNetizenWindowDel(Window w) {
1709 NetizenList::iterator it = netizenList.begin();
1710 for (; it != netizenList.end(); ++it)
1711 (*it)->sendWindowDel(w);
1712 }
1713
1714
1715 void BScreen::updateNetizenWindowRaise(Window w) {
1716 NetizenList::iterator it = netizenList.begin();
1717 for (; it != netizenList.end(); ++it)
1718 (*it)->sendWindowRaise(w);
1719 }
1720
1721
1722 void BScreen::updateNetizenWindowLower(Window w) {
1723 NetizenList::iterator it = netizenList.begin();
1724 for (; it != netizenList.end(); ++it)
1725 (*it)->sendWindowLower(w);
1726 }
1727
1728
1729 void BScreen::updateNetizenConfigNotify(XEvent *e) {
1730 NetizenList::iterator it = netizenList.begin();
1731 for (; it != netizenList.end(); ++it)
1732 (*it)->sendConfigNotify(e);
1733 }
1734
1735
1736 void BScreen::raiseWindows(Window *workspace_stack, unsigned int num) {
1737 // the 13 represents the number of blackbox windows such as menus
1738 int bbwins = 15;
1739 #ifdef XINERAMA
1740 ++bbwins;
1741 #endif // XINERAMA
1742
1743 Window *session_stack = new
1744 Window[(num + workspacesList.size() + rootmenuList.size() +
1745 specialWindowList.size() + bbwins)];
1746 unsigned int i = 0, k = num;
1747
1748 XRaiseWindow(blackbox->getXDisplay(), iconmenu->getWindowID());
1749 *(session_stack + i++) = iconmenu->getWindowID();
1750
1751 WorkspaceList::iterator wit = workspacesList.begin();
1752 const WorkspaceList::iterator w_end = workspacesList.end();
1753 for (; wit != w_end; ++wit)
1754 *(session_stack + i++) = (*wit)->getMenu()->getWindowID();
1755
1756 *(session_stack + i++) = workspacemenu->getWindowID();
1757
1758 *(session_stack + i++) = configmenu->getFocusmenu()->getWindowID();
1759 *(session_stack + i++) = configmenu->getPlacementmenu()->getWindowID();
1760 *(session_stack + i++) = configmenu->getWindowSnapmenu()->getWindowID();
1761 *(session_stack + i++) = configmenu->getEdgeSnapmenu()->getWindowID();
1762 #ifdef XINERAMA
1763 *(session_stack + i++) = configmenu->getXineramamenu()->getWindowID();
1764 #endif // XINERAMA
1765 *(session_stack + i++) = configmenu->getWindowID();
1766
1767 *(session_stack + i++) = slit->getMenu()->getDirectionmenu()->getWindowID();
1768 *(session_stack + i++) = slit->getMenu()->getPlacementmenu()->getWindowID();
1769 *(session_stack + i++) = slit->getMenu()->getWindowID();
1770
1771 *(session_stack + i++) =
1772 toolbar->getMenu()->getPlacementmenu()->getWindowID();
1773 *(session_stack + i++) = toolbar->getMenu()->getWindowID();
1774
1775 RootmenuList::iterator rit = rootmenuList.begin();
1776 for (; rit != rootmenuList.end(); ++rit)
1777 *(session_stack + i++) = (*rit)->getWindowID();
1778 *(session_stack + i++) = rootmenu->getWindowID();
1779
1780 if (toolbar->isOnTop())
1781 *(session_stack + i++) = toolbar->getWindowID();
1782
1783 if (slit->isOnTop())
1784 *(session_stack + i++) = slit->getWindowID();
1785
1786 WindowList::iterator sit, send = specialWindowList.end();
1787 for (sit = specialWindowList.begin(); sit != send; ++sit)
1788 *(session_stack + i++) = *sit;
1789
1790 while (k--)
1791 *(session_stack + i++) = *(workspace_stack + k);
1792
1793 XRestackWindows(blackbox->getXDisplay(), session_stack, i);
1794
1795 delete [] session_stack;
1796
1797 updateStackingList();
1798 }
1799
1800
1801 void BScreen::lowerWindows(Window *workspace_stack, unsigned int num) {
1802 assert(num > 0); // this would cause trouble in the XRaiseWindow call
1803
1804 Window *session_stack = new Window[(num + desktopWindowList.size())];
1805 unsigned int i = 0, k = num;
1806
1807 XLowerWindow(blackbox->getXDisplay(), workspace_stack[0]);
1808
1809 while (k--)
1810 *(session_stack + i++) = *(workspace_stack + k);
1811
1812 WindowList::iterator dit = desktopWindowList.begin();
1813 const WindowList::iterator d_end = desktopWindowList.end();
1814 for (; dit != d_end; ++dit)
1815 *(session_stack + i++) = *dit;
1816
1817 XRestackWindows(blackbox->getXDisplay(), session_stack, i);
1818
1819 delete [] session_stack;
1820
1821 updateStackingList();
1822 }
1823
1824
1825 void BScreen::reassociateWindow(BlackboxWindow *w, unsigned int wkspc_id,
1826 bool ignore_sticky) {
1827 if (! w) return;
1828
1829 if (wkspc_id == BSENTINEL)
1830 wkspc_id = current_workspace->getID();
1831
1832 if (w->getWorkspaceNumber() == wkspc_id)
1833 return;
1834
1835 if (w->isIconic()) {
1836 removeIcon(w);
1837 getWorkspace(wkspc_id)->addWindow(w);
1838 if (w->isStuck())
1839 for (unsigned int i = 0; i < getNumberOfWorkspaces(); ++i)
1840 if (i != w->getWorkspaceNumber())
1841 getWorkspace(i)->addWindow(w, True);
1842 } else if (ignore_sticky || ! w->isStuck()) {
1843 if (w->isStuck())
1844 w->stick();
1845 getWorkspace(w->getWorkspaceNumber())->removeWindow(w);
1846 getWorkspace(wkspc_id)->addWindow(w);
1847 }
1848 updateStackingList();
1849 }
1850
1851
1852 void BScreen::propagateWindowName(const BlackboxWindow *bw) {
1853 if (bw->isIconic()) {
1854 iconmenu->changeItemLabel(bw->getWindowNumber(), bw->getIconTitle());
1855 iconmenu->update();
1856 }
1857 else {
1858 Clientmenu *clientmenu = getWorkspace(bw->getWorkspaceNumber())->getMenu();
1859 clientmenu->changeItemLabel(bw->getWindowNumber(), bw->getTitle());
1860 clientmenu->update();
1861
1862 if (blackbox->getFocusedWindow() == bw)
1863 toolbar->redrawWindowLabel(True);
1864 }
1865 }
1866
1867
1868 void BScreen::nextFocus(void) {
1869 BlackboxWindow *focused = blackbox->getFocusedWindow(),
1870 *next = focused;
1871
1872 if (focused) {
1873 // if window is not on this screen, ignore it
1874 if (focused->getScreen()->getScreenNumber() != getScreenNumber())
1875 focused = (BlackboxWindow*) 0;
1876 }
1877
1878 if (focused && current_workspace->getCount() > 1) {
1879 // next is the next window to recieve focus, current is a place holder
1880 BlackboxWindow *current;
1881 do {
1882 current = next;
1883 next = current_workspace->getNextWindowInList(current);
1884 } while(! next->setInputFocus() && next != focused);
1885
1886 if (next != focused)
1887 current_workspace->raiseWindow(next);
1888 } else if (current_workspace->getCount() >= 1) {
1889 next = current_workspace->getTopWindowOnStack();
1890
1891 current_workspace->raiseWindow(next);
1892 next->setInputFocus();
1893 }
1894 }
1895
1896
1897 void BScreen::prevFocus(void) {
1898 BlackboxWindow *focused = blackbox->getFocusedWindow(),
1899 *next = focused;
1900
1901 if (focused) {
1902 // if window is not on this screen, ignore it
1903 if (focused->getScreen()->getScreenNumber() != getScreenNumber())
1904 focused = (BlackboxWindow*) 0;
1905 }
1906
1907 if (focused && current_workspace->getCount() > 1) {
1908 // next is the next window to recieve focus, current is a place holder
1909 BlackboxWindow *current;
1910 do {
1911 current = next;
1912 next = current_workspace->getPrevWindowInList(current);
1913 } while(! next->setInputFocus() && next != focused);
1914
1915 if (next != focused)
1916 current_workspace->raiseWindow(next);
1917 } else if (current_workspace->getCount() >= 1) {
1918 next = current_workspace->getTopWindowOnStack();
1919
1920 current_workspace->raiseWindow(next);
1921 next->setInputFocus();
1922 }
1923 }
1924
1925
1926 void BScreen::raiseFocus(void) {
1927 BlackboxWindow *focused = blackbox->getFocusedWindow();
1928 if (! focused)
1929 return;
1930
1931 // if on this Screen, raise it
1932 if (focused->getScreen()->getScreenNumber() == getScreenNumber()) {
1933 Workspace *workspace = getWorkspace(focused->getWorkspaceNumber());
1934 workspace->raiseWindow(focused);
1935 }
1936 }
1937
1938
1939 void BScreen::InitMenu(void) {
1940 if (rootmenu) {
1941 rootmenuList.clear();
1942
1943 while (rootmenu->getCount())
1944 rootmenu->remove(0);
1945 } else {
1946 rootmenu = new Rootmenu(this);
1947 }
1948 bool defaultMenu = True;
1949
1950 FILE *menu_file = (FILE *) 0;
1951 const char *menu_filename = blackbox->getMenuFilename();
1952
1953 if (menu_filename)
1954 if (! (menu_file = fopen(menu_filename, "r")))
1955 perror(menu_filename);
1956 if (! menu_file) { // opening the menu file failed, try the default menu
1957 menu_filename = DEFAULTMENU;
1958 if (! (menu_file = fopen(menu_filename, "r")))
1959 perror(menu_filename);
1960 }
1961
1962 if (menu_file) {
1963 if (feof(menu_file)) {
1964 fprintf(stderr, i18n(ScreenSet, ScreenEmptyMenuFile,
1965 "%s: Empty menu file"),
1966 menu_filename);
1967 } else {
1968 char line[1024], label[1024];
1969 memset(line, 0, 1024);
1970 memset(label, 0, 1024);
1971
1972 while (fgets(line, 1024, menu_file) && ! feof(menu_file)) {
1973 if (line[0] == '#')
1974 continue;
1975
1976 int i, key = 0, index = -1, len = strlen(line);
1977
1978 for (i = 0; i < len; i++) {
1979 if (line[i] == '[') index = 0;
1980 else if (line[i] == ']') break;
1981 else if (line[i] != ' ')
1982 if (index++ >= 0)
1983 key += tolower(line[i]);
1984 }
1985
1986 if (key == 517) { // [begin]
1987 index = -1;
1988 for (i = index; i < len; i++) {
1989 if (line[i] == '(') index = 0;
1990 else if (line[i] == ')') break;
1991 else if (index++ >= 0) {
1992 if (line[i] == '\\' && i < len - 1) i++;
1993 label[index - 1] = line[i];
1994 }
1995 }
1996
1997 if (index == -1) index = 0;
1998 label[index] = '\0';
1999
2000 rootmenu->setLabel(label);
2001 defaultMenu = parseMenuFile(menu_file, rootmenu);
2002 if (! defaultMenu)
2003 blackbox->addMenuTimestamp(menu_filename);
2004 break;
2005 }
2006 }
2007 }
2008 fclose(menu_file);
2009 }
2010
2011 if (defaultMenu) {
2012 rootmenu->setInternalMenu();
2013 rootmenu->insert(i18n(ScreenSet, Screenxterm, "xterm"),
2014 BScreen::Execute,
2015 i18n(ScreenSet, Screenxterm, "xterm"));
2016 rootmenu->insert(i18n(ScreenSet, ScreenRestart, "Restart"),
2017 BScreen::Restart);
2018 rootmenu->insert(i18n(ScreenSet, ScreenExit, "Exit"),
2019 BScreen::Exit);
2020 rootmenu->setLabel(i18n(BasemenuSet, BasemenuBlackboxMenu,
2021 "Openbox Menu"));
2022 }
2023 }
2024
2025
2026 static
2027 size_t string_within(char begin, char end,
2028 const char *input, size_t start_at, size_t length,
2029 char *output) {
2030 bool parse = False;
2031 size_t index = 0;
2032 size_t i = start_at;
2033 for (; i < length; ++i) {
2034 if (input[i] == begin) {
2035 parse = True;
2036 } else if (input[i] == end) {
2037 break;
2038 } else if (parse) {
2039 if (input[i] == '\\' && i < length - 1) i++;
2040 output[index++] = input[i];
2041 }
2042 }
2043
2044 if (parse)
2045 output[index] = '\0';
2046 else
2047 output[0] = '\0';
2048
2049 return i;
2050 }
2051
2052
2053 bool BScreen::parseMenuFile(FILE *file, Rootmenu *menu) {
2054 char line[1024], keyword[1024], label[1024], command[1024];
2055 bool done = False;
2056
2057 while (! (done || feof(file))) {
2058 memset(line, 0, 1024);
2059 memset(label, 0, 1024);
2060 memset(command, 0, 1024);
2061
2062 if (! fgets(line, 1024, file))
2063 continue;
2064
2065 if (line[0] == '#') // comment, skip it
2066 continue;
2067
2068 size_t line_length = strlen(line);
2069 unsigned int key = 0;
2070
2071 // get the keyword enclosed in []'s
2072 size_t pos = string_within('[', ']', line, 0, line_length, keyword);
2073
2074 if (keyword[0] == '\0') { // no keyword, no menu entry
2075 continue;
2076 } else {
2077 size_t len = strlen(keyword);
2078 for (size_t i = 0; i < len; ++i) {
2079 if (keyword[i] != ' ')
2080 key += tolower(keyword[i]);
2081 }
2082 }
2083
2084 // get the label enclosed in ()'s
2085 pos = string_within('(', ')', line, pos, line_length, label);
2086
2087 // get the command enclosed in {}'s
2088 pos = string_within('{', '}', line, pos, line_length, command);
2089
2090 switch (key) {
2091 case 311: // end
2092 done = True;
2093
2094 break;
2095
2096 case 333: // nop
2097 if (! *label)
2098 label[0] = '\0';
2099 menu->insert(label);
2100
2101 break;
2102
2103 case 421: // exec
2104 if (! (*label && *command)) {
2105 fprintf(stderr, i18n(ScreenSet, ScreenEXECError,
2106 "BScreen::parseMenuFile: [exec] error, "
2107 "no menu label and/or command defined\n"));
2108 continue;
2109 }
2110
2111 menu->insert(label, BScreen::Execute, command);
2112
2113 break;
2114
2115 case 442: // exit
2116 if (! *label) {
2117 fprintf(stderr, i18n(ScreenSet, ScreenEXITError,
2118 "BScreen::parseMenuFile: [exit] error, "
2119 "no menu label defined\n"));
2120 continue;
2121 }
2122
2123 menu->insert(label, BScreen::Exit);
2124
2125 break;
2126
2127 case 561: { // style
2128 if (! (*label && *command)) {
2129 fprintf(stderr,
2130 i18n(ScreenSet, ScreenSTYLEError,
2131 "BScreen::parseMenuFile: [style] error, "
2132 "no menu label and/or filename defined\n"));
2133 continue;
2134 }
2135
2136 string style = expandTilde(command);
2137
2138 menu->insert(label, BScreen::SetStyle, style.c_str());
2139 }
2140 break;
2141
2142 case 630: // config
2143 if (! *label) {
2144 fprintf(stderr, i18n(ScreenSet, ScreenCONFIGError,
2145 "BScreen::parseMenufile: [config] error, "
2146 "no label defined"));
2147 continue;
2148 }
2149
2150 menu->insert(label, configmenu);
2151
2152 break;
2153
2154 case 740: { // include
2155 if (! *label) {
2156 fprintf(stderr, i18n(ScreenSet, ScreenINCLUDEError,
2157 "BScreen::parseMenuFile: [include] error, "
2158 "no filename defined\n"));
2159 continue;
2160 }
2161
2162 string newfile = expandTilde(label);
2163 FILE *submenufile = fopen(newfile.c_str(), "r");
2164
2165 if (! submenufile) {
2166 perror(newfile.c_str());
2167 continue;
2168 }
2169
2170 struct stat buf;
2171 if (fstat(fileno(submenufile), &buf) ||
2172 ! S_ISREG(buf.st_mode)) {
2173 fprintf(stderr,
2174 i18n(ScreenSet, ScreenINCLUDEErrorReg,
2175 "BScreen::parseMenuFile: [include] error: "
2176 "'%s' is not a regular file\n"), newfile.c_str());
2177 break;
2178 }
2179
2180 if (! feof(submenufile)) {
2181 if (! parseMenuFile(submenufile, menu))
2182 blackbox->addMenuTimestamp(newfile);
2183
2184 fclose(submenufile);
2185 }
2186 }
2187
2188 break;
2189
2190 case 767: { // submenu
2191 if (! *label) {
2192 fprintf(stderr, i18n(ScreenSet, ScreenSUBMENUError,
2193 "BScreen::parseMenuFile: [submenu] error, "
2194 "no menu label defined\n"));
2195 continue;
2196 }
2197
2198 Rootmenu *submenu = new Rootmenu(this);
2199
2200 if (*command)
2201 submenu->setLabel(command);
2202 else
2203 submenu->setLabel(label);
2204
2205 parseMenuFile(file, submenu);
2206 submenu->update();
2207 menu->insert(label, submenu);
2208 rootmenuList.push_back(submenu);
2209 }
2210
2211 break;
2212
2213 case 773: { // restart
2214 if (! *label) {
2215 fprintf(stderr, i18n(ScreenSet, ScreenRESTARTError,
2216 "BScreen::parseMenuFile: [restart] error, "
2217 "no menu label defined\n"));
2218 continue;
2219 }
2220
2221 if (*command)
2222 menu->insert(label, BScreen::RestartOther, command);
2223 else
2224 menu->insert(label, BScreen::Restart);
2225 }
2226
2227 break;
2228
2229 case 845: { // reconfig
2230 if (! *label) {
2231 fprintf(stderr,
2232 i18n(ScreenSet, ScreenRECONFIGError,
2233 "BScreen::parseMenuFile: [reconfig] error, "
2234 "no menu label defined\n"));
2235 continue;
2236 }
2237
2238 menu->insert(label, BScreen::Reconfigure);
2239 }
2240
2241 break;
2242
2243 case 995: // stylesdir
2244 case 1113: { // stylesmenu
2245 bool newmenu = ((key == 1113) ? True : False);
2246
2247 if (! *label || (! *command && newmenu)) {
2248 fprintf(stderr,
2249 i18n(ScreenSet, ScreenSTYLESDIRError,
2250 "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
2251 " error, no directory defined\n"));
2252 continue;
2253 }
2254
2255 char *directory = ((newmenu) ? command : label);
2256
2257 string stylesdir = expandTilde(directory);
2258
2259 struct stat statbuf;
2260
2261 if (stat(stylesdir.c_str(), &statbuf) == -1) {
2262 fprintf(stderr,
2263 i18n(ScreenSet, ScreenSTYLESDIRErrorNoExist,
2264 "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
2265 " error, %s does not exist\n"), stylesdir.c_str());
2266 continue;
2267 }
2268 if (! S_ISDIR(statbuf.st_mode)) {
2269 fprintf(stderr,
2270 i18n(ScreenSet, ScreenSTYLESDIRErrorNotDir,
2271 "BScreen::parseMenuFile:"
2272 " [stylesdir/stylesmenu] error, %s is not a"
2273 " directory\n"), stylesdir.c_str());
2274 continue;
2275 }
2276
2277 Rootmenu *stylesmenu;
2278
2279 if (newmenu)
2280 stylesmenu = new Rootmenu(this);
2281 else
2282 stylesmenu = menu;
2283
2284 DIR *d = opendir(stylesdir.c_str());
2285 struct dirent *p;
2286 std::vector<string> ls;
2287
2288 while((p = readdir(d)))
2289 ls.push_back(p->d_name);
2290
2291 closedir(d);
2292
2293 std::sort(ls.begin(), ls.end());
2294
2295 std::vector<string>::iterator it = ls.begin(),
2296 end = ls.end();
2297 for (; it != end; ++it) {
2298 const string& fname = *it;
2299
2300 if (fname[fname.size()-1] == '~')
2301 continue;
2302
2303 string style = stylesdir;
2304 style += '/';
2305 style += fname;
2306
2307 if (! stat(style.c_str(), &statbuf) && S_ISREG(statbuf.st_mode))
2308 stylesmenu->insert(fname, BScreen::SetStyle, style);
2309 }
2310
2311 stylesmenu->update();
2312
2313 if (newmenu) {
2314 stylesmenu->setLabel(label);
2315 menu->insert(label, stylesmenu);
2316 rootmenuList.push_back(stylesmenu);
2317 }
2318
2319 blackbox->addMenuTimestamp(stylesdir);
2320 }
2321 break;
2322
2323 case 1090: { // workspaces
2324 if (! *label) {
2325 fprintf(stderr,
2326 i18n(ScreenSet, ScreenWORKSPACESError,
2327 "BScreen:parseMenuFile: [workspaces] error, "
2328 "no menu label defined\n"));
2329 continue;
2330 }
2331
2332 menu->insert(label, workspacemenu);
2333 }
2334 break;
2335 }
2336 }
2337
2338 return ((menu->getCount() == 0) ? True : False);
2339 }
2340
2341
2342 void BScreen::shutdown(void) {
2343 XSelectInput(blackbox->getXDisplay(), getRootWindow(), NoEventMask);
2344 XSync(blackbox->getXDisplay(), False);
2345
2346 while(! windowList.empty())
2347 unmanageWindow(windowList.front(), True);
2348
2349 while(! desktopWindowList.empty()) {
2350 BlackboxWindow *win = blackbox->searchWindow(desktopWindowList.front());
2351 assert(win);
2352 unmanageWindow(win, True);
2353 }
2354
2355 slit->shutdown();
2356 }
2357
2358
2359 void BScreen::showPosition(int x, int y) {
2360 if (! geom_visible) {
2361 XMoveResizeWindow(blackbox->getXDisplay(), geom_window,
2362 (getWidth() - geom_w) / 2,
2363 (getHeight() - geom_h) / 2, geom_w, geom_h);
2364 XMapWindow(blackbox->getXDisplay(), geom_window);
2365 XRaiseWindow(blackbox->getXDisplay(), geom_window);
2366
2367 geom_visible = True;
2368 }
2369
2370 char label[1024];
2371
2372 sprintf(label, i18n(ScreenSet, ScreenPositionFormat,
2373 "X: %4d x Y: %4d"), x, y);
2374
2375 XClearWindow(blackbox->getXDisplay(), geom_window);
2376
2377 resource.wstyle.font->drawString(geom_window,
2378 resource.bevel_width, resource.bevel_width,
2379 resource.wstyle.l_text_focus,
2380 label);
2381 }
2382
2383
2384 void BScreen::showGeometry(unsigned int gx, unsigned int gy) {
2385 if (! geom_visible) {
2386 XMoveResizeWindow(blackbox->getXDisplay(), geom_window,
2387 (getWidth() - geom_w) / 2,
2388 (getHeight() - geom_h) / 2, geom_w, geom_h);
2389 XMapWindow(blackbox->getXDisplay(), geom_window);
2390 XRaiseWindow(blackbox->getXDisplay(), geom_window);
2391
2392 geom_visible = True;
2393 }
2394
2395 char label[1024];
2396
2397 sprintf(label, i18n(ScreenSet, ScreenGeometryFormat,
2398 "W: %4d x H: %4d"), gx, gy);
2399
2400 XClearWindow(blackbox->getXDisplay(), geom_window);
2401
2402 resource.wstyle.font->drawString(geom_window,
2403 resource.bevel_width, resource.bevel_width,
2404 resource.wstyle.l_text_focus,
2405 label);
2406 }
2407
2408
2409 void BScreen::hideGeometry(void) {
2410 if (geom_visible) {
2411 XUnmapWindow(blackbox->getXDisplay(), geom_window);
2412 geom_visible = False;
2413 }
2414 }
2415
2416
2417 void BScreen::addStrut(Strut *strut) {
2418 strutList.push_back(strut);
2419 }
2420
2421
2422 void BScreen::removeStrut(Strut *strut) {
2423 strutList.remove(strut);
2424 }
2425
2426
2427 const Rect& BScreen::availableArea(void) const {
2428 if (doFullMax())
2429 return getRect(); // return the full screen
2430 return usableArea;
2431 }
2432
2433
2434 #ifdef XINERAMA
2435 const RectList& BScreen::allAvailableAreas(void) const {
2436 assert(isXineramaActive());
2437 assert(xineramaUsableArea.size() > 0);
2438 fprintf(stderr, "1found x %d y %d w %d h %d\n",
2439 xineramaUsableArea[0].x(), xineramaUsableArea[0].y(),
2440 xineramaUsableArea[0].width(), xineramaUsableArea[0].height());
2441 return xineramaUsableArea;
2442 }
2443 #endif // XINERAMA
2444
2445
2446 void BScreen::updateAvailableArea(void) {
2447 Rect old_area = usableArea;
2448 usableArea = getRect(); // reset to full screen
2449
2450 #ifdef XINERAMA
2451 // reset to the full areas
2452 if (isXineramaActive())
2453 xineramaUsableArea = getXineramaAreas();
2454 #endif // XINERAMA
2455
2456 /* these values represent offsets from the screen edge
2457 * we look for the biggest offset on each edge and then apply them
2458 * all at once
2459 * do not be confused by the similarity to the names of Rect's members
2460 */
2461 unsigned int current_left = 0, current_right = 0, current_top = 0,
2462 current_bottom = 0;
2463
2464 StrutList::const_iterator it = strutList.begin(), end = strutList.end();
2465
2466 for(; it != end; ++it) {
2467 Strut *strut = *it;
2468 if (strut->left > current_left)
2469 current_left = strut->left;
2470 if (strut->top > current_top)
2471 current_top = strut->top;
2472 if (strut->right > current_right)
2473 current_right = strut->right;
2474 if (strut->bottom > current_bottom)
2475 current_bottom = strut->bottom;
2476 }
2477
2478 usableArea.setPos(current_left, current_top);
2479 usableArea.setSize(usableArea.width() - (current_left + current_right),
2480 usableArea.height() - (current_top + current_bottom));
2481
2482 #ifdef XINERAMA
2483 if (isXineramaActive()) {
2484 // keep each of the ximerama-defined areas inside the strut
2485 RectList::iterator xit, xend = xineramaUsableArea.end();
2486 for (xit = xineramaUsableArea.begin(); xit != xend; ++xit) {
2487 if (xit->x() < usableArea.x()) {
2488 xit->setX(usableArea.x());
2489 xit->setWidth(xit->width() - usableArea.x());
2490 }
2491 if (xit->y() < usableArea.y()) {
2492 xit->setY(usableArea.y());
2493 xit->setHeight(xit->height() - usableArea.y());
2494 }
2495 if (xit->x() + xit->width() > usableArea.width())
2496 xit->setWidth(usableArea.width() - xit->x());
2497 if (xit->y() + xit->height() > usableArea.height())
2498 xit->setHeight(usableArea.height() - xit->y());
2499 }
2500 }
2501 #endif // XINERAMA
2502
2503 if (old_area != usableArea) {
2504 BlackboxWindowList::iterator it = windowList.begin(),
2505 end = windowList.end();
2506 for (; it != end; ++it)
2507 if ((*it)->isMaximized()) (*it)->remaximize();
2508 }
2509
2510 updateWorkArea();
2511 }
2512
2513
2514 Workspace* BScreen::getWorkspace(unsigned int index) {
2515 assert(index < workspacesList.size());
2516 return workspacesList[index];
2517 }
2518
2519
2520 void BScreen::buttonPressEvent(const XButtonEvent *xbutton) {
2521 if (xbutton->button == 1) {
2522 if (! isRootColormapInstalled())
2523 image_control->installRootColormap();
2524
2525 if (workspacemenu->isVisible())
2526 workspacemenu->hide();
2527
2528 if (rootmenu->isVisible())
2529 rootmenu->hide();
2530 // mouse wheel up
2531 } else if ((xbutton->button == 4 && resource.root_scroll == NormalScroll) ||
2532 (xbutton->button == 5 && resource.root_scroll == ReverseScroll)) {
2533 if (getCurrentWorkspaceID() >= getWorkspaceCount() - 1)
2534 changeWorkspaceID(0);
2535 else
2536 changeWorkspaceID(getCurrentWorkspaceID() + 1);
2537 // mouse wheel down
2538 } else if ((xbutton->button == 5 && resource.root_scroll == NormalScroll) ||
2539 (xbutton->button == 4 && resource.root_scroll == ReverseScroll)) {
2540 if (getCurrentWorkspaceID() == 0)
2541 changeWorkspaceID(getWorkspaceCount() - 1);
2542 else
2543 changeWorkspaceID(getCurrentWorkspaceID() - 1);
2544 }
2545
2546 if (resource.root_menu_button > 0 &&
2547 xbutton->button == resource.root_menu_button)
2548 showRootMenu(xbutton->x_root, xbutton->y_root);
2549 else if (resource.workspace_menu_button > 0 &&
2550 xbutton->button == resource.workspace_menu_button)
2551 showWorkspaceMenu(xbutton->x_root, xbutton->y_root);
2552 }
2553
2554
2555 void BScreen::showWorkspaceMenu(int x, int y) {
2556 int mx = x - (workspacemenu->getWidth() / 2);
2557 int my = y - (workspacemenu->getTitleHeight() / 2);
2558
2559 if (mx < 0) mx = 0;
2560 if (my < 0) my = 0;
2561
2562 if (mx + workspacemenu->getWidth() > getWidth())
2563 mx = getWidth() - workspacemenu->getWidth() - getBorderWidth();
2564
2565 if (my + workspacemenu->getHeight() > getHeight())
2566 my = getHeight() - workspacemenu->getHeight() - getBorderWidth();
2567
2568 workspacemenu->move(mx, my);
2569
2570 if (! workspacemenu->isVisible()) {
2571 workspacemenu->removeParent();
2572 workspacemenu->show();
2573 }
2574 }
2575
2576
2577 void BScreen::showRootMenu(int x, int y) {
2578 int mx = x - (rootmenu->getWidth() / 2);
2579 int my = y - (rootmenu->getTitleHeight() / 2);
2580
2581 if (mx < 0) mx = 0;
2582 if (my < 0) my = 0;
2583
2584 if (mx + rootmenu->getWidth() > getWidth())
2585 mx = getWidth() - rootmenu->getWidth() - getBorderWidth();
2586
2587 if (my + rootmenu->getHeight() > getHeight())
2588 my = getHeight() - rootmenu->getHeight() - getBorderWidth();
2589
2590 rootmenu->move(mx, my);
2591
2592 if (! rootmenu->isVisible()) {
2593 blackbox->checkMenu();
2594 rootmenu->show();
2595 }
2596 }
2597
2598
2599 void BScreen::propertyNotifyEvent(const XPropertyEvent *pe) {
2600 if (pe->atom == xatom->getAtom(XAtom::net_desktop_names)) {
2601 // _NET_WM_DESKTOP_NAMES
2602 WorkspaceList::iterator it = workspacesList.begin();
2603 const WorkspaceList::iterator end = workspacesList.end();
2604 for (; it != end; ++it) {
2605 (*it)->readName(); // re-read its name from the window property
2606 workspacemenu->changeWorkspaceLabel((*it)->getID(), (*it)->getName());
2607 }
2608 workspacemenu->update();
2609 toolbar->reconfigure();
2610 saveWorkspaceNames();
2611 }
2612 }
2613
2614
2615 void BScreen::toggleFocusModel(FocusModel model) {
2616 std::for_each(windowList.begin(), windowList.end(),
2617 std::mem_fun(&BlackboxWindow::ungrabButtons));
2618
2619 if (model == SloppyFocus) {
2620 saveSloppyFocus(True);
2621 } else {
2622 // we're cheating here to save writing the config file 3 times
2623 resource.auto_raise = False;
2624 resource.click_raise = False;
2625 saveSloppyFocus(False);
2626 }
2627
2628 std::for_each(windowList.begin(), windowList.end(),
2629 std::mem_fun(&BlackboxWindow::grabButtons));
2630 }
2631
2632 void BScreen::readDatabaseMask(const string &rname, PixmapMask &pixmapMask,
2633 const Configuration &style) {
2634 string s;
2635 int hx, hy; //ignored
2636 int ret = BitmapOpenFailed; //default to failure.
2637
2638 if (style.getValue(rname, s))
2639 {
2640 if (s[0] != '/' && s[0] != '~')
2641 {
2642 std::string xbmFile = std::string("~/.openbox/buttons/") + s;
2643 ret = XReadBitmapFile(blackbox->getXDisplay(), getRootWindow(),
2644 expandTilde(xbmFile).c_str(), &pixmapMask.w,
2645 &pixmapMask.h, &pixmapMask.mask, &hx, &hy);
2646 } else
2647 ret = XReadBitmapFile(blackbox->getXDisplay(), getRootWindow(),
2648 expandTilde(s).c_str(), &pixmapMask.w,
2649 &pixmapMask.h, &pixmapMask.mask, &hx, &hy);
2650
2651 if (ret == BitmapSuccess)
2652 return;
2653 }
2654
2655 pixmapMask.mask = None;
2656 pixmapMask.w = pixmapMask.h = 0;
2657 }
2658
2659 BTexture BScreen::readDatabaseTexture(const string &rname,
2660 const string &default_color,
2661 const Configuration &style) {
2662 BTexture texture;
2663 string s;
2664
2665 if (style.getValue(rname, s))
2666 texture = BTexture(s);
2667 else
2668 texture.setTexture(BTexture::Solid | BTexture::Flat);
2669
2670 // associate this texture with this screen
2671 texture.setDisplay(getBaseDisplay(), getScreenNumber());
2672 texture.setImageControl(image_control);
2673
2674 texture.setColor(readDatabaseColor(rname + ".color", default_color, style));
2675 texture.setColorTo(readDatabaseColor(rname + ".colorTo", default_color,
2676 style));
2677 texture.setBorderColor(readDatabaseColor(rname + ".borderColor",
2678 default_color, style));
2679
2680 return texture;
2681 }
2682
2683
2684 BColor BScreen::readDatabaseColor(const string &rname,
2685 const string &default_color,
2686 const Configuration &style) {
2687 BColor color;
2688 string s;
2689 if (style.getValue(rname, s))
2690 color = BColor(s, getBaseDisplay(), getScreenNumber());
2691 else
2692 color = BColor(default_color, getBaseDisplay(), getScreenNumber());
2693 return color;
2694 }
2695
2696
2697 BFont *BScreen::readDatabaseFont(const string &rbasename,
2698 const Configuration &style) {
2699 string fontname;
2700
2701 string s;
2702
2703 #ifdef XFT
2704 int i;
2705 if (style.getValue(rbasename + "xft.font", s) &&
2706 style.getValue(rbasename + "xft.size", i)) {
2707 string family = s;
2708 bool bold = False;
2709 bool italic = False;
2710 if (style.getValue(rbasename + "xft.flags", s)) {
2711 if (s.find("bold") != string::npos)
2712 bold = True;
2713 if (s.find("italic") != string::npos)
2714 italic = True;
2715 }
2716
2717 BFont *b = new BFont(blackbox->getXDisplay(), this, family, i, bold,
2718 italic, resource.shadow_fonts, resource.aa_fonts);
2719 if (b->valid())
2720 return b;
2721 else
2722 delete b; // fall back to the normal X font stuff
2723 }
2724 #endif // XFT
2725
2726 style.getValue(rbasename + "font", s);
2727 // if this fails, a blank string will be used, which will cause the fallback
2728 // font to load.
2729
2730 BFont *b = new BFont(blackbox->getXDisplay(), this, s);
2731 if (! b->valid())
2732 exit(2); // can't continue without a font
2733 return b;
2734 }
This page took 0.15848 seconds and 4 git commands to generate.