1 // -*- mode: C++; indent-tabs-mode: nil; -*-
2 // Toolbar.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)
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:
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
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.
25 # include "../config.h"
26 #endif // HAVE_CONFIG_H
29 #include <X11/keysym.h>
33 #endif // HAVE_STRING_H
37 #endif // HAVE_STDIO_H
39 #ifdef TIME_WITH_SYS_TIME
40 # include <sys/time.h>
42 #else // !TIME_WITH_SYS_TIME
43 # ifdef HAVE_SYS_TIME_H
44 # include <sys/time.h>
45 # else // !HAVE_SYS_TIME_H
47 # endif // HAVE_SYS_TIME_H
48 #endif // TIME_WITH_SYS_TIME
55 #include "blackbox.hh"
56 #include "Clientmenu.hh"
58 #include "Iconmenu.hh"
60 #include "Rootmenu.hh"
64 #include "Workspace.hh"
65 #include "Workspacemenu.hh"
69 static long aMinuteFromNow(void) {
71 gettimeofday(&now, 0);
72 return ((60 - (now.tv_sec % 60)) * 1000);
76 Toolbar::Toolbar(BScreen *scrn) {
78 blackbox = screen->getBlackbox();
79 toolbarstr = (string)"session.screen" + itostring(screen->getScreenNumber())
81 config = blackbox->getConfig();
85 // get the clock updating every minute
86 clock_timer = new BTimer(blackbox, this);
87 clock_timer->setTimeout(aMinuteFromNow());
88 clock_timer->recurring(True);
90 frame.minute = frame.hour = -1;
92 hide_handler.toolbar = this;
93 hide_timer = new BTimer(blackbox, &hide_handler);
94 hide_timer->setTimeout(blackbox->getAutoRaiseDelay());
98 frame.grab_x = frame.grab_y = 0;
100 toolbarmenu = new Toolbarmenu(this);
102 display = blackbox->getXDisplay();
103 XSetWindowAttributes attrib;
104 unsigned long create_mask = CWBackPixmap | CWBackPixel | CWBorderPixel |
105 CWColormap | CWOverrideRedirect | CWEventMask;
106 attrib.background_pixmap = None;
107 attrib.background_pixel = attrib.border_pixel =
108 screen->getBorderColor()->pixel();
109 attrib.colormap = screen->getColormap();
110 attrib.override_redirect = True;
111 attrib.event_mask = ButtonPressMask | ButtonReleaseMask |
112 EnterWindowMask | LeaveWindowMask;
115 XCreateWindow(display, screen->getRootWindow(), 0, 0, 1, 1, 0,
116 screen->getDepth(), InputOutput, screen->getVisual(),
117 create_mask, &attrib);
118 blackbox->saveToolbarSearch(frame.window, this);
120 attrib.event_mask = ButtonPressMask | ButtonReleaseMask | ExposureMask |
121 KeyPressMask | EnterWindowMask;
123 frame.workspace_label =
124 XCreateWindow(display, frame.window, 0, 0, 1, 1, 0, screen->getDepth(),
125 InputOutput, screen->getVisual(), create_mask, &attrib);
126 blackbox->saveToolbarSearch(frame.workspace_label, this);
129 XCreateWindow(display, frame.window, 0, 0, 1, 1, 0, screen->getDepth(),
130 InputOutput, screen->getVisual(), create_mask, &attrib);
131 blackbox->saveToolbarSearch(frame.window_label, this);
134 XCreateWindow(display, frame.window, 0, 0, 1, 1, 0, screen->getDepth(),
135 InputOutput, screen->getVisual(), create_mask, &attrib);
136 blackbox->saveToolbarSearch(frame.clock, this);
139 XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen->getDepth(),
140 InputOutput, screen->getVisual(), create_mask, &attrib);
141 blackbox->saveToolbarSearch(frame.psbutton, this);
144 XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen->getDepth(),
145 InputOutput, screen->getVisual(), create_mask, &attrib);
146 blackbox->saveToolbarSearch(frame.nsbutton, this);
149 XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen->getDepth(),
150 InputOutput, screen->getVisual(), create_mask, &attrib);
151 blackbox->saveToolbarSearch(frame.pwbutton, this);
154 XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen->getDepth(),
155 InputOutput, screen->getVisual(), create_mask, &attrib);
156 blackbox->saveToolbarSearch(frame.nwbutton, this);
158 frame.base = frame.label = frame.wlabel = frame.clk = frame.button =
159 frame.pbutton = None;
161 screen->addStrut(&strut);
168 Toolbar::~Toolbar(void) {
171 if (frame.base) screen->getImageControl()->removeImage(frame.base);
172 if (frame.label) screen->getImageControl()->removeImage(frame.label);
173 if (frame.wlabel) screen->getImageControl()->removeImage(frame.wlabel);
174 if (frame.clk) screen->getImageControl()->removeImage(frame.clk);
175 if (frame.button) screen->getImageControl()->removeImage(frame.button);
176 if (frame.pbutton) screen->getImageControl()->removeImage(frame.pbutton);
178 blackbox->removeToolbarSearch(frame.window);
179 blackbox->removeToolbarSearch(frame.workspace_label);
180 blackbox->removeToolbarSearch(frame.window_label);
181 blackbox->removeToolbarSearch(frame.clock);
182 blackbox->removeToolbarSearch(frame.psbutton);
183 blackbox->removeToolbarSearch(frame.nsbutton);
184 blackbox->removeToolbarSearch(frame.pwbutton);
185 blackbox->removeToolbarSearch(frame.nwbutton);
187 XDestroyWindow(display, frame.workspace_label);
188 XDestroyWindow(display, frame.window_label);
189 XDestroyWindow(display, frame.clock);
191 XDestroyWindow(display, frame.window);
199 void Toolbar::mapToolbar() {
200 if (!screen->doHideToolbar()) {
201 //not hidden, so windows should not maximize over the toolbar
202 XMapSubwindows(display, frame.window);
203 XMapWindow(display, frame.window);
209 void Toolbar::unmapToolbar() {
210 if (toolbarmenu->isVisible())
212 //hidden so we can maximize over the toolbar
213 XUnmapWindow(display, frame.window);
218 void Toolbar::saveOnTop(bool b) {
220 config->setValue(toolbarstr + "onTop", on_top);
224 void Toolbar::saveAutoHide(bool b) {
226 config->setValue(toolbarstr + "autoHide", do_auto_hide);
230 void Toolbar::saveWidthPercent(unsigned int w) {
232 config->setValue(toolbarstr + "widthPercent", width_percent);
236 void Toolbar::savePlacement(int p) {
240 case TopLeft: pname = "TopLeft"; break;
241 case BottomLeft: pname = "BottomLeft"; break;
242 case TopCenter: pname = "TopCenter"; break;
243 case TopRight: pname = "TopRight"; break;
244 case BottomRight: pname = "BottomRight"; break;
245 case BottomCenter: default: pname = "BottomCenter"; break;
247 config->setValue(toolbarstr + "placement", pname);
251 void Toolbar::save_rc(void) {
253 saveAutoHide(do_auto_hide);
254 saveWidthPercent(width_percent);
255 savePlacement(placement);
259 void Toolbar::load_rc(void) {
262 if (! config->getValue(toolbarstr + "onTop", on_top))
265 if (! config->getValue(toolbarstr + "autoHide", do_auto_hide))
266 do_auto_hide = false;
267 hidden = do_auto_hide;
269 if (! config->getValue(toolbarstr + "widthPercent", width_percent) ||
270 width_percent == 0 || width_percent > 100)
273 if (config->getValue(toolbarstr + "placement", s)) {
276 else if (s == "BottomLeft")
277 placement = BottomLeft;
278 else if (s == "TopCenter")
279 placement = TopCenter;
280 else if (s == "TopRight")
281 placement = TopRight;
282 else if (s == "BottomRight")
283 placement = BottomRight;
284 else //if (s == "BottomCenter")
285 placement = BottomCenter;
287 placement = BottomCenter;
291 void Toolbar::reconfigure(void) {
292 unsigned int height = 0,
293 width = (screen->getWidth() * width_percent) / 100;
295 if (i18n.multibyte())
296 height = screen->getToolbarStyle()->fontset_extents->max_ink_extent.height;
298 height = screen->getToolbarStyle()->font->ascent +
299 screen->getToolbarStyle()->font->descent;
301 frame.bevel_w = screen->getBevelWidth();
302 frame.button_w = height;
304 frame.label_h = height;
305 height += (frame.bevel_w * 2);
307 frame.rect.setSize(width, height);
314 if (placement == TopLeft)
316 else if (placement == TopRight)
317 x = screen->getWidth() - frame.rect.width()
318 - (screen->getBorderWidth() * 2);
320 x = (screen->getWidth() - frame.rect.width()) / 2;
325 frame.y_hidden = screen->getBevelWidth() - screen->getBorderWidth()
326 - frame.rect.height();
333 if (placement == BottomLeft)
335 else if (placement == BottomRight)
336 x = screen->getWidth() - frame.rect.width()
337 - (screen->getBorderWidth() * 2);
339 x = (screen->getWidth() - frame.rect.width()) / 2;
341 y = screen->getHeight() - frame.rect.height()
342 - (screen->getBorderWidth() * 2);
345 frame.y_hidden = screen->getHeight() - screen->getBevelWidth()
346 - screen->getBorderWidth();
350 frame.rect.setPos(x, y);
355 time_t ttmp = time(NULL);
359 struct tm *tt = localtime(&ttmp);
362 int len = strftime(t, 1024, screen->getStrftimeFormat(), tt);
363 if (len == 0) { // invalid time format found
364 screen->saveStrftimeFormat("%I:%M %p"); // so use the default
365 len = strftime(t, 1024, screen->getStrftimeFormat(), tt);
367 // find the length of the rendered string and add room for two extra
368 // characters to it. This allows for variable width output of the fonts
369 if (i18n.multibyte()) {
370 XRectangle ink, logical;
371 XmbTextExtents(screen->getToolbarStyle()->fontset, t, len,
373 XFontSetExtents* extents = screen->getToolbarStyle()->fontset_extents;
374 frame.clock_w = logical.width +
375 (extents->max_logical_extent.width * 2);
377 XFontStruct* font = screen->getToolbarStyle()->font;
378 frame.clock_w = XTextWidth(font, t, len) +
379 ((font->max_bounds.rbearing - font->min_bounds.lbearing) * 2);
383 #else // !HAVE_STRFTIME
385 XTextWidth(screen->getToolbarStyle()->font,
386 i18n(ToolbarSet, ToolbarNoStrftimeLength, "00:00000"),
387 strlen(i18n(ToolbarSet, ToolbarNoStrftimeLength,
389 #endif // HAVE_STRFTIME
391 frame.workspace_label_w = 0;
393 for (unsigned int i = 0; i < screen->getWorkspaceCount(); i++) {
394 const string& workspace_name = screen->getWorkspace(i)->getName();
395 if (i18n.multibyte()) {
396 XRectangle ink, logical;
397 XmbTextExtents(screen->getToolbarStyle()->fontset,
398 workspace_name.c_str(), workspace_name.length(),
400 width = logical.width;
402 width = XTextWidth(screen->getToolbarStyle()->font,
403 workspace_name.c_str(), workspace_name.length());
406 if (width > frame.workspace_label_w) frame.workspace_label_w = width;
409 frame.workspace_label_w = frame.clock_w =
410 std::max(frame.workspace_label_w, frame.clock_w) + (frame.bevel_w * 4);
412 // XXX: where'd the +6 come from?
413 frame.window_label_w =
414 (frame.rect.width() - (frame.clock_w + (frame.button_w * 4) +
415 frame.workspace_label_w + (frame.bevel_w * 8) + 6));
418 XMoveResizeWindow(display, frame.window, frame.x_hidden, frame.y_hidden,
419 frame.rect.width(), frame.rect.height());
421 XMoveResizeWindow(display, frame.window, frame.rect.x(), frame.rect.y(),
422 frame.rect.width(), frame.rect.height());
425 XMoveResizeWindow(display, frame.workspace_label, frame.bevel_w,
426 frame.bevel_w, frame.workspace_label_w,
428 XMoveResizeWindow(display, frame.psbutton,
429 ((frame.bevel_w * 2) + frame.workspace_label_w + 1),
430 frame.bevel_w + 1, frame.button_w, frame.button_w);
431 XMoveResizeWindow(display, frame.nsbutton,
432 ((frame.bevel_w * 3) + frame.workspace_label_w +
433 frame.button_w + 2), frame.bevel_w + 1, frame.button_w,
435 XMoveResizeWindow(display, frame.window_label,
436 ((frame.bevel_w * 4) + (frame.button_w * 2) +
437 frame.workspace_label_w + 3), frame.bevel_w,
438 frame.window_label_w, frame.label_h);
439 XMoveResizeWindow(display, frame.pwbutton,
440 ((frame.bevel_w * 5) + (frame.button_w * 2) +
441 frame.workspace_label_w + frame.window_label_w + 4),
442 frame.bevel_w + 1, frame.button_w, frame.button_w);
443 XMoveResizeWindow(display, frame.nwbutton,
444 ((frame.bevel_w * 6) + (frame.button_w * 3) +
445 frame.workspace_label_w + frame.window_label_w + 5),
446 frame.bevel_w + 1, frame.button_w, frame.button_w);
447 XMoveResizeWindow(display, frame.clock,
448 frame.rect.width() - frame.clock_w - (frame.bevel_w * 2),
449 frame.bevel_w, frame.clock_w, frame.label_h);
451 ToolbarStyle *style = screen->getToolbarStyle();
452 frame.base = style->toolbar.render(frame.rect.width(), frame.rect.height(),
455 XSetWindowBackground(display, frame.window,
456 style->toolbar.color().pixel());
458 XSetWindowBackgroundPixmap(display, frame.window, frame.base);
460 frame.label = style->window.render(frame.window_label_w, frame.label_h,
463 XSetWindowBackground(display, frame.window_label,
464 style->window.color().pixel());
466 XSetWindowBackgroundPixmap(display, frame.window_label, frame.label);
468 frame.wlabel = style->label.render(frame.workspace_label_w, frame.label_h,
471 XSetWindowBackground(display, frame.workspace_label,
472 style->label.color().pixel());
474 XSetWindowBackgroundPixmap(display, frame.workspace_label, frame.wlabel);
476 frame.clk = style->clock.render(frame.clock_w, frame.label_h, frame.clk);
478 XSetWindowBackground(display, frame.clock, style->clock.color().pixel());
480 XSetWindowBackgroundPixmap(display, frame.clock, frame.clk);
482 frame.button = style->button.render(frame.button_w, frame.button_w,
484 if (! frame.button) {
485 frame.button_pixel = style->button.color().pixel();
486 XSetWindowBackground(display, frame.psbutton, frame.button_pixel);
487 XSetWindowBackground(display, frame.nsbutton, frame.button_pixel);
488 XSetWindowBackground(display, frame.pwbutton, frame.button_pixel);
489 XSetWindowBackground(display, frame.nwbutton, frame.button_pixel);
491 XSetWindowBackgroundPixmap(display, frame.psbutton, frame.button);
492 XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.button);
493 XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.button);
494 XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.button);
497 frame.pbutton = style->pressed.render(frame.button_w, frame.button_w,
500 frame.pbutton_pixel = style->pressed.color().pixel();
502 XSetWindowBorder(display, frame.window,
503 screen->getBorderColor()->pixel());
504 XSetWindowBorderWidth(display, frame.window, screen->getBorderWidth());
506 XClearWindow(display, frame.window);
507 XClearWindow(display, frame.workspace_label);
508 XClearWindow(display, frame.window_label);
509 XClearWindow(display, frame.clock);
510 XClearWindow(display, frame.psbutton);
511 XClearWindow(display, frame.nsbutton);
512 XClearWindow(display, frame.pwbutton);
513 XClearWindow(display, frame.nwbutton);
516 redrawWorkspaceLabel();
517 redrawPrevWorkspaceButton();
518 redrawNextWorkspaceButton();
519 redrawPrevWindowButton();
520 redrawNextWindowButton();
523 toolbarmenu->reconfigure();
527 void Toolbar::updateStrut(void) {
528 // left and right are always 0
529 strut.top = strut.bottom = 0;
531 if (! screen->doHideToolbar()) {
536 strut.top = getExposedHeight() + (screen->getBorderWidth() * 2);
539 strut.bottom = getExposedHeight() + (screen->getBorderWidth() * 2);
543 screen->updateAvailableArea();
548 void Toolbar::checkClock(bool redraw) {
549 #else // !HAVE_STRFTIME
550 void Toolbar::checkClock(bool redraw, bool date) {
551 #endif // HAVE_STRFTIME
555 if ((tmp = time(NULL)) != -1) {
556 if (! (tt = localtime(&tmp))) return;
557 if (tt->tm_min != frame.minute || tt->tm_hour != frame.hour) {
558 frame.hour = tt->tm_hour;
559 frame.minute = tt->tm_min;
560 XClearWindow(display, frame.clock);
568 if (! strftime(t, 1024, screen->getStrftimeFormat(), tt))
570 #else // !HAVE_STRFTIME
573 // format the date... with special consideration for y2k ;)
574 if (screen->getDateFormat() == Blackbox::B_EuropeanDate)
575 sprintf(t, 18n(ToolbarSet, ToolbarNoStrftimeDateFormatEu,
577 tt->tm_mday, tt->tm_mon + 1,
578 (tt->tm_year >= 100) ? tt->tm_year - 100 : tt->tm_year);
580 sprintf(t, i18n(ToolbarSet, ToolbarNoStrftimeDateFormat,
582 tt->tm_mon + 1, tt->tm_mday,
583 (tt->tm_year >= 100) ? tt->tm_year - 100 : tt->tm_year);
585 if (screen->isClock24Hour())
586 sprintf(t, i18n(ToolbarSet, ToolbarNoStrftimeTimeFormat24,
588 frame.hour, frame.minute);
590 sprintf(t, i18n(ToolbarSet, ToolbarNoStrftimeTimeFormat12,
592 ((frame.hour > 12) ? frame.hour - 12 :
593 ((frame.hour == 0) ? 12 : frame.hour)), frame.minute,
594 ((frame.hour >= 12) ?
595 i18n(ToolbarSet, ToolbarNoStrftimeTimeFormatP, "p") :
596 i18n(ToolbarSet, ToolbarNoStrftimeTimeFormatA, "a")));
598 #endif // HAVE_STRFTIME
600 ToolbarStyle *style = screen->getToolbarStyle();
602 int pos = frame.bevel_w * 2, // this is modified by doJustify()
603 dlen = style->doJustify(t, pos, frame.clock_w,
604 frame.bevel_w * 4, i18n.multibyte());
605 BPen pen(style->c_text, style->font);
606 if (i18n.multibyte())
607 XmbDrawString(display, frame.clock, style->fontset, pen.gc(),
608 pos, (1 - style->fontset_extents->max_ink_extent.y),
611 XDrawString(display, frame.clock, pen.gc(), pos,
612 (style->font->ascent + 1), t, dlen);
617 void Toolbar::redrawWindowLabel(bool redraw) {
618 BlackboxWindow *foc = screen->getBlackbox()->getFocusedWindow();
620 XClearWindow(display, frame.window_label);
625 XClearWindow(display, frame.window_label);
627 if (foc->getScreen() != screen) return;
629 const char *title = foc->getTitle();
630 ToolbarStyle *style = screen->getToolbarStyle();
632 int pos = frame.bevel_w * 2, // modified by doJustify()
633 dlen = style->doJustify(title, pos, frame.window_label_w,
634 frame.bevel_w * 4, i18n.multibyte());
635 BPen pen(style->w_text, style->font);
636 if (i18n.multibyte())
637 XmbDrawString(display, frame.window_label, style->fontset, pen.gc(), pos,
638 (1 - style->fontset_extents->max_ink_extent.y),
641 XDrawString(display, frame.window_label, pen.gc(), pos,
642 (style->font->ascent + 1), title, dlen);
646 void Toolbar::redrawWorkspaceLabel(bool redraw) {
647 const string& name = screen->getCurrentWorkspace()->getName();
650 XClearWindow(display, frame.workspace_label);
652 ToolbarStyle *style = screen->getToolbarStyle();
654 int pos = frame.bevel_w * 2,
655 dlen = style->doJustify(name.c_str(), pos, frame.workspace_label_w,
656 frame.bevel_w * 4, i18n.multibyte());
657 BPen pen(style->l_text, style->font);
658 if (i18n.multibyte())
659 XmbDrawString(display, frame.workspace_label, style->fontset, pen.gc(),
660 pos, (1 - style->fontset_extents->max_ink_extent.y),
663 XDrawString(display, frame.workspace_label, pen.gc(), pos,
664 (style->font->ascent + 1),
669 void Toolbar::redrawPrevWorkspaceButton(bool pressed, bool redraw) {
673 XSetWindowBackgroundPixmap(display, frame.psbutton, frame.pbutton);
675 XSetWindowBackground(display, frame.psbutton, frame.pbutton_pixel);
678 XSetWindowBackgroundPixmap(display, frame.psbutton, frame.button);
680 XSetWindowBackground(display, frame.psbutton, frame.button_pixel);
682 XClearWindow(display, frame.psbutton);
685 int hh = frame.button_w / 2, hw = frame.button_w / 2;
688 pts[0].x = hw - 2; pts[0].y = hh;
689 pts[1].x = 4; pts[1].y = 2;
690 pts[2].x = 0; pts[2].y = -4;
692 ToolbarStyle *style = screen->getToolbarStyle();
693 BPen pen(style->b_pic, style->font);
694 XFillPolygon(display, frame.psbutton, pen.gc(),
695 pts, 3, Convex, CoordModePrevious);
699 void Toolbar::redrawNextWorkspaceButton(bool pressed, bool redraw) {
703 XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.pbutton);
705 XSetWindowBackground(display, frame.nsbutton, frame.pbutton_pixel);
708 XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.button);
710 XSetWindowBackground(display, frame.nsbutton, frame.button_pixel);
712 XClearWindow(display, frame.nsbutton);
715 int hh = frame.button_w / 2, hw = frame.button_w / 2;
718 pts[0].x = hw - 2; pts[0].y = hh - 2;
719 pts[1].x = 4; pts[1].y = 2;
720 pts[2].x = -4; pts[2].y = 2;
722 ToolbarStyle *style = screen->getToolbarStyle();
723 BPen pen(style->b_pic, style->font);
724 XFillPolygon(display, frame.nsbutton, pen.gc(),
725 pts, 3, Convex, CoordModePrevious);
729 void Toolbar::redrawPrevWindowButton(bool pressed, bool redraw) {
733 XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.pbutton);
735 XSetWindowBackground(display, frame.pwbutton, frame.pbutton_pixel);
738 XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.button);
740 XSetWindowBackground(display, frame.pwbutton, frame.button_pixel);
742 XClearWindow(display, frame.pwbutton);
745 int hh = frame.button_w / 2, hw = frame.button_w / 2;
748 pts[0].x = hw - 2; pts[0].y = hh;
749 pts[1].x = 4; pts[1].y = 2;
750 pts[2].x = 0; pts[2].y = -4;
752 ToolbarStyle *style = screen->getToolbarStyle();
753 BPen pen(style->b_pic, style->font);
754 XFillPolygon(display, frame.pwbutton, pen.gc(),
755 pts, 3, Convex, CoordModePrevious);
759 void Toolbar::redrawNextWindowButton(bool pressed, bool redraw) {
763 XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.pbutton);
765 XSetWindowBackground(display, frame.nwbutton, frame.pbutton_pixel);
768 XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.button);
770 XSetWindowBackground(display, frame.nwbutton, frame.button_pixel);
772 XClearWindow(display, frame.nwbutton);
775 int hh = frame.button_w / 2, hw = frame.button_w / 2;
778 pts[0].x = hw - 2; pts[0].y = hh - 2;
779 pts[1].x = 4; pts[1].y = 2;
780 pts[2].x = -4; pts[2].y = 2;
782 ToolbarStyle *style = screen->getToolbarStyle();
783 BPen pen(style->b_pic, style->font);
784 XFillPolygon(display, frame.nwbutton, pen.gc(), pts, 3, Convex,
789 void Toolbar::edit(void) {
794 XGetInputFocus(display, &window, &foo);
795 if (window == frame.workspace_label)
798 XSetInputFocus(display, frame.workspace_label,
799 RevertToPointerRoot, CurrentTime);
800 XClearWindow(display, frame.workspace_label);
802 blackbox->setNoFocus(True);
803 if (blackbox->getFocusedWindow())
804 blackbox->getFocusedWindow()->setFocusFlag(False);
806 ToolbarStyle *style = screen->getToolbarStyle();
807 BPen pen(style->l_text, style->font);
808 XDrawRectangle(display, frame.workspace_label, pen.gc(),
809 frame.workspace_label_w / 2, 0, 1,
811 // change the background of the window to that of an active window label
812 BTexture *texture = &(screen->getWindowStyle()->l_focus);
813 frame.wlabel = texture->render(frame.workspace_label_w, frame.label_h,
816 XSetWindowBackground(display, frame.workspace_label,
817 texture->color().pixel());
819 XSetWindowBackgroundPixmap(display, frame.workspace_label, frame.wlabel);
823 void Toolbar::buttonPressEvent(XButtonEvent *be) {
824 if (be->button == 1) {
825 if (be->window == frame.psbutton)
826 redrawPrevWorkspaceButton(True, True);
827 else if (be->window == frame.nsbutton)
828 redrawNextWorkspaceButton(True, True);
829 else if (be->window == frame.pwbutton)
830 redrawPrevWindowButton(True, True);
831 else if (be->window == frame.nwbutton)
832 redrawNextWindowButton(True, True);
833 #ifndef HAVE_STRFTIME
834 else if (be->window == frame.clock) {
835 XClearWindow(display, frame.clock);
836 checkClock(True, True);
838 #endif // HAVE_STRFTIME
840 Window w[1] = { frame.window };
841 screen->raiseWindows(w, 1);
843 } else if (be->button == 2 && (! on_top)) {
844 XLowerWindow(display, frame.window);
845 } else if (be->button == 3) {
846 if (toolbarmenu->isVisible()) {
851 x = be->x_root - (toolbarmenu->getWidth() / 2);
852 y = be->y_root - (toolbarmenu->getHeight() / 2);
856 else if (x + toolbarmenu->getWidth() > screen->getWidth())
857 x = screen->getWidth() - toolbarmenu->getWidth();
861 else if (y + toolbarmenu->getHeight() > screen->getHeight())
862 y = screen->getHeight() - toolbarmenu->getHeight();
864 toolbarmenu->move(x, y);
872 void Toolbar::buttonReleaseEvent(XButtonEvent *re) {
873 if (re->button == 1) {
874 if (re->window == frame.psbutton) {
875 redrawPrevWorkspaceButton(False, True);
877 if (re->x >= 0 && re->x < static_cast<signed>(frame.button_w) &&
878 re->y >= 0 && re->y < static_cast<signed>(frame.button_w))
879 if (screen->getCurrentWorkspace()->getID() > 0)
880 screen->changeWorkspaceID(screen->getCurrentWorkspace()->
883 screen->changeWorkspaceID(screen->getWorkspaceCount() - 1);
884 } else if (re->window == frame.nsbutton) {
885 redrawNextWorkspaceButton(False, True);
887 if (re->x >= 0 && re->x < static_cast<signed>(frame.button_w) &&
888 re->y >= 0 && re->y < static_cast<signed>(frame.button_w))
889 if (screen->getCurrentWorkspace()->getID() <
890 (screen->getWorkspaceCount() - 1))
891 screen->changeWorkspaceID(screen->getCurrentWorkspace()->
894 screen->changeWorkspaceID(0);
895 } else if (re->window == frame.pwbutton) {
896 redrawPrevWindowButton(False, True);
898 if (re->x >= 0 && re->x < static_cast<signed>(frame.button_w) &&
899 re->y >= 0 && re->y < static_cast<signed>(frame.button_w))
901 } else if (re->window == frame.nwbutton) {
902 redrawNextWindowButton(False, True);
904 if (re->x >= 0 && re->x < static_cast<signed>(frame.button_w) &&
905 re->y >= 0 && re->y < static_cast<signed>(frame.button_w))
907 } else if (re->window == frame.window_label)
908 screen->raiseFocus();
909 #ifndef HAVE_STRFTIME
910 else if (re->window == frame.clock) {
911 XClearWindow(display, frame.clock);
914 #endif // HAVE_STRFTIME
919 void Toolbar::enterNotifyEvent(XCrossingEvent *) {
924 if (! hide_timer->isTiming()) hide_timer->start();
926 if (hide_timer->isTiming()) hide_timer->stop();
930 void Toolbar::leaveNotifyEvent(XCrossingEvent *) {
935 if (hide_timer->isTiming()) hide_timer->stop();
936 } else if (! toolbarmenu->isVisible()) {
937 if (! hide_timer->isTiming()) hide_timer->start();
942 void Toolbar::exposeEvent(XExposeEvent *ee) {
943 if (ee->window == frame.clock) checkClock(True);
944 else if (ee->window == frame.workspace_label && (! editing))
945 redrawWorkspaceLabel();
946 else if (ee->window == frame.window_label) redrawWindowLabel();
947 else if (ee->window == frame.psbutton) redrawPrevWorkspaceButton();
948 else if (ee->window == frame.nsbutton) redrawNextWorkspaceButton();
949 else if (ee->window == frame.pwbutton) redrawPrevWindowButton();
950 else if (ee->window == frame.nwbutton) redrawNextWindowButton();
954 void Toolbar::keyPressEvent(XKeyEvent *ke) {
955 if (ke->window == frame.workspace_label && editing) {
956 if (new_workspace_name.empty()) {
962 XLookupString(ke, keychar, 1, &ks, 0);
964 // either we are told to end with a return or we hit 127 chars
965 if (ks == XK_Return || new_name_pos == 127) {
968 blackbox->setNoFocus(False);
969 if (blackbox->getFocusedWindow()) {
970 blackbox->getFocusedWindow()->setInputFocus();
972 blackbox->setFocusedWindow(0);
975 Workspace *wkspc = screen->getCurrentWorkspace();
976 wkspc->setName(new_workspace_name);
977 wkspc->getMenu()->hide();
979 screen->getWorkspacemenu()->changeItemLabel(wkspc->getID() + 2,
981 screen->getWorkspacemenu()->update();
983 new_workspace_name.erase();
986 // reset the background to that of the workspace label (its normal
988 BTexture *texture = &(screen->getToolbarStyle()->label);
989 frame.wlabel = texture->render(frame.workspace_label_w, frame.label_h,
992 XSetWindowBackground(display, frame.workspace_label,
993 texture->color().pixel());
995 XSetWindowBackgroundPixmap(display, frame.workspace_label,
998 } else if (! (ks == XK_Shift_L || ks == XK_Shift_R ||
999 ks == XK_Control_L || ks == XK_Control_R ||
1000 ks == XK_Caps_Lock || ks == XK_Shift_Lock ||
1001 ks == XK_Meta_L || ks == XK_Meta_R ||
1002 ks == XK_Alt_L || ks == XK_Alt_R ||
1003 ks == XK_Super_L || ks == XK_Super_R ||
1004 ks == XK_Hyper_L || ks == XK_Hyper_R)) {
1005 if (ks == XK_BackSpace) {
1006 if (new_name_pos > 0) {
1008 new_workspace_name.erase(new_name_pos);
1010 new_workspace_name.resize(0);
1013 new_workspace_name += (*keychar);
1017 XClearWindow(display, frame.workspace_label);
1018 unsigned int l = new_workspace_name.length(), tw, x;
1020 if (i18n.multibyte()) {
1021 XRectangle ink, logical;
1022 XmbTextExtents(screen->getToolbarStyle()->fontset,
1023 new_workspace_name.c_str(), l, &ink, &logical);
1026 tw = XTextWidth(screen->getToolbarStyle()->font,
1027 new_workspace_name.c_str(), l);
1029 x = (frame.workspace_label_w - tw) / 2;
1031 if (x < frame.bevel_w) x = frame.bevel_w;
1033 ToolbarStyle *style = screen->getToolbarStyle();
1034 BPen pen(style->l_text, style->font);
1035 if (i18n.multibyte())
1036 XmbDrawString(display, frame.workspace_label, style->fontset,
1038 (1 - style->fontset_extents->max_ink_extent.y),
1039 new_workspace_name.c_str(), l);
1041 XDrawString(display, frame.workspace_label, pen.gc(), x,
1042 (style->font->ascent + 1),
1043 new_workspace_name.c_str(), l);
1044 XDrawRectangle(display, frame.workspace_label, pen.gc(), x + tw, 0, 1,
1051 void Toolbar::timeout(void) {
1054 clock_timer->setTimeout(aMinuteFromNow());
1058 void Toolbar::HideHandler::timeout(void) {
1059 toolbar->hidden = ! toolbar->hidden;
1060 if (toolbar->hidden)
1061 XMoveWindow(toolbar->display, toolbar->frame.window,
1062 toolbar->frame.x_hidden, toolbar->frame.y_hidden);
1064 XMoveWindow(toolbar->display, toolbar->frame.window,
1065 toolbar->frame.rect.x(), toolbar->frame.rect.y());
1069 void Toolbar::toggleAutoHide(void) {
1070 saveAutoHide(! doAutoHide());
1073 screen->getSlit()->reposition();
1075 if (do_auto_hide == False && hidden) {
1076 // force the slit to be visible
1077 if (hide_timer->isTiming()) hide_timer->stop();
1078 hide_handler.timeout();
1083 Toolbarmenu::Toolbarmenu(Toolbar *tb) : Basemenu(tb->screen) {
1086 setLabel(i18n(ToolbarSet, ToolbarToolbarTitle, "Toolbar"));
1089 placementmenu = new Placementmenu(this);
1091 insert(i18n(CommonSet, CommonPlacementTitle, "Placement"),
1093 insert(i18n(CommonSet, CommonAlwaysOnTop, "Always on top"), 1);
1094 insert(i18n(CommonSet, CommonAutoHide, "Auto hide"), 2);
1095 insert(i18n(ToolbarSet, ToolbarEditWkspcName,
1096 "Edit current workspace name"), 3);
1103 void Toolbarmenu::setValues() {
1104 setItemSelected(1, toolbar->isOnTop());
1105 setItemSelected(2, toolbar->doAutoHide());
1109 Toolbarmenu::~Toolbarmenu(void) {
1110 delete placementmenu;
1114 void Toolbarmenu::itemSelected(int button, unsigned int index) {
1118 BasemenuItem *item = find(index);
1121 switch (item->function()) {
1122 case 1: { // always on top
1123 toolbar->saveOnTop(! toolbar->isOnTop());
1124 setItemSelected(1, toolbar->isOnTop());
1126 if (toolbar->isOnTop()) getScreen()->raiseWindows((Window *) 0, 0);
1130 case 2: { // auto hide
1131 toolbar->toggleAutoHide();
1132 setItemSelected(2, toolbar->doAutoHide());
1137 case 3: { // edit current workspace name
1147 void Toolbarmenu::internal_hide(void) {
1148 Basemenu::internal_hide();
1149 if (toolbar->doAutoHide() && ! toolbar->isEditing())
1150 toolbar->hide_handler.timeout();
1154 void Toolbarmenu::reconfigure(void) {
1156 placementmenu->reconfigure();
1158 Basemenu::reconfigure();
1162 Toolbarmenu::Placementmenu::Placementmenu(Toolbarmenu *tm)
1163 : Basemenu(tm->toolbar->screen), toolbar(tm->toolbar) {
1164 setLabel(i18n(ToolbarSet, ToolbarToolbarPlacement, "Toolbar Placement"));
1166 setMinimumSublevels(3);
1168 insert(i18n(CommonSet, CommonPlacementTopLeft, "Top Left"),
1170 insert(i18n(CommonSet, CommonPlacementBottomLeft, "Bottom Left"),
1171 Toolbar::BottomLeft);
1172 insert(i18n(CommonSet, CommonPlacementTopCenter, "Top Center"),
1173 Toolbar::TopCenter);
1174 insert(i18n(CommonSet, CommonPlacementBottomCenter, "Bottom Center"),
1175 Toolbar::BottomCenter);
1176 insert(i18n(CommonSet, CommonPlacementTopRight, "Top Right"),
1178 insert(i18n(CommonSet, CommonPlacementBottomRight, "Bottom Right"),
1179 Toolbar::BottomRight);
1185 void Toolbarmenu::Placementmenu::setValues(void) {
1187 switch (toolbar->getPlacement()) {
1188 case Toolbar::BottomRight:
1190 case Toolbar::TopRight:
1192 case Toolbar::BottomCenter:
1194 case Toolbar::TopCenter:
1196 case Toolbar::BottomLeft:
1198 case Toolbar::TopLeft:
1201 setItemSelected(0, 0 == place);
1202 setItemSelected(1, 1 == place);
1203 setItemSelected(2, 2 == place);
1204 setItemSelected(3, 3 == place);
1205 setItemSelected(4, 4 == place);
1206 setItemSelected(5, 5 == place);
1210 void Toolbarmenu::Placementmenu::reconfigure(void) {
1212 Basemenu::reconfigure();
1216 void Toolbarmenu::Placementmenu::itemSelected(int button, unsigned int index) {
1220 BasemenuItem *item = find(index);
1223 toolbar->savePlacement(item->function());
1225 toolbar->reconfigure();
1227 // reposition the slit as well to make sure it doesn't intersect the
1229 getScreen()->getSlit()->reposition();
1233 int ToolbarStyle::doJustify(const char *text, int &start_pos,
1234 unsigned int max_length, unsigned int modifier,
1235 bool multibyte) const {
1236 size_t text_len = strlen(text);
1237 unsigned int length;
1241 XRectangle ink, logical;
1242 XmbTextExtents(fontset, text, text_len, &ink, &logical);
1243 length = logical.width;
1245 length = XTextWidth(font, text, text_len);
1248 } while (length > max_length && text_len-- > 0);
1252 start_pos += max_length - length;
1256 start_pos += (max_length - length) / 2;