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