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