1 // Screen.cc for Openbox
2 // Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
3 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
5 // Permission is hereby granted, free of charge, to any person obtaining a
6 // copy of this software and associated documentation files (the "Software"),
7 // to deal in the Software without restriction, including without limitation
8 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 // and/or sell copies of the Software, and to permit persons to whom the
10 // Software is furnished to do so, subject to the following conditions:
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 // DEALINGS IN THE SOFTWARE.
23 // stupid macros needed to access some functions in version 2 of the GNU C
30 # include "../config.h"
31 #endif // HAVE_CONFIG_H
33 #include <X11/Xatom.h>
34 #include <X11/keysym.h>
38 #include "Clientmenu.h"
50 #include "Workspace.h"
51 #include "Workspacemenu.h"
56 # include <sys/types.h>
57 #endif // STDC_HEADERS
61 #endif // HAVE_CTYPE_H
65 #endif // HAVE_DIRENT_H
69 #endif // HAVE_LOCALE_H
72 # include <sys/types.h>
74 #endif // HAVE_UNISTD_H
76 #ifdef HAVE_SYS_STAT_H
77 # include <sys/stat.h>
78 #endif // HAVE_SYS_STAT_H
82 #endif // HAVE_STDARG_H
85 # include "bsd-snprintf.h"
86 #endif // !HAVE_SNPRINTF
89 #define MAXPATHLEN 255
92 #ifndef FONT_ELEMENT_SIZE
93 #define FONT_ELEMENT_SIZE 50
94 #endif // FONT_ELEMENT_SIZE
99 static Bool running = True;
101 static int anotherWMRunning(Display *display, XErrorEvent *) {
102 fprintf(stderr, i18n->getMessage(ScreenSet, ScreenAnotherWMRunning,
103 "BScreen::BScreen: an error occured while querying the X server.\n"
104 " another window manager already running on display %s.\n"),
105 DisplayString(display));
113 bool operator()(const char *one, const char *two) const {
114 return (strcmp(one, two) < 0) ? True : False;
118 #ifndef HAVE_STRCASESTR
119 static const char * strcasestr(const char *str, const char *ptn) {
121 for( ; *str; str++) {
122 for(s2=str,p2=ptn; ; s2++,p2++) {
123 if (!*p2) return str;
124 if (toupper(*s2) != toupper(*p2)) break;
129 #endif // HAVE_STRCASESTR
131 static const char *getFontElement(const char *pattern, char *buf, int bufsiz, ...) {
136 va_start(va, bufsiz);
139 while((v = va_arg(va, char *)) != NULL) {
140 p = strcasestr(pattern, v);
142 strncpy(buf, p+1, bufsiz-2);
143 p2 = strchr(buf, '-');
150 strncpy(buf, "*", bufsiz);
154 static const char *getFontSize(const char *pattern, int *size) {
159 for (p=pattern; 1; p++) {
161 if (p2!=NULL && n>1 && n<72) {
162 *size = n; return p2+1;
164 *size = 16; return NULL;
166 } else if (*p=='-') {
167 if (n>1 && n<72 && p2!=NULL) {
172 } else if (*p>='0' && *p<='9' && p2!=NULL) {
182 BScreen::BScreen(Openbox &ob, int scrn) : ScreenInfo(ob, scrn), openbox(ob) {
183 event_mask = ColormapChangeMask | EnterWindowMask | PropertyChangeMask |
184 SubstructureRedirectMask | KeyPressMask | KeyReleaseMask |
185 ButtonPressMask | ButtonReleaseMask;
187 XErrorHandler old = XSetErrorHandler((XErrorHandler) anotherWMRunning);
188 XSelectInput(getBaseDisplay().getXDisplay(), getRootWindow(), event_mask);
189 XSync(getBaseDisplay().getXDisplay(), False);
190 XSetErrorHandler((XErrorHandler) old);
193 if (! managed) return;
195 fprintf(stderr, i18n->getMessage(ScreenSet, ScreenManagingScreen,
196 "BScreen::BScreen: managing screen %d "
197 "using visual 0x%lx, depth %d\n"),
198 getScreenNumber(), XVisualIDFromVisual(getVisual()),
203 resource.mstyle.t_fontset = resource.mstyle.f_fontset =
204 resource.tstyle.fontset = resource.wstyle.fontset = (XFontSet) 0;
205 resource.mstyle.t_font = resource.mstyle.f_font = resource.tstyle.font =
206 resource.wstyle.font = (XFontStruct *) 0;
207 resource.root_command = NULL;
210 resource.strftime_format = 0;
211 #endif // HAVE_STRFTIME
214 pid_t bpid = getpid();
216 XChangeProperty(getBaseDisplay().getXDisplay(), getRootWindow(),
217 openbox.getOpenboxPidAtom(), XA_CARDINAL,
218 sizeof(pid_t) * 8, PropModeReplace,
219 (unsigned char *) &bpid, 1);
220 #endif // HAVE_GETPID
222 XDefineCursor(getBaseDisplay().getXDisplay(), getRootWindow(),
223 openbox.getSessionCursor());
225 workspaceNames = new LinkedList<char>;
226 workspacesList = new LinkedList<Workspace>;
227 rootmenuList = new LinkedList<Rootmenu>;
228 netizenList = new LinkedList<Netizen>;
229 iconList = new LinkedList<OpenboxWindow>;
232 new BImageControl(openbox, *this, True, openbox.getColorsPerChannel(),
233 openbox.getCacheLife(), openbox.getCacheMax());
234 image_control->installRootColormap();
235 root_colormap_installed = True;
237 openbox.load_rc(this);
239 image_control->setDither(resource.image_dither);
244 unsigned long gc_value_mask = GCForeground;
245 if (! i18n->multibyte()) gc_value_mask |= GCFont;
247 gcv.foreground = WhitePixel(getBaseDisplay().getXDisplay(),
249 ^ BlackPixel(getBaseDisplay().getXDisplay(),
251 gcv.function = GXxor;
252 gcv.subwindow_mode = IncludeInferiors;
253 opGC = XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
254 GCForeground | GCFunction | GCSubwindowMode, &gcv);
256 gcv.foreground = resource.wstyle.l_text_focus.getPixel();
257 if (resource.wstyle.font)
258 gcv.font = resource.wstyle.font->fid;
259 resource.wstyle.l_text_focus_gc =
260 XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
261 gc_value_mask, &gcv);
263 gcv.foreground = resource.wstyle.l_text_unfocus.getPixel();
264 if (resource.wstyle.font)
265 gcv.font = resource.wstyle.font->fid;
266 resource.wstyle.l_text_unfocus_gc =
267 XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
268 gc_value_mask, &gcv);
270 gcv.foreground = resource.wstyle.b_pic_focus.getPixel();
271 resource.wstyle.b_pic_focus_gc =
272 XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
275 gcv.foreground = resource.wstyle.b_pic_unfocus.getPixel();
276 resource.wstyle.b_pic_unfocus_gc =
277 XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
280 gcv.foreground = resource.mstyle.t_text.getPixel();
281 if (resource.mstyle.t_font)
282 gcv.font = resource.mstyle.t_font->fid;
283 resource.mstyle.t_text_gc =
284 XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
285 gc_value_mask, &gcv);
287 gcv.foreground = resource.mstyle.f_text.getPixel();
288 if (resource.mstyle.f_font)
289 gcv.font = resource.mstyle.f_font->fid;
290 resource.mstyle.f_text_gc =
291 XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
292 gc_value_mask, &gcv);
294 gcv.foreground = resource.mstyle.h_text.getPixel();
295 resource.mstyle.h_text_gc =
296 XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
297 gc_value_mask, &gcv);
299 gcv.foreground = resource.mstyle.d_text.getPixel();
300 resource.mstyle.d_text_gc =
301 XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
302 gc_value_mask, &gcv);
304 gcv.foreground = resource.mstyle.hilite.getColor()->getPixel();
305 resource.mstyle.hilite_gc =
306 XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
307 gc_value_mask, &gcv);
309 gcv.foreground = resource.tstyle.l_text.getPixel();
310 if (resource.tstyle.font)
311 gcv.font = resource.tstyle.font->fid;
312 resource.tstyle.l_text_gc =
313 XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
314 gc_value_mask, &gcv);
316 gcv.foreground = resource.tstyle.w_text.getPixel();
317 resource.tstyle.w_text_gc =
318 XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
319 gc_value_mask, &gcv);
321 gcv.foreground = resource.tstyle.c_text.getPixel();
322 resource.tstyle.c_text_gc =
323 XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
324 gc_value_mask, &gcv);
326 gcv.foreground = resource.tstyle.b_pic.getPixel();
327 resource.tstyle.b_pic_gc =
328 XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
329 gc_value_mask, &gcv);
331 const char *s = i18n->getMessage(ScreenSet, ScreenPositionLength,
332 "0: 0000 x 0: 0000");
335 if (i18n->multibyte()) {
336 XRectangle ink, logical;
337 XmbTextExtents(resource.wstyle.fontset, s, l, &ink, &logical);
338 geom_w = logical.width;
340 geom_h = resource.wstyle.fontset_extents->max_ink_extent.height;
342 geom_h = resource.wstyle.font->ascent +
343 resource.wstyle.font->descent;
345 geom_w = XTextWidth(resource.wstyle.font, s, l);
348 geom_w += (resource.bevel_width * 2);
349 geom_h += (resource.bevel_width * 2);
351 XSetWindowAttributes attrib;
352 unsigned long mask = CWBorderPixel | CWColormap | CWSaveUnder;
353 attrib.border_pixel = getBorderColor()->getPixel();
354 attrib.colormap = getColormap();
355 attrib.save_under = True;
358 XCreateWindow(getBaseDisplay().getXDisplay(), getRootWindow(),
359 0, 0, geom_w, geom_h, resource.border_width, getDepth(),
360 InputOutput, getVisual(), mask, &attrib);
361 geom_visible = False;
363 if (resource.wstyle.l_focus.getTexture() & BImage_ParentRelative) {
364 if (resource.wstyle.t_focus.getTexture() ==
365 (BImage_Flat | BImage_Solid)) {
367 XSetWindowBackground(getBaseDisplay().getXDisplay(), geom_window,
368 resource.wstyle.t_focus.getColor()->getPixel());
370 geom_pixmap = image_control->renderImage(geom_w, geom_h,
371 &resource.wstyle.t_focus);
372 XSetWindowBackgroundPixmap(getBaseDisplay().getXDisplay(),
373 geom_window, geom_pixmap);
376 if (resource.wstyle.l_focus.getTexture() ==
377 (BImage_Flat | BImage_Solid)) {
379 XSetWindowBackground(getBaseDisplay().getXDisplay(), geom_window,
380 resource.wstyle.l_focus.getColor()->getPixel());
382 geom_pixmap = image_control->renderImage(geom_w, geom_h,
383 &resource.wstyle.l_focus);
384 XSetWindowBackgroundPixmap(getBaseDisplay().getXDisplay(),
385 geom_window, geom_pixmap);
389 workspacemenu = new Workspacemenu(*this);
390 iconmenu = new Iconmenu(*this);
391 configmenu = new Configmenu(*this);
393 Workspace *wkspc = (Workspace *) 0;
394 if (resource.workspaces != 0) {
395 for (int i = 0; i < resource.workspaces; ++i) {
396 wkspc = new Workspace(*this, workspacesList->count());
397 workspacesList->insert(wkspc);
398 workspacemenu->insert(wkspc->getName(), wkspc->getMenu());
401 wkspc = new Workspace(*this, workspacesList->count());
402 workspacesList->insert(wkspc);
403 workspacemenu->insert(wkspc->getName(), wkspc->getMenu());
406 workspacemenu->insert(i18n->getMessage(IconSet, IconIcons, "Icons"),
408 workspacemenu->update();
410 current_workspace = workspacesList->first();
411 workspacemenu->setItemSelected(2, True);
413 toolbar = new Toolbar(*this);
416 slit = new Slit(*this);
424 changeWorkspaceID(0);
428 Window r, p, *children;
429 XQueryTree(getBaseDisplay().getXDisplay(), getRootWindow(), &r, &p,
432 // preen the window list of all icon windows... for better dockapp support
433 for (i = 0; i < (int) nchild; i++) {
434 if (children[i] == None) continue;
436 XWMHints *wmhints = XGetWMHints(getBaseDisplay().getXDisplay(),
440 if ((wmhints->flags & IconWindowHint) &&
441 (wmhints->icon_window != children[i]))
442 for (int j = 0; j < (int) nchild; j++)
443 if (children[j] == wmhints->icon_window) {
453 // manage shown windows
454 for (i = 0; i < (int) nchild; ++i) {
455 if (children[i] == None || (! openbox.validateWindow(children[i])))
458 XWindowAttributes attrib;
459 if (XGetWindowAttributes(getBaseDisplay().getXDisplay(), children[i],
461 if (attrib.override_redirect) continue;
463 if (attrib.map_state != IsUnmapped) {
464 new OpenboxWindow(openbox, children[i], this);
466 OpenboxWindow *win = openbox.searchWindow(children[i]);
468 XMapRequestEvent mre;
469 mre.window = children[i];
470 win->restoreAttributes();
471 win->mapRequestEvent(&mre);
477 if (! resource.sloppy_focus)
478 XSetInputFocus(getBaseDisplay().getXDisplay(), toolbar->getWindowID(),
479 RevertToParent, CurrentTime);
482 XFlush(getBaseDisplay().getXDisplay());
486 BScreen::~BScreen(void) {
487 if (! managed) return;
489 if (geom_pixmap != None)
490 image_control->removeImage(geom_pixmap);
492 if (geom_window != None)
493 XDestroyWindow(getBaseDisplay().getXDisplay(), geom_window);
495 removeWorkspaceNames();
497 while (workspacesList->count())
498 delete workspacesList->remove(0);
500 while (rootmenuList->count())
501 rootmenuList->remove(0);
503 while (iconList->count())
504 delete iconList->remove(0);
506 while (netizenList->count())
507 delete netizenList->remove(0);
510 if (resource.strftime_format)
511 delete [] resource.strftime_format;
512 #endif // HAVE_STRFTIME
515 delete workspacemenu;
524 delete image_control;
526 delete workspacesList;
527 delete workspaceNames;
532 if (resource.wstyle.fontset)
533 XFreeFontSet(getBaseDisplay().getXDisplay(), resource.wstyle.fontset);
534 if (resource.mstyle.t_fontset)
535 XFreeFontSet(getBaseDisplay().getXDisplay(), resource.mstyle.t_fontset);
536 if (resource.mstyle.f_fontset)
537 XFreeFontSet(getBaseDisplay().getXDisplay(), resource.mstyle.f_fontset);
538 if (resource.tstyle.fontset)
539 XFreeFontSet(getBaseDisplay().getXDisplay(), resource.tstyle.fontset);
541 if (resource.wstyle.font)
542 XFreeFont(getBaseDisplay().getXDisplay(), resource.wstyle.font);
543 if (resource.mstyle.t_font)
544 XFreeFont(getBaseDisplay().getXDisplay(), resource.mstyle.t_font);
545 if (resource.mstyle.f_font)
546 XFreeFont(getBaseDisplay().getXDisplay(), resource.mstyle.f_font);
547 if (resource.tstyle.font)
548 XFreeFont(getBaseDisplay().getXDisplay(), resource.tstyle.font);
549 if (resource.root_command != NULL)
550 delete [] resource.root_command;
552 XFreeGC(getBaseDisplay().getXDisplay(), opGC);
554 XFreeGC(getBaseDisplay().getXDisplay(),
555 resource.wstyle.l_text_focus_gc);
556 XFreeGC(getBaseDisplay().getXDisplay(),
557 resource.wstyle.l_text_unfocus_gc);
558 XFreeGC(getBaseDisplay().getXDisplay(),
559 resource.wstyle.b_pic_focus_gc);
560 XFreeGC(getBaseDisplay().getXDisplay(),
561 resource.wstyle.b_pic_unfocus_gc);
563 XFreeGC(getBaseDisplay().getXDisplay(),
564 resource.mstyle.t_text_gc);
565 XFreeGC(getBaseDisplay().getXDisplay(),
566 resource.mstyle.f_text_gc);
567 XFreeGC(getBaseDisplay().getXDisplay(),
568 resource.mstyle.h_text_gc);
569 XFreeGC(getBaseDisplay().getXDisplay(),
570 resource.mstyle.d_text_gc);
571 XFreeGC(getBaseDisplay().getXDisplay(),
572 resource.mstyle.hilite_gc);
574 XFreeGC(getBaseDisplay().getXDisplay(),
575 resource.tstyle.l_text_gc);
576 XFreeGC(getBaseDisplay().getXDisplay(),
577 resource.tstyle.w_text_gc);
578 XFreeGC(getBaseDisplay().getXDisplay(),
579 resource.tstyle.c_text_gc);
580 XFreeGC(getBaseDisplay().getXDisplay(),
581 resource.tstyle.b_pic_gc);
584 void BScreen::readDatabaseTexture(const char *rname, const char *rclass,
586 unsigned long default_pixel)
590 if (resource.styleconfig.getValue(rname, rclass, s))
591 image_control->parseTexture(texture, s.c_str());
593 texture->setTexture(BImage_Solid | BImage_Flat);
595 if (texture->getTexture() & BImage_Solid) {
596 int clen = strlen(rclass) + 32, nlen = strlen(rname) + 32;
598 char *colorclass = new char[clen], *colorname = new char[nlen];
600 sprintf(colorclass, "%s.Color", rclass);
601 sprintf(colorname, "%s.color", rname);
603 readDatabaseColor(colorname, colorclass, texture->getColor(),
607 sprintf(colorclass, "%s.ColorTo", rclass);
608 sprintf(colorname, "%s.colorTo", rname);
610 readDatabaseColor(colorname, colorclass, texture->getColorTo(),
614 delete [] colorclass;
617 if ((! texture->getColor()->isAllocated()) ||
618 (texture->getTexture() & BImage_Flat))
623 xcol.red = (unsigned int) (texture->getColor()->getRed() +
624 (texture->getColor()->getRed() >> 1));
625 if (xcol.red >= 0xff) xcol.red = 0xffff;
626 else xcol.red *= 0xff;
627 xcol.green = (unsigned int) (texture->getColor()->getGreen() +
628 (texture->getColor()->getGreen() >> 1));
629 if (xcol.green >= 0xff) xcol.green = 0xffff;
630 else xcol.green *= 0xff;
631 xcol.blue = (unsigned int) (texture->getColor()->getBlue() +
632 (texture->getColor()->getBlue() >> 1));
633 if (xcol.blue >= 0xff) xcol.blue = 0xffff;
634 else xcol.blue *= 0xff;
636 if (! XAllocColor(getBaseDisplay().getXDisplay(),
637 getColormap(), &xcol))
640 texture->getHiColor()->setPixel(xcol.pixel);
643 (unsigned int) ((texture->getColor()->getRed() >> 2) +
644 (texture->getColor()->getRed() >> 1)) * 0xff;
646 (unsigned int) ((texture->getColor()->getGreen() >> 2) +
647 (texture->getColor()->getGreen() >> 1)) * 0xff;
649 (unsigned int) ((texture->getColor()->getBlue() >> 2) +
650 (texture->getColor()->getBlue() >> 1)) * 0xff;
652 if (! XAllocColor(getBaseDisplay().getXDisplay(),
653 getColormap(), &xcol))
656 texture->getLoColor()->setPixel(xcol.pixel);
657 } else if (texture->getTexture() & BImage_Gradient) {
658 int clen = strlen(rclass) + 10, nlen = strlen(rname) + 10;
660 char *colorclass = new char[clen], *colorname = new char[nlen],
661 *colortoclass = new char[clen], *colortoname = new char[nlen];
663 sprintf(colorclass, "%s.Color", rclass);
664 sprintf(colorname, "%s.color", rname);
666 sprintf(colortoclass, "%s.ColorTo", rclass);
667 sprintf(colortoname, "%s.colorTo", rname);
669 readDatabaseColor(colorname, colorclass, texture->getColor(),
671 readDatabaseColor(colortoname, colortoclass, texture->getColorTo(),
674 delete [] colorclass;
676 delete [] colortoclass;
677 delete [] colortoname;
682 void BScreen::readDatabaseColor(const char *rname, const char *rclass,
683 BColor *color, unsigned long default_pixel)
687 if (resource.styleconfig.getValue(rname, rclass, s))
688 image_control->parseColor(color, s.c_str());
690 // parsing with no color string just deallocates the color, if it has
691 // been previously allocated
692 image_control->parseColor(color);
693 color->setPixel(default_pixel);
698 void BScreen::readDatabaseFontSet(const char *rname, const char *rclass,
700 if (! fontset) return;
702 static char *defaultFont = "fixed";
703 bool load_default = false;
707 XFreeFontSet(getBaseDisplay().getXDisplay(), *fontset);
709 if (resource.styleconfig.getValue(rname, rclass, s)) {
710 if (! (*fontset = createFontSet(s.c_str())))
716 *fontset = createFontSet(defaultFont);
719 fprintf(stderr, i18n->getMessage(ScreenSet, ScreenDefaultFontLoadFail,
720 "BScreen::LoadStyle(): couldn't load default font.\n"));
727 void BScreen::readDatabaseFont(const char *rname, const char *rclass,
728 XFontStruct **font) {
731 static char *defaultFont = "fixed";
732 bool load_default = false;
736 XFreeFont(getBaseDisplay().getXDisplay(), *font);
738 if (resource.styleconfig.getValue(rname, rclass, s)) {
739 if ((*font = XLoadQueryFont(getBaseDisplay().getXDisplay(),
740 s.c_str())) == NULL) {
741 fprintf(stderr, i18n->getMessage(ScreenSet, ScreenFontLoadFail,
742 "BScreen::LoadStyle(): couldn't load font '%s'\n"),
750 if ((*font = XLoadQueryFont(getBaseDisplay().getXDisplay(),
751 defaultFont)) == NULL) {
752 fprintf(stderr, i18n->getMessage(ScreenSet, ScreenDefaultFontLoadFail,
753 "BScreen::LoadStyle(): couldn't load default font.\n"));
760 XFontSet BScreen::createFontSet(const char *fontname) {
762 char **missing, *def = "-";
763 int nmissing, pixel_size = 0, buf_size = 0;
764 char weight[FONT_ELEMENT_SIZE], slant[FONT_ELEMENT_SIZE];
766 fs = XCreateFontSet(getBaseDisplay().getXDisplay(),
767 fontname, &missing, &nmissing, &def);
768 if (fs && (! nmissing)) return fs;
770 #ifdef HAVE_SETLOCALE
772 if (nmissing) XFreeStringList(missing);
774 setlocale(LC_CTYPE, "C");
775 fs = XCreateFontSet(getBaseDisplay().getXDisplay(), fontname,
776 &missing, &nmissing, &def);
777 setlocale(LC_CTYPE, "");
779 #endif // HAVE_SETLOCALE
782 XFontStruct **fontstructs;
784 XFontsOfFontSet(fs, &fontstructs, &fontnames);
785 fontname = fontnames[0];
788 getFontElement(fontname, weight, FONT_ELEMENT_SIZE,
789 "-medium-", "-bold-", "-demibold-", "-regular-", NULL);
790 getFontElement(fontname, slant, FONT_ELEMENT_SIZE,
791 "-r-", "-i-", "-o-", "-ri-", "-ro-", NULL);
792 getFontSize(fontname, &pixel_size);
794 if (! strcmp(weight, "*")) strncpy(weight, "medium", FONT_ELEMENT_SIZE);
795 if (! strcmp(slant, "*")) strncpy(slant, "r", FONT_ELEMENT_SIZE);
796 if (pixel_size < 3) pixel_size = 3;
797 else if (pixel_size > 97) pixel_size = 97;
799 buf_size = strlen(fontname) + (FONT_ELEMENT_SIZE * 2) + 64;
800 char *pattern2 = new char[buf_size];
801 snprintf(pattern2, buf_size - 1,
803 "-*-*-%s-%s-*-*-%d-*-*-*-*-*-*-*,"
804 "-*-*-*-*-*-*-%d-*-*-*-*-*-*-*,*",
805 fontname, weight, slant, pixel_size, pixel_size);
808 if (nmissing) XFreeStringList(missing);
809 if (fs) XFreeFontSet(getBaseDisplay().getXDisplay(), fs);
811 fs = XCreateFontSet(getBaseDisplay().getXDisplay(), fontname,
812 &missing, &nmissing, &def);
819 void BScreen::reconfigure(void) {
823 unsigned long gc_value_mask = GCForeground;
824 if (! i18n->multibyte()) gc_value_mask |= GCFont;
826 gcv.foreground = WhitePixel(getBaseDisplay().getXDisplay(),
828 gcv.function = GXinvert;
829 gcv.subwindow_mode = IncludeInferiors;
830 XChangeGC(getBaseDisplay().getXDisplay(), opGC,
831 GCForeground | GCFunction | GCSubwindowMode, &gcv);
833 gcv.foreground = resource.wstyle.l_text_focus.getPixel();
834 if (resource.wstyle.font)
835 gcv.font = resource.wstyle.font->fid;
836 XChangeGC(getBaseDisplay().getXDisplay(), resource.wstyle.l_text_focus_gc,
837 gc_value_mask, &gcv);
839 gcv.foreground = resource.wstyle.l_text_unfocus.getPixel();
840 XChangeGC(getBaseDisplay().getXDisplay(), resource.wstyle.l_text_unfocus_gc,
841 gc_value_mask, &gcv);
843 gcv.foreground = resource.wstyle.b_pic_focus.getPixel();
844 XChangeGC(getBaseDisplay().getXDisplay(), resource.wstyle.b_pic_focus_gc,
847 gcv.foreground = resource.wstyle.b_pic_unfocus.getPixel();
848 XChangeGC(getBaseDisplay().getXDisplay(), resource.wstyle.b_pic_unfocus_gc,
851 gcv.foreground = resource.mstyle.t_text.getPixel();
852 if (resource.mstyle.t_font)
853 gcv.font = resource.mstyle.t_font->fid;
854 XChangeGC(getBaseDisplay().getXDisplay(), resource.mstyle.t_text_gc,
855 gc_value_mask, &gcv);
857 gcv.foreground = resource.mstyle.f_text.getPixel();
858 if (resource.mstyle.f_font)
859 gcv.font = resource.mstyle.f_font->fid;
860 XChangeGC(getBaseDisplay().getXDisplay(), resource.mstyle.f_text_gc,
861 gc_value_mask, &gcv);
863 gcv.foreground = resource.mstyle.h_text.getPixel();
864 XChangeGC(getBaseDisplay().getXDisplay(), resource.mstyle.h_text_gc,
865 gc_value_mask, &gcv);
867 gcv.foreground = resource.mstyle.d_text.getPixel();
868 XChangeGC(getBaseDisplay().getXDisplay(), resource.mstyle.d_text_gc,
869 gc_value_mask, &gcv);
871 gcv.foreground = resource.mstyle.hilite.getColor()->getPixel();
872 XChangeGC(getBaseDisplay().getXDisplay(), resource.mstyle.hilite_gc,
873 gc_value_mask, &gcv);
875 gcv.foreground = resource.tstyle.l_text.getPixel();
876 if (resource.tstyle.font)
877 gcv.font = resource.tstyle.font->fid;
878 XChangeGC(getBaseDisplay().getXDisplay(), resource.tstyle.l_text_gc,
879 gc_value_mask, &gcv);
881 gcv.foreground = resource.tstyle.w_text.getPixel();
882 XChangeGC(getBaseDisplay().getXDisplay(), resource.tstyle.w_text_gc,
883 gc_value_mask, &gcv);
885 gcv.foreground = resource.tstyle.c_text.getPixel();
886 XChangeGC(getBaseDisplay().getXDisplay(), resource.tstyle.c_text_gc,
887 gc_value_mask, &gcv);
889 gcv.foreground = resource.tstyle.b_pic.getPixel();
890 XChangeGC(getBaseDisplay().getXDisplay(), resource.tstyle.b_pic_gc,
891 gc_value_mask, &gcv);
893 const char *s = i18n->getMessage(ScreenSet, ScreenPositionLength,
894 "0: 0000 x 0: 0000");
897 if (i18n->multibyte()) {
898 XRectangle ink, logical;
899 XmbTextExtents(resource.wstyle.fontset, s, l, &ink, &logical);
900 geom_w = logical.width;
902 geom_h = resource.wstyle.fontset_extents->max_ink_extent.height;
904 geom_w = XTextWidth(resource.wstyle.font, s, l);
906 geom_h = resource.wstyle.font->ascent +
907 resource.wstyle.font->descent;
910 geom_w += (resource.bevel_width * 2);
911 geom_h += (resource.bevel_width * 2);
913 Pixmap tmp = geom_pixmap;
914 if (resource.wstyle.l_focus.getTexture() & BImage_ParentRelative) {
915 if (resource.wstyle.t_focus.getTexture() ==
916 (BImage_Flat | BImage_Solid)) {
918 XSetWindowBackground(getBaseDisplay().getXDisplay(), geom_window,
919 resource.wstyle.t_focus.getColor()->getPixel());
921 geom_pixmap = image_control->renderImage(geom_w, geom_h,
922 &resource.wstyle.t_focus);
923 XSetWindowBackgroundPixmap(getBaseDisplay().getXDisplay(),
924 geom_window, geom_pixmap);
927 if (resource.wstyle.l_focus.getTexture() ==
928 (BImage_Flat | BImage_Solid)) {
930 XSetWindowBackground(getBaseDisplay().getXDisplay(), geom_window,
931 resource.wstyle.l_focus.getColor()->getPixel());
933 geom_pixmap = image_control->renderImage(geom_w, geom_h,
934 &resource.wstyle.l_focus);
935 XSetWindowBackgroundPixmap(getBaseDisplay().getXDisplay(),
936 geom_window, geom_pixmap);
939 if (tmp) image_control->removeImage(tmp);
941 XSetWindowBorderWidth(getBaseDisplay().getXDisplay(), geom_window,
942 resource.border_width);
943 XSetWindowBorder(getBaseDisplay().getXDisplay(), geom_window,
944 resource.border_color.getPixel());
946 workspacemenu->reconfigure();
947 iconmenu->reconfigure();
950 int remember_sub = rootmenu->getCurrentSubmenu();
953 rootmenu->reconfigure();
954 rootmenu->drawSubmenu(remember_sub);
957 configmenu->reconfigure();
959 toolbar->reconfigure();
965 LinkedListIterator<Workspace> wit(workspacesList);
966 for (Workspace *w = wit.current(); w; wit++, w = wit.current())
969 LinkedListIterator<OpenboxWindow> iit(iconList);
970 for (OpenboxWindow *bw = iit.current(); bw; iit++, bw = iit.current())
971 if (bw->validateClient())
974 image_control->timeout();
978 void BScreen::rereadMenu(void) {
982 rootmenu->reconfigure();
986 void BScreen::removeWorkspaceNames(void) {
987 while (workspaceNames->count())
988 delete [] workspaceNames->remove(0);
992 void BScreen::LoadStyle(void) {
993 obResource &conf = resource.styleconfig;
995 conf.setFile(openbox.getStyleFilename());
997 conf.setFile(DEFAULTSTYLE);
999 fprintf(stderr, i18n->getMessage(ScreenSet, ScreenDefaultStyleLoadFail,
1000 "BScreen::LoadStyle(): couldn't load "
1001 "default style.\n"));
1009 // load fonts/fontsets
1011 if (i18n->multibyte()) {
1012 readDatabaseFontSet("window.font", "Window.Font",
1013 &resource.wstyle.fontset);
1014 readDatabaseFontSet("toolbar.font", "Toolbar.Font",
1015 &resource.tstyle.fontset);
1016 readDatabaseFontSet("menu.title.font", "Menu.Title.Font",
1017 &resource.mstyle.t_fontset);
1018 readDatabaseFontSet("menu.frame.font", "Menu.Frame.Font",
1019 &resource.mstyle.f_fontset);
1021 resource.mstyle.t_fontset_extents =
1022 XExtentsOfFontSet(resource.mstyle.t_fontset);
1023 resource.mstyle.f_fontset_extents =
1024 XExtentsOfFontSet(resource.mstyle.f_fontset);
1025 resource.tstyle.fontset_extents =
1026 XExtentsOfFontSet(resource.tstyle.fontset);
1027 resource.wstyle.fontset_extents =
1028 XExtentsOfFontSet(resource.wstyle.fontset);
1030 readDatabaseFont("window.font", "Window.Font",
1031 &resource.wstyle.font);
1032 readDatabaseFont("menu.title.font", "Menu.Title.Font",
1033 &resource.mstyle.t_font);
1034 readDatabaseFont("menu.frame.font", "Menu.Frame.Font",
1035 &resource.mstyle.f_font);
1036 readDatabaseFont("toolbar.font", "Toolbar.Font",
1037 &resource.tstyle.font);
1040 // load window config
1041 readDatabaseTexture("window.title.focus", "Window.Title.Focus",
1042 &resource.wstyle.t_focus,
1043 WhitePixel(getBaseDisplay().getXDisplay(),
1044 getScreenNumber()));
1045 readDatabaseTexture("window.title.unfocus", "Window.Title.Unfocus",
1046 &resource.wstyle.t_unfocus,
1047 BlackPixel(getBaseDisplay().getXDisplay(),
1048 getScreenNumber()));
1049 readDatabaseTexture("window.label.focus", "Window.Label.Focus",
1050 &resource.wstyle.l_focus,
1051 WhitePixel(getBaseDisplay().getXDisplay(),
1052 getScreenNumber()));
1053 readDatabaseTexture("window.label.unfocus", "Window.Label.Unfocus",
1054 &resource.wstyle.l_unfocus,
1055 BlackPixel(getBaseDisplay().getXDisplay(),
1056 getScreenNumber()));
1057 readDatabaseTexture("window.handle.focus", "Window.Handle.Focus",
1058 &resource.wstyle.h_focus,
1059 WhitePixel(getBaseDisplay().getXDisplay(),
1060 getScreenNumber()));
1061 readDatabaseTexture("window.handle.unfocus", "Window.Handle.Unfocus",
1062 &resource.wstyle.h_unfocus,
1063 BlackPixel(getBaseDisplay().getXDisplay(),
1064 getScreenNumber()));
1065 readDatabaseTexture("window.grip.focus", "Window.Grip.Focus",
1066 &resource.wstyle.g_focus,
1067 WhitePixel(getBaseDisplay().getXDisplay(),
1068 getScreenNumber()));
1069 readDatabaseTexture("window.grip.unfocus", "Window.Grip.Unfocus",
1070 &resource.wstyle.g_unfocus,
1071 BlackPixel(getBaseDisplay().getXDisplay(),
1072 getScreenNumber()));
1073 readDatabaseTexture("window.button.focus", "Window.Button.Focus",
1074 &resource.wstyle.b_focus,
1075 WhitePixel(getBaseDisplay().getXDisplay(),
1076 getScreenNumber()));
1077 readDatabaseTexture("window.button.unfocus", "Window.Button.Unfocus",
1078 &resource.wstyle.b_unfocus,
1079 BlackPixel(getBaseDisplay().getXDisplay(),
1080 getScreenNumber()));
1081 readDatabaseTexture("window.button.pressed", "Window.Button.Pressed",
1082 &resource.wstyle.b_pressed,
1083 BlackPixel(getBaseDisplay().getXDisplay(),
1084 getScreenNumber()));
1085 readDatabaseColor("window.frame.focusColor",
1086 "Window.Frame.FocusColor",
1087 &resource.wstyle.f_focus,
1088 WhitePixel(getBaseDisplay().getXDisplay(),
1089 getScreenNumber()));
1090 readDatabaseColor("window.frame.unfocusColor",
1091 "Window.Frame.UnfocusColor",
1092 &resource.wstyle.f_unfocus,
1093 BlackPixel(getBaseDisplay().getXDisplay(),
1094 getScreenNumber()));
1095 readDatabaseColor("window.label.focus.textColor",
1096 "Window.Label.Focus.TextColor",
1097 &resource.wstyle.l_text_focus,
1098 BlackPixel(getBaseDisplay().getXDisplay(),
1099 getScreenNumber()));
1100 readDatabaseColor("window.label.unfocus.textColor",
1101 "Window.Label.Unfocus.TextColor",
1102 &resource.wstyle.l_text_unfocus,
1103 WhitePixel(getBaseDisplay().getXDisplay(),
1104 getScreenNumber()));
1105 readDatabaseColor("window.button.focus.picColor",
1106 "Window.Button.Focus.PicColor",
1107 &resource.wstyle.b_pic_focus,
1108 BlackPixel(getBaseDisplay().getXDisplay(),
1109 getScreenNumber()));
1110 readDatabaseColor("window.button.unfocus.picColor",
1111 "Window.Button.Unfocus.PicColor",
1112 &resource.wstyle.b_pic_unfocus,
1113 WhitePixel(getBaseDisplay().getXDisplay(),
1114 getScreenNumber()));
1116 if (conf.getValue("window.justify", "Window.Justify", s)) {
1117 if (0 == strncasecmp(s.c_str(), "right", s.length()))
1118 resource.wstyle.justify = BScreen::RightJustify;
1119 else if (0 == strncasecmp(s.c_str(), "center", s.length()))
1120 resource.wstyle.justify = BScreen::CenterJustify;
1122 resource.wstyle.justify = BScreen::LeftJustify;
1124 resource.wstyle.justify = BScreen::LeftJustify;
1126 // load toolbar config
1127 readDatabaseTexture("toolbar", "Toolbar",
1128 &resource.tstyle.toolbar,
1129 BlackPixel(getBaseDisplay().getXDisplay(),
1130 getScreenNumber()));
1131 readDatabaseTexture("toolbar.label", "Toolbar.Label",
1132 &resource.tstyle.label,
1133 BlackPixel(getBaseDisplay().getXDisplay(),
1134 getScreenNumber()));
1135 readDatabaseTexture("toolbar.windowLabel", "Toolbar.WindowLabel",
1136 &resource.tstyle.window,
1137 BlackPixel(getBaseDisplay().getXDisplay(),
1138 getScreenNumber()));
1139 readDatabaseTexture("toolbar.button", "Toolbar.Button",
1140 &resource.tstyle.button,
1141 WhitePixel(getBaseDisplay().getXDisplay(),
1142 getScreenNumber()));
1143 readDatabaseTexture("toolbar.button.pressed", "Toolbar.Button.Pressed",
1144 &resource.tstyle.pressed,
1145 BlackPixel(getBaseDisplay().getXDisplay(),
1146 getScreenNumber()));
1147 readDatabaseTexture("toolbar.clock", "Toolbar.Clock",
1148 &resource.tstyle.clock,
1149 BlackPixel(getBaseDisplay().getXDisplay(),
1150 getScreenNumber()));
1151 readDatabaseColor("toolbar.label.textColor", "Toolbar.Label.TextColor",
1152 &resource.tstyle.l_text,
1153 WhitePixel(getBaseDisplay().getXDisplay(),
1154 getScreenNumber()));
1155 readDatabaseColor("toolbar.windowLabel.textColor",
1156 "Toolbar.WindowLabel.TextColor",
1157 &resource.tstyle.w_text,
1158 WhitePixel(getBaseDisplay().getXDisplay(),
1159 getScreenNumber()));
1160 readDatabaseColor("toolbar.clock.textColor", "Toolbar.Clock.TextColor",
1161 &resource.tstyle.c_text,
1162 WhitePixel(getBaseDisplay().getXDisplay(),
1163 getScreenNumber()));
1164 readDatabaseColor("toolbar.button.picColor", "Toolbar.Button.PicColor",
1165 &resource.tstyle.b_pic,
1166 BlackPixel(getBaseDisplay().getXDisplay(),
1167 getScreenNumber()));
1169 if (conf.getValue("toolbar.justify", "Toolbar.Justify", s)) {
1170 if (0 == strncasecmp(s.c_str(), "right", s.length()))
1171 resource.tstyle.justify = BScreen::RightJustify;
1172 else if (0 == strncasecmp(s.c_str(), "center", s.length()))
1173 resource.tstyle.justify = BScreen::CenterJustify;
1175 resource.tstyle.justify = BScreen::LeftJustify;
1177 resource.tstyle.justify = BScreen::LeftJustify;
1180 readDatabaseTexture("menu.title", "Menu.Title",
1181 &resource.mstyle.title,
1182 WhitePixel(getBaseDisplay().getXDisplay(),
1183 getScreenNumber()));
1184 readDatabaseTexture("menu.frame", "Menu.Frame",
1185 &resource.mstyle.frame,
1186 BlackPixel(getBaseDisplay().getXDisplay(),
1187 getScreenNumber()));
1188 readDatabaseTexture("menu.hilite", "Menu.Hilite",
1189 &resource.mstyle.hilite,
1190 WhitePixel(getBaseDisplay().getXDisplay(),
1191 getScreenNumber()));
1192 readDatabaseColor("menu.title.textColor", "Menu.Title.TextColor",
1193 &resource.mstyle.t_text,
1194 BlackPixel(getBaseDisplay().getXDisplay(),
1195 getScreenNumber()));
1196 readDatabaseColor("menu.frame.textColor", "Menu.Frame.TextColor",
1197 &resource.mstyle.f_text,
1198 WhitePixel(getBaseDisplay().getXDisplay(),
1199 getScreenNumber()));
1200 readDatabaseColor("menu.frame.disableColor", "Menu.Frame.DisableColor",
1201 &resource.mstyle.d_text,
1202 BlackPixel(getBaseDisplay().getXDisplay(),
1203 getScreenNumber()));
1204 readDatabaseColor("menu.hilite.textColor", "Menu.Hilite.TextColor",
1205 &resource.mstyle.h_text,
1206 BlackPixel(getBaseDisplay().getXDisplay(),
1207 getScreenNumber()));
1209 if (conf.getValue("menu.title.justify", "Menu.Title.Justify", s)) {
1210 if (0 == strncasecmp(s.c_str(), "right", s.length()))
1211 resource.mstyle.t_justify = BScreen::RightJustify;
1212 else if (0 == strncasecmp(s.c_str(), "center", s.length()))
1213 resource.mstyle.t_justify = BScreen::CenterJustify;
1215 resource.mstyle.t_justify = BScreen::LeftJustify;
1217 resource.mstyle.t_justify = BScreen::LeftJustify;
1219 if (conf.getValue("menu.frame.justify", "Menu.Frame.Justify", s)) {
1220 if (0 == strncasecmp(s.c_str(), "right", s.length()))
1221 resource.mstyle.f_justify = BScreen::RightJustify;
1222 else if (0 == strncasecmp(s.c_str(), "center", s.length()))
1223 resource.mstyle.f_justify = BScreen::CenterJustify;
1225 resource.mstyle.f_justify = BScreen::LeftJustify;
1227 resource.mstyle.f_justify = BScreen::LeftJustify;
1229 if (conf.getValue("menu.bullet", "Menu.Bullet", s)) {
1230 if (0 == strncasecmp(s.c_str(), "empty", s.length()))
1231 resource.mstyle.bullet = Basemenu::Empty;
1232 else if (0 == strncasecmp(s.c_str(), "square", s.length()))
1233 resource.mstyle.bullet = Basemenu::Square;
1234 else if (0 == strncasecmp(s.c_str(), "diamond", s.length()))
1235 resource.mstyle.bullet = Basemenu::Diamond;
1237 resource.mstyle.bullet = Basemenu::Triangle;
1239 resource.mstyle.bullet = Basemenu::Triangle;
1241 if (conf.getValue("menu.bullet.position", "Menu.Bullet.Position", s)) {
1242 if (0 == strncasecmp(s.c_str(), "right", s.length()))
1243 resource.mstyle.bullet_pos = Basemenu::Right;
1245 resource.mstyle.bullet_pos = Basemenu::Left;
1247 resource.mstyle.bullet_pos = Basemenu::Left;
1249 readDatabaseColor("borderColor", "BorderColor", &resource.border_color,
1250 BlackPixel(getBaseDisplay().getXDisplay(),
1251 getScreenNumber()));
1253 // load bevel, border and handle widths
1254 if (conf.getValue("handleWidth", "HandleWidth", l)) {
1255 if (l <= size().w() / 2 && l != 0)
1256 resource.handle_width = l;
1258 resource.handle_width = 6;
1260 resource.handle_width = 6;
1262 if (conf.getValue("borderWidth", "BorderWidth", l))
1263 resource.border_width = l;
1265 resource.border_width = 1;
1267 if (conf.getValue("bevelWidth", "BevelWidth", l)) {
1268 if (l <= size().w() / 2 && l != 0)
1269 resource.bevel_width = l;
1271 resource.bevel_width = 3;
1273 resource.bevel_width = 3;
1275 if (conf.getValue("frameWidth", "FrameWidth", l)) {
1276 if (l <= size().w() / 2)
1277 resource.frame_width = l;
1279 resource.frame_width = resource.bevel_width;
1281 resource.frame_width = resource.bevel_width;
1283 const char *cmd = resource.root_command;
1284 if (cmd != NULL || conf.getValue("rootCommand", "RootCommand", s)) {
1286 cmd = s.c_str(); // not specified by the screen, so use the one from the
1289 char displaystring[MAXPATHLEN];
1290 sprintf(displaystring, "DISPLAY=%s",
1291 DisplayString(getBaseDisplay().getXDisplay()));
1292 sprintf(displaystring + strlen(displaystring) - 1, "%d",
1295 bexec(cmd, displaystring);
1297 spawnlp(P_NOWAIT, "cmd.exe", "cmd.exe", "/c", cmd, NULL);
1303 void BScreen::addIcon(OpenboxWindow *w) {
1306 w->setWorkspace(-1);
1307 w->setWindowNumber(iconList->count());
1309 iconList->insert(w);
1311 iconmenu->insert((const char **) w->getIconTitle());
1316 void BScreen::removeIcon(OpenboxWindow *w) {
1319 iconList->remove(w->getWindowNumber());
1321 iconmenu->remove(w->getWindowNumber());
1324 LinkedListIterator<OpenboxWindow> it(iconList);
1325 OpenboxWindow *bw = it.current();
1326 for (int i = 0; bw; it++, bw = it.current())
1327 bw->setWindowNumber(i++);
1331 OpenboxWindow *BScreen::getIcon(int index) {
1332 if (index >= 0 && index < iconList->count())
1333 return iconList->find(index);
1335 return (OpenboxWindow *) 0;
1339 int BScreen::addWorkspace(void) {
1340 Workspace *wkspc = new Workspace(*this, workspacesList->count());
1341 workspacesList->insert(wkspc);
1343 workspacemenu->insert(wkspc->getName(), wkspc->getMenu(),
1344 wkspc->getWorkspaceID() + 2);
1345 workspacemenu->update();
1347 toolbar->reconfigure();
1349 updateNetizenWorkspaceCount();
1351 return workspacesList->count();
1355 int BScreen::removeLastWorkspace(void) {
1356 if (workspacesList->count() == 1)
1359 Workspace *wkspc = workspacesList->last();
1361 if (current_workspace->getWorkspaceID() == wkspc->getWorkspaceID())
1362 changeWorkspaceID(current_workspace->getWorkspaceID() - 1);
1366 workspacemenu->remove(wkspc->getWorkspaceID() + 2);
1367 workspacemenu->update();
1369 workspacesList->remove(wkspc);
1372 toolbar->reconfigure();
1374 updateNetizenWorkspaceCount();
1376 return workspacesList->count();
1380 void BScreen::changeWorkspaceID(int id) {
1381 if (! current_workspace) return;
1383 if (id != current_workspace->getWorkspaceID()) {
1384 current_workspace->hideAll();
1386 workspacemenu->setItemSelected(current_workspace->getWorkspaceID() + 2,
1389 if (openbox.getFocusedWindow() &&
1390 openbox.getFocusedWindow()->getScreen() == this &&
1391 (! openbox.getFocusedWindow()->isStuck())) {
1392 current_workspace->setLastFocusedWindow(openbox.getFocusedWindow());
1393 openbox.setFocusedWindow((OpenboxWindow *) 0);
1396 current_workspace = getWorkspace(id);
1398 workspacemenu->setItemSelected(current_workspace->getWorkspaceID() + 2,
1400 toolbar->redrawWorkspaceLabel(True);
1402 current_workspace->showAll();
1404 if (resource.focus_last && current_workspace->getLastFocusedWindow()) {
1405 XSync(openbox.getXDisplay(), False);
1406 current_workspace->getLastFocusedWindow()->setInputFocus();
1410 updateNetizenCurrentWorkspace();
1414 void BScreen::addNetizen(Netizen *n) {
1415 netizenList->insert(n);
1417 n->sendWorkspaceCount();
1418 n->sendCurrentWorkspace();
1420 LinkedListIterator<Workspace> it(workspacesList);
1421 for (Workspace *w = it.current(); w; it++, w = it.current()) {
1422 for (int i = 0; i < w->getCount(); i++)
1423 n->sendWindowAdd(w->getWindow(i)->getClientWindow(),
1424 w->getWorkspaceID());
1427 Window f = ((openbox.getFocusedWindow()) ?
1428 openbox.getFocusedWindow()->getClientWindow() : None);
1429 n->sendWindowFocus(f);
1433 void BScreen::removeNetizen(Window w) {
1434 LinkedListIterator<Netizen> it(netizenList);
1437 for (Netizen *n = it.current(); n; it++, i++, n = it.current())
1438 if (n->getWindowID() == w) {
1439 Netizen *tmp = netizenList->remove(i);
1447 void BScreen::updateNetizenCurrentWorkspace(void) {
1448 LinkedListIterator<Netizen> it(netizenList);
1449 for (Netizen *n = it.current(); n; it++, n = it.current())
1450 n->sendCurrentWorkspace();
1454 void BScreen::updateNetizenWorkspaceCount(void) {
1455 LinkedListIterator<Netizen> it(netizenList);
1456 for (Netizen *n = it.current(); n; it++, n = it.current())
1457 n->sendWorkspaceCount();
1461 void BScreen::updateNetizenWindowFocus(void) {
1462 Window f = ((openbox.getFocusedWindow()) ?
1463 openbox.getFocusedWindow()->getClientWindow() : None);
1464 LinkedListIterator<Netizen> it(netizenList);
1465 for (Netizen *n = it.current(); n; it++, n = it.current())
1466 n->sendWindowFocus(f);
1470 void BScreen::updateNetizenWindowAdd(Window w, unsigned long p) {
1471 LinkedListIterator<Netizen> it(netizenList);
1472 for (Netizen *n = it.current(); n; it++, n = it.current())
1473 n->sendWindowAdd(w, p);
1477 void BScreen::updateNetizenWindowDel(Window w) {
1478 LinkedListIterator<Netizen> it(netizenList);
1479 for (Netizen *n = it.current(); n; it++, n = it.current())
1480 n->sendWindowDel(w);
1484 void BScreen::updateNetizenWindowRaise(Window w) {
1485 LinkedListIterator<Netizen> it(netizenList);
1486 for (Netizen *n = it.current(); n; it++, n = it.current())
1487 n->sendWindowRaise(w);
1491 void BScreen::updateNetizenWindowLower(Window w) {
1492 LinkedListIterator<Netizen> it(netizenList);
1493 for (Netizen *n = it.current(); n; it++, n = it.current())
1494 n->sendWindowLower(w);
1498 void BScreen::updateNetizenConfigNotify(XEvent *e) {
1499 LinkedListIterator<Netizen> it(netizenList);
1500 for (Netizen *n = it.current(); n; it++, n = it.current())
1501 n->sendConfigNotify(e);
1505 void BScreen::raiseWindows(Window *workspace_stack, int num) {
1506 Window *session_stack = new
1507 Window[(num + workspacesList->count() + rootmenuList->count() + 13)];
1510 XRaiseWindow(getBaseDisplay().getXDisplay(), iconmenu->getWindowID());
1511 *(session_stack + i++) = iconmenu->getWindowID();
1513 LinkedListIterator<Workspace> wit(workspacesList);
1514 for (Workspace *tmp = wit.current(); tmp; wit++, tmp = wit.current())
1515 *(session_stack + i++) = tmp->getMenu()->getWindowID();
1517 *(session_stack + i++) = workspacemenu->getWindowID();
1519 *(session_stack + i++) = configmenu->getFocusmenu()->getWindowID();
1520 *(session_stack + i++) = configmenu->getPlacementmenu()->getWindowID();
1521 *(session_stack + i++) = configmenu->getWindowID();
1524 *(session_stack + i++) = slit->getMenu()->getDirectionmenu()->getWindowID();
1525 *(session_stack + i++) = slit->getMenu()->getPlacementmenu()->getWindowID();
1526 *(session_stack + i++) = slit->getMenu()->getWindowID();
1529 *(session_stack + i++) =
1530 toolbar->getMenu()->getPlacementmenu()->getWindowID();
1531 *(session_stack + i++) = toolbar->getMenu()->getWindowID();
1533 LinkedListIterator<Rootmenu> rit(rootmenuList);
1534 for (Rootmenu *tmp = rit.current(); tmp; rit++, tmp = rit.current())
1535 *(session_stack + i++) = tmp->getWindowID();
1536 *(session_stack + i++) = rootmenu->getWindowID();
1538 if (toolbar->isOnTop())
1539 *(session_stack + i++) = toolbar->getWindowID();
1542 if (slit->isOnTop())
1543 *(session_stack + i++) = slit->getWindowID();
1547 *(session_stack + i++) = *(workspace_stack + k);
1549 XRestackWindows(getBaseDisplay().getXDisplay(), session_stack, i);
1551 delete [] session_stack;
1555 #ifdef HAVE_STRFTIME
1556 void BScreen::saveStrftimeFormat(const char *format) {
1557 if (resource.strftime_format)
1558 delete [] resource.strftime_format;
1560 resource.strftime_format = bstrdup(format);
1562 #endif // HAVE_STRFTIME
1565 void BScreen::addWorkspaceName(const char *name) {
1566 workspaceNames->insert(bstrdup(name));
1570 char* BScreen::getNameOfWorkspace(int id) {
1571 char *name = (char *) 0;
1573 if (id >= 0 && id < workspaceNames->count()) {
1574 char *wkspc_name = workspaceNames->find(id);
1583 void BScreen::reassociateWindow(OpenboxWindow *w, int wkspc_id, Bool ignore_sticky) {
1587 wkspc_id = current_workspace->getWorkspaceID();
1589 if (w->getWorkspaceNumber() == wkspc_id)
1592 if (w->isIconic()) {
1594 getWorkspace(wkspc_id)->addWindow(w);
1595 } else if (ignore_sticky || ! w->isStuck()) {
1596 getWorkspace(w->getWorkspaceNumber())->removeWindow(w);
1597 getWorkspace(wkspc_id)->addWindow(w);
1602 void BScreen::nextFocus(void) {
1603 Bool have_focused = False;
1604 int focused_window_number = -1;
1605 OpenboxWindow *next;
1607 if (openbox.getFocusedWindow()) {
1608 if (openbox.getFocusedWindow()->getScreen()->getScreenNumber() ==
1609 getScreenNumber()) {
1610 have_focused = True;
1611 focused_window_number = openbox.getFocusedWindow()->getWindowNumber();
1615 if ((getCurrentWorkspace()->getCount() > 1) && have_focused) {
1616 int next_window_number = focused_window_number;
1618 if ((++next_window_number) >= getCurrentWorkspace()->getCount())
1619 next_window_number = 0;
1621 next = getCurrentWorkspace()->getWindow(next_window_number);
1622 } while ((! next->setInputFocus()) && (next_window_number !=
1623 focused_window_number));
1625 if (next_window_number != focused_window_number)
1626 getCurrentWorkspace()->raiseWindow(next);
1627 } else if (getCurrentWorkspace()->getCount() >= 1) {
1628 next = current_workspace->getWindow(0);
1630 current_workspace->raiseWindow(next);
1631 next->setInputFocus();
1636 void BScreen::prevFocus(void) {
1637 Bool have_focused = False;
1638 int focused_window_number = -1;
1639 OpenboxWindow *prev;
1641 if (openbox.getFocusedWindow()) {
1642 if (openbox.getFocusedWindow()->getScreen()->getScreenNumber() ==
1643 getScreenNumber()) {
1644 have_focused = True;
1645 focused_window_number = openbox.getFocusedWindow()->getWindowNumber();
1649 if ((getCurrentWorkspace()->getCount() > 1) && have_focused) {
1650 int prev_window_number = focused_window_number;
1652 if ((--prev_window_number) < 0)
1653 prev_window_number = getCurrentWorkspace()->getCount() - 1;
1655 prev = getCurrentWorkspace()->getWindow(prev_window_number);
1656 } while ((! prev->setInputFocus()) && (prev_window_number !=
1657 focused_window_number));
1659 if (prev_window_number != focused_window_number)
1660 getCurrentWorkspace()->raiseWindow(prev);
1661 } else if (getCurrentWorkspace()->getCount() >= 1) {
1662 prev = current_workspace->getWindow(0);
1664 current_workspace->raiseWindow(prev);
1665 prev->setInputFocus();
1670 void BScreen::raiseFocus(void) {
1671 Bool have_focused = False;
1672 int focused_window_number = -1;
1674 if (openbox.getFocusedWindow()) {
1675 if (openbox.getFocusedWindow()->getScreen()->getScreenNumber() ==
1676 getScreenNumber()) {
1677 have_focused = True;
1678 focused_window_number = openbox.getFocusedWindow()->getWindowNumber();
1682 if ((getCurrentWorkspace()->getCount() > 1) && have_focused)
1683 getWorkspace(openbox.getFocusedWindow()->getWorkspaceNumber())->
1684 raiseWindow(openbox.getFocusedWindow());
1688 void BScreen::InitMenu(void) {
1690 while (rootmenuList->count())
1691 rootmenuList->remove(0);
1693 while (rootmenu->getCount())
1694 rootmenu->remove(0);
1696 rootmenu = new Rootmenu(*this);
1698 Bool defaultMenu = True;
1700 if (openbox.getMenuFilename()) {
1701 FILE *menu_file = fopen(openbox.getMenuFilename(), "r");
1704 perror(openbox.getMenuFilename());
1706 if (feof(menu_file)) {
1707 fprintf(stderr, i18n->getMessage(ScreenSet, ScreenEmptyMenuFile,
1708 "%s: Empty menu file"),
1709 openbox.getMenuFilename());
1711 char line[1024], label[1024];
1712 memset(line, 0, 1024);
1713 memset(label, 0, 1024);
1715 while (fgets(line, 1024, menu_file) && ! feof(menu_file)) {
1716 if (line[0] != '#') {
1717 int i, key = 0, index = -1, len = strlen(line);
1720 for (i = 0; i < len; i++) {
1721 if (line[i] == '[') index = 0;
1722 else if (line[i] == ']') break;
1723 else if (line[i] != ' ')
1725 key += tolower(line[i]);
1730 for (i = index; i < len; i++) {
1731 if (line[i] == '(') index = 0;
1732 else if (line[i] == ')') break;
1733 else if (index++ >= 0) {
1734 if (line[i] == '\\' && i < len - 1) i++;
1735 label[index - 1] = line[i];
1739 if (index == -1) index = 0;
1740 label[index] = '\0';
1742 rootmenu->setLabel(label);
1743 defaultMenu = parseMenuFile(menu_file, rootmenu);
1754 rootmenu->setInternalMenu();
1755 rootmenu->insert(i18n->getMessage(ScreenSet, Screenxterm, "xterm"),
1757 i18n->getMessage(ScreenSet, Screenxterm, "xterm"));
1758 rootmenu->insert(i18n->getMessage(ScreenSet, ScreenRestart, "Restart"),
1760 rootmenu->insert(i18n->getMessage(ScreenSet, ScreenExit, "Exit"),
1763 openbox.saveMenuFilename(openbox.getMenuFilename());
1768 Bool BScreen::parseMenuFile(FILE *file, Rootmenu *menu) {
1769 char line[1024], label[1024], command[1024];
1771 while (! feof(file)) {
1772 memset(line, 0, 1024);
1773 memset(label, 0, 1024);
1774 memset(command, 0, 1024);
1776 if (fgets(line, 1024, file)) {
1777 if (line[0] != '#') {
1778 register int i, key = 0, parse = 0, index = -1,
1779 line_length = strlen(line),
1780 label_length = 0, command_length = 0;
1782 // determine the keyword
1784 for (i = 0; i < line_length; i++) {
1785 if (line[i] == '[') parse = 1;
1786 else if (line[i] == ']') break;
1787 else if (line[i] != ' ')
1789 key += tolower(line[i]);
1792 // get the label enclosed in ()'s
1795 for (i = 0; i < line_length; i++) {
1796 if (line[i] == '(') {
1799 } else if (line[i] == ')') break;
1800 else if (index++ >= 0) {
1801 if (line[i] == '\\' && i < line_length - 1) i++;
1802 label[index - 1] = line[i];
1807 label[index] = '\0';
1808 label_length = index;
1814 // get the command enclosed in {}'s
1817 for (i = 0; i < line_length; i++) {
1818 if (line[i] == '{') {
1821 } else if (line[i] == '}') break;
1822 else if (index++ >= 0) {
1823 if (line[i] == '\\' && i < line_length - 1) i++;
1824 command[index - 1] = line[i];
1829 command[index] = '\0';
1830 command_length = index;
1838 return ((menu->getCount() == 0) ? True : False);
1843 menu->insert(label);
1848 if ((! *label) && (! *command)) {
1849 fprintf(stderr, i18n->getMessage(ScreenSet, ScreenEXECError,
1850 "BScreen::parseMenuFile: [exec] error, "
1851 "no menu label and/or command defined\n"));
1855 menu->insert(label, BScreen::Execute, command);
1861 fprintf(stderr, i18n->getMessage(ScreenSet, ScreenEXITError,
1862 "BScreen::parseMenuFile: [exit] error, "
1863 "no menu label defined\n"));
1867 menu->insert(label, BScreen::Exit);
1873 if ((! *label) || (! *command)) {
1874 fprintf(stderr, i18n->getMessage(ScreenSet, ScreenSTYLEError,
1875 "BScreen::parseMenuFile: [style] error, "
1876 "no menu label and/or filename defined\n"));
1880 char style[MAXPATHLEN];
1882 // perform shell style ~ home directory expansion
1884 int homedir_len = 0;
1885 if (*command == '~' && *(command + 1) == '/') {
1886 homedir = getenv("HOME");
1887 homedir_len = strlen(homedir);
1890 if (homedir && homedir_len != 0) {
1891 strncpy(style, homedir, homedir_len);
1893 strncpy(style + homedir_len, command + 1,
1894 command_length - 1);
1895 *(style + command_length + homedir_len - 1) = '\0';
1897 strncpy(style, command, command_length);
1898 *(style + command_length) = '\0';
1901 menu->insert(label, BScreen::SetStyle, style);
1908 fprintf(stderr, i18n->getMessage(ScreenSet, ScreenCONFIGError,
1909 "BScreen::parseMenufile: [config] error, "
1910 "no label defined"));
1914 menu->insert(label, configmenu);
1918 case 740: // include
1921 fprintf(stderr, i18n->getMessage(ScreenSet, ScreenINCLUDEError,
1922 "BScreen::parseMenuFile: [include] error, "
1923 "no filename defined\n"));
1927 char newfile[MAXPATHLEN];
1929 // perform shell style ~ home directory expansion
1931 int homedir_len = 0;
1932 if (*label == '~' && *(label + 1) == '/') {
1933 homedir = getenv("HOME");
1934 homedir_len = strlen(homedir);
1937 if (homedir && homedir_len != 0) {
1938 strncpy(newfile, homedir, homedir_len);
1940 strncpy(newfile + homedir_len, label + 1,
1942 *(newfile + label_length + homedir_len - 1) = '\0';
1944 strncpy(newfile, label, label_length);
1945 *(newfile + label_length) = '\0';
1949 FILE *submenufile = fopen(newfile, "r");
1953 if (fstat(fileno(submenufile), &buf) ||
1954 (! S_ISREG(buf.st_mode))) {
1956 i18n->getMessage(ScreenSet, ScreenINCLUDEErrorReg,
1957 "BScreen::parseMenuFile: [include] error: "
1958 "'%s' is not a regular file\n"), newfile);
1962 if (! feof(submenufile)) {
1963 if (! parseMenuFile(submenufile, menu))
1964 openbox.saveMenuFilename(newfile);
1966 fclose(submenufile);
1975 case 767: // submenu
1978 fprintf(stderr, i18n->getMessage(ScreenSet, ScreenSUBMENUError,
1979 "BScreen::parseMenuFile: [submenu] error, "
1980 "no menu label defined\n"));
1984 Rootmenu *submenu = new Rootmenu(*this);
1987 submenu->setLabel(command);
1989 submenu->setLabel(label);
1991 parseMenuFile(file, submenu);
1993 menu->insert(label, submenu);
1994 rootmenuList->insert(submenu);
1999 case 773: // restart
2002 fprintf(stderr, i18n->getMessage(ScreenSet, ScreenRESTARTError,
2003 "BScreen::parseMenuFile: [restart] error, "
2004 "no menu label defined\n"));
2009 menu->insert(label, BScreen::RestartOther, command);
2011 menu->insert(label, BScreen::Restart);
2016 case 845: // reconfig
2019 fprintf(stderr, i18n->getMessage(ScreenSet, ScreenRECONFIGError,
2020 "BScreen::parseMenuFile: [reconfig] error, "
2021 "no menu label defined\n"));
2025 menu->insert(label, BScreen::Reconfigure);
2030 case 995: // stylesdir
2031 case 1113: // stylesmenu
2033 Bool newmenu = ((key == 1113) ? True : False);
2035 if ((! *label) || ((! *command) && newmenu)) {
2037 i18n->getMessage(ScreenSet, ScreenSTYLESDIRError,
2038 "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
2039 " error, no directory defined\n"));
2043 char stylesdir[MAXPATHLEN];
2045 char *directory = ((newmenu) ? command : label);
2046 int directory_length = ((newmenu) ? command_length : label_length);
2048 // perform shell style ~ home directory expansion
2050 int homedir_len = 0;
2052 if (*directory == '~' && *(directory + 1) == '/') {
2053 homedir = getenv("HOME");
2054 homedir_len = strlen(homedir);
2057 if (homedir && homedir_len != 0) {
2058 strncpy(stylesdir, homedir, homedir_len);
2060 strncpy(stylesdir + homedir_len, directory + 1,
2061 directory_length - 1);
2062 *(stylesdir + directory_length + homedir_len - 1) = '\0';
2064 strncpy(stylesdir, directory, directory_length);
2065 *(stylesdir + directory_length) = '\0';
2068 struct stat statbuf;
2070 if (! stat(stylesdir, &statbuf)) {
2071 if (S_ISDIR(statbuf.st_mode)) {
2072 Rootmenu *stylesmenu;
2075 stylesmenu = new Rootmenu(*this);
2079 DIR *d = opendir(stylesdir);
2083 // get the total number of directory entries
2084 while ((p = readdir(d))) entries++;
2087 char **ls = new char* [entries];
2089 while ((p = readdir(d)))
2090 ls[index++] = bstrdup(p->d_name);
2094 std::sort(ls, ls + entries, dcmp());
2096 int n, slen = strlen(stylesdir);
2097 for (n = 0; n < entries; n++) {
2098 if (ls[n][strlen(ls[n])-1] != '~') {
2099 int nlen = strlen(ls[n]);
2100 char style[MAXPATHLEN + 1];
2102 strncpy(style, stylesdir, slen);
2103 *(style + slen) = '/';
2104 strncpy(style + slen + 1, ls[n], nlen + 1);
2106 if ((! stat(style, &statbuf)) && S_ISREG(statbuf.st_mode))
2107 stylesmenu->insert(ls[n], BScreen::SetStyle, style);
2115 stylesmenu->update();
2118 stylesmenu->setLabel(label);
2119 menu->insert(label, stylesmenu);
2120 rootmenuList->insert(stylesmenu);
2123 openbox.saveMenuFilename(stylesdir);
2125 fprintf(stderr, i18n->getMessage(ScreenSet,
2126 ScreenSTYLESDIRErrorNotDir,
2127 "BScreen::parseMenuFile:"
2128 " [stylesdir/stylesmenu] error, %s is not a"
2129 " directory\n"), stylesdir);
2133 i18n->getMessage(ScreenSet, ScreenSTYLESDIRErrorNoExist,
2134 "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
2135 " error, %s does not exist\n"), stylesdir);
2141 case 1090: // workspaces
2145 i18n->getMessage(ScreenSet, ScreenWORKSPACESError,
2146 "BScreen:parseMenuFile: [workspaces] error, "
2147 "no menu label defined\n"));
2151 menu->insert(label, workspacemenu);
2160 return ((menu->getCount() == 0) ? True : False);
2164 void BScreen::shutdown(void) {
2167 XSelectInput(getBaseDisplay().getXDisplay(), getRootWindow(), NoEventMask);
2168 XSync(getBaseDisplay().getXDisplay(), False);
2170 LinkedListIterator<Workspace> it(workspacesList);
2171 for (Workspace *w = it.current(); w; it++, w = it.current())
2174 while (iconList->count()) {
2175 iconList->first()->restore();
2176 delete iconList->first();
2187 void BScreen::showPosition(int x, int y) {
2188 if (! geom_visible) {
2189 XMoveResizeWindow(getBaseDisplay().getXDisplay(), geom_window,
2190 (size().w() - geom_w) / 2,
2191 (size().h() - geom_h) / 2, geom_w, geom_h);
2192 XMapWindow(getBaseDisplay().getXDisplay(), geom_window);
2193 XRaiseWindow(getBaseDisplay().getXDisplay(), geom_window);
2195 geom_visible = True;
2200 sprintf(label, i18n->getMessage(ScreenSet, ScreenPositionFormat,
2201 "X: %4d x Y: %4d"), x, y);
2203 XClearWindow(getBaseDisplay().getXDisplay(), geom_window);
2205 if (i18n->multibyte()) {
2206 XmbDrawString(getBaseDisplay().getXDisplay(), geom_window,
2207 resource.wstyle.fontset, resource.wstyle.l_text_focus_gc,
2208 resource.bevel_width, resource.bevel_width -
2209 resource.wstyle.fontset_extents->max_ink_extent.y,
2210 label, strlen(label));
2212 XDrawString(getBaseDisplay().getXDisplay(), geom_window,
2213 resource.wstyle.l_text_focus_gc,
2214 resource.bevel_width,
2215 resource.wstyle.font->ascent +
2216 resource.bevel_width, label, strlen(label));
2221 void BScreen::showGeometry(unsigned int gx, unsigned int gy) {
2222 if (! geom_visible) {
2223 XMoveResizeWindow(getBaseDisplay().getXDisplay(), geom_window,
2224 (size().w() - geom_w) / 2,
2225 (size().h() - geom_h) / 2, geom_w, geom_h);
2226 XMapWindow(getBaseDisplay().getXDisplay(), geom_window);
2227 XRaiseWindow(getBaseDisplay().getXDisplay(), geom_window);
2229 geom_visible = True;
2234 sprintf(label, i18n->getMessage(ScreenSet, ScreenGeometryFormat,
2235 "W: %4d x H: %4d"), gx, gy);
2237 XClearWindow(getBaseDisplay().getXDisplay(), geom_window);
2239 if (i18n->multibyte()) {
2240 XmbDrawString(getBaseDisplay().getXDisplay(), geom_window,
2241 resource.wstyle.fontset, resource.wstyle.l_text_focus_gc,
2242 resource.bevel_width, resource.bevel_width -
2243 resource.wstyle.fontset_extents->max_ink_extent.y,
2244 label, strlen(label));
2246 XDrawString(getBaseDisplay().getXDisplay(), geom_window,
2247 resource.wstyle.l_text_focus_gc,
2248 resource.bevel_width,
2249 resource.wstyle.font->ascent +
2250 resource.bevel_width, label, strlen(label));
2255 void BScreen::hideGeometry(void) {
2257 XUnmapWindow(getBaseDisplay().getXDisplay(), geom_window);
2258 geom_visible = False;