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