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