]> Dogcows Code - chaz/openbox/blob - src/screen.cc
add comment for later
[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 "blackbox.hh"
79 #include "font.hh"
80 #include "gccache.hh"
81 #include "image.hh"
82 #include "screen.hh"
83 #include "util.hh"
84 #include "window.hh"
85 #include "workspace.hh"
86 #include "util.hh"
87 #include "xatom.hh"
88
89 #ifndef FONT_ELEMENT_SIZE
90 #define FONT_ELEMENT_SIZE 50
91 #endif // FONT_ELEMENT_SIZE
92
93
94 static bool running = True;
95
96 static int anotherWMRunning(Display *display, XErrorEvent *) {
97 fprintf(stderr,
98 "BScreen::BScreen: an error occured while querying the X server.\n"
99 " another window manager already running on display %s.\n",
100 DisplayString(display));
101
102 running = False;
103
104 return(-1);
105 }
106
107
108 BScreen::BScreen(Blackbox *bb, unsigned int scrn) : ScreenInfo(bb, scrn) {
109 blackbox = bb;
110 screenstr = "session.screen" + itostring(scrn) + '.';
111 config = blackbox->getConfig();
112 xatom = blackbox->getXAtom();
113
114 event_mask = ColormapChangeMask | EnterWindowMask | PropertyChangeMask |
115 SubstructureRedirectMask | ButtonPressMask | ButtonReleaseMask;
116
117 XErrorHandler old = XSetErrorHandler((XErrorHandler) anotherWMRunning);
118 XSelectInput(getBaseDisplay()->getXDisplay(), getRootWindow(), event_mask);
119 XSync(getBaseDisplay()->getXDisplay(), False);
120 XSetErrorHandler((XErrorHandler) old);
121
122 managed = running;
123 if (! managed) return;
124
125 fprintf(stderr, "BScreen::BScreen: managing screen %d "
126 "using visual 0x%lx, depth %d\n",
127 getScreenNumber(), XVisualIDFromVisual(getVisual()),
128 getDepth());
129
130 resource.wstyle.font = (BFont *) 0;
131
132 geom_pixmap = None;
133
134 xatom->setSupported(this); // set-up netwm support
135 #ifdef HAVE_GETPID
136 xatom->setValue(getRootWindow(), XAtom::blackbox_pid, XAtom::cardinal,
137 (unsigned long) getpid());
138 #endif // HAVE_GETPID
139 unsigned long geometry[] = { getWidth(),
140 getHeight()};
141 xatom->setValue(getRootWindow(), XAtom::net_desktop_geometry,
142 XAtom::cardinal, geometry, 2);
143 unsigned long viewport[] = {0,0};
144 xatom->setValue(getRootWindow(), XAtom::net_desktop_viewport,
145 XAtom::cardinal, viewport, 2);
146
147
148 XDefineCursor(blackbox->getXDisplay(), getRootWindow(),
149 blackbox->getSessionCursor());
150
151 updateAvailableArea();
152
153 image_control =
154 new BImageControl(blackbox, this, True, blackbox->getColorsPerChannel(),
155 blackbox->getCacheLife(), blackbox->getCacheMax());
156 image_control->installRootColormap();
157 root_colormap_installed = True;
158
159 load_rc();
160 LoadStyle();
161
162 XGCValues gcv;
163 gcv.foreground = WhitePixel(blackbox->getXDisplay(), getScreenNumber())
164 ^ BlackPixel(blackbox->getXDisplay(), getScreenNumber());
165 gcv.function = GXxor;
166 gcv.subwindow_mode = IncludeInferiors;
167 opGC = XCreateGC(blackbox->getXDisplay(), getRootWindow(),
168 GCForeground | GCFunction | GCSubwindowMode, &gcv);
169
170 const char *s = "0: 0000 x 0: 0000";
171 geom_w = resource.wstyle.font->measureString(s) + resource.bevel_width * 2;
172 geom_h = resource.wstyle.font->height() + resource.bevel_width * 2;
173
174 XSetWindowAttributes attrib;
175 unsigned long mask = CWBorderPixel | CWColormap | CWSaveUnder;
176 attrib.border_pixel = getBorderColor()->pixel();
177 attrib.colormap = getColormap();
178 attrib.save_under = True;
179
180 geom_window = XCreateWindow(blackbox->getXDisplay(), getRootWindow(),
181 0, 0, geom_w, geom_h, resource.border_width,
182 getDepth(), InputOutput, getVisual(),
183 mask, &attrib);
184 geom_visible = False;
185
186 BTexture* texture = &(resource.wstyle.l_focus);
187 geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap);
188 if (geom_pixmap == ParentRelative) {
189 texture = &(resource.wstyle.t_focus);
190 geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap);
191 }
192 if (! geom_pixmap)
193 XSetWindowBackground(blackbox->getXDisplay(), geom_window,
194 texture->color().pixel());
195 else
196 XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
197 geom_window, geom_pixmap);
198
199 if (resource.workspaces > 0) {
200 for (unsigned int i = 0; i < resource.workspaces; ++i) {
201 Workspace *wkspc = new Workspace(this, workspacesList.size());
202 workspacesList.push_back(wkspc);
203
204 }
205 } else {
206 Workspace *wkspc = new Workspace(this, workspacesList.size());
207 workspacesList.push_back(wkspc);
208 }
209 saveWorkspaceNames();
210
211 updateNetizenWorkspaceCount();
212
213 current_workspace = workspacesList.front();
214
215 xatom->setValue(getRootWindow(), XAtom::net_current_desktop,
216 XAtom::cardinal, 0); //first workspace
217
218 raiseWindows(0, 0); // this also initializes the empty stacking list
219
220 updateClientList(); // initialize the client lists, which will be empty
221 updateAvailableArea();
222
223 changeWorkspaceID(0);
224
225 unsigned int i, j, nchild;
226 Window r, p, *children;
227 XQueryTree(blackbox->getXDisplay(), getRootWindow(), &r, &p,
228 &children, &nchild);
229
230 // preen the window list of all icon windows... for better dockapp support
231 for (i = 0; i < nchild; i++) {
232 if (children[i] == None) continue;
233
234 XWMHints *wmhints = XGetWMHints(blackbox->getXDisplay(),
235 children[i]);
236
237 if (wmhints) {
238 if ((wmhints->flags & IconWindowHint) &&
239 (wmhints->icon_window != children[i])) {
240 for (j = 0; j < nchild; j++) {
241 if (children[j] == wmhints->icon_window) {
242 children[j] = None;
243 break;
244 }
245 }
246 }
247
248 XFree(wmhints);
249 }
250 }
251
252 // manage shown windows
253 for (i = 0; i < nchild; ++i) {
254 if (children[i] == None || ! blackbox->validateWindow(children[i]))
255 continue;
256
257 XWindowAttributes attrib;
258 if (XGetWindowAttributes(blackbox->getXDisplay(), children[i], &attrib)) {
259 if (attrib.override_redirect) continue;
260
261 if (attrib.map_state != IsUnmapped) {
262 manageWindow(children[i]);
263 }
264 }
265 }
266
267 XFree(children);
268
269 // call this again just in case a window we found updates the Strut list
270 updateAvailableArea();
271 }
272
273
274 BScreen::~BScreen(void) {
275 if (! managed) return;
276
277 if (geom_pixmap != None)
278 image_control->removeImage(geom_pixmap);
279
280 if (geom_window != None)
281 XDestroyWindow(blackbox->getXDisplay(), geom_window);
282
283 std::for_each(workspacesList.begin(), workspacesList.end(),
284 PointerAssassin());
285
286 std::for_each(iconList.begin(), iconList.end(), PointerAssassin());
287
288 while (! systrayWindowList.empty())
289 removeSystrayWindow(systrayWindowList[0]);
290
291 delete image_control;
292
293 if (resource.wstyle.font)
294 delete resource.wstyle.font;
295
296 #ifdef BITMAPBUTTONS
297 if (resource.wstyle.close_button.mask != None)
298 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.close_button.mask);
299 if (resource.wstyle.max_button.mask != None)
300 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.max_button.mask);
301 if (resource.wstyle.icon_button.mask != None)
302 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.icon_button.mask);
303 if (resource.wstyle.stick_button.mask != None)
304 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.stick_button.mask);
305
306 resource.wstyle.max_button.mask = resource.wstyle.close_button.mask =
307 resource.wstyle.icon_button.mask =
308 resource.wstyle.stick_button.mask = None;
309 #endif // BITMAPBUTTONS
310
311 XFreeGC(blackbox->getXDisplay(), opGC);
312 }
313
314
315 void BScreen::saveSloppyFocus(bool s) {
316 resource.sloppy_focus = s;
317
318 string fmodel;
319 if (resource.sloppy_focus) {
320 fmodel = "SloppyFocus";
321 if (resource.auto_raise) fmodel += " AutoRaise";
322 if (resource.click_raise) fmodel += " ClickRaise";
323 } else {
324 fmodel = "ClickToFocus";
325 }
326 config->setValue(screenstr + "focusModel", fmodel);
327 }
328
329
330 void BScreen::saveAutoRaise(bool a) {
331 resource.auto_raise = a;
332 saveSloppyFocus(resource.sloppy_focus);
333 }
334
335
336 void BScreen::saveClickRaise(bool c) {
337 resource.click_raise = c;
338 saveSloppyFocus(resource.sloppy_focus);
339 }
340
341
342 void BScreen::saveImageDither(bool d) {
343 image_control->setDither(d);
344 config->setValue(screenstr + "imageDither", doImageDither());
345 }
346
347
348 void BScreen::saveOpaqueMove(bool o) {
349 resource.opaque_move = o;
350 config->setValue(screenstr + "opaqueMove", resource.opaque_move);
351 }
352
353
354 void BScreen::saveFullMax(bool f) {
355 resource.full_max = f;
356 config->setValue(screenstr + "fullMaximization", resource.full_max);
357 }
358
359
360 void BScreen::saveFocusNew(bool f) {
361 resource.focus_new = f;
362 config->setValue(screenstr + "focusNewWindows", resource.focus_new);
363 }
364
365
366 void BScreen::saveFocusLast(bool f) {
367 resource.focus_last = f;
368 config->setValue(screenstr + "focusLastWindow", resource.focus_last);
369 }
370
371
372 void BScreen::saveAAFonts(bool f) {
373 resource.aa_fonts = f;
374 config->setValue(screenstr + "antialiasFonts", resource.aa_fonts);
375 reconfigure();
376 }
377
378
379 void BScreen::saveShadowFonts(bool f) {
380 resource.shadow_fonts = f;
381 config->setValue(screenstr + "dropShadowFonts", resource.shadow_fonts);
382 reconfigure();
383 }
384
385
386 void BScreen::saveWindowToEdgeSnap(int s) {
387 resource.snap_to_edges = s;
388
389 const char *snap;
390 switch (resource.snap_to_edges) {
391 case WindowNoSnap: snap = "NoSnap"; break;
392 case WindowResistance: snap = "Resistance"; break;
393 case WindowSnap: default: snap = "Snap"; break;
394 }
395 config->setValue(screenstr + "windowToEdgeSnap", snap);
396 }
397
398
399 void BScreen::saveWindowToWindowSnap(int s) {
400 resource.snap_to_windows = s;
401
402 const char *snap;
403 switch (resource.snap_to_windows) {
404 case WindowNoSnap: snap = "NoSnap"; break;
405 case WindowResistance: snap = "Resistance"; break;
406 case WindowSnap: default: snap = "Snap"; break;
407 }
408 config->setValue(screenstr + "windowToWindowSnap", snap);
409 }
410
411
412 void BScreen::saveResizeZones(unsigned int z) {
413 resource.resize_zones = z;
414 config->setValue(screenstr + "resizeZones", resource.resize_zones);
415 }
416
417
418 void BScreen::saveWindowCornerSnap(bool s) {
419 resource.window_corner_snap = s;
420 config->setValue(screenstr + "windowCornerSnap",
421 resource.window_corner_snap);
422 }
423
424
425 void BScreen::saveWorkspaces(unsigned int w) {
426 resource.workspaces = w;
427 config->setValue(screenstr + "workspaces", resource.workspaces);
428 }
429
430
431 void BScreen::savePlacementPolicy(int p) {
432 resource.placement_policy = p;
433 const char *placement;
434 switch (resource.placement_policy) {
435 case CascadePlacement: placement = "CascadePlacement"; break;
436 case UnderMousePlacement: placement = "UnderMousePlacement"; break;
437 case ClickMousePlacement: placement = "ClickMousePlacement"; break;
438 case ColSmartPlacement: placement = "ColSmartPlacement"; break;
439 case RowSmartPlacement: default: placement = "RowSmartPlacement"; break;
440 }
441 config->setValue(screenstr + "windowPlacement", placement);
442 }
443
444
445 void BScreen::saveResistanceSize(int s) {
446 resource.resistance_size = s;
447 config->setValue(screenstr + "resistanceSize",
448 resource.resistance_size);
449 }
450
451
452 void BScreen::saveSnapThreshold(int t) {
453 resource.snap_threshold = t;
454 config->setValue(screenstr + "edgeSnapThreshold",
455 resource.snap_threshold);
456 }
457
458
459 void BScreen::saveSnapOffset(int t) {
460 resource.snap_offset = t;
461 config->setValue(screenstr + "edgeSnapOffset",
462 resource.snap_offset);
463 }
464
465
466 void BScreen::saveRowPlacementDirection(int d) {
467 resource.row_direction = d;
468 config->setValue(screenstr + "rowPlacementDirection",
469 resource.row_direction == LeftRight ?
470 "LeftToRight" : "RightToLeft");
471 }
472
473
474 void BScreen::saveColPlacementDirection(int d) {
475 resource.col_direction = d;
476 config->setValue(screenstr + "colPlacementDirection",
477 resource.col_direction == TopBottom ?
478 "TopToBottom" : "BottomToTop");
479 }
480
481
482 void BScreen::saveStrftimeFormat(const std::string& format) {
483 resource.strftime_format = format;
484 config->setValue(screenstr + "strftimeFormat", resource.strftime_format);
485 }
486
487
488 void BScreen::saveWorkspaceNames() {
489 string names;
490
491 for (unsigned int i = 0; i < workspacesList.size(); ++i) {
492 names += workspacesList[i]->getName();
493 if (i < workspacesList.size() - 1)
494 names += ',';
495 }
496
497 config->setValue(screenstr + "workspaceNames", names);
498 }
499
500
501 void BScreen::savePlaceIgnoreShaded(bool i) {
502 resource.ignore_shaded = i;
503 config->setValue(screenstr + "placementIgnoreShaded",
504 resource.ignore_shaded);
505 }
506
507
508 void BScreen::savePlaceIgnoreMaximized(bool i) {
509 resource.ignore_maximized = i;
510 config->setValue(screenstr + "placementIgnoreMaximized",
511 resource.ignore_maximized);
512 }
513
514
515 void BScreen::saveAllowScrollLock(bool a) {
516 resource.allow_scroll_lock = a;
517 config->setValue(screenstr + "disableBindingsWithScrollLock",
518 resource.allow_scroll_lock);
519 }
520
521
522 void BScreen::saveWorkspaceWarping(bool w) {
523 resource.workspace_warping = w;
524 config->setValue(screenstr + "workspaceWarping",
525 resource.workspace_warping);
526 }
527
528
529 void BScreen::saveRootScrollDirection(int d) {
530 resource.root_scroll = d;
531 const char *dir;
532 switch (resource.root_scroll) {
533 case NoScroll: dir = "None"; break;
534 case ReverseScroll: dir = "Reverse"; break;
535 case NormalScroll: default: dir = "Normal"; break;
536 }
537 config->setValue(screenstr + "rootScrollDirection", dir);
538 }
539
540
541 void BScreen::save_rc(void) {
542 saveSloppyFocus(resource.sloppy_focus);
543 saveAutoRaise(resource.auto_raise);
544 saveImageDither(doImageDither());
545 saveShadowFonts(resource.shadow_fonts);
546 saveAAFonts(resource.aa_fonts);
547 saveResizeZones(resource.resize_zones);
548 saveOpaqueMove(resource.opaque_move);
549 saveFullMax(resource.full_max);
550 saveFocusNew(resource.focus_new);
551 saveFocusLast(resource.focus_last);
552 saveWindowToWindowSnap(resource.snap_to_windows);
553 saveWindowToEdgeSnap(resource.snap_to_edges);
554 saveWindowCornerSnap(resource.window_corner_snap);
555 saveWorkspaces(resource.workspaces);
556 savePlacementPolicy(resource.placement_policy);
557 saveSnapThreshold(resource.snap_threshold);
558 saveSnapOffset(resource.snap_offset);
559 saveResistanceSize(resource.resistance_size);
560 saveRowPlacementDirection(resource.row_direction);
561 saveColPlacementDirection(resource.col_direction);
562 saveStrftimeFormat(resource.strftime_format);
563 savePlaceIgnoreShaded(resource.ignore_shaded);
564 savePlaceIgnoreMaximized(resource.ignore_maximized);
565 saveAllowScrollLock(resource.allow_scroll_lock);
566 saveWorkspaceWarping(resource.workspace_warping);
567 saveRootScrollDirection(resource.root_scroll);
568 }
569
570
571 void BScreen::load_rc(void) {
572 std::string s;
573 bool b;
574
575 if (! config->getValue(screenstr + "fullMaximization", resource.full_max))
576 resource.full_max = false;
577
578 if (! config->getValue(screenstr + "focusNewWindows", resource.focus_new))
579 resource.focus_new = false;
580
581 if (! config->getValue(screenstr + "focusLastWindow", resource.focus_last))
582 resource.focus_last = false;
583
584 if (! config->getValue(screenstr + "workspaces", resource.workspaces))
585 resource.workspaces = 1;
586
587 if (! config->getValue(screenstr + "opaqueMove", resource.opaque_move))
588 resource.opaque_move = false;
589
590 if (! config->getValue(screenstr + "antialiasFonts", resource.aa_fonts))
591 resource.aa_fonts = true;
592
593 if (! resource.aa_fonts ||
594 ! config->getValue(screenstr + "dropShadowFonts", resource.shadow_fonts))
595 resource.shadow_fonts = false;
596
597 if (! config->getValue(screenstr + "resizeZones", resource.resize_zones) ||
598 (resource.resize_zones != 1 && resource.resize_zones != 2 &&
599 resource.resize_zones != 4))
600 resource.resize_zones = 4;
601
602 resource.snap_to_windows = WindowResistance;
603 if (config->getValue(screenstr + "windowToWindowSnap", s)) {
604 if (s == "NoSnap")
605 resource.snap_to_windows = WindowNoSnap;
606 else if (s == "Snap")
607 resource.snap_to_windows = WindowSnap;
608 }
609
610 resource.snap_to_edges = WindowResistance;
611 if (config->getValue(screenstr + "windowToEdgeSnap", s)) {
612 if (s == "NoSnap")
613 resource.snap_to_edges = WindowNoSnap;
614 else if (s == "Snap")
615 resource.snap_to_edges = WindowSnap;
616 }
617
618 if (! config->getValue(screenstr + "windowCornerSnap",
619 resource.window_corner_snap))
620 resource.window_corner_snap = true;
621
622 if (! config->getValue(screenstr + "imageDither", b))
623 b = true;
624 image_control->setDither(b);
625
626 if (! config->getValue(screenstr + "edgeSnapOffset",
627 resource.snap_offset))
628 resource.snap_offset = 0;
629 if (resource.snap_offset > 50) // sanity check, setting this huge would
630 resource.snap_offset = 50; // seriously suck.
631
632 if (! config->getValue(screenstr + "edgeSnapThreshold",
633 resource.snap_threshold))
634 resource.snap_threshold = 4;
635
636 if (! config->getValue(screenstr + "resistanceSize",
637 resource.resistance_size))
638 resource.resistance_size = 18;
639
640 if (config->getValue(screenstr + "rowPlacementDirection", s) &&
641 s == "RightToLeft")
642 resource.row_direction = RightLeft;
643 else
644 resource.row_direction = LeftRight;
645
646 if (config->getValue(screenstr + "colPlacementDirection", s) &&
647 s == "BottomToTop")
648 resource.col_direction = BottomTop;
649 else
650 resource.col_direction = TopBottom;
651
652 if (config->getValue(screenstr + "workspaceNames", s)) {
653 XAtom::StringVect workspaceNames;
654
655 string::const_iterator it = s.begin(), end = s.end();
656 while(1) {
657 string::const_iterator tmp = it; // current string.begin()
658 it = std::find(tmp, end, ','); // look for comma between tmp and end
659 workspaceNames.push_back(string(tmp, it)); // s[tmp:it]
660 if (it == end)
661 break;
662 ++it;
663 }
664
665 xatom->setValue(getRootWindow(), XAtom::net_desktop_names, XAtom::utf8,
666 workspaceNames);
667 }
668
669 resource.sloppy_focus = true;
670 resource.auto_raise = false;
671 resource.click_raise = false;
672 if (config->getValue(screenstr + "focusModel", s)) {
673 if (s.find("ClickToFocus") != string::npos) {
674 resource.sloppy_focus = false;
675 } else {
676 // must be sloppy
677 if (s.find("AutoRaise") != string::npos)
678 resource.auto_raise = true;
679 if (s.find("ClickRaise") != string::npos)
680 resource.click_raise = true;
681 }
682 }
683
684 if (config->getValue(screenstr + "windowPlacement", s)) {
685 if (s == "CascadePlacement")
686 resource.placement_policy = CascadePlacement;
687 else if (s == "UnderMousePlacement")
688 resource.placement_policy = UnderMousePlacement;
689 else if (s == "ClickMousePlacement")
690 resource.placement_policy = ClickMousePlacement;
691 else if (s == "ColSmartPlacement")
692 resource.placement_policy = ColSmartPlacement;
693 else //if (s == "RowSmartPlacement")
694 resource.placement_policy = RowSmartPlacement;
695 } else
696 resource.placement_policy = RowSmartPlacement;
697
698 if (! config->getValue(screenstr + "strftimeFormat",
699 resource.strftime_format))
700 resource.strftime_format = "%I:%M %p";
701
702 if (! config->getValue(screenstr + "placementIgnoreShaded",
703 resource.ignore_shaded))
704 resource.ignore_shaded = true;
705
706 if (! config->getValue(screenstr + "placementIgnoreMaximized",
707 resource.ignore_maximized))
708 resource.ignore_maximized = true;
709
710 if (! config->getValue(screenstr + "disableBindingsWithScrollLock",
711 resource.allow_scroll_lock))
712 resource.allow_scroll_lock = false;
713
714 if (! config->getValue(screenstr + "workspaceWarping",
715 resource.workspace_warping))
716 resource.workspace_warping = false;
717
718 resource.root_scroll = NormalScroll;
719 if (config->getValue(screenstr + "rootScrollDirection", s)) {
720 if (s == "None")
721 resource.root_scroll = NoScroll;
722 else if (s == "Reverse")
723 resource.root_scroll = ReverseScroll;
724 }
725 }
726
727
728 void BScreen::changeWorkspaceCount(unsigned int new_count) {
729 assert(new_count > 0);
730
731 if (new_count < workspacesList.size()) {
732 // shrink
733 for (unsigned int i = workspacesList.size(); i > new_count; --i)
734 removeLastWorkspace();
735 // removeLast already sets the current workspace to the
736 // last available one.
737 } else if (new_count > workspacesList.size()) {
738 // grow
739 for(unsigned int i = workspacesList.size(); i < new_count; ++i)
740 addWorkspace();
741 }
742 }
743
744
745 void BScreen::reconfigure(void) {
746 // don't reconfigure while saving the initial rc file, it's a waste and it
747 // breaks somethings (workspace names)
748 if (blackbox->isStartup()) return;
749
750 load_rc();
751 LoadStyle();
752
753 // we need to do this explicitly, because just loading this value from the rc
754 // does nothing
755 changeWorkspaceCount(resource.workspaces);
756
757 XGCValues gcv;
758 gcv.foreground = WhitePixel(blackbox->getXDisplay(),
759 getScreenNumber());
760 gcv.function = GXinvert;
761 gcv.subwindow_mode = IncludeInferiors;
762 XChangeGC(blackbox->getXDisplay(), opGC,
763 GCForeground | GCFunction | GCSubwindowMode, &gcv);
764
765 const char *s = "0: 0000 x 0: 0000";
766
767 geom_w = resource.wstyle.font->measureString(s) + resource.bevel_width * 2;
768 geom_h = resource.wstyle.font->height() + resource.bevel_width * 2;
769
770 BTexture* texture = &(resource.wstyle.l_focus);
771 geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap);
772 if (geom_pixmap == ParentRelative) {
773 texture = &(resource.wstyle.t_focus);
774 geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap);
775 }
776 if (! geom_pixmap)
777 XSetWindowBackground(blackbox->getXDisplay(), geom_window,
778 texture->color().pixel());
779 else
780 XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
781 geom_window, geom_pixmap);
782
783 XSetWindowBorderWidth(blackbox->getXDisplay(), geom_window,
784 resource.border_width);
785 XSetWindowBorder(blackbox->getXDisplay(), geom_window,
786 resource.border_color.pixel());
787
788 typedef std::vector<int> SubList;
789 SubList remember_subs;
790
791 raiseWindows(0, 0);
792
793 std::for_each(workspacesList.begin(), workspacesList.end(),
794 std::mem_fun(&Workspace::reconfigure));
795
796 BlackboxWindowList::iterator iit = iconList.begin();
797 for (; iit != iconList.end(); ++iit) {
798 BlackboxWindow *bw = *iit;
799 if (bw->validateClient())
800 bw->reconfigure();
801 }
802
803 image_control->timeout();
804 }
805
806
807 void BScreen::LoadStyle(void) {
808 Configuration style(False);
809
810 const char *sfile = blackbox->getStyleFilename();
811 if (sfile != NULL) {
812 style.setFile(sfile);
813 if (! style.load()) {
814 style.setFile(DEFAULTSTYLE);
815 if (! style.load())
816 style.create(); // hardcoded default values will be used.
817 }
818 }
819
820 // merge in the rc file
821 style.merge(config->file(), True);
822
823 string s;
824
825 // load fonts/fontsets
826 if (resource.wstyle.font)
827 delete resource.wstyle.font;
828
829 resource.wstyle.font = readDatabaseFont("window.", style);
830
831 // load window config
832 resource.wstyle.t_focus =
833 readDatabaseTexture("window.title.focus", "white", style);
834 resource.wstyle.t_unfocus =
835 readDatabaseTexture("window.title.unfocus", "black", style);
836 resource.wstyle.l_focus =
837 readDatabaseTexture("window.label.focus", "white", style);
838 resource.wstyle.l_unfocus =
839 readDatabaseTexture("window.label.unfocus", "black", style);
840 resource.wstyle.h_focus =
841 readDatabaseTexture("window.handle.focus", "white", style);
842 resource.wstyle.h_unfocus =
843 readDatabaseTexture("window.handle.unfocus", "black", style);
844 resource.wstyle.g_focus =
845 readDatabaseTexture("window.grip.focus", "white", style);
846 resource.wstyle.g_unfocus =
847 readDatabaseTexture("window.grip.unfocus", "black", style);
848 resource.wstyle.b_focus =
849 readDatabaseTexture("window.button.focus", "white", style);
850 resource.wstyle.b_unfocus =
851 readDatabaseTexture("window.button.unfocus", "black", style);
852 resource.wstyle.b_pressed =
853 readDatabaseTexture("window.button.pressed", "black", style);
854
855 //if neither of these can be found, we will use the previous resource
856 resource.wstyle.b_pressed_focus =
857 readDatabaseTexture("window.button.pressed.focus", "black", style, true);
858 resource.wstyle.b_pressed_unfocus =
859 readDatabaseTexture("window.button.pressed.unfocus", "black", style, true);
860
861 #ifdef BITMAPBUTTONS
862 if (resource.wstyle.close_button.mask != None)
863 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.close_button.mask);
864 if (resource.wstyle.max_button.mask != None)
865 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.max_button.mask);
866 if (resource.wstyle.icon_button.mask != None)
867 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.icon_button.mask);
868 if (resource.wstyle.stick_button.mask != None)
869 XFreePixmap(blackbox->getXDisplay(), resource.wstyle.stick_button.mask);
870
871 resource.wstyle.close_button.mask = resource.wstyle.max_button.mask =
872 resource.wstyle.icon_button.mask =
873 resource.wstyle.icon_button.mask = None;
874
875 readDatabaseMask("window.button.close.mask", resource.wstyle.close_button,
876 style);
877 readDatabaseMask("window.button.max.mask", resource.wstyle.max_button,
878 style);
879 readDatabaseMask("window.button.icon.mask", resource.wstyle.icon_button,
880 style);
881 readDatabaseMask("window.button.stick.mask", resource.wstyle.stick_button,
882 style);
883 #endif // BITMAPBUTTONS
884
885 // we create the window.frame texture by hand because it exists only to
886 // make the code cleaner and is not actually used for display
887 BColor color = readDatabaseColor("window.frame.focusColor", "white", style);
888 resource.wstyle.f_focus = BTexture("solid flat", getBaseDisplay(),
889 getScreenNumber(), image_control);
890 resource.wstyle.f_focus.setColor(color);
891
892 color = readDatabaseColor("window.frame.unfocusColor", "white", style);
893 resource.wstyle.f_unfocus = BTexture("solid flat", getBaseDisplay(),
894 getScreenNumber(), image_control);
895 resource.wstyle.f_unfocus.setColor(color);
896
897 resource.wstyle.l_text_focus =
898 readDatabaseColor("window.label.focus.textColor", "black", style);
899 resource.wstyle.l_text_unfocus =
900 readDatabaseColor("window.label.unfocus.textColor", "white", style);
901 resource.wstyle.b_pic_focus =
902 readDatabaseColor("window.button.focus.picColor", "black", style);
903 resource.wstyle.b_pic_unfocus =
904 readDatabaseColor("window.button.unfocus.picColor", "white", style);
905
906 resource.wstyle.justify = LeftJustify;
907 if (style.getValue("window.justify", s)) {
908 if (s == "right" || s == "Right")
909 resource.wstyle.justify = RightJustify;
910 else if (s == "center" || s == "Center")
911 resource.wstyle.justify = CenterJustify;
912 }
913
914 // sanity checks
915 if (resource.wstyle.t_focus.texture() == BTexture::Parent_Relative)
916 resource.wstyle.t_focus = resource.wstyle.f_focus;
917 if (resource.wstyle.t_unfocus.texture() == BTexture::Parent_Relative)
918 resource.wstyle.t_unfocus = resource.wstyle.f_unfocus;
919 if (resource.wstyle.h_focus.texture() == BTexture::Parent_Relative)
920 resource.wstyle.h_focus = resource.wstyle.f_focus;
921 if (resource.wstyle.h_unfocus.texture() == BTexture::Parent_Relative)
922 resource.wstyle.h_unfocus = resource.wstyle.f_unfocus;
923
924 resource.border_color =
925 readDatabaseColor("borderColor", "black", style);
926
927 // load bevel, border and handle widths
928 if (! style.getValue("handleWidth", resource.handle_width) ||
929 resource.handle_width > (getWidth() / 2) || resource.handle_width == 0)
930 resource.handle_width = 6;
931
932 if (! style.getValue("borderWidth", resource.border_width))
933 resource.border_width = 1;
934
935 if (! style.getValue("bevelWidth", resource.bevel_width) ||
936 resource.bevel_width > (getWidth() / 2) || resource.bevel_width == 0)
937 resource.bevel_width = 3;
938
939 if (! style.getValue("frameWidth", resource.frame_width) ||
940 resource.frame_width > (getWidth() / 2))
941 resource.frame_width = resource.bevel_width;
942
943 if (style.getValue("rootCommand", s))
944 bexec(s, displayString());
945 }
946
947
948 void BScreen::addIcon(BlackboxWindow *w) {
949 if (! w) return;
950
951 w->setWorkspace(BSENTINEL);
952 w->setWindowNumber(iconList.size());
953
954 iconList.push_back(w);
955 }
956
957
958 void BScreen::removeIcon(BlackboxWindow *w) {
959 if (! w) return;
960
961 iconList.remove(w);
962
963 BlackboxWindowList::iterator it = iconList.begin(),
964 end = iconList.end();
965 for (int i = 0; it != end; ++it)
966 (*it)->setWindowNumber(i++);
967 }
968
969
970 BlackboxWindow *BScreen::getIcon(unsigned int index) {
971 if (index < iconList.size()) {
972 BlackboxWindowList::iterator it = iconList.begin();
973 while (index-- > 0) // increment to index
974 ++it;
975 return *it;
976 }
977
978 return (BlackboxWindow *) 0;
979 }
980
981
982 unsigned int BScreen::addWorkspace(void) {
983 Workspace *wkspc = new Workspace(this, workspacesList.size());
984 workspacesList.push_back(wkspc);
985 saveWorkspaces(getWorkspaceCount());
986 saveWorkspaceNames();
987
988 return workspacesList.size();
989 }
990
991
992 unsigned int BScreen::removeLastWorkspace(void) {
993 if (workspacesList.size() == 1)
994 return 1;
995
996 Workspace *wkspc = workspacesList.back();
997
998 if (current_workspace->getID() == wkspc->getID())
999 changeWorkspaceID(current_workspace->getID() - 1);
1000
1001 wkspc->removeAll();
1002
1003 workspacesList.pop_back();
1004 delete wkspc;
1005
1006 saveWorkspaces(getWorkspaceCount());
1007 saveWorkspaceNames();
1008
1009 updateNetizenWorkspaceCount();
1010
1011 return workspacesList.size();
1012 }
1013
1014
1015 void BScreen::changeWorkspaceID(unsigned int id) {
1016 if (! current_workspace || id == current_workspace->getID()) return;
1017
1018 BlackboxWindow *focused = blackbox->getFocusedWindow();
1019 if (focused && focused->getScreen() == this) {
1020 assert(focused->isStuck() ||
1021 focused->getWorkspaceNumber() == current_workspace->getID());
1022
1023 current_workspace->setLastFocusedWindow(focused);
1024 } else {
1025 // if no window had focus, no need to store a last focus
1026 current_workspace->setLastFocusedWindow((BlackboxWindow *) 0);
1027 }
1028
1029 // when we switch workspaces, unfocus whatever was focused if it is going
1030 // to be unmapped
1031 if (focused && ! focused->isStuck())
1032 blackbox->setFocusedWindow((BlackboxWindow *) 0);
1033
1034 current_workspace->hideAll();
1035
1036 current_workspace = getWorkspace(id);
1037
1038 xatom->setValue(getRootWindow(), XAtom::net_current_desktop,
1039 XAtom::cardinal, id);
1040
1041 current_workspace->showAll();
1042
1043 int x, y, rx, ry;
1044 Window c, r;
1045 unsigned int m;
1046 BlackboxWindow *win = (BlackboxWindow *) 0;
1047 bool f = False;
1048
1049 XSync(blackbox->getXDisplay(), False);
1050
1051 // If sloppy focus and we can find the client window under the pointer,
1052 // try to focus it.
1053 if (resource.sloppy_focus &&
1054 XQueryPointer(blackbox->getXDisplay(), getRootWindow(), &r, &c,
1055 &rx, &ry, &x, &y, &m) &&
1056 c != None) {
1057 if ( (win = blackbox->searchWindow(c)) )
1058 f = win->setInputFocus();
1059 }
1060
1061 // If that fails, and we're doing focus_last, try to focus the last window.
1062 if (! f && resource.focus_last &&
1063 (win = current_workspace->getLastFocusedWindow()))
1064 f = win->setInputFocus();
1065
1066 /*
1067 if we found a focus target, then we set the focused window explicitly
1068 because it is possible to switch off this workspace before the x server
1069 generates the FocusIn event for the window. if that happens, openbox would
1070 lose track of what window was the 'LastFocused' window on the workspace.
1071
1072 if we did not find a focus target, then set the current focused window to
1073 nothing.
1074 */
1075 if (f)
1076 blackbox->setFocusedWindow(win);
1077 else
1078 blackbox->setFocusedWindow((BlackboxWindow *) 0);
1079 }
1080
1081
1082 /*
1083 * Set the _NET_CLIENT_LIST root window property.
1084 */
1085 void BScreen::updateClientList(void) {
1086 if (windowList.size() > 0) {
1087 Window *windows = new Window[windowList.size()];
1088 Window *win_it = windows;
1089 BlackboxWindowList::iterator it = windowList.begin();
1090 const BlackboxWindowList::iterator end = windowList.end();
1091 for (; it != end; ++it, ++win_it)
1092 *win_it = (*it)->getClientWindow();
1093 xatom->setValue(getRootWindow(), XAtom::net_client_list, XAtom::window,
1094 windows, windowList.size());
1095 delete [] windows;
1096 } else
1097 xatom->setValue(getRootWindow(), XAtom::net_client_list, XAtom::window,
1098 0, 0);
1099
1100 updateStackingList();
1101 }
1102
1103
1104 /*
1105 * Set the _NET_CLIENT_LIST_STACKING root window property.
1106 */
1107 void BScreen::updateStackingList(void) {
1108
1109 BlackboxWindowList stack_order;
1110
1111 /*
1112 * Get the stacking order from all of the workspaces.
1113 * We start with the current workspace so that the sticky windows will be
1114 * in the right order on the current workspace.
1115 * XXX: Do we need to have sticky windows in the list once for each workspace?
1116 */
1117 getCurrentWorkspace()->appendStackOrder(stack_order);
1118 for (unsigned int i = 0; i < getWorkspaceCount(); ++i)
1119 if (i != getCurrentWorkspaceID())
1120 getWorkspace(i)->appendStackOrder(stack_order);
1121
1122 if (stack_order.size() > 0) {
1123 // set the client list atoms
1124 Window *windows = new Window[stack_order.size()];
1125 Window *win_it = windows;
1126 BlackboxWindowList::iterator it = stack_order.begin(),
1127 end = stack_order.end();
1128 for (; it != end; ++it, ++win_it)
1129 *win_it = (*it)->getClientWindow();
1130 xatom->setValue(getRootWindow(), XAtom::net_client_list_stacking,
1131 XAtom::window, windows, stack_order.size());
1132 delete [] windows;
1133 } else
1134 xatom->setValue(getRootWindow(), XAtom::net_client_list_stacking,
1135 XAtom::window, 0, 0);
1136 }
1137
1138
1139 void BScreen::addSystrayWindow(Window window) {
1140 XGrabServer(blackbox->getXDisplay());
1141
1142 XSelectInput(blackbox->getXDisplay(), window, StructureNotifyMask);
1143 systrayWindowList.push_back(window);
1144 xatom->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows,
1145 XAtom::window,
1146 &systrayWindowList[0], systrayWindowList.size());
1147 blackbox->saveSystrayWindowSearch(window, this);
1148
1149 XUngrabServer(blackbox->getXDisplay());
1150 }
1151
1152
1153 void BScreen::removeSystrayWindow(Window window) {
1154 XGrabServer(blackbox->getXDisplay());
1155
1156 WindowList::iterator it = systrayWindowList.begin();
1157 const WindowList::iterator end = systrayWindowList.end();
1158 for (; it != end; ++it)
1159 if (*it == window) {
1160 systrayWindowList.erase(it);
1161 xatom->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows,
1162 XAtom::window,
1163 &systrayWindowList[0], systrayWindowList.size());
1164 blackbox->removeSystrayWindowSearch(window);
1165 XSelectInput(blackbox->getXDisplay(), window, NoEventMask);
1166 break;
1167 }
1168
1169 assert(it != end); // not a systray window
1170
1171 XUngrabServer(blackbox->getXDisplay());
1172 }
1173
1174
1175 void BScreen::manageWindow(Window w) {
1176 // is the window a KDE systray window?
1177 Window systray;
1178 if (xatom->getValue(w, XAtom::kde_net_wm_system_tray_window_for,
1179 XAtom::window, systray) && systray != None) {
1180 addSystrayWindow(w);
1181 return;
1182 }
1183
1184 // is the window a docking app
1185 XWMHints *wmhint = XGetWMHints(blackbox->getXDisplay(), w);
1186 if (wmhint && (wmhint->flags & StateHint) &&
1187 wmhint->initial_state == WithdrawnState) {
1188 //slit->addClient(w);
1189 return;
1190 }
1191
1192 new BlackboxWindow(blackbox, w, this);
1193
1194 BlackboxWindow *win = blackbox->searchWindow(w);
1195 if (! win)
1196 return;
1197
1198 if (win->isDesktop()) {
1199 desktopWindowList.push_back(win->getFrameWindow());
1200 } else { // if (win->isNormal()) {
1201 // don't list desktop windows as managed windows
1202 windowList.push_back(win);
1203 updateClientList();
1204
1205 if (win->isTopmost())
1206 specialWindowList.push_back(win->getFrameWindow());
1207 }
1208
1209 XMapRequestEvent mre;
1210 mre.window = w;
1211 if (blackbox->isStartup() && win->isNormal()) win->restoreAttributes();
1212 win->mapRequestEvent(&mre);
1213 }
1214
1215
1216 void BScreen::unmanageWindow(BlackboxWindow *w, bool remap) {
1217 // is the window a KDE systray window?
1218 Window systray;
1219 if (xatom->getValue(w->getClientWindow(),
1220 XAtom::kde_net_wm_system_tray_window_for,
1221 XAtom::window, systray) && systray != None) {
1222 removeSystrayWindow(w->getClientWindow());
1223 return;
1224 }
1225
1226 w->restore(remap);
1227
1228 // Remove the modality so that its parent won't try to re-focus the window
1229 if (w->isModal()) w->setModal(False);
1230
1231 if (w->getWorkspaceNumber() != BSENTINEL &&
1232 w->getWindowNumber() != BSENTINEL) {
1233 getWorkspace(w->getWorkspaceNumber())->removeWindow(w);
1234 if (w->isStuck()) {
1235 for (unsigned int i = 0; i < getNumberOfWorkspaces(); ++i)
1236 if (i != w->getWorkspaceNumber())
1237 getWorkspace(i)->removeWindow(w, True);
1238 }
1239 } else if (w->isIconic())
1240 removeIcon(w);
1241
1242 if (w->isDesktop()) {
1243 WindowList::iterator it = desktopWindowList.begin();
1244 const WindowList::iterator end = desktopWindowList.end();
1245 for (; it != end; ++it)
1246 if (*it == w->getFrameWindow()) {
1247 desktopWindowList.erase(it);
1248 break;
1249 }
1250 assert(it != end); // the window wasnt a desktop window?
1251 } else { // if (w->isNormal()) {
1252 // we don't list desktop windows as managed windows
1253 windowList.remove(w);
1254 updateClientList();
1255
1256 if (w->isTopmost()) {
1257 WindowList::iterator it = specialWindowList.begin();
1258 const WindowList::iterator end = specialWindowList.end();
1259 for (; it != end; ++it)
1260 if (*it == w->getFrameWindow()) {
1261 specialWindowList.erase(it);
1262 break;
1263 }
1264 assert(it != end); // the window wasnt a special window?
1265 }
1266 }
1267
1268 if (blackbox->getFocusedWindow() == w)
1269 blackbox->setFocusedWindow((BlackboxWindow *) 0);
1270
1271 /*
1272 some managed windows can also be window group controllers. when
1273 unmanaging such windows, we should also delete the window group.
1274 */
1275 BWindowGroup *group = blackbox->searchGroup(w->getClientWindow());
1276 delete group;
1277
1278 delete w;
1279 }
1280
1281
1282 void BScreen::updateWorkArea(void) {
1283 if (workspacesList.size() > 0) {
1284 unsigned long *dims = new unsigned long[4 * workspacesList.size()];
1285 for (unsigned int i = 0, m = workspacesList.size(); i < m; ++i) {
1286 // XXX: this could be different for each workspace
1287 const Rect &area = availableArea();
1288 dims[(i * 4) + 0] = area.x();
1289 dims[(i * 4) + 1] = area.y();
1290 dims[(i * 4) + 2] = area.width();
1291 dims[(i * 4) + 3] = area.height();
1292 }
1293 xatom->setValue(getRootWindow(), XAtom::net_workarea, XAtom::cardinal,
1294 dims, 4 * workspacesList.size());
1295 delete [] dims;
1296 } else
1297 xatom->setValue(getRootWindow(), XAtom::net_workarea, XAtom::cardinal,
1298 0, 0);
1299 }
1300
1301
1302 void BScreen::updateNetizenWorkspaceCount(void) {
1303 xatom->setValue(getRootWindow(), XAtom::net_number_of_desktops,
1304 XAtom::cardinal, workspacesList.size());
1305
1306 updateWorkArea();
1307 }
1308
1309
1310 void BScreen::updateNetizenWindowFocus(void) {
1311 Window f = ((blackbox->getFocusedWindow()) ?
1312 blackbox->getFocusedWindow()->getClientWindow() : None);
1313
1314 xatom->setValue(getRootWindow(), XAtom::net_active_window,
1315 XAtom::window, f);
1316 }
1317
1318
1319 void BScreen::raiseWindows(Window *workspace_stack, unsigned int num) {
1320 // the 13 represents the number of blackbox windows such as menus
1321 int bbwins = 15;
1322 #ifdef XINERAMA
1323 ++bbwins;
1324 #endif // XINERAMA
1325
1326 Window *session_stack = new
1327 Window[(num + specialWindowList.size() + bbwins)];
1328 unsigned int i = 0, k = num;
1329
1330 WindowList::iterator sit, send = specialWindowList.end();
1331 for (sit = specialWindowList.begin(); sit != send; ++sit)
1332 *(session_stack + i++) = *sit;
1333
1334 while (k--)
1335 *(session_stack + i++) = *(workspace_stack + k);
1336
1337 XRestackWindows(blackbox->getXDisplay(), session_stack, i);
1338
1339 delete [] session_stack;
1340
1341 updateStackingList();
1342 }
1343
1344
1345 void BScreen::lowerWindows(Window *workspace_stack, unsigned int num) {
1346 assert(num > 0); // this would cause trouble in the XRaiseWindow call
1347
1348 Window *session_stack = new Window[(num + desktopWindowList.size())];
1349 unsigned int i = 0, k = num;
1350
1351 XLowerWindow(blackbox->getXDisplay(), workspace_stack[0]);
1352
1353 while (k--)
1354 *(session_stack + i++) = *(workspace_stack + k);
1355
1356 WindowList::iterator dit = desktopWindowList.begin();
1357 const WindowList::iterator d_end = desktopWindowList.end();
1358 for (; dit != d_end; ++dit)
1359 *(session_stack + i++) = *dit;
1360
1361 XRestackWindows(blackbox->getXDisplay(), session_stack, i);
1362
1363 delete [] session_stack;
1364
1365 updateStackingList();
1366 }
1367
1368
1369 void BScreen::reassociateWindow(BlackboxWindow *w, unsigned int wkspc_id,
1370 bool ignore_sticky) {
1371 if (! w) return;
1372
1373 if (wkspc_id == BSENTINEL)
1374 wkspc_id = current_workspace->getID();
1375
1376 if (w->getWorkspaceNumber() == wkspc_id)
1377 return;
1378
1379 if (w->isIconic()) {
1380 removeIcon(w);
1381 getWorkspace(wkspc_id)->addWindow(w);
1382 if (w->isStuck())
1383 for (unsigned int i = 0; i < getNumberOfWorkspaces(); ++i)
1384 if (i != w->getWorkspaceNumber())
1385 getWorkspace(i)->addWindow(w, True);
1386 } else if (ignore_sticky || ! w->isStuck()) {
1387 if (w->isStuck())
1388 w->stick();
1389 getWorkspace(w->getWorkspaceNumber())->removeWindow(w);
1390 getWorkspace(wkspc_id)->addWindow(w);
1391 }
1392 updateStackingList();
1393 }
1394
1395
1396 void BScreen::propagateWindowName(const BlackboxWindow *bw) {
1397 if (bw->isIconic()) {
1398 } else {
1399 }
1400 }
1401
1402
1403 void BScreen::nextFocus(void) const {
1404 BlackboxWindow *focused = blackbox->getFocusedWindow(),
1405 *next = focused;
1406
1407 if (focused &&
1408 focused->getScreen()->getScreenNumber() == getScreenNumber() &&
1409 current_workspace->getCount() > 1) {
1410 do {
1411 next = current_workspace->getNextWindowInList(next);
1412 } while (next != focused && ! next->setInputFocus());
1413
1414 if (next != focused)
1415 current_workspace->raiseWindow(next);
1416 } else if (current_workspace->getCount() > 0) {
1417 next = current_workspace->getTopWindowOnStack();
1418 next->setInputFocus();
1419 current_workspace->raiseWindow(next);
1420 }
1421 }
1422
1423
1424 void BScreen::prevFocus(void) const {
1425 BlackboxWindow *focused = blackbox->getFocusedWindow(),
1426 *next = focused;
1427
1428 if (focused) {
1429 // if window is not on this screen, ignore it
1430 if (focused->getScreen()->getScreenNumber() != getScreenNumber())
1431 focused = (BlackboxWindow*) 0;
1432 }
1433
1434 if (focused &&
1435 focused->getScreen()->getScreenNumber() == getScreenNumber() &&
1436 current_workspace->getCount() > 1) {
1437 // next is the next window to receive focus, current is a place holder
1438 do {
1439 next = current_workspace->getPrevWindowInList(next);
1440 } while (next != focused && ! next->setInputFocus());
1441
1442 if (next != focused)
1443 current_workspace->raiseWindow(next);
1444 } else if (current_workspace->getCount() > 0) {
1445 next = current_workspace->getTopWindowOnStack();
1446 next->setInputFocus();
1447 current_workspace->raiseWindow(next);
1448 }
1449 }
1450
1451
1452 void BScreen::raiseFocus(void) const {
1453 BlackboxWindow *focused = blackbox->getFocusedWindow();
1454 if (! focused)
1455 return;
1456
1457 // if on this Screen, raise it
1458 if (focused->getScreen()->getScreenNumber() == getScreenNumber()) {
1459 Workspace *workspace = getWorkspace(focused->getWorkspaceNumber());
1460 workspace->raiseWindow(focused);
1461 }
1462 }
1463
1464
1465 void BScreen::shutdown(void) {
1466 XSelectInput(blackbox->getXDisplay(), getRootWindow(), NoEventMask);
1467 XSync(blackbox->getXDisplay(), False);
1468
1469 while(! windowList.empty())
1470 unmanageWindow(windowList.front(), True);
1471
1472 while(! desktopWindowList.empty()) {
1473 BlackboxWindow *win = blackbox->searchWindow(desktopWindowList.front());
1474 assert(win);
1475 unmanageWindow(win, True);
1476 }
1477 }
1478
1479
1480 void BScreen::showPosition(int x, int y) {
1481 if (! geom_visible) {
1482 XMoveResizeWindow(blackbox->getXDisplay(), geom_window,
1483 (getWidth() - geom_w) / 2,
1484 (getHeight() - geom_h) / 2, geom_w, geom_h);
1485 XMapWindow(blackbox->getXDisplay(), geom_window);
1486 XRaiseWindow(blackbox->getXDisplay(), geom_window);
1487
1488 geom_visible = True;
1489 }
1490
1491 char label[1024];
1492
1493 sprintf(label, "X: %4d x Y: %4d", x, y);
1494
1495 XClearWindow(blackbox->getXDisplay(), geom_window);
1496
1497 resource.wstyle.font->drawString(geom_window,
1498 resource.bevel_width, resource.bevel_width,
1499 resource.wstyle.l_text_focus,
1500 label);
1501 }
1502
1503
1504 void BScreen::showGeometry(unsigned int gx, unsigned int gy) {
1505 if (! geom_visible) {
1506 XMoveResizeWindow(blackbox->getXDisplay(), geom_window,
1507 (getWidth() - geom_w) / 2,
1508 (getHeight() - geom_h) / 2, geom_w, geom_h);
1509 XMapWindow(blackbox->getXDisplay(), geom_window);
1510 XRaiseWindow(blackbox->getXDisplay(), geom_window);
1511
1512 geom_visible = True;
1513 }
1514
1515 char label[1024];
1516
1517 sprintf(label, "W: %4d x H: %4d", gx, gy);
1518
1519 XClearWindow(blackbox->getXDisplay(), geom_window);
1520
1521 resource.wstyle.font->drawString(geom_window,
1522 resource.bevel_width, resource.bevel_width,
1523 resource.wstyle.l_text_focus,
1524 label);
1525 }
1526
1527
1528 void BScreen::hideGeometry(void) {
1529 if (geom_visible) {
1530 XUnmapWindow(blackbox->getXDisplay(), geom_window);
1531 geom_visible = False;
1532 }
1533 }
1534
1535
1536 void BScreen::addStrut(Strut *strut) {
1537 strutList.push_back(strut);
1538 }
1539
1540
1541 void BScreen::removeStrut(Strut *strut) {
1542 strutList.remove(strut);
1543 }
1544
1545
1546 const Rect& BScreen::availableArea(void) const {
1547 if (doFullMax())
1548 return getRect(); // return the full screen
1549 return usableArea;
1550 }
1551
1552
1553 #ifdef XINERAMA
1554 const RectList& BScreen::allAvailableAreas(void) const {
1555 assert(isXineramaActive());
1556 assert(xineramaUsableArea.size() > 0);
1557 fprintf(stderr, "1found x %d y %d w %d h %d\n",
1558 xineramaUsableArea[0].x(), xineramaUsableArea[0].y(),
1559 xineramaUsableArea[0].width(), xineramaUsableArea[0].height());
1560 return xineramaUsableArea;
1561 }
1562 #endif // XINERAMA
1563
1564
1565 void BScreen::updateAvailableArea(void) {
1566 Rect old_area = usableArea;
1567 usableArea = getRect(); // reset to full screen
1568
1569 #ifdef XINERAMA
1570 // reset to the full areas
1571 if (isXineramaActive())
1572 xineramaUsableArea = getXineramaAreas();
1573 #endif // XINERAMA
1574
1575 /* these values represent offsets from the screen edge
1576 * we look for the biggest offset on each edge and then apply them
1577 * all at once
1578 * do not be confused by the similarity to the names of Rect's members
1579 */
1580 unsigned int current_left = 0, current_right = 0, current_top = 0,
1581 current_bottom = 0;
1582
1583 StrutList::const_iterator it = strutList.begin(), end = strutList.end();
1584
1585 for(; it != end; ++it) {
1586 Strut *strut = *it;
1587 if (strut->left > current_left)
1588 current_left = strut->left;
1589 if (strut->top > current_top)
1590 current_top = strut->top;
1591 if (strut->right > current_right)
1592 current_right = strut->right;
1593 if (strut->bottom > current_bottom)
1594 current_bottom = strut->bottom;
1595 }
1596
1597 usableArea.setPos(current_left, current_top);
1598 usableArea.setSize(usableArea.width() - (current_left + current_right),
1599 usableArea.height() - (current_top + current_bottom));
1600
1601 #ifdef XINERAMA
1602 if (isXineramaActive()) {
1603 // keep each of the ximerama-defined areas inside the strut
1604 RectList::iterator xit, xend = xineramaUsableArea.end();
1605 for (xit = xineramaUsableArea.begin(); xit != xend; ++xit) {
1606 if (xit->x() < usableArea.x()) {
1607 xit->setX(usableArea.x());
1608 xit->setWidth(xit->width() - usableArea.x());
1609 }
1610 if (xit->y() < usableArea.y()) {
1611 xit->setY(usableArea.y());
1612 xit->setHeight(xit->height() - usableArea.y());
1613 }
1614 if (xit->x() + xit->width() > usableArea.width())
1615 xit->setWidth(usableArea.width() - xit->x());
1616 if (xit->y() + xit->height() > usableArea.height())
1617 xit->setHeight(usableArea.height() - xit->y());
1618 }
1619 }
1620 #endif // XINERAMA
1621
1622 if (old_area != usableArea) {
1623 BlackboxWindowList::iterator it = windowList.begin(),
1624 end = windowList.end();
1625 for (; it != end; ++it)
1626 if ((*it)->isMaximized()) (*it)->remaximize();
1627 }
1628
1629 updateWorkArea();
1630 }
1631
1632
1633 Workspace* BScreen::getWorkspace(unsigned int index) const {
1634 assert(index < workspacesList.size());
1635 return workspacesList[index];
1636 }
1637
1638
1639 void BScreen::buttonPressEvent(const XButtonEvent *xbutton) {
1640 if (xbutton->button == 1) {
1641 if (! isRootColormapInstalled())
1642 image_control->installRootColormap();
1643
1644 // mouse wheel up
1645 } else if ((xbutton->button == 4 && resource.root_scroll == NormalScroll) ||
1646 (xbutton->button == 5 && resource.root_scroll == ReverseScroll)) {
1647 if (getCurrentWorkspaceID() >= getWorkspaceCount() - 1)
1648 changeWorkspaceID(0);
1649 else
1650 changeWorkspaceID(getCurrentWorkspaceID() + 1);
1651 // mouse wheel down
1652 } else if ((xbutton->button == 5 && resource.root_scroll == NormalScroll) ||
1653 (xbutton->button == 4 && resource.root_scroll == ReverseScroll)) {
1654 if (getCurrentWorkspaceID() == 0)
1655 changeWorkspaceID(getWorkspaceCount() - 1);
1656 else
1657 changeWorkspaceID(getCurrentWorkspaceID() - 1);
1658 }
1659 }
1660
1661
1662 void BScreen::propertyNotifyEvent(const XPropertyEvent *pe) {
1663 if (pe->atom == xatom->getAtom(XAtom::net_desktop_names)) {
1664 // _NET_WM_DESKTOP_NAMES
1665 WorkspaceList::iterator it = workspacesList.begin();
1666 const WorkspaceList::iterator end = workspacesList.end();
1667 for (; it != end; ++it) {
1668 (*it)->readName(); // re-read its name from the window property
1669 //workspacemenu->changeWorkspaceLabel((*it)->getID(), (*it)->getName());
1670 }
1671 //workspacemenu->update();
1672 saveWorkspaceNames();
1673 }
1674 }
1675
1676
1677 void BScreen::toggleFocusModel(FocusModel model) {
1678 std::for_each(windowList.begin(), windowList.end(),
1679 std::mem_fun(&BlackboxWindow::ungrabButtons));
1680
1681 if (model == SloppyFocus) {
1682 saveSloppyFocus(True);
1683 } else {
1684 // we're cheating here to save writing the config file 3 times
1685 resource.auto_raise = False;
1686 resource.click_raise = False;
1687 saveSloppyFocus(False);
1688 }
1689
1690 std::for_each(windowList.begin(), windowList.end(),
1691 std::mem_fun(&BlackboxWindow::grabButtons));
1692 }
1693
1694 #ifdef BITMAPBUTTONS
1695 void BScreen::readDatabaseMask(const string &rname, PixmapMask &pixmapMask,
1696 const Configuration &style) {
1697 string s;
1698 int hx, hy; //ignored
1699 int ret = BitmapOpenFailed; //default to failure.
1700
1701 if (style.getValue(rname, s))
1702 {
1703 if (s[0] != '/' && s[0] != '~')
1704 {
1705 std::string xbmFile = std::string("~/.openbox/buttons/") + s;
1706 ret = XReadBitmapFile(blackbox->getXDisplay(), getRootWindow(),
1707 expandTilde(xbmFile).c_str(), &pixmapMask.w,
1708 &pixmapMask.h, &pixmapMask.mask, &hx, &hy);
1709 } else
1710 ret = XReadBitmapFile(blackbox->getXDisplay(), getRootWindow(),
1711 expandTilde(s).c_str(), &pixmapMask.w,
1712 &pixmapMask.h, &pixmapMask.mask, &hx, &hy);
1713
1714 if (ret == BitmapSuccess)
1715 return;
1716 }
1717
1718 pixmapMask.mask = None;
1719 pixmapMask.w = pixmapMask.h = 0;
1720 }
1721 #endif // BITMAPSUCCESS
1722
1723 BTexture BScreen::readDatabaseTexture(const string &rname,
1724 const string &default_color,
1725 const Configuration &style,
1726 bool allowNoTexture) {
1727 BTexture texture;
1728 string s;
1729
1730 if (style.getValue(rname, s))
1731 texture = BTexture(s);
1732 else if (allowNoTexture) //no default
1733 texture.setTexture(BTexture::NoTexture);
1734 else
1735 texture.setTexture(BTexture::Solid | BTexture::Flat);
1736
1737 // associate this texture with this screen
1738 texture.setDisplay(getBaseDisplay(), getScreenNumber());
1739 texture.setImageControl(image_control);
1740
1741 if (texture.texture() != BTexture::NoTexture) {
1742 texture.setColor(readDatabaseColor(rname + ".color", default_color,
1743 style));
1744 texture.setColorTo(readDatabaseColor(rname + ".colorTo", default_color,
1745 style));
1746 texture.setBorderColor(readDatabaseColor(rname + ".borderColor",
1747 default_color, style));
1748 }
1749
1750 return texture;
1751 }
1752
1753
1754 BColor BScreen::readDatabaseColor(const string &rname,
1755 const string &default_color,
1756 const Configuration &style) {
1757 BColor color;
1758 string s;
1759 if (style.getValue(rname, s))
1760 color = BColor(s, getBaseDisplay(), getScreenNumber());
1761 else
1762 color = BColor(default_color, getBaseDisplay(), getScreenNumber());
1763 return color;
1764 }
1765
1766
1767 BFont *BScreen::readDatabaseFont(const string &rbasename,
1768 const Configuration &style) {
1769 string fontname;
1770
1771 string s;
1772
1773 int i;
1774 if (style.getValue(rbasename + "xft.font", s) &&
1775 style.getValue(rbasename + "xft.size", i)) {
1776 string family = s;
1777 bool bold = False;
1778 bool italic = False;
1779 bool dropShadow = False;
1780
1781 if (style.getValue(rbasename + "xft.flags", s)) {
1782 if (s.find("bold") != string::npos)
1783 bold = True;
1784 if (s.find("italic") != string::npos)
1785 italic = True;
1786 if (s.find("shadow") != string::npos)
1787 dropShadow = True;
1788 }
1789
1790 unsigned char offset = 1;
1791 if (style.getValue(rbasename + "xft.shadow.offset", s)) {
1792 offset = atoi(s.c_str()); //doesn't detect errors
1793 if (offset > CHAR_MAX)
1794 offset = 1;
1795 }
1796
1797 unsigned char tint = 0x40;
1798 if (style.getValue(rbasename + "xft.shadow.tint", s)) {
1799 tint = atoi(s.c_str());
1800 }
1801
1802
1803 BFont *b = new BFont(blackbox->getXDisplay(), this, family, i, bold,
1804 italic, dropShadow && resource.shadow_fonts, offset,
1805 tint, resource.aa_fonts);
1806 if (b->valid())
1807 return b;
1808 delete b;
1809 }
1810
1811 exit(2); // can't continue without a font
1812 }
This page took 0.112116 seconds and 4 git commands to generate.