]> Dogcows Code - chaz/openbox/blob - src/Screen.cc
Configureable button mappings!
[chaz/openbox] / src / Screen.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // Screen.cc for Blackbox - an X11 Window manager
3 // Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
4 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a
7 // copy of this software and associated documentation files (the "Software"),
8 // to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 // and/or sell copies of the Software, and to permit persons to whom the
11 // Software is furnished to do so, subject to the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 // DEALINGS IN THE SOFTWARE.
23
24 #include "../config.h"
25
26 extern "C" {
27 #include <X11/Xatom.h>
28 #include <X11/keysym.h>
29
30 // for strcasestr()
31 #ifndef _GNU_SOURCE
32 # define _GNU_SOURCE
33 #endif // _GNU_SOURCE
34
35 #ifdef HAVE_STDLIB_H
36 # include <stdlib.h>
37 #endif // HAVE_STDLIB_H
38
39 #ifdef HAVE_STRING_H
40 # include <string.h>
41 #endif // HAVE_STRING_H
42
43 #ifdef HAVE_CTYPE_H
44 # include <ctype.h>
45 #endif // HAVE_CTYPE_H
46
47 #ifdef HAVE_UNISTD_H
48 # include <sys/types.h>
49 # include <unistd.h>
50 #endif // HAVE_UNISTD_H
51
52 #ifdef HAVE_DIRENT_H
53 # include <dirent.h>
54 #endif // HAVE_DIRENT_H
55
56 #ifdef HAVE_LOCALE_H
57 # include <locale.h>
58 #endif // HAVE_LOCALE_H
59
60 #ifdef HAVE_SYS_STAT_H
61 # include <sys/stat.h>
62 #endif // HAVE_SYS_STAT_H
63
64 #ifdef HAVE_STDARG_H
65 # include <stdarg.h>
66 #endif // HAVE_STDARG_H
67 }
68
69 #include <assert.h>
70
71 #include <algorithm>
72 #include <functional>
73 #include <string>
74 using std::string;
75
76 #include "i18n.hh"
77 #include "blackbox.hh"
78 #include "Clientmenu.hh"
79 #include "GCCache.hh"
80 #include "Iconmenu.hh"
81 #include "Image.hh"
82 #include "Screen.hh"
83 #include "Slit.hh"
84 #include "Rootmenu.hh"
85 #include "Toolbar.hh"
86 #include "Util.hh"
87 #include "Window.hh"
88 #include "Workspace.hh"
89 #include "Workspacemenu.hh"
90 #include "XAtom.hh"
91 #include "Input.hh"
92
93 #ifndef FONT_ELEMENT_SIZE
94 #define FONT_ELEMENT_SIZE 50
95 #endif // FONT_ELEMENT_SIZE
96
97
98 static bool running = True;
99
100 static int anotherWMRunning(Display *display, XErrorEvent *) {
101 fprintf(stderr, i18n(ScreenSet, ScreenAnotherWMRunning,
102 "BScreen::BScreen: an error occured while querying the X server.\n"
103 " another window manager already running on display %s.\n"),
104 DisplayString(display));
105
106 running = False;
107
108 return(-1);
109 }
110
111
112 BScreen::BScreen(Blackbox *bb, unsigned int scrn) : ScreenInfo(bb, scrn) {
113 blackbox = bb;
114 screenstr = (string)"session.screen" + itostring(scrn) + '.';
115 config = blackbox->getConfig();
116 xatom = blackbox->getXAtom();
117
118 event_mask = ColormapChangeMask | EnterWindowMask | PropertyChangeMask |
119 SubstructureRedirectMask | ButtonPressMask | ButtonReleaseMask;
120
121 XErrorHandler old = XSetErrorHandler((XErrorHandler) anotherWMRunning);
122 XSelectInput(getBaseDisplay()->getXDisplay(), getRootWindow(), event_mask);
123 XSync(getBaseDisplay()->getXDisplay(), False);
124 XSetErrorHandler((XErrorHandler) old);
125
126 managed = running;
127 if (! managed) return;
128
129 fprintf(stderr, i18n(ScreenSet, ScreenManagingScreen,
130 "BScreen::BScreen: managing screen %d "
131 "using visual 0x%lx, depth %d\n"),
132 getScreenNumber(), XVisualIDFromVisual(getVisual()),
133 getDepth());
134
135 rootmenu = 0;
136
137 resource.mstyle.t_fontset = resource.mstyle.f_fontset =
138 resource.tstyle.fontset = resource.wstyle.fontset = (XFontSet) 0;
139 resource.mstyle.t_font = resource.mstyle.f_font = resource.tstyle.font =
140 resource.wstyle.font = (XFontStruct *) 0;
141
142 xatom->setSupported(this); // set-up netwm support
143 #ifdef HAVE_GETPID
144 xatom->setValue(getRootWindow(), XAtom::blackbox_pid, XAtom::cardinal,
145 (unsigned long) getpid());
146 #endif // HAVE_GETPID
147 unsigned long geometry[] = { getWidth(),
148 getHeight()};
149 xatom->setValue(getRootWindow(), XAtom::net_desktop_geometry,
150 XAtom::cardinal, geometry, 2);
151 unsigned long viewport[] = {0,0};
152 xatom->setValue(getRootWindow(), XAtom::net_desktop_viewport,
153 XAtom::cardinal, viewport, 2);
154
155
156 XDefineCursor(blackbox->getXDisplay(), getRootWindow(),
157 blackbox->getSessionCursor());
158
159 // start off full screen, top left.
160 usableArea.setSize(getWidth(), getHeight());
161
162 image_control =
163 new BImageControl(blackbox, this, True, blackbox->getColorsPerChannel(),
164 blackbox->getCacheLife(), blackbox->getCacheMax());
165 image_control->installRootColormap();
166 root_colormap_installed = True;
167
168 load_rc();
169 LoadStyle();
170
171 XGCValues gcv;
172 unsigned long gc_value_mask = GCForeground;
173 if (! i18n.multibyte()) gc_value_mask |= GCFont;
174
175 gcv.foreground = WhitePixel(blackbox->getXDisplay(), getScreenNumber())
176 ^ BlackPixel(blackbox->getXDisplay(), getScreenNumber());
177 gcv.function = GXxor;
178 gcv.subwindow_mode = IncludeInferiors;
179 opGC = XCreateGC(blackbox->getXDisplay(), getRootWindow(),
180 GCForeground | GCFunction | GCSubwindowMode, &gcv);
181
182 const char *s = i18n(ScreenSet, ScreenPositionLength,
183 "0: 0000 x 0: 0000");
184 int l = strlen(s);
185
186 if (i18n.multibyte()) {
187 XRectangle ink, logical;
188 XmbTextExtents(resource.wstyle.fontset, s, l, &ink, &logical);
189 geom_w = logical.width;
190
191 geom_h = resource.wstyle.fontset_extents->max_ink_extent.height;
192 } else {
193 geom_h = resource.wstyle.font->ascent +
194 resource.wstyle.font->descent;
195
196 geom_w = XTextWidth(resource.wstyle.font, s, l);
197 }
198
199 geom_w += (resource.bevel_width * 2);
200 geom_h += (resource.bevel_width * 2);
201
202 XSetWindowAttributes attrib;
203 unsigned long mask = CWBorderPixel | CWColormap | CWSaveUnder;
204 attrib.border_pixel = getBorderColor()->pixel();
205 attrib.colormap = getColormap();
206 attrib.save_under = True;
207
208 geom_window = XCreateWindow(blackbox->getXDisplay(), getRootWindow(),
209 0, 0, geom_w, geom_h, resource.border_width,
210 getDepth(), InputOutput, getVisual(),
211 mask, &attrib);
212 geom_visible = False;
213
214 BTexture* texture = &(resource.wstyle.l_focus);
215 geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap);
216 if (geom_pixmap == ParentRelative) {
217 texture = &(resource.wstyle.t_focus);
218 geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap);
219 }
220 if (! geom_pixmap)
221 XSetWindowBackground(blackbox->getXDisplay(), geom_window,
222 texture->color().pixel());
223 else
224 XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
225 geom_window, geom_pixmap);
226
227 workspacemenu = new Workspacemenu(this);
228 iconmenu = new Iconmenu(this);
229 configmenu = new Configmenu(this);
230
231 Workspace *wkspc = (Workspace *) 0;
232 if (resource.workspaces != 0) {
233 for (unsigned int i = 0; i < resource.workspaces; ++i) {
234 wkspc = new Workspace(this, workspacesList.size());
235 workspacesList.push_back(wkspc);
236 workspacemenu->insert(wkspc->getName(), wkspc->getMenu());
237 }
238 } else {
239 wkspc = new Workspace(this, workspacesList.size());
240 workspacesList.push_back(wkspc);
241 workspacemenu->insert(wkspc->getName(), wkspc->getMenu());
242 }
243 saveWorkspaceNames();
244
245 updateNetizenWorkspaceCount();
246
247 workspacemenu->insert(i18n(IconSet, IconIcons, "Icons"), iconmenu);
248 workspacemenu->update();
249
250 current_workspace = workspacesList.front();
251
252 xatom->setValue(getRootWindow(), XAtom::net_current_desktop,
253 XAtom::cardinal, 0); //first workspace
254
255 workspacemenu->setItemSelected(2, True);
256
257 toolbar = new Toolbar(this);
258
259 slit = new Slit(this);
260
261 InitMenu();
262
263 raiseWindows(0, 0); // this also initializes the empty stacking list
264 rootmenu->update();
265
266 updateClientList(); // initialize the client list, which will be empty
267 updateAvailableArea();
268
269 changeWorkspaceID(0);
270
271 unsigned int i, j, nchild;
272 Window r, p, *children;
273 XQueryTree(blackbox->getXDisplay(), getRootWindow(), &r, &p,
274 &children, &nchild);
275
276 // preen the window list of all icon windows... for better dockapp support
277 for (i = 0; i < nchild; i++) {
278 if (children[i] == None) continue;
279
280 XWMHints *wmhints = XGetWMHints(blackbox->getXDisplay(),
281 children[i]);
282
283 if (wmhints) {
284 if ((wmhints->flags & IconWindowHint) &&
285 (wmhints->icon_window != children[i])) {
286 for (j = 0; j < nchild; j++) {
287 if (children[j] == wmhints->icon_window) {
288 children[j] = None;
289 break;
290 }
291 }
292 }
293
294 XFree(wmhints);
295 }
296 }
297
298 // manage shown windows
299 for (i = 0; i < nchild; ++i) {
300 if (children[i] == None || (! blackbox->validateWindow(children[i])))
301 continue;
302
303 XWindowAttributes attrib;
304 if (XGetWindowAttributes(blackbox->getXDisplay(), children[i], &attrib)) {
305 if (attrib.override_redirect) continue;
306
307 if (attrib.map_state != IsUnmapped) {
308 manageWindow(children[i]);
309 }
310 }
311 }
312
313 XFree(children);
314
315 // call this again just in case a window we found updates the Strut list
316 updateAvailableArea();
317 updateFocusModel();
318 }
319
320
321 BScreen::~BScreen(void) {
322 if (! managed) return;
323
324 if (geom_pixmap != None)
325 image_control->removeImage(geom_pixmap);
326
327 if (geom_window != None)
328 XDestroyWindow(blackbox->getXDisplay(), geom_window);
329
330 std::for_each(workspacesList.begin(), workspacesList.end(),
331 PointerAssassin());
332
333 std::for_each(iconList.begin(), iconList.end(), PointerAssassin());
334
335 std::for_each(netizenList.begin(), netizenList.end(), PointerAssassin());
336
337 delete rootmenu;
338 delete workspacemenu;
339 delete iconmenu;
340 delete configmenu;
341 delete slit;
342 delete toolbar;
343 delete image_control;
344
345 if (resource.wstyle.fontset)
346 XFreeFontSet(blackbox->getXDisplay(), resource.wstyle.fontset);
347 if (resource.mstyle.t_fontset)
348 XFreeFontSet(blackbox->getXDisplay(), resource.mstyle.t_fontset);
349 if (resource.mstyle.f_fontset)
350 XFreeFontSet(blackbox->getXDisplay(), resource.mstyle.f_fontset);
351 if (resource.tstyle.fontset)
352 XFreeFontSet(blackbox->getXDisplay(), resource.tstyle.fontset);
353
354 if (resource.wstyle.font)
355 XFreeFont(blackbox->getXDisplay(), resource.wstyle.font);
356 if (resource.mstyle.t_font)
357 XFreeFont(blackbox->getXDisplay(), resource.mstyle.t_font);
358 if (resource.mstyle.f_font)
359 XFreeFont(blackbox->getXDisplay(), resource.mstyle.f_font);
360 if (resource.tstyle.font)
361 XFreeFont(blackbox->getXDisplay(), resource.tstyle.font);
362
363 XFreeGC(blackbox->getXDisplay(), opGC);
364 }
365
366
367 void BScreen::saveSloppyFocus(bool s) {
368 resource.sloppy_focus = s;
369
370 string fmodel;
371 if (resource.sloppy_focus) {
372 fmodel = "SloppyFocus";
373 if (resource.auto_raise) fmodel += " AutoRaise";
374 if (resource.click_raise) fmodel += " ClickRaise";
375 } else {
376 fmodel = "ClickToFocus";
377 }
378 config->setValue(screenstr + "focusModel", fmodel);
379 }
380
381
382 void BScreen::saveAutoRaise(bool a) {
383 resource.auto_raise = a;
384 saveSloppyFocus(resource.sloppy_focus);
385 }
386
387
388 void BScreen::saveClickRaise(bool c) {
389 resource.click_raise = c;
390 saveSloppyFocus(resource.sloppy_focus);
391 }
392
393
394 void BScreen::saveImageDither(bool d) {
395 image_control->setDither(d);
396 config->setValue(screenstr + "imageDither", doImageDither());
397 }
398
399
400 void BScreen::saveOpaqueMove(bool o) {
401 resource.opaque_move = o;
402 config->setValue(screenstr + "opaqueMove", resource.opaque_move);
403 }
404
405
406 void BScreen::saveFullMax(bool f) {
407 resource.full_max = f;
408 config->setValue(screenstr + "fullMaximization", resource.full_max);
409 }
410
411
412 void BScreen::saveFocusNew(bool f) {
413 resource.focus_new = f;
414 config->setValue(screenstr + "focusNewWindows", resource.focus_new);
415 }
416
417
418 void BScreen::saveFocusLast(bool f) {
419 resource.focus_last = f;
420 config->setValue(screenstr + "focusLastWindow", resource.focus_last);
421 }
422
423
424 void BScreen::saveHideToolbar(bool h) {
425 resource.hide_toolbar = h;
426 if (resource.hide_toolbar)
427 toolbar->unmapToolbar();
428 else
429 toolbar->mapToolbar();
430 config->setValue(screenstr + "hideToolbar", resource.hide_toolbar);
431 }
432
433
434 void BScreen::saveWindowToWindowSnap(bool s) {
435 resource.window_to_window_snap = s;
436 config->setValue(screenstr + "windowToWindowSnap",
437 resource.window_to_window_snap);
438 }
439
440
441 void BScreen::saveWindowCornerSnap(bool s) {
442 resource.window_corner_snap = s;
443 config->setValue(screenstr + "windowCornerSnap",
444 resource.window_corner_snap);
445 }
446
447
448 void BScreen::saveWorkspaces(unsigned int w) {
449 resource.workspaces = w;
450 config->setValue(screenstr + "workspaces", resource.workspaces);
451 }
452
453
454 void BScreen::savePlacementPolicy(int p) {
455 resource.placement_policy = p;
456 const char *placement;
457 switch (resource.placement_policy) {
458 case CascadePlacement: placement = "CascadePlacement"; break;
459 case ColSmartPlacement: placement = "ColSmartPlacement"; break;
460 case RowSmartPlacement: default: placement = "RowSmartPlacement"; break;
461 }
462 config->setValue(screenstr + "windowPlacement", placement);
463 }
464
465
466 void BScreen::saveEdgeSnapThreshold(int t) {
467 resource.edge_snap_threshold = t;
468 config->setValue(screenstr + "edgeSnapThreshold",
469 resource.edge_snap_threshold);
470 }
471
472
473 void BScreen::saveRowPlacementDirection(int d) {
474 resource.row_direction = d;
475 config->setValue(screenstr + "rowPlacementDirection",
476 resource.row_direction == LeftRight ?
477 "LeftToRight" : "RightToLeft");
478 }
479
480
481 void BScreen::saveColPlacementDirection(int d) {
482 resource.col_direction = d;
483 config->setValue(screenstr + "colPlacementDirection",
484 resource.col_direction == TopBottom ?
485 "TopToBottom" : "BottomToTop");
486 }
487
488
489 #ifdef HAVE_STRFTIME
490 void BScreen::saveStrftimeFormat(const std::string& format) {
491 resource.strftime_format = format;
492 config->setValue(screenstr + "strftimeFormat", resource.strftime_format);
493 }
494
495 #else // !HAVE_STRFTIME
496
497 void BScreen::saveDateFormat(int f) {
498 resource.date_format = f;
499 config->setValue(screenstr + "dateFormat",
500 resource.date_format == B_EuropeanDate ?
501 "European" : "American");
502 }
503
504
505 void BScreen::saveClock24Hour(Bool c) {
506 resource.clock24hour = c;
507 config->setValue(screenstr + "clockFormat", resource.clock24hour ? 24 : 12);
508 }
509 #endif // HAVE_STRFTIME
510
511
512 void BScreen::saveWorkspaceNames() {
513 XAtom::StringVect nameList;
514 unsigned long numnames = (unsigned) -1;
515 string names;
516
517 if (numnames > 0 &&
518 xatom->getValue(getRootWindow(), XAtom::net_desktop_names, XAtom::utf8,
519 numnames, nameList)) {
520 for (unsigned int i = 0; i < nameList.size(); ++i) {
521 if (i > 0) names += ",";
522 names += nameList[i];
523 }
524 }
525 config->setValue(screenstr + "workspaceNames", names);
526 }
527
528
529 void BScreen::save_rc(void) {
530 saveSloppyFocus(resource.sloppy_focus);
531 saveAutoRaise(resource.auto_raise);
532 saveImageDither(doImageDither());
533 saveOpaqueMove(resource.opaque_move);
534 saveFullMax(resource.full_max);
535 saveFocusNew(resource.focus_new);
536 saveFocusLast(resource.focus_last);
537 saveHideToolbar(resource.hide_toolbar);
538 saveWindowToWindowSnap(resource.window_to_window_snap);
539 saveWindowCornerSnap(resource.window_corner_snap);
540 saveWorkspaces(resource.workspaces);
541 savePlacementPolicy(resource.placement_policy);
542 saveEdgeSnapThreshold(resource.edge_snap_threshold);
543 saveRowPlacementDirection(resource.row_direction);
544 saveColPlacementDirection(resource.col_direction);
545 #ifdef HAVE_STRFTIME
546 saveStrftimeFormat(resource.strftime_format);
547 #else // !HAVE_STRFTIME
548 saveDateFormat(resource.date_format);
549 savwClock24Hour(resource.clock24hour);
550 #endif // HAVE_STRFTIME
551
552 toolbar->save_rc();
553 slit->save_rc();
554 }
555
556
557 void BScreen::load_rc(void) {
558 std::string s;
559 bool b;
560
561 if (! config->getValue(screenstr + "fullMaximization", resource.full_max))
562 resource.full_max = false;
563
564 if (! config->getValue(screenstr + "focusNewWindows", resource.focus_new))
565 resource.focus_new = false;
566
567 if (! config->getValue(screenstr + "focusLastWindow", resource.focus_last))
568 resource.focus_last = false;
569
570 if (! config->getValue(screenstr + "workspaces", resource.workspaces))
571 resource.workspaces = 1;
572
573 if (! config->getValue(screenstr + "opaqueMove", resource.opaque_move))
574 resource.opaque_move = false;
575
576 if (! config->getValue(screenstr + "hideToolbar", resource.hide_toolbar))
577 resource.hide_toolbar = false;
578
579 if (! config->getValue(screenstr + "windowToWindowSnap",
580 resource.window_to_window_snap))
581 resource.window_to_window_snap = true;
582
583 if (! config->getValue(screenstr + "windowCornerSnap",
584 resource.window_corner_snap))
585 resource.window_corner_snap = true;
586
587 if (! config->getValue(screenstr + "imageDither", b))
588 b = true;
589 image_control->setDither(b);
590
591 if (! config->getValue(screenstr + "edgeSnapThreshold",
592 resource.edge_snap_threshold))
593 resource.edge_snap_threshold = 4;
594
595 if (config->getValue(screenstr + "rowPlacementDirection", s) &&
596 s == "RightToLeft")
597 resource.row_direction = RightLeft;
598 else
599 resource.row_direction = LeftRight;
600
601 if (config->getValue(screenstr + "colPlacementDirection", s) &&
602 s == "BottomToTop")
603 resource.col_direction = BottomTop;
604 else
605 resource.col_direction = TopBottom;
606
607 XAtom::StringVect workspaceNames;
608 if (config->getValue(screenstr + "workspaceNames", s)) {
609 string::const_iterator it = s.begin(), end = s.end();
610 while(1) {
611 string::const_iterator tmp = it; // current string.begin()
612 it = std::find(tmp, end, ','); // look for comma between tmp and end
613 workspaceNames.push_back(string(tmp, it)); // s[tmp:it]
614 if (it == end)
615 break;
616 ++it;
617 }
618 }
619 xatom->setValue(getRootWindow(), XAtom::net_desktop_names, XAtom::utf8,
620 workspaceNames);
621
622 resource.sloppy_focus = true;
623 resource.auto_raise = false;
624 resource.click_raise = false;
625 if (config->getValue(screenstr + "focusModel", s)) {
626 if (s.find("ClickToFocus") != string::npos) {
627 resource.sloppy_focus = false;
628 } else {
629 // must be sloppy
630 if (s.find("AutoRaise") != string::npos)
631 resource.auto_raise = true;
632 if (s.find("ClickRaise") != string::npos)
633 resource.click_raise = true;
634 }
635 }
636
637 if (config->getValue(screenstr + "windowPlacement", s)) {
638 if (s == "CascadePlacement")
639 resource.placement_policy = CascadePlacement;
640 else if (s == "ColSmartPlacement")
641 resource.placement_policy = ColSmartPlacement;
642 else //if (s == "RowSmartPlacement")
643 resource.placement_policy = RowSmartPlacement;
644 } else
645 resource.placement_policy = RowSmartPlacement;
646
647 #ifdef HAVE_STRFTIME
648 if (config->getValue(screenstr + "strftimeFormat", s))
649 resource.strftime_format = s;
650 else
651 resource.strftime_format = "%I:%M %p";
652 #else // !HAVE_STRFTIME
653 long l;
654
655 if (config->getValue(screenstr + "dateFormat", s) && s == "European")
656 resource.date_format = B_EuropeanDate;
657 else
658 resource.date_format = B_AmericanDate;
659
660 if (! config->getValue(screenstr + "clockFormat", l))
661 l = 12;
662 resource.clock24hour = l == 24;
663 #endif // HAVE_STRFTIME
664 }
665
666
667 void BScreen::reconfigure(void) {
668 load_rc();
669 toolbar->load_rc();
670 slit->load_rc();
671 LoadStyle();
672
673 XGCValues gcv;
674 unsigned long gc_value_mask = GCForeground;
675 if (! i18n.multibyte()) gc_value_mask |= GCFont;
676
677 gcv.foreground = WhitePixel(blackbox->getXDisplay(),
678 getScreenNumber());
679 gcv.function = GXinvert;
680 gcv.subwindow_mode = IncludeInferiors;
681 XChangeGC(blackbox->getXDisplay(), opGC,
682 GCForeground | GCFunction | GCSubwindowMode, &gcv);
683
684 const char *s = i18n(ScreenSet, ScreenPositionLength,
685 "0: 0000 x 0: 0000");
686 int l = strlen(s);
687
688 if (i18n.multibyte()) {
689 XRectangle ink, logical;
690 XmbTextExtents(resource.wstyle.fontset, s, l, &ink, &logical);
691 geom_w = logical.width;
692
693 geom_h = resource.wstyle.fontset_extents->max_ink_extent.height;
694 } else {
695 geom_w = XTextWidth(resource.wstyle.font, s, l);
696
697 geom_h = resource.wstyle.font->ascent + resource.wstyle.font->descent;
698 }
699
700 geom_w += (resource.bevel_width * 2);
701 geom_h += (resource.bevel_width * 2);
702
703 BTexture* texture = &(resource.wstyle.l_focus);
704 geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap);
705 if (geom_pixmap == ParentRelative) {
706 texture = &(resource.wstyle.t_focus);
707 geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap);
708 }
709 if (! geom_pixmap)
710 XSetWindowBackground(blackbox->getXDisplay(), geom_window,
711 texture->color().pixel());
712 else
713 XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
714 geom_window, geom_pixmap);
715
716 XSetWindowBorderWidth(blackbox->getXDisplay(), geom_window,
717 resource.border_width);
718 XSetWindowBorder(blackbox->getXDisplay(), geom_window,
719 resource.border_color.pixel());
720
721 workspacemenu->reconfigure();
722 iconmenu->reconfigure();
723
724 typedef std::vector<int> SubList;
725 SubList remember_subs;
726
727 // save the current open menus
728 Basemenu *menu = rootmenu;
729 int submenu;
730 while ((submenu = menu->getCurrentSubmenu()) >= 0) {
731 remember_subs.push_back(submenu);
732 menu = menu->find(submenu)->submenu();
733 assert(menu);
734 }
735
736 InitMenu();
737 raiseWindows(0, 0);
738 rootmenu->reconfigure();
739
740 // reopen the saved menus
741 menu = rootmenu;
742 const SubList::iterator subs_end = remember_subs.end();
743 for (SubList::iterator it = remember_subs.begin(); it != subs_end; ++it) {
744 menu->drawSubmenu(*it);
745 menu = menu->find(*it)->submenu();
746 if (! menu)
747 break;
748 }
749
750 configmenu->reconfigure();
751
752 toolbar->reconfigure();
753
754 slit->reconfigure();
755
756 std::for_each(workspacesList.begin(), workspacesList.end(),
757 std::mem_fun(&Workspace::reconfigure));
758
759 BlackboxWindowList::iterator iit = iconList.begin();
760 for (; iit != iconList.end(); ++iit) {
761 BlackboxWindow *bw = *iit;
762 if (bw->validateClient())
763 bw->reconfigure();
764 }
765
766 image_control->timeout();
767 }
768
769
770 void BScreen::rereadMenu(void) {
771 InitMenu();
772 raiseWindows(0, 0);
773
774 rootmenu->reconfigure();
775 }
776
777
778 void BScreen::LoadStyle(void) {
779 Configuration style;
780
781 const char *sfile = blackbox->getStyleFilename();
782 if (sfile != NULL) {
783 style.setFile(sfile);
784 if (! style.load()) {
785 style.setFile(DEFAULTSTYLE);
786 if (! style.load())
787 style.create(); // hardcoded default values will be used.
788 }
789 }
790
791 string s;
792
793 // load fonts/fontsets
794 if (resource.wstyle.fontset)
795 XFreeFontSet(blackbox->getXDisplay(), resource.wstyle.fontset);
796 if (resource.tstyle.fontset)
797 XFreeFontSet(blackbox->getXDisplay(), resource.tstyle.fontset);
798 if (resource.mstyle.f_fontset)
799 XFreeFontSet(blackbox->getXDisplay(), resource.mstyle.f_fontset);
800 if (resource.mstyle.t_fontset)
801 XFreeFontSet(blackbox->getXDisplay(), resource.mstyle.t_fontset);
802 resource.wstyle.fontset = 0;
803 resource.tstyle.fontset = 0;
804 resource.mstyle.f_fontset = 0;
805 resource.mstyle.t_fontset = 0;
806 if (resource.wstyle.font)
807 XFreeFont(blackbox->getXDisplay(), resource.wstyle.font);
808 if (resource.tstyle.font)
809 XFreeFont(blackbox->getXDisplay(), resource.tstyle.font);
810 if (resource.mstyle.f_font)
811 XFreeFont(blackbox->getXDisplay(), resource.mstyle.f_font);
812 if (resource.mstyle.t_font)
813 XFreeFont(blackbox->getXDisplay(), resource.mstyle.t_font);
814 resource.wstyle.font = 0;
815 resource.tstyle.font = 0;
816 resource.mstyle.f_font = 0;
817 resource.mstyle.t_font = 0;
818
819 if (i18n.multibyte()) {
820 resource.wstyle.fontset = readDatabaseFontSet("window.font", style);
821 resource.tstyle.fontset = readDatabaseFontSet("toolbar.font", style);
822 resource.mstyle.t_fontset = readDatabaseFontSet("menu.title.font", style);
823 resource.mstyle.f_fontset = readDatabaseFontSet("menu.frame.font", style);
824
825 resource.mstyle.t_fontset_extents =
826 XExtentsOfFontSet(resource.mstyle.t_fontset);
827 resource.mstyle.f_fontset_extents =
828 XExtentsOfFontSet(resource.mstyle.f_fontset);
829 resource.tstyle.fontset_extents =
830 XExtentsOfFontSet(resource.tstyle.fontset);
831 resource.wstyle.fontset_extents =
832 XExtentsOfFontSet(resource.wstyle.fontset);
833 } else {
834 resource.wstyle.font = readDatabaseFont("window.font", style);
835 resource.tstyle.font = readDatabaseFont("toolbar.font", style);
836 resource.mstyle.t_font = readDatabaseFont("menu.title.font", style);
837 resource.mstyle.f_font = readDatabaseFont("menu.frame.font", style);
838 }
839
840 // load window config
841 resource.wstyle.t_focus =
842 readDatabaseTexture("window.title.focus", "white", style);
843 resource.wstyle.t_unfocus =
844 readDatabaseTexture("window.title.unfocus", "black", style);
845 resource.wstyle.l_focus =
846 readDatabaseTexture("window.label.focus", "white", style);
847 resource.wstyle.l_unfocus =
848 readDatabaseTexture("window.label.unfocus", "black", style);
849 resource.wstyle.h_focus =
850 readDatabaseTexture("window.handle.focus", "white", style);
851 resource.wstyle.h_unfocus =
852 readDatabaseTexture("window.handle.unfocus", "black", style);
853 resource.wstyle.g_focus =
854 readDatabaseTexture("window.grip.focus", "white", style);
855 resource.wstyle.g_unfocus =
856 readDatabaseTexture("window.grip.unfocus", "black", style);
857 resource.wstyle.b_focus =
858 readDatabaseTexture("window.button.focus", "white", style);
859 resource.wstyle.b_unfocus =
860 readDatabaseTexture("window.button.unfocus", "black", style);
861 resource.wstyle.b_pressed =
862 readDatabaseTexture("window.button.pressed", "black", style);
863 resource.wstyle.f_focus =
864 readDatabaseColor("window.frame.focusColor", "white", style);
865 resource.wstyle.f_unfocus =
866 readDatabaseColor("window.frame.unfocusColor", "black", style);
867 resource.wstyle.l_text_focus =
868 readDatabaseColor("window.label.focus.textColor", "black", style);
869 resource.wstyle.l_text_unfocus =
870 readDatabaseColor("window.label.unfocus.textColor", "white", style);
871 resource.wstyle.b_pic_focus =
872 readDatabaseColor("window.button.focus.picColor", "black", style);
873 resource.wstyle.b_pic_unfocus =
874 readDatabaseColor("window.button.unfocus.picColor", "white", style);
875
876 resource.wstyle.justify = LeftJustify;
877 if (style.getValue("window.justify", s)) {
878 if (s == "right" || s == "Right")
879 resource.wstyle.justify = RightJustify;
880 else if (s == "center" || s == "Center")
881 resource.wstyle.justify = CenterJustify;
882 }
883
884 // load toolbar config
885 resource.tstyle.toolbar =
886 readDatabaseTexture("toolbar", "black", style);
887 resource.tstyle.label =
888 readDatabaseTexture("toolbar.label", "black", style);
889 resource.tstyle.window =
890 readDatabaseTexture("toolbar.windowLabel", "black", style);
891 resource.tstyle.button =
892 readDatabaseTexture("toolbar.button", "white", style);
893 resource.tstyle.pressed =
894 readDatabaseTexture("toolbar.button.pressed", "black", style);
895 resource.tstyle.clock =
896 readDatabaseTexture("toolbar.clock", "black", style);
897 resource.tstyle.l_text =
898 readDatabaseColor("toolbar.label.textColor", "white", style);
899 resource.tstyle.w_text =
900 readDatabaseColor("toolbar.windowLabel.textColor", "white", style);
901 resource.tstyle.c_text =
902 readDatabaseColor("toolbar.clock.textColor", "white", style);
903 resource.tstyle.b_pic =
904 readDatabaseColor("toolbar.button.picColor", "black", style);
905
906 resource.tstyle.justify = LeftJustify;
907 if (style.getValue("toolbar.justify", s)) {
908 if (s == "right" || s == "Right")
909 resource.tstyle.justify = RightJustify;
910 else if (s == "center" || s == "Center")
911 resource.tstyle.justify = CenterJustify;
912 }
913
914 // load menu config
915 resource.mstyle.title =
916 readDatabaseTexture("menu.title", "white", style);
917 resource.mstyle.frame =
918 readDatabaseTexture("menu.frame", "black", style);
919 resource.mstyle.hilite =
920 readDatabaseTexture("menu.hilite", "white", style);
921 resource.mstyle.t_text =
922 readDatabaseColor("menu.title.textColor", "black", style);
923 resource.mstyle.f_text =
924 readDatabaseColor("menu.frame.textColor", "white", style);
925 resource.mstyle.d_text =
926 readDatabaseColor("menu.frame.disableColor", "black", style);
927 resource.mstyle.h_text =
928 readDatabaseColor("menu.hilite.textColor", "black", style);
929
930 resource.mstyle.t_justify = LeftJustify;
931 if (style.getValue("menu.title.justify", s)) {
932 if (s == "right" || s == "Right")
933 resource.mstyle.t_justify = RightJustify;
934 else if (s == "center" || s == "Center")
935 resource.mstyle.t_justify = CenterJustify;
936 }
937
938 resource.mstyle.f_justify = LeftJustify;
939 if (style.getValue("menu.frame.justify", s)) {
940 if (s == "right" || s == "Right")
941 resource.mstyle.f_justify = RightJustify;
942 else if (s == "center" || s == "Center")
943 resource.mstyle.f_justify = CenterJustify;
944 }
945
946 resource.mstyle.bullet = Basemenu::Triangle;
947 if (style.getValue("menu.bullet", s)) {
948 if (s == "empty" || s == "Empty")
949 resource.mstyle.bullet = Basemenu::Empty;
950 else if (s == "square" || s == "Square")
951 resource.mstyle.bullet = Basemenu::Square;
952 else if (s == "diamond" || s == "Diamond")
953 resource.mstyle.bullet = Basemenu::Diamond;
954 }
955
956 resource.mstyle.bullet_pos = Basemenu::Left;
957 if (style.getValue("menu.bullet.position", s)) {
958 if (s == "right" || s == "Right")
959 resource.mstyle.bullet_pos = Basemenu::Right;
960 }
961
962 resource.border_color =
963 readDatabaseColor("borderColor", "black", style);
964
965 // load bevel, border and handle widths
966 if (! style.getValue("handleWidth", resource.handle_width) ||
967 resource.handle_width > (getWidth() / 2) || resource.handle_width == 0)
968 resource.handle_width = 6;
969
970 if (! style.getValue("borderWidth", resource.border_width))
971 resource.border_width = 1;
972
973 if (! style.getValue("bevelWidth", resource.bevel_width) ||
974 resource.bevel_width > (getWidth() / 2) || resource.bevel_width == 0)
975 resource.bevel_width = 3;
976
977 if (! style.getValue("frameWidth", resource.frame_width) ||
978 resource.frame_width > (getWidth() / 2))
979 resource.frame_width = resource.bevel_width;
980
981 if (style.getValue("rootCommand", s))
982 bexec(s, displayString());
983 }
984
985
986 void BScreen::addIcon(BlackboxWindow *w) {
987 if (! w) return;
988
989 w->setWorkspace(BSENTINEL);
990 w->setWindowNumber(iconList.size());
991
992 iconList.push_back(w);
993
994 const char* title = w->getIconTitle();
995 iconmenu->insert(title);
996 iconmenu->update();
997 }
998
999
1000 void BScreen::removeIcon(BlackboxWindow *w) {
1001 if (! w) return;
1002
1003 iconList.remove(w);
1004
1005 iconmenu->remove(w->getWindowNumber());
1006 iconmenu->update();
1007
1008 BlackboxWindowList::iterator it = iconList.begin(),
1009 end = iconList.end();
1010 for (int i = 0; it != end; ++it)
1011 (*it)->setWindowNumber(i++);
1012 }
1013
1014
1015 BlackboxWindow *BScreen::getIcon(unsigned int index) {
1016 if (index < iconList.size()) {
1017 BlackboxWindowList::iterator it = iconList.begin();
1018 for (; index > 0; --index, ++it) ; /* increment to index */
1019 return *it;
1020 }
1021
1022 return (BlackboxWindow *) 0;
1023 }
1024
1025
1026 unsigned int BScreen::addWorkspace(void) {
1027 Workspace *wkspc = new Workspace(this, workspacesList.size());
1028 workspacesList.push_back(wkspc);
1029 saveWorkspaces(getWorkspaceCount());
1030
1031 workspacemenu->insert(wkspc->getName(), wkspc->getMenu(),
1032 wkspc->getID() + 2);
1033 workspacemenu->update();
1034
1035 toolbar->reconfigure();
1036
1037 updateNetizenWorkspaceCount();
1038
1039 return workspacesList.size();
1040 }
1041
1042
1043 unsigned int BScreen::removeLastWorkspace(void) {
1044 if (workspacesList.size() == 1)
1045 return 1;
1046
1047 Workspace *wkspc = workspacesList.back();
1048
1049 if (current_workspace->getID() == wkspc->getID())
1050 changeWorkspaceID(current_workspace->getID() - 1);
1051
1052 wkspc->removeAll();
1053
1054 workspacemenu->remove(wkspc->getID() + 2);
1055 workspacemenu->update();
1056
1057 workspacesList.pop_back();
1058 delete wkspc;
1059
1060 saveWorkspaces(getWorkspaceCount());
1061
1062 toolbar->reconfigure();
1063
1064 updateNetizenWorkspaceCount();
1065
1066 return workspacesList.size();
1067 }
1068
1069
1070 void BScreen::changeWorkspaceID(unsigned int id) {
1071 if (! current_workspace) return;
1072
1073 if (id != current_workspace->getID()) {
1074 BlackboxWindow *focused = blackbox->getFocusedWindow();
1075 if (focused && focused->getScreen() == this && ! focused->isStuck()) {
1076 if (focused->getWorkspaceNumber() != current_workspace->getID()) {
1077 fprintf(stderr, "%s is on the wrong workspace, aborting\n",
1078 focused->getTitle());
1079 abort();
1080 }
1081 current_workspace->setLastFocusedWindow(focused);
1082 } else {
1083 // if no window had focus, no need to store a last focus
1084 current_workspace->setLastFocusedWindow((BlackboxWindow *) 0);
1085 }
1086 // when we switch workspaces, unfocus whatever was focused
1087 blackbox->setFocusedWindow((BlackboxWindow *) 0);
1088
1089 current_workspace->hideAll();
1090 workspacemenu->setItemSelected(current_workspace->getID() + 2, False);
1091
1092 current_workspace = getWorkspace(id);
1093
1094 xatom->setValue(getRootWindow(), XAtom::net_current_desktop,
1095 XAtom::cardinal, id);
1096
1097 workspacemenu->setItemSelected(current_workspace->getID() + 2, True);
1098 toolbar->redrawWorkspaceLabel(True);
1099
1100 current_workspace->showAll();
1101
1102 if (resource.focus_last && current_workspace->getLastFocusedWindow()) {
1103 XSync(blackbox->getXDisplay(), False);
1104 current_workspace->getLastFocusedWindow()->setInputFocus();
1105 }
1106 }
1107
1108 updateNetizenCurrentWorkspace();
1109 }
1110
1111
1112 /*
1113 * Set the _NET_CLIENT_LIST root window property.
1114 */
1115 void BScreen::updateClientList(void) {
1116 if (windowList.size() > 0) {
1117 Window *windows = new Window[windowList.size()];
1118 Window *win_it = windows;
1119 BlackboxWindowList::iterator it = windowList.begin();
1120 const BlackboxWindowList::iterator end = windowList.end();
1121 for (; it != end; ++it, ++win_it)
1122 *win_it = (*it)->getClientWindow();
1123 xatom->setValue(getRootWindow(), XAtom::net_client_list, XAtom::window,
1124 windows, windowList.size());
1125 delete [] windows;
1126 } else
1127 xatom->setValue(getRootWindow(), XAtom::net_client_list, XAtom::window,
1128 0, 0);
1129 }
1130
1131
1132 /*
1133 * Set the _NET_CLIENT_LIST_STACKING root window property.
1134 */
1135 void BScreen::updateStackingList(void) {
1136
1137 BlackboxWindowList stack_order;
1138
1139 /*
1140 * Get the atacking order from all of the workspaces.
1141 * We start with the current workspace so that the sticky windows will be
1142 * in the right order on the current workspace.
1143 * XXX: Do we need to have sticky windows in the list once for each workspace?
1144 */
1145 getCurrentWorkspace()->appendStackOrder(stack_order);
1146 for (unsigned int i = 0; i < getWorkspaceCount(); ++i)
1147 if (i != getCurrentWorkspaceID())
1148 getWorkspace(i)->appendStackOrder(stack_order);
1149
1150 if (stack_order.size() > 0) {
1151 // set the client list atoms
1152 Window *windows = new Window[stack_order.size()];
1153 Window *win_it = windows;
1154 BlackboxWindowList::iterator it = stack_order.begin();
1155 const BlackboxWindowList::iterator end = stack_order.end();
1156 for (; it != end; ++it, ++win_it)
1157 *win_it = (*it)->getClientWindow();
1158 xatom->setValue(getRootWindow(), XAtom::net_client_list_stacking,
1159 XAtom::window, windows, stack_order.size());
1160 delete [] windows;
1161 } else
1162 xatom->setValue(getRootWindow(), XAtom::net_client_list_stacking,
1163 XAtom::window, 0, 0);
1164 }
1165
1166
1167 void BScreen::addSystrayWindow(Window window) {
1168 systrayWindowList.push_back(window);
1169 xatom->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows,
1170 XAtom::window,
1171 &systrayWindowList[0], systrayWindowList.size());
1172 blackbox->saveSystrayWindowSearch(window, this);
1173 }
1174
1175
1176 void BScreen::removeSystrayWindow(Window window) {
1177 WindowList::iterator it = systrayWindowList.begin();
1178 const WindowList::iterator end = systrayWindowList.end();
1179 for (; it != end; ++it)
1180 if (*it == window) {
1181 systrayWindowList.erase(it);
1182 xatom->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows,
1183 XAtom::window,
1184 &systrayWindowList[0], systrayWindowList.size());
1185 blackbox->removeSystrayWindowSearch(window);
1186 break;
1187 }
1188 }
1189
1190
1191 void BScreen::addDesktopWindow(Window window) {
1192 desktopWindowList.push_back(window);
1193 XLowerWindow(blackbox->getXDisplay(), window);
1194 XSelectInput(blackbox->getXDisplay(), window, StructureNotifyMask);
1195 blackbox->saveDesktopWindowSearch(window, this);
1196 }
1197
1198
1199 void BScreen::removeDesktopWindow(Window window) {
1200 WindowList::iterator it = desktopWindowList.begin();
1201 const WindowList::iterator end = desktopWindowList.end();
1202 for (; it != end; ++it)
1203 if (*it == window) {
1204 desktopWindowList.erase(it);
1205 XSelectInput(blackbox->getXDisplay(), window, None);
1206 blackbox->removeDesktopWindowSearch(window);
1207 break;
1208 }
1209 }
1210
1211
1212 void BScreen::manageWindow(Window w) {
1213 new BlackboxWindow(blackbox, w, this);
1214
1215 BlackboxWindow *win = blackbox->searchWindow(w);
1216 if (! win)
1217 return;
1218 if (win->isDesktop()) {
1219 // desktop windows cant do anything, so we remove all the normal window
1220 // stuff from them, they are only kept around so that we can keep them on
1221 // the bottom of the z-order
1222 win->restore(True);
1223 addDesktopWindow(win->getClientWindow());
1224 delete win;
1225 return;
1226 }
1227
1228 windowList.push_back(win);
1229 updateClientList();
1230
1231 XMapRequestEvent mre;
1232 mre.window = w;
1233 if (blackbox->isStartup()) win->restoreAttributes();
1234 win->mapRequestEvent(&mre);
1235 }
1236
1237
1238 void BScreen::unmanageWindow(BlackboxWindow *w, bool remap) {
1239 w->restore(remap);
1240
1241 if (w->getWorkspaceNumber() != BSENTINEL &&
1242 w->getWindowNumber() != BSENTINEL)
1243 getWorkspace(w->getWorkspaceNumber())->removeWindow(w);
1244 else if (w->isIconic())
1245 removeIcon(w);
1246
1247 windowList.remove(w);
1248 updateClientList();
1249
1250 if (blackbox->getFocusedWindow() == w)
1251 blackbox->setFocusedWindow((BlackboxWindow *) 0);
1252
1253 removeNetizen(w->getClientWindow());
1254
1255 /*
1256 some managed windows can also be window group controllers. when
1257 unmanaging such windows, we should also delete the window group.
1258 */
1259 BWindowGroup *group = blackbox->searchGroup(w->getClientWindow());
1260 delete group;
1261
1262 delete w;
1263 }
1264
1265
1266 void BScreen::addNetizen(Netizen *n) {
1267 netizenList.push_back(n);
1268
1269 n->sendWorkspaceCount();
1270 n->sendCurrentWorkspace();
1271
1272 WorkspaceList::iterator it = workspacesList.begin();
1273 const WorkspaceList::iterator end = workspacesList.end();
1274 for (; it != end; ++it)
1275 (*it)->sendWindowList(*n);
1276
1277 Window f = ((blackbox->getFocusedWindow()) ?
1278 blackbox->getFocusedWindow()->getClientWindow() : None);
1279 n->sendWindowFocus(f);
1280 }
1281
1282
1283 void BScreen::removeNetizen(Window w) {
1284 NetizenList::iterator it = netizenList.begin();
1285 for (; it != netizenList.end(); ++it) {
1286 if ((*it)->getWindowID() == w) {
1287 delete *it;
1288 netizenList.erase(it);
1289 break;
1290 }
1291 }
1292 }
1293
1294
1295 void BScreen::updateWorkArea(void) {
1296 if (workspacesList.size() > 0) {
1297 unsigned long *dims = new unsigned long[4 * workspacesList.size()];
1298 for (unsigned int i = 0, m = workspacesList.size(); i < m; ++i) {
1299 // XXX: this could be different for each workspace
1300 const Rect &area = availableArea();
1301 dims[(i * 4) + 0] = area.x();
1302 dims[(i * 4) + 1] = area.y();
1303 dims[(i * 4) + 2] = area.width();
1304 dims[(i * 4) + 3] = area.height();
1305 }
1306 xatom->setValue(getRootWindow(), XAtom::net_workarea, XAtom::cardinal,
1307 dims, 4 * workspacesList.size());
1308 } else
1309 xatom->setValue(getRootWindow(), XAtom::net_workarea, XAtom::cardinal,
1310 0, 0);
1311 }
1312
1313
1314 void BScreen::updateNetizenCurrentWorkspace(void) {
1315 std::for_each(netizenList.begin(), netizenList.end(),
1316 std::mem_fun(&Netizen::sendCurrentWorkspace));
1317 }
1318
1319
1320 void BScreen::updateNetizenWorkspaceCount(void) {
1321 xatom->setValue(getRootWindow(), XAtom::net_number_of_desktops,
1322 XAtom::cardinal, workspacesList.size());
1323
1324 updateWorkArea();
1325
1326 std::for_each(netizenList.begin(), netizenList.end(),
1327 std::mem_fun(&Netizen::sendWorkspaceCount));
1328 }
1329
1330
1331 void BScreen::updateNetizenWindowFocus(void) {
1332 Window f = ((blackbox->getFocusedWindow()) ?
1333 blackbox->getFocusedWindow()->getClientWindow() : None);
1334
1335 xatom->setValue(getRootWindow(), XAtom::net_active_window,
1336 XAtom::window, f);
1337
1338 NetizenList::iterator it = netizenList.begin();
1339 for (; it != netizenList.end(); ++it)
1340 (*it)->sendWindowFocus(f);
1341 }
1342
1343
1344 void BScreen::updateNetizenWindowAdd(Window w, unsigned long p) {
1345 NetizenList::iterator it = netizenList.begin();
1346 for (; it != netizenList.end(); ++it) {
1347 (*it)->sendWindowAdd(w, p);
1348 }
1349 }
1350
1351
1352 void BScreen::updateNetizenWindowDel(Window w) {
1353 NetizenList::iterator it = netizenList.begin();
1354 for (; it != netizenList.end(); ++it)
1355 (*it)->sendWindowDel(w);
1356 }
1357
1358
1359 void BScreen::updateNetizenWindowRaise(Window w) {
1360 NetizenList::iterator it = netizenList.begin();
1361 for (; it != netizenList.end(); ++it)
1362 (*it)->sendWindowRaise(w);
1363 }
1364
1365
1366 void BScreen::updateNetizenWindowLower(Window w) {
1367 NetizenList::iterator it = netizenList.begin();
1368 for (; it != netizenList.end(); ++it)
1369 (*it)->sendWindowLower(w);
1370 }
1371
1372
1373 void BScreen::updateNetizenConfigNotify(XEvent *e) {
1374 NetizenList::iterator it = netizenList.begin();
1375 for (; it != netizenList.end(); ++it)
1376 (*it)->sendConfigNotify(e);
1377 }
1378
1379
1380 void BScreen::raiseWindows(Window *workspace_stack, unsigned int num) {
1381 // the 13 represents the number of blackbox windows such as menus
1382 Window *session_stack = new
1383 Window[(num + workspacesList.size() + rootmenuList.size() + 13)];
1384 unsigned int i = 0, k = num;
1385
1386 XRaiseWindow(blackbox->getXDisplay(), iconmenu->getWindowID());
1387 *(session_stack + i++) = iconmenu->getWindowID();
1388
1389 WorkspaceList::iterator wit = workspacesList.begin();
1390 const WorkspaceList::iterator w_end = workspacesList.end();
1391 for (; wit != w_end; ++wit)
1392 *(session_stack + i++) = (*wit)->getMenu()->getWindowID();
1393
1394 *(session_stack + i++) = workspacemenu->getWindowID();
1395
1396 *(session_stack + i++) = configmenu->getFocusmenu()->getWindowID();
1397 *(session_stack + i++) = configmenu->getPlacementmenu()->getWindowID();
1398 *(session_stack + i++) = configmenu->getWindowID();
1399
1400 *(session_stack + i++) = slit->getMenu()->getDirectionmenu()->getWindowID();
1401 *(session_stack + i++) = slit->getMenu()->getPlacementmenu()->getWindowID();
1402 *(session_stack + i++) = slit->getMenu()->getWindowID();
1403
1404 *(session_stack + i++) =
1405 toolbar->getMenu()->getPlacementmenu()->getWindowID();
1406 *(session_stack + i++) = toolbar->getMenu()->getWindowID();
1407
1408 RootmenuList::iterator rit = rootmenuList.begin();
1409 for (; rit != rootmenuList.end(); ++rit)
1410 *(session_stack + i++) = (*rit)->getWindowID();
1411 *(session_stack + i++) = rootmenu->getWindowID();
1412
1413 if (toolbar->isOnTop())
1414 *(session_stack + i++) = toolbar->getWindowID();
1415
1416 if (slit->isOnTop())
1417 *(session_stack + i++) = slit->getWindowID();
1418
1419 while (k--)
1420 *(session_stack + i++) = *(workspace_stack + k);
1421
1422 XRestackWindows(blackbox->getXDisplay(), session_stack, i);
1423
1424 delete [] session_stack;
1425
1426 updateStackingList();
1427 }
1428
1429
1430 void BScreen::lowerDesktops(void) {
1431 if (desktopWindowList.empty()) return;
1432
1433 XLowerWindow(blackbox->getXDisplay(), desktopWindowList[0]);
1434 if (desktopWindowList.size() > 1)
1435 XRestackWindows(blackbox->getXDisplay(), &desktopWindowList[0],
1436 desktopWindowList.size());
1437 }
1438
1439
1440 void BScreen::reassociateWindow(BlackboxWindow *w, unsigned int wkspc_id,
1441 bool ignore_sticky) {
1442 if (! w) return;
1443
1444 if (wkspc_id == BSENTINEL)
1445 wkspc_id = current_workspace->getID();
1446
1447 if (w->getWorkspaceNumber() == wkspc_id)
1448 return;
1449
1450 if (w->isIconic()) {
1451 removeIcon(w);
1452 getWorkspace(wkspc_id)->addWindow(w);
1453 } else if (ignore_sticky || ! w->isStuck()) {
1454 getWorkspace(w->getWorkspaceNumber())->removeWindow(w);
1455 getWorkspace(wkspc_id)->addWindow(w);
1456 }
1457 }
1458
1459
1460 void BScreen::propagateWindowName(const BlackboxWindow *bw) {
1461 if (bw->isIconic()) {
1462 iconmenu->changeItemLabel(bw->getWindowNumber(), bw->getIconTitle());
1463 iconmenu->update();
1464 }
1465 else {
1466 Clientmenu *clientmenu = getWorkspace(bw->getWorkspaceNumber())->getMenu();
1467 clientmenu->changeItemLabel(bw->getWindowNumber(), bw->getTitle());
1468 clientmenu->update();
1469
1470 if (blackbox->getFocusedWindow() == bw)
1471 toolbar->redrawWindowLabel(True);
1472 }
1473 }
1474
1475
1476 void BScreen::nextFocus(void) {
1477 BlackboxWindow *focused = blackbox->getFocusedWindow(),
1478 *next = focused;
1479
1480 if (focused) {
1481 // if window is not on this screen, ignore it
1482 if (focused->getScreen()->getScreenNumber() != getScreenNumber())
1483 focused = (BlackboxWindow*) 0;
1484 }
1485
1486 if (focused && current_workspace->getCount() > 1) {
1487 // next is the next window to recieve focus, current is a place holder
1488 BlackboxWindow *current;
1489 do {
1490 current = next;
1491 next = current_workspace->getNextWindowInList(current);
1492 } while(! next->setInputFocus() && next != focused);
1493
1494 if (next != focused)
1495 current_workspace->raiseWindow(next);
1496 } else if (current_workspace->getCount() >= 1) {
1497 next = current_workspace->getTopWindowOnStack();
1498
1499 current_workspace->raiseWindow(next);
1500 next->setInputFocus();
1501 }
1502 }
1503
1504
1505 void BScreen::prevFocus(void) {
1506 BlackboxWindow *focused = blackbox->getFocusedWindow(),
1507 *next = focused;
1508
1509 if (focused) {
1510 // if window is not on this screen, ignore it
1511 if (focused->getScreen()->getScreenNumber() != getScreenNumber())
1512 focused = (BlackboxWindow*) 0;
1513 }
1514
1515 if (focused && current_workspace->getCount() > 1) {
1516 // next is the next window to recieve focus, current is a place holder
1517 BlackboxWindow *current;
1518 do {
1519 current = next;
1520 next = current_workspace->getPrevWindowInList(current);
1521 } while(! next->setInputFocus() && next != focused);
1522
1523 if (next != focused)
1524 current_workspace->raiseWindow(next);
1525 } else if (current_workspace->getCount() >= 1) {
1526 next = current_workspace->getTopWindowOnStack();
1527
1528 current_workspace->raiseWindow(next);
1529 next->setInputFocus();
1530 }
1531 }
1532
1533
1534 void BScreen::raiseFocus(void) {
1535 BlackboxWindow *focused = blackbox->getFocusedWindow();
1536 if (! focused)
1537 return;
1538
1539 // if on this Screen, raise it
1540 if (focused->getScreen()->getScreenNumber() == getScreenNumber()) {
1541 Workspace *workspace = getWorkspace(focused->getWorkspaceNumber());
1542 workspace->raiseWindow(focused);
1543 }
1544 }
1545
1546
1547 void BScreen::InitMenu(void) {
1548 if (rootmenu) {
1549 rootmenuList.clear();
1550
1551 while (rootmenu->getCount())
1552 rootmenu->remove(0);
1553 } else {
1554 rootmenu = new Rootmenu(this);
1555 }
1556 bool defaultMenu = True;
1557
1558 FILE *menu_file = (FILE *) 0;
1559 const char *menu_filename = blackbox->getMenuFilename();
1560
1561 if (menu_filename)
1562 if (! (menu_file = fopen(menu_filename, "r")))
1563 perror(menu_filename);
1564 if (! menu_file) { // opening the menu file failed, try the default menu
1565 menu_filename = DEFAULTMENU;
1566 if (! (menu_file = fopen(menu_filename, "r")))
1567 perror(menu_filename);
1568 }
1569
1570 if (menu_file) {
1571 if (feof(menu_file)) {
1572 fprintf(stderr, i18n(ScreenSet, ScreenEmptyMenuFile,
1573 "%s: Empty menu file"),
1574 menu_filename);
1575 } else {
1576 char line[1024], label[1024];
1577 memset(line, 0, 1024);
1578 memset(label, 0, 1024);
1579
1580 while (fgets(line, 1024, menu_file) && ! feof(menu_file)) {
1581 if (line[0] != '#') {
1582 int i, key = 0, index = -1, len = strlen(line);
1583
1584 for (i = 0; i < len; i++) {
1585 if (line[i] == '[') index = 0;
1586 else if (line[i] == ']') break;
1587 else if (line[i] != ' ')
1588 if (index++ >= 0)
1589 key += tolower(line[i]);
1590 }
1591
1592 if (key == 517) { // [begin]
1593 index = -1;
1594 for (i = index; i < len; i++) {
1595 if (line[i] == '(') index = 0;
1596 else if (line[i] == ')') break;
1597 else if (index++ >= 0) {
1598 if (line[i] == '\\' && i < len - 1) i++;
1599 label[index - 1] = line[i];
1600 }
1601 }
1602
1603 if (index == -1) index = 0;
1604 label[index] = '\0';
1605
1606 rootmenu->setLabel(label);
1607 defaultMenu = parseMenuFile(menu_file, rootmenu);
1608 if (! defaultMenu)
1609 blackbox->addMenuTimestamp(menu_filename);
1610 break;
1611 }
1612 }
1613 }
1614 }
1615 fclose(menu_file);
1616 }
1617
1618 if (defaultMenu) {
1619 rootmenu->setInternalMenu();
1620 rootmenu->insert(i18n(ScreenSet, Screenxterm, "xterm"),
1621 BScreen::Execute,
1622 i18n(ScreenSet, Screenxterm, "xterm"));
1623 rootmenu->insert(i18n(ScreenSet, ScreenRestart, "Restart"),
1624 BScreen::Restart);
1625 rootmenu->insert(i18n(ScreenSet, ScreenExit, "Exit"),
1626 BScreen::Exit);
1627 rootmenu->setLabel(i18n(BasemenuSet, BasemenuBlackboxMenu,
1628 "Openbox Menu"));
1629 }
1630 }
1631
1632
1633 bool BScreen::parseMenuFile(FILE *file, Rootmenu *menu) {
1634 char line[1024], label[1024], command[1024];
1635
1636 while (! feof(file)) {
1637 memset(line, 0, 1024);
1638 memset(label, 0, 1024);
1639 memset(command, 0, 1024);
1640
1641 if (fgets(line, 1024, file)) {
1642 if (line[0] != '#') {
1643 int i, key = 0, parse = 0, index = -1, line_length = strlen(line);
1644
1645 // determine the keyword
1646 for (i = 0; i < line_length; i++) {
1647 if (line[i] == '[') parse = 1;
1648 else if (line[i] == ']') break;
1649 else if (line[i] != ' ')
1650 if (parse)
1651 key += tolower(line[i]);
1652 }
1653
1654 // get the label enclosed in ()'s
1655 parse = 0;
1656
1657 for (i = 0; i < line_length; i++) {
1658 if (line[i] == '(') {
1659 index = 0;
1660 parse = 1;
1661 } else if (line[i] == ')') break;
1662 else if (index++ >= 0) {
1663 if (line[i] == '\\' && i < line_length - 1) i++;
1664 label[index - 1] = line[i];
1665 }
1666 }
1667
1668 if (parse) {
1669 label[index] = '\0';
1670 } else {
1671 label[0] = '\0';
1672 }
1673
1674 // get the command enclosed in {}'s
1675 parse = 0;
1676 index = -1;
1677 for (i = 0; i < line_length; i++) {
1678 if (line[i] == '{') {
1679 index = 0;
1680 parse = 1;
1681 } else if (line[i] == '}') break;
1682 else if (index++ >= 0) {
1683 if (line[i] == '\\' && i < line_length - 1) i++;
1684 command[index - 1] = line[i];
1685 }
1686 }
1687
1688 if (parse) {
1689 command[index] = '\0';
1690 } else {
1691 command[0] = '\0';
1692 }
1693
1694 switch (key) {
1695 case 311: // end
1696 return ((menu->getCount() == 0) ? True : False);
1697
1698 break;
1699
1700 case 333: // nop
1701 if (! *label)
1702 label[0] = '\0';
1703 menu->insert(label);
1704
1705 break;
1706
1707 case 421: // exec
1708 if ((! *label) && (! *command)) {
1709 fprintf(stderr, i18n(ScreenSet, ScreenEXECError,
1710 "BScreen::parseMenuFile: [exec] error, "
1711 "no menu label and/or command defined\n"));
1712 continue;
1713 }
1714
1715 menu->insert(label, BScreen::Execute, command);
1716
1717 break;
1718
1719 case 442: // exit
1720 if (! *label) {
1721 fprintf(stderr, i18n(ScreenSet, ScreenEXITError,
1722 "BScreen::parseMenuFile: [exit] error, "
1723 "no menu label defined\n"));
1724 continue;
1725 }
1726
1727 menu->insert(label, BScreen::Exit);
1728
1729 break;
1730
1731 case 561: // style
1732 {
1733 if ((! *label) || (! *command)) {
1734 fprintf(stderr,
1735 i18n(ScreenSet, ScreenSTYLEError,
1736 "BScreen::parseMenuFile: [style] error, "
1737 "no menu label and/or filename defined\n"));
1738 continue;
1739 }
1740
1741 string style = expandTilde(command);
1742
1743 menu->insert(label, BScreen::SetStyle, style.c_str());
1744 }
1745
1746 break;
1747
1748 case 630: // config
1749 if (! *label) {
1750 fprintf(stderr, i18n(ScreenSet, ScreenCONFIGError,
1751 "BScreen::parseMenufile: [config] error, "
1752 "no label defined"));
1753 continue;
1754 }
1755
1756 menu->insert(label, configmenu);
1757
1758 break;
1759
1760 case 740: // include
1761 {
1762 if (! *label) {
1763 fprintf(stderr, i18n(ScreenSet, ScreenINCLUDEError,
1764 "BScreen::parseMenuFile: [include] error, "
1765 "no filename defined\n"));
1766 continue;
1767 }
1768
1769 string newfile = expandTilde(label);
1770 FILE *submenufile = fopen(newfile.c_str(), "r");
1771
1772 if (submenufile) {
1773 struct stat buf;
1774 if (fstat(fileno(submenufile), &buf) ||
1775 (! S_ISREG(buf.st_mode))) {
1776 fprintf(stderr,
1777 i18n(ScreenSet, ScreenINCLUDEErrorReg,
1778 "BScreen::parseMenuFile: [include] error: "
1779 "'%s' is not a regular file\n"), newfile.c_str());
1780 break;
1781 }
1782
1783 if (! feof(submenufile)) {
1784 if (! parseMenuFile(submenufile, menu))
1785 blackbox->addMenuTimestamp(newfile);
1786
1787 fclose(submenufile);
1788 }
1789 } else {
1790 perror(newfile.c_str());
1791 }
1792 }
1793
1794 break;
1795
1796 case 767: // submenu
1797 {
1798 if (! *label) {
1799 fprintf(stderr, i18n(ScreenSet, ScreenSUBMENUError,
1800 "BScreen::parseMenuFile: [submenu] error, "
1801 "no menu label defined\n"));
1802 continue;
1803 }
1804
1805 Rootmenu *submenu = new Rootmenu(this);
1806
1807 if (*command)
1808 submenu->setLabel(command);
1809 else
1810 submenu->setLabel(label);
1811
1812 parseMenuFile(file, submenu);
1813 submenu->update();
1814 menu->insert(label, submenu);
1815 rootmenuList.push_back(submenu);
1816 }
1817
1818 break;
1819
1820 case 773: // restart
1821 {
1822 if (! *label) {
1823 fprintf(stderr, i18n(ScreenSet, ScreenRESTARTError,
1824 "BScreen::parseMenuFile: [restart] error, "
1825 "no menu label defined\n"));
1826 continue;
1827 }
1828
1829 if (*command)
1830 menu->insert(label, BScreen::RestartOther, command);
1831 else
1832 menu->insert(label, BScreen::Restart);
1833 }
1834
1835 break;
1836
1837 case 845: // reconfig
1838 {
1839 if (! *label) {
1840 fprintf(stderr,
1841 i18n(ScreenSet, ScreenRECONFIGError,
1842 "BScreen::parseMenuFile: [reconfig] error, "
1843 "no menu label defined\n"));
1844 continue;
1845 }
1846
1847 menu->insert(label, BScreen::Reconfigure);
1848 }
1849
1850 break;
1851
1852 case 995: // stylesdir
1853 case 1113: // stylesmenu
1854 {
1855 bool newmenu = ((key == 1113) ? True : False);
1856
1857 if ((! *label) || ((! *command) && newmenu)) {
1858 fprintf(stderr,
1859 i18n(ScreenSet, ScreenSTYLESDIRError,
1860 "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
1861 " error, no directory defined\n"));
1862 continue;
1863 }
1864
1865 char *directory = ((newmenu) ? command : label);
1866
1867 string stylesdir = expandTilde(directory);
1868
1869 struct stat statbuf;
1870
1871 if (! stat(stylesdir.c_str(), &statbuf)) {
1872 if (S_ISDIR(statbuf.st_mode)) {
1873 Rootmenu *stylesmenu;
1874
1875 if (newmenu)
1876 stylesmenu = new Rootmenu(this);
1877 else
1878 stylesmenu = menu;
1879
1880 DIR *d = opendir(stylesdir.c_str());
1881 struct dirent *p;
1882 std::vector<string> ls;
1883
1884 while((p = readdir(d)))
1885 ls.push_back(p->d_name);
1886
1887 closedir(d);
1888
1889 std::sort(ls.begin(), ls.end());
1890
1891 std::vector<string>::iterator it = ls.begin(),
1892 end = ls.end();
1893 for (; it != end; ++it) {
1894 const string& fname = *it;
1895
1896 if (fname[fname.size()-1] == '~')
1897 continue;
1898
1899 string style = stylesdir;
1900 style += '/';
1901 style += fname;
1902
1903 if ((! stat(style.c_str(), &statbuf)) &&
1904 S_ISREG(statbuf.st_mode))
1905 stylesmenu->insert(fname, BScreen::SetStyle, style);
1906 }
1907
1908 stylesmenu->update();
1909
1910 if (newmenu) {
1911 stylesmenu->setLabel(label);
1912 menu->insert(label, stylesmenu);
1913 rootmenuList.push_back(stylesmenu);
1914 }
1915
1916 blackbox->addMenuTimestamp(stylesdir);
1917 } else {
1918 fprintf(stderr,
1919 i18n(ScreenSet, ScreenSTYLESDIRErrorNotDir,
1920 "BScreen::parseMenuFile:"
1921 " [stylesdir/stylesmenu] error, %s is not a"
1922 " directory\n"), stylesdir.c_str());
1923 }
1924 } else {
1925 fprintf(stderr,
1926 i18n(ScreenSet, ScreenSTYLESDIRErrorNoExist,
1927 "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
1928 " error, %s does not exist\n"), stylesdir.c_str());
1929 }
1930 break;
1931 }
1932
1933 case 1090: // workspaces
1934 {
1935 if (! *label) {
1936 fprintf(stderr,
1937 i18n(ScreenSet, ScreenWORKSPACESError,
1938 "BScreen:parseMenuFile: [workspaces] error, "
1939 "no menu label defined\n"));
1940 continue;
1941 }
1942
1943 menu->insert(label, workspacemenu);
1944
1945 break;
1946 }
1947 }
1948 }
1949 }
1950 }
1951
1952 return ((menu->getCount() == 0) ? True : False);
1953 }
1954
1955
1956 void BScreen::shutdown(void) {
1957 XSelectInput(blackbox->getXDisplay(), getRootWindow(), NoEventMask);
1958 XSync(blackbox->getXDisplay(), False);
1959
1960 while(! windowList.empty())
1961 unmanageWindow(windowList.front(), True);
1962
1963 slit->shutdown();
1964 }
1965
1966
1967 void BScreen::showPosition(int x, int y) {
1968 if (! geom_visible) {
1969 XMoveResizeWindow(blackbox->getXDisplay(), geom_window,
1970 (getWidth() - geom_w) / 2,
1971 (getHeight() - geom_h) / 2, geom_w, geom_h);
1972 XMapWindow(blackbox->getXDisplay(), geom_window);
1973 XRaiseWindow(blackbox->getXDisplay(), geom_window);
1974
1975 geom_visible = True;
1976 }
1977
1978 char label[1024];
1979
1980 sprintf(label, i18n(ScreenSet, ScreenPositionFormat,
1981 "X: %4d x Y: %4d"), x, y);
1982
1983 XClearWindow(blackbox->getXDisplay(), geom_window);
1984
1985 BPen pen(resource.wstyle.l_text_focus, resource.wstyle.font);
1986 if (i18n.multibyte()) {
1987 XmbDrawString(blackbox->getXDisplay(), geom_window,
1988 resource.wstyle.fontset, pen.gc(),
1989 resource.bevel_width, resource.bevel_width -
1990 resource.wstyle.fontset_extents->max_ink_extent.y,
1991 label, strlen(label));
1992 } else {
1993 XDrawString(blackbox->getXDisplay(), geom_window,
1994 pen.gc(), resource.bevel_width,
1995 resource.wstyle.font->ascent + resource.bevel_width,
1996 label, strlen(label));
1997 }
1998 }
1999
2000
2001 void BScreen::showGeometry(unsigned int gx, unsigned int gy) {
2002 if (! geom_visible) {
2003 XMoveResizeWindow(blackbox->getXDisplay(), geom_window,
2004 (getWidth() - geom_w) / 2,
2005 (getHeight() - geom_h) / 2, geom_w, geom_h);
2006 XMapWindow(blackbox->getXDisplay(), geom_window);
2007 XRaiseWindow(blackbox->getXDisplay(), geom_window);
2008
2009 geom_visible = True;
2010 }
2011
2012 char label[1024];
2013
2014 sprintf(label, i18n(ScreenSet, ScreenGeometryFormat,
2015 "W: %4d x H: %4d"), gx, gy);
2016
2017 XClearWindow(blackbox->getXDisplay(), geom_window);
2018
2019 BPen pen(resource.wstyle.l_text_focus, resource.wstyle.font);
2020 if (i18n.multibyte()) {
2021 XmbDrawString(blackbox->getXDisplay(), geom_window,
2022 resource.wstyle.fontset, pen.gc(),
2023 resource.bevel_width, resource.bevel_width -
2024 resource.wstyle.fontset_extents->max_ink_extent.y,
2025 label, strlen(label));
2026 } else {
2027 XDrawString(blackbox->getXDisplay(), geom_window,
2028 pen.gc(), resource.bevel_width,
2029 resource.wstyle.font->ascent +
2030 resource.bevel_width, label, strlen(label));
2031 }
2032 }
2033
2034
2035 void BScreen::hideGeometry(void) {
2036 if (geom_visible) {
2037 XUnmapWindow(blackbox->getXDisplay(), geom_window);
2038 geom_visible = False;
2039 }
2040 }
2041
2042
2043 void BScreen::addStrut(Strut *strut) {
2044 strutList.push_back(strut);
2045 }
2046
2047
2048 void BScreen::removeStrut(Strut *strut) {
2049 strutList.remove(strut);
2050 }
2051
2052
2053 const Rect& BScreen::availableArea(void) const {
2054 if (doFullMax())
2055 return getRect(); // return the full screen
2056 return usableArea;
2057 }
2058
2059
2060 void BScreen::updateAvailableArea(void) {
2061 Rect old_area = usableArea;
2062 usableArea = getRect(); // reset to full screen
2063
2064 /* these values represent offsets from the screen edge
2065 * we look for the biggest offset on each edge and then apply them
2066 * all at once
2067 * do not be confused by the similarity to the names of Rect's members
2068 */
2069 unsigned int current_left = 0, current_right = 0, current_top = 0,
2070 current_bottom = 0;
2071
2072 StrutList::const_iterator it = strutList.begin(), end = strutList.end();
2073
2074 for(; it != end; ++it) {
2075 Strut *strut = *it;
2076 if (strut->left > current_left)
2077 current_left = strut->left;
2078 if (strut->top > current_top)
2079 current_top = strut->top;
2080 if (strut->right > current_right)
2081 current_right = strut->right;
2082 if (strut->bottom > current_bottom)
2083 current_bottom = strut->bottom;
2084 }
2085
2086 usableArea.setPos(current_left, current_top);
2087 usableArea.setSize(usableArea.width() - (current_left + current_right),
2088 usableArea.height() - (current_top + current_bottom));
2089
2090 if (old_area != usableArea) {
2091 BlackboxWindowList::iterator it = windowList.begin(),
2092 end = windowList.end();
2093 for (; it != end; ++it)
2094 if ((*it)->isMaximized()) (*it)->remaximize();
2095 }
2096
2097 updateWorkArea();
2098 }
2099
2100
2101 Workspace* BScreen::getWorkspace(unsigned int index) {
2102 assert(index < workspacesList.size());
2103 return workspacesList[index];
2104 }
2105
2106
2107 void BScreen::buttonPressEvent(XButtonEvent *xbutton) {
2108 if (xbutton->button == 1) {
2109 if (! isRootColormapInstalled())
2110 image_control->installRootColormap();
2111
2112 if (workspacemenu->isVisible())
2113 workspacemenu->hide();
2114
2115 if (rootmenu->isVisible())
2116 rootmenu->hide();
2117 } else if (xbutton->button == 2) {
2118 int mx = xbutton->x_root - (workspacemenu->getWidth() / 2);
2119 int my = xbutton->y_root - (workspacemenu->getTitleHeight() / 2);
2120
2121 if (mx < 0) mx = 0;
2122 if (my < 0) my = 0;
2123
2124 if (mx + workspacemenu->getWidth() > getWidth())
2125 mx = getWidth() - workspacemenu->getWidth() - getBorderWidth();
2126
2127 if (my + workspacemenu->getHeight() > getHeight())
2128 my = getHeight() - workspacemenu->getHeight() - getBorderWidth();
2129
2130 workspacemenu->move(mx, my);
2131
2132 if (! workspacemenu->isVisible()) {
2133 workspacemenu->removeParent();
2134 workspacemenu->show();
2135 }
2136 } else if (xbutton->button == 3) {
2137 int mx = xbutton->x_root - (rootmenu->getWidth() / 2);
2138 int my = xbutton->y_root - (rootmenu->getTitleHeight() / 2);
2139
2140 if (mx < 0) mx = 0;
2141 if (my < 0) my = 0;
2142
2143 if (mx + rootmenu->getWidth() > getWidth())
2144 mx = getWidth() - rootmenu->getWidth() - getBorderWidth();
2145
2146 if (my + rootmenu->getHeight() > getHeight())
2147 my = getHeight() - rootmenu->getHeight() - getBorderWidth();
2148
2149 rootmenu->move(mx, my);
2150
2151 if (! rootmenu->isVisible()) {
2152 blackbox->checkMenu();
2153 rootmenu->show();
2154 }
2155 // mouse wheel up
2156 } else if (xbutton->button == 4) {
2157 if (getCurrentWorkspaceID() >= getWorkspaceCount() - 1)
2158 changeWorkspaceID(0);
2159 else
2160 changeWorkspaceID(getCurrentWorkspaceID() + 1);
2161 // mouse wheel down
2162 } else if (xbutton->button == 5) {
2163 if (getCurrentWorkspaceID() == 0)
2164 changeWorkspaceID(getWorkspaceCount() - 1);
2165 else
2166 changeWorkspaceID(getCurrentWorkspaceID() - 1);
2167 }
2168 }
2169
2170
2171 void BScreen::toggleFocusModel(FocusModel model) {
2172 if (model == SloppyFocus) {
2173 saveSloppyFocus(True);
2174 } else {
2175 // we're cheating here to save writing the config file 3 times
2176 resource.auto_raise = False;
2177 resource.click_raise = False;
2178 saveSloppyFocus(False);
2179 }
2180
2181 updateFocusModel();
2182 }
2183
2184
2185 void BScreen::updateFocusModel()
2186 {
2187 std::for_each(iconList.begin(), iconList.end(),
2188 std::mem_fun(&BlackboxWindow::ungrabButtons));
2189 std::for_each(windowList.begin(), windowList.end(),
2190 std::mem_fun(&BlackboxWindow::ungrabButtons));
2191
2192 if (! resource.sloppy_focus) {
2193 blackbox->getInput()->add(Button1, 0, BInput::WindowClientPress,
2194 BInput::Raise);
2195 blackbox->getInput()->add(Button1, 0, BInput::WindowClientPress,
2196 BInput::Focus);
2197 } else {
2198 if (resource.click_raise)
2199 blackbox->getInput()->add(Button1, 0, BInput::WindowClientPress,
2200 BInput::Raise);
2201 else
2202 blackbox->getInput()->remove(Button1, 0, BInput::WindowClientPress,
2203 BInput::Raise);
2204 blackbox->getInput()->remove(Button1, 0, BInput::WindowClientPress,
2205 BInput::Focus);
2206 }
2207
2208 std::for_each(iconList.begin(), iconList.end(),
2209 std::mem_fun(&BlackboxWindow::grabButtons));
2210 std::for_each(windowList.begin(), windowList.end(),
2211 std::mem_fun(&BlackboxWindow::grabButtons));
2212 }
2213
2214
2215 BTexture BScreen::readDatabaseTexture(const string &rname,
2216 const string &default_color,
2217 Configuration &style) {
2218 BTexture texture;
2219 string s;
2220
2221 if (style.getValue(rname, s))
2222 texture = BTexture(s);
2223 else
2224 texture.setTexture(BTexture::Solid | BTexture::Flat);
2225
2226 // associate this texture with this screen
2227 texture.setDisplay(getBaseDisplay(), getScreenNumber());
2228 texture.setImageControl(image_control);
2229
2230 if (texture.texture() & BTexture::Solid) {
2231 texture.setColor(readDatabaseColor(rname + ".color",
2232 default_color, style));
2233 texture.setColorTo(readDatabaseColor(rname + ".colorTo",
2234 default_color, style));
2235 } else if (texture.texture() & BTexture::Gradient) {
2236 texture.setColor(readDatabaseColor(rname + ".color",
2237 default_color, style));
2238 texture.setColorTo(readDatabaseColor(rname + ".colorTo",
2239 default_color, style));
2240 }
2241
2242 return texture;
2243 }
2244
2245
2246 BColor BScreen::readDatabaseColor(const string &rname,
2247 const string &default_color,
2248 Configuration &style) {
2249 BColor color;
2250 string s;
2251 if (style.getValue(rname, s))
2252 color = BColor(s, getBaseDisplay(), getScreenNumber());
2253 else
2254 color = BColor(default_color, getBaseDisplay(), getScreenNumber());
2255 return color;
2256 }
2257
2258
2259 XFontSet BScreen::readDatabaseFontSet(const string &rname,
2260 Configuration &style) {
2261 char *defaultFont = "fixed";
2262
2263 bool load_default = True;
2264 string s;
2265 XFontSet fontset = 0;
2266 if (style.getValue(rname, s) && (fontset = createFontSet(s)))
2267 load_default = False;
2268
2269 if (load_default) {
2270 fontset = createFontSet(defaultFont);
2271
2272 if (! fontset) {
2273 fprintf(stderr,
2274 i18n(ScreenSet, ScreenDefaultFontLoadFail,
2275 "BScreen::setCurrentStyle(): couldn't load default font.\n"));
2276 exit(2);
2277 }
2278 }
2279
2280 return fontset;
2281 }
2282
2283
2284 XFontStruct *BScreen::readDatabaseFont(const string &rname,
2285 Configuration &style) {
2286 char *defaultFont = "fixed";
2287
2288 bool load_default = False;
2289 string s;
2290 XFontStruct *font = 0;
2291 if (style.getValue(rname, s)) {
2292 if ((font = XLoadQueryFont(blackbox->getXDisplay(), s.c_str())) == NULL) {
2293 fprintf(stderr,
2294 i18n(ScreenSet, ScreenFontLoadFail,
2295 "BScreen::setCurrentStyle(): couldn't load font '%s'\n"),
2296 s.c_str());
2297
2298 load_default = True;
2299 }
2300 } else {
2301 load_default = True;
2302 }
2303
2304 if (load_default) {
2305 font = XLoadQueryFont(blackbox->getXDisplay(), defaultFont);
2306 if (font == NULL) {
2307 fprintf(stderr,
2308 i18n(ScreenSet, ScreenDefaultFontLoadFail,
2309 "BScreen::setCurrentStyle(): couldn't load default font.\n"));
2310 exit(2);
2311 }
2312 }
2313
2314 return font;
2315 }
2316
2317
2318 #ifndef HAVE_STRCASESTR
2319 static const char * strcasestr(const char *str, const char *ptn) {
2320 const char *s2, *p2;
2321 for(; *str; str++) {
2322 for(s2=str,p2=ptn; ; s2++,p2++) {
2323 if (! *p2) return str;
2324 if (toupper(*s2) != toupper(*p2)) break;
2325 }
2326 }
2327 return NULL;
2328 }
2329 #endif // HAVE_STRCASESTR
2330
2331
2332 static const char *getFontElement(const char *pattern, char *buf,
2333 int bufsiz, ...) {
2334 const char *p, *v;
2335 char *p2;
2336 va_list va;
2337
2338 va_start(va, bufsiz);
2339 buf[bufsiz-1] = 0;
2340 buf[bufsiz-2] = '*';
2341 while((v = va_arg(va, char *)) != NULL) {
2342 p = strcasestr(pattern, v);
2343 if (p) {
2344 strncpy(buf, p+1, bufsiz-2);
2345 p2 = strchr(buf, '-');
2346 if (p2) *p2=0;
2347 va_end(va);
2348 return p;
2349 }
2350 }
2351 va_end(va);
2352 strncpy(buf, "*", bufsiz);
2353 return NULL;
2354 }
2355
2356
2357 static const char *getFontSize(const char *pattern, int *size) {
2358 const char *p;
2359 const char *p2=NULL;
2360 int n=0;
2361
2362 for (p=pattern; 1; p++) {
2363 if (! *p) {
2364 if (p2!=NULL && n>1 && n<72) {
2365 *size = n; return p2+1;
2366 } else {
2367 *size = 16; return NULL;
2368 }
2369 } else if (*p=='-') {
2370 if (n>1 && n<72 && p2!=NULL) {
2371 *size = n;
2372 return p2+1;
2373 }
2374 p2=p; n=0;
2375 } else if (*p>='0' && *p<='9' && p2!=NULL) {
2376 n *= 10;
2377 n += *p-'0';
2378 } else {
2379 p2=NULL; n=0;
2380 }
2381 }
2382 }
2383
2384
2385 XFontSet BScreen::createFontSet(const string &fontname) {
2386 XFontSet fs;
2387 char **missing, *def = "-";
2388 int nmissing, pixel_size = 0, buf_size = 0;
2389 char weight[FONT_ELEMENT_SIZE], slant[FONT_ELEMENT_SIZE];
2390
2391 fs = XCreateFontSet(blackbox->getXDisplay(),
2392 fontname.c_str(), &missing, &nmissing, &def);
2393 if (fs && (! nmissing))
2394 return fs;
2395
2396 const char *nfontname = fontname.c_str();
2397 #ifdef HAVE_SETLOCALE
2398 if (! fs) {
2399 if (nmissing) XFreeStringList(missing);
2400
2401 setlocale(LC_CTYPE, "C");
2402 fs = XCreateFontSet(blackbox->getXDisplay(), fontname.c_str(),
2403 &missing, &nmissing, &def);
2404 setlocale(LC_CTYPE, "");
2405 }
2406 #endif // HAVE_SETLOCALE
2407
2408 if (fs) {
2409 XFontStruct **fontstructs;
2410 char **fontnames;
2411 XFontsOfFontSet(fs, &fontstructs, &fontnames);
2412 nfontname = fontnames[0];
2413 }
2414
2415 getFontElement(nfontname, weight, FONT_ELEMENT_SIZE,
2416 "-medium-", "-bold-", "-demibold-", "-regular-", NULL);
2417 getFontElement(nfontname, slant, FONT_ELEMENT_SIZE,
2418 "-r-", "-i-", "-o-", "-ri-", "-ro-", NULL);
2419 getFontSize(nfontname, &pixel_size);
2420
2421 if (! strcmp(weight, "*"))
2422 strncpy(weight, "medium", FONT_ELEMENT_SIZE);
2423 if (! strcmp(slant, "*"))
2424 strncpy(slant, "r", FONT_ELEMENT_SIZE);
2425 if (pixel_size < 3)
2426 pixel_size = 3;
2427 else if (pixel_size > 97)
2428 pixel_size = 97;
2429
2430 buf_size = strlen(nfontname) + (FONT_ELEMENT_SIZE * 2) + 64;
2431 char *pattern2 = new char[buf_size];
2432 sprintf(pattern2,
2433 "%s,"
2434 "-*-*-%s-%s-*-*-%d-*-*-*-*-*-*-*,"
2435 "-*-*-*-*-*-*-%d-*-*-*-*-*-*-*,*",
2436 nfontname, weight, slant, pixel_size, pixel_size);
2437 nfontname = pattern2;
2438
2439 if (nmissing)
2440 XFreeStringList(missing);
2441 if (fs)
2442 XFreeFontSet(blackbox->getXDisplay(), fs);
2443
2444 fs = XCreateFontSet(blackbox->getXDisplay(), nfontname, &missing,
2445 &nmissing, &def);
2446
2447 delete [] pattern2;
2448
2449 return fs;
2450 }
This page took 0.139163 seconds and 5 git commands to generate.