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