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