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