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