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