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"
59 #include "Iconmenu.hh"
61 #include "Rootmenu.hh"
65 #include "Workspace.hh"
66 #include "Workspacemenu.hh"
70 static long aMinuteFromNow(void) {
72 gettimeofday(&now, 0);
73 return ((60 - (now.tv_sec % 60)) * 1000);
77 Toolbar::Toolbar(BScreen *scrn) {
79 blackbox = screen->getBlackbox();
80 toolbarstr = (string)"session.screen" + itostring(screen->getScreenNumber())
82 config = blackbox->getConfig();
86 // get the clock updating every minute
87 clock_timer = new BTimer(blackbox, this);
88 clock_timer->setTimeout(aMinuteFromNow());
89 clock_timer->recurring(True);
91 frame.minute = frame.hour = -1;
93 hide_handler.toolbar = this;
94 hide_timer = new BTimer(blackbox, &hide_handler);
95 hide_timer->setTimeout(blackbox->getAutoRaiseDelay());
99 frame.grab_x = frame.grab_y = 0;
101 toolbarmenu = new Toolbarmenu(this);
103 display = blackbox->getXDisplay();
104 XSetWindowAttributes attrib;
105 unsigned long create_mask = CWBackPixmap | CWBackPixel | CWBorderPixel |
106 CWColormap | CWOverrideRedirect | CWEventMask;
107 attrib.background_pixmap = None;
108 attrib.background_pixel = attrib.border_pixel =
109 screen->getBorderColor()->pixel();
110 attrib.colormap = screen->getColormap();
111 attrib.override_redirect = True;
112 attrib.event_mask = ButtonPressMask | ButtonReleaseMask |
113 EnterWindowMask | LeaveWindowMask;
116 XCreateWindow(display, screen->getRootWindow(), 0, 0, 1, 1, 0,
117 screen->getDepth(), InputOutput, screen->getVisual(),
118 create_mask, &attrib);
119 blackbox->saveToolbarSearch(frame.window, this);
121 attrib.event_mask = ButtonPressMask | ButtonReleaseMask | ExposureMask |
122 KeyPressMask | EnterWindowMask;
124 frame.workspace_label =
125 XCreateWindow(display, frame.window, 0, 0, 1, 1, 0, screen->getDepth(),
126 InputOutput, screen->getVisual(), create_mask, &attrib);
127 blackbox->saveToolbarSearch(frame.workspace_label, this);
130 XCreateWindow(display, frame.window, 0, 0, 1, 1, 0, screen->getDepth(),
131 InputOutput, screen->getVisual(), create_mask, &attrib);
132 blackbox->saveToolbarSearch(frame.window_label, this);
135 XCreateWindow(display, frame.window, 0, 0, 1, 1, 0, screen->getDepth(),
136 InputOutput, screen->getVisual(), create_mask, &attrib);
137 blackbox->saveToolbarSearch(frame.clock, this);
140 XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen->getDepth(),
141 InputOutput, screen->getVisual(), create_mask, &attrib);
142 blackbox->saveToolbarSearch(frame.psbutton, this);
145 XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen->getDepth(),
146 InputOutput, screen->getVisual(), create_mask, &attrib);
147 blackbox->saveToolbarSearch(frame.nsbutton, this);
150 XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen->getDepth(),
151 InputOutput, screen->getVisual(), create_mask, &attrib);
152 blackbox->saveToolbarSearch(frame.pwbutton, this);
155 XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen->getDepth(),
156 InputOutput, screen->getVisual(), create_mask, &attrib);
157 blackbox->saveToolbarSearch(frame.nwbutton, this);
159 frame.base = frame.label = frame.wlabel = frame.clk = frame.button =
160 frame.pbutton = None;
162 screen->addStrut(&strut);
169 Toolbar::~Toolbar(void) {
172 if (frame.base) screen->getImageControl()->removeImage(frame.base);
173 if (frame.label) screen->getImageControl()->removeImage(frame.label);
174 if (frame.wlabel) screen->getImageControl()->removeImage(frame.wlabel);
175 if (frame.clk) screen->getImageControl()->removeImage(frame.clk);
176 if (frame.button) screen->getImageControl()->removeImage(frame.button);
177 if (frame.pbutton) screen->getImageControl()->removeImage(frame.pbutton);
179 blackbox->removeToolbarSearch(frame.window);
180 blackbox->removeToolbarSearch(frame.workspace_label);
181 blackbox->removeToolbarSearch(frame.window_label);
182 blackbox->removeToolbarSearch(frame.clock);
183 blackbox->removeToolbarSearch(frame.psbutton);
184 blackbox->removeToolbarSearch(frame.nsbutton);
185 blackbox->removeToolbarSearch(frame.pwbutton);
186 blackbox->removeToolbarSearch(frame.nwbutton);
188 XDestroyWindow(display, frame.workspace_label);
189 XDestroyWindow(display, frame.window_label);
190 XDestroyWindow(display, frame.clock);
192 XDestroyWindow(display, frame.window);
200 void Toolbar::mapToolbar() {
201 if (!screen->doHideToolbar()) {
202 //not hidden, so windows should not maximize over the toolbar
203 XMapSubwindows(display, frame.window);
204 XMapWindow(display, frame.window);
210 void Toolbar::unmapToolbar() {
211 if (toolbarmenu->isVisible())
213 //hidden so we can maximize over the toolbar
214 XUnmapWindow(display, frame.window);
219 void Toolbar::saveOnTop(bool b) {
221 config->setValue(toolbarstr + "onTop", on_top);
225 void Toolbar::saveAutoHide(bool b) {
227 config->setValue(toolbarstr + "autoHide", do_auto_hide);
231 void Toolbar::saveWidthPercent(unsigned int w) {
233 config->setValue(toolbarstr + "widthPercent", width_percent);
237 void Toolbar::savePlacement(int p) {
241 case TopLeft: pname = "TopLeft"; break;
242 case BottomLeft: pname = "BottomLeft"; break;
243 case TopCenter: pname = "TopCenter"; break;
244 case TopRight: pname = "TopRight"; break;
245 case BottomRight: pname = "BottomRight"; break;
246 case BottomCenter: default: pname = "BottomCenter"; break;
248 config->setValue(toolbarstr + "placement", pname);
252 void Toolbar::save_rc(void) {
254 saveAutoHide(do_auto_hide);
255 saveWidthPercent(width_percent);
256 savePlacement(placement);
260 void Toolbar::load_rc(void) {
263 if (! config->getValue(toolbarstr + "onTop", on_top))
266 if (! config->getValue(toolbarstr + "autoHide", do_auto_hide))
267 do_auto_hide = false;
268 hidden = do_auto_hide;
270 if (! config->getValue(toolbarstr + "widthPercent", width_percent) ||
271 width_percent == 0 || width_percent > 100)
274 if (config->getValue(toolbarstr + "placement", s)) {
277 else if (s == "BottomLeft")
278 placement = BottomLeft;
279 else if (s == "TopCenter")
280 placement = TopCenter;
281 else if (s == "TopRight")
282 placement = TopRight;
283 else if (s == "BottomRight")
284 placement = BottomRight;
285 else //if (s == "BottomCenter")
286 placement = BottomCenter;
288 placement = BottomCenter;
292 void Toolbar::reconfigure(void) {
293 unsigned int width, height;
295 width = (screen->getWidth() * width_percent) / 100;
296 height = screen->getToolbarStyle()->font->height();
298 frame.bevel_w = screen->getBevelWidth();
299 frame.button_w = height;
301 frame.label_h = height;
302 height += (frame.bevel_w * 2);
304 frame.rect.setSize(width, height);
311 if (placement == TopLeft)
313 else if (placement == TopRight)
314 x = screen->getWidth() - frame.rect.width()
315 - (screen->getBorderWidth() * 2);
317 x = (screen->getWidth() - frame.rect.width()) / 2;
322 frame.y_hidden = screen->getBevelWidth() - screen->getBorderWidth()
323 - frame.rect.height();
330 if (placement == BottomLeft)
332 else if (placement == BottomRight)
333 x = screen->getWidth() - frame.rect.width()
334 - (screen->getBorderWidth() * 2);
336 x = (screen->getWidth() - frame.rect.width()) / 2;
338 y = screen->getHeight() - frame.rect.height()
339 - (screen->getBorderWidth() * 2);
342 frame.y_hidden = screen->getHeight() - screen->getBevelWidth()
343 - screen->getBorderWidth();
347 frame.rect.setPos(x, y);
352 time_t ttmp = time(NULL);
356 struct tm *tt = localtime(&ttmp);
359 int len = strftime(t, 1024, screen->getStrftimeFormat(), tt);
360 if (len == 0) { // invalid time format found
361 screen->saveStrftimeFormat("%I:%M %p"); // so use the default
362 strftime(t, 1024, screen->getStrftimeFormat(), tt);
364 // find the length of the rendered string and add room for two extra
365 // characters to it. This allows for variable width output of the fonts
366 BFont *font = screen->getToolbarStyle()->font;
367 frame.clock_w = font->measureString(t) + font->maxCharWidth() * 2;
370 #else // !HAVE_STRFTIME
372 string s = i18n(ToolbarSet, ToolbarNoStrftimeLength, "00:00000");
373 frame.clock_w = screen->getToolbarStyle()->font->measureString(s);
375 #endif // HAVE_STRFTIME
377 frame.workspace_label_w = 0;
379 for (unsigned int i = 0; i < screen->getWorkspaceCount(); i++) {
380 const string& workspace_name = screen->getWorkspace(i)->getName();
381 width = screen->getToolbarStyle()->font->measureString(workspace_name);
382 if (width > frame.workspace_label_w) frame.workspace_label_w = width;
385 frame.workspace_label_w = frame.clock_w =
386 std::max(frame.workspace_label_w, frame.clock_w) + (frame.bevel_w * 4);
388 // XXX: where'd the +6 come from?
389 frame.window_label_w =
390 (frame.rect.width() - (frame.clock_w + (frame.button_w * 4) +
391 frame.workspace_label_w + (frame.bevel_w * 8) + 6));
394 XMoveResizeWindow(display, frame.window, frame.x_hidden, frame.y_hidden,
395 frame.rect.width(), frame.rect.height());
397 XMoveResizeWindow(display, frame.window, frame.rect.x(), frame.rect.y(),
398 frame.rect.width(), frame.rect.height());
401 XMoveResizeWindow(display, frame.workspace_label, frame.bevel_w,
402 frame.bevel_w, frame.workspace_label_w,
404 XMoveResizeWindow(display, frame.psbutton,
405 ((frame.bevel_w * 2) + frame.workspace_label_w + 1),
406 frame.bevel_w + 1, frame.button_w, frame.button_w);
407 XMoveResizeWindow(display, frame.nsbutton,
408 ((frame.bevel_w * 3) + frame.workspace_label_w +
409 frame.button_w + 2), frame.bevel_w + 1, frame.button_w,
411 XMoveResizeWindow(display, frame.window_label,
412 ((frame.bevel_w * 4) + (frame.button_w * 2) +
413 frame.workspace_label_w + 3), frame.bevel_w,
414 frame.window_label_w, frame.label_h);
415 XMoveResizeWindow(display, frame.pwbutton,
416 ((frame.bevel_w * 5) + (frame.button_w * 2) +
417 frame.workspace_label_w + frame.window_label_w + 4),
418 frame.bevel_w + 1, frame.button_w, frame.button_w);
419 XMoveResizeWindow(display, frame.nwbutton,
420 ((frame.bevel_w * 6) + (frame.button_w * 3) +
421 frame.workspace_label_w + frame.window_label_w + 5),
422 frame.bevel_w + 1, frame.button_w, frame.button_w);
423 XMoveResizeWindow(display, frame.clock,
424 frame.rect.width() - frame.clock_w - (frame.bevel_w * 2),
425 frame.bevel_w, frame.clock_w, frame.label_h);
427 ToolbarStyle *style = screen->getToolbarStyle();
428 frame.base = style->toolbar.render(frame.rect.width(), frame.rect.height(),
431 XSetWindowBackground(display, frame.window,
432 style->toolbar.color().pixel());
434 XSetWindowBackgroundPixmap(display, frame.window, frame.base);
436 frame.label = style->window.render(frame.window_label_w, frame.label_h,
439 XSetWindowBackground(display, frame.window_label,
440 style->window.color().pixel());
442 XSetWindowBackgroundPixmap(display, frame.window_label, frame.label);
444 frame.wlabel = style->label.render(frame.workspace_label_w, frame.label_h,
447 XSetWindowBackground(display, frame.workspace_label,
448 style->label.color().pixel());
450 XSetWindowBackgroundPixmap(display, frame.workspace_label, frame.wlabel);
452 frame.clk = style->clock.render(frame.clock_w, frame.label_h, frame.clk);
454 XSetWindowBackground(display, frame.clock, style->clock.color().pixel());
456 XSetWindowBackgroundPixmap(display, frame.clock, frame.clk);
458 frame.button = style->button.render(frame.button_w, frame.button_w,
460 if (! frame.button) {
461 frame.button_pixel = style->button.color().pixel();
462 XSetWindowBackground(display, frame.psbutton, frame.button_pixel);
463 XSetWindowBackground(display, frame.nsbutton, frame.button_pixel);
464 XSetWindowBackground(display, frame.pwbutton, frame.button_pixel);
465 XSetWindowBackground(display, frame.nwbutton, frame.button_pixel);
467 XSetWindowBackgroundPixmap(display, frame.psbutton, frame.button);
468 XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.button);
469 XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.button);
470 XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.button);
473 frame.pbutton = style->pressed.render(frame.button_w, frame.button_w,
476 frame.pbutton_pixel = style->pressed.color().pixel();
478 XSetWindowBorder(display, frame.window,
479 screen->getBorderColor()->pixel());
480 XSetWindowBorderWidth(display, frame.window, screen->getBorderWidth());
482 XClearWindow(display, frame.window);
483 XClearWindow(display, frame.workspace_label);
484 XClearWindow(display, frame.window_label);
485 XClearWindow(display, frame.clock);
486 XClearWindow(display, frame.psbutton);
487 XClearWindow(display, frame.nsbutton);
488 XClearWindow(display, frame.pwbutton);
489 XClearWindow(display, frame.nwbutton);
492 redrawWorkspaceLabel();
493 redrawPrevWorkspaceButton();
494 redrawNextWorkspaceButton();
495 redrawPrevWindowButton();
496 redrawNextWindowButton();
499 toolbarmenu->reconfigure();
503 void Toolbar::updateStrut(void) {
504 // left and right are always 0
505 strut.top = strut.bottom = 0;
507 // when hidden only one border is visible
508 unsigned int border_width = screen->getBorderWidth();
512 if (! screen->doHideToolbar()) {
517 strut.top = getExposedHeight() + border_width;
520 strut.bottom = getExposedHeight() + border_width;
524 screen->updateAvailableArea();
529 void Toolbar::checkClock(bool redraw) {
530 #else // !HAVE_STRFTIME
531 void Toolbar::checkClock(bool redraw, bool date) {
532 #endif // HAVE_STRFTIME
536 if ((tmp = time(NULL)) != -1) {
537 if (! (tt = localtime(&tmp))) return;
538 if (tt->tm_min != frame.minute || tt->tm_hour != frame.hour) {
539 frame.hour = tt->tm_hour;
540 frame.minute = tt->tm_min;
541 XClearWindow(display, frame.clock);
549 if (! strftime(t, 1024, screen->getStrftimeFormat(), tt))
551 #else // !HAVE_STRFTIME
554 // format the date... with special consideration for y2k ;)
555 if (screen->getDateFormat() == Blackbox::B_EuropeanDate)
556 sprintf(t, 18n(ToolbarSet, ToolbarNoStrftimeDateFormatEu,
558 tt->tm_mday, tt->tm_mon + 1,
559 (tt->tm_year >= 100) ? tt->tm_year - 100 : tt->tm_year);
561 sprintf(t, i18n(ToolbarSet, ToolbarNoStrftimeDateFormat,
563 tt->tm_mon + 1, tt->tm_mday,
564 (tt->tm_year >= 100) ? tt->tm_year - 100 : tt->tm_year);
566 if (screen->isClock24Hour())
567 sprintf(t, i18n(ToolbarSet, ToolbarNoStrftimeTimeFormat24,
569 frame.hour, frame.minute);
571 sprintf(t, i18n(ToolbarSet, ToolbarNoStrftimeTimeFormat12,
573 ((frame.hour > 12) ? frame.hour - 12 :
574 ((frame.hour == 0) ? 12 : frame.hour)), frame.minute,
575 ((frame.hour >= 12) ?
576 i18n(ToolbarSet, ToolbarNoStrftimeTimeFormatP, "p") :
577 i18n(ToolbarSet, ToolbarNoStrftimeTimeFormatA, "a")));
579 #endif // HAVE_STRFTIME
581 ToolbarStyle *style = screen->getToolbarStyle();
583 int pos = frame.bevel_w * 2; // this is modified by doJustify()
584 style->doJustify(t, pos, frame.clock_w, frame.bevel_w * 4);
585 style->font->drawString(frame.clock, pos, 1, style->c_text, t);
590 void Toolbar::redrawWindowLabel(bool redraw) {
591 BlackboxWindow *foc = screen->getBlackbox()->getFocusedWindow();
593 XClearWindow(display, frame.window_label);
598 XClearWindow(display, frame.window_label);
600 if (foc->getScreen() != screen) return;
602 const char *title = foc->getTitle();
603 ToolbarStyle *style = screen->getToolbarStyle();
605 int pos = frame.bevel_w * 2; // modified by doJustify()
606 style->doJustify(title, pos, frame.window_label_w, frame.bevel_w * 4);
607 style->font->drawString(frame.window_label, pos, 1, style->w_text, title);
611 void Toolbar::redrawWorkspaceLabel(bool redraw) {
612 const string& name = screen->getCurrentWorkspace()->getName();
615 XClearWindow(display, frame.workspace_label);
617 ToolbarStyle *style = screen->getToolbarStyle();
619 int pos = frame.bevel_w * 2;
620 style->doJustify(name.c_str(), pos, frame.workspace_label_w,
622 style->font->drawString(frame.workspace_label, pos, 1, style->l_text, name);
626 void Toolbar::redrawPrevWorkspaceButton(bool pressed, bool redraw) {
630 XSetWindowBackgroundPixmap(display, frame.psbutton, frame.pbutton);
632 XSetWindowBackground(display, frame.psbutton, frame.pbutton_pixel);
635 XSetWindowBackgroundPixmap(display, frame.psbutton, frame.button);
637 XSetWindowBackground(display, frame.psbutton, frame.button_pixel);
639 XClearWindow(display, frame.psbutton);
642 int hh = frame.button_w / 2, hw = frame.button_w / 2;
645 pts[0].x = hw - 2; pts[0].y = hh;
646 pts[1].x = 4; pts[1].y = 2;
647 pts[2].x = 0; pts[2].y = -4;
649 ToolbarStyle *style = screen->getToolbarStyle();
650 BPen pen(style->b_pic);
651 XFillPolygon(display, frame.psbutton, pen.gc(),
652 pts, 3, Convex, CoordModePrevious);
656 void Toolbar::redrawNextWorkspaceButton(bool pressed, bool redraw) {
660 XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.pbutton);
662 XSetWindowBackground(display, frame.nsbutton, frame.pbutton_pixel);
665 XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.button);
667 XSetWindowBackground(display, frame.nsbutton, frame.button_pixel);
669 XClearWindow(display, frame.nsbutton);
672 int hh = frame.button_w / 2, hw = frame.button_w / 2;
675 pts[0].x = hw - 2; pts[0].y = hh - 2;
676 pts[1].x = 4; pts[1].y = 2;
677 pts[2].x = -4; pts[2].y = 2;
679 ToolbarStyle *style = screen->getToolbarStyle();
680 BPen pen(style->b_pic);
681 XFillPolygon(display, frame.nsbutton, pen.gc(),
682 pts, 3, Convex, CoordModePrevious);
686 void Toolbar::redrawPrevWindowButton(bool pressed, bool redraw) {
690 XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.pbutton);
692 XSetWindowBackground(display, frame.pwbutton, frame.pbutton_pixel);
695 XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.button);
697 XSetWindowBackground(display, frame.pwbutton, frame.button_pixel);
699 XClearWindow(display, frame.pwbutton);
702 int hh = frame.button_w / 2, hw = frame.button_w / 2;
705 pts[0].x = hw - 2; pts[0].y = hh;
706 pts[1].x = 4; pts[1].y = 2;
707 pts[2].x = 0; pts[2].y = -4;
709 ToolbarStyle *style = screen->getToolbarStyle();
710 BPen pen(style->b_pic);
711 XFillPolygon(display, frame.pwbutton, pen.gc(),
712 pts, 3, Convex, CoordModePrevious);
716 void Toolbar::redrawNextWindowButton(bool pressed, bool redraw) {
720 XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.pbutton);
722 XSetWindowBackground(display, frame.nwbutton, frame.pbutton_pixel);
725 XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.button);
727 XSetWindowBackground(display, frame.nwbutton, frame.button_pixel);
729 XClearWindow(display, frame.nwbutton);
732 int hh = frame.button_w / 2, hw = frame.button_w / 2;
735 pts[0].x = hw - 2; pts[0].y = hh - 2;
736 pts[1].x = 4; pts[1].y = 2;
737 pts[2].x = -4; pts[2].y = 2;
739 ToolbarStyle *style = screen->getToolbarStyle();
740 BPen pen(style->b_pic);
741 XFillPolygon(display, frame.nwbutton, pen.gc(), pts, 3, Convex,
746 void Toolbar::edit(void) {
751 XGetInputFocus(display, &window, &foo);
752 if (window == frame.workspace_label)
755 XSetInputFocus(display, frame.workspace_label,
756 RevertToPointerRoot, CurrentTime);
757 XClearWindow(display, frame.workspace_label);
759 blackbox->setNoFocus(True);
760 if (blackbox->getFocusedWindow())
761 blackbox->getFocusedWindow()->setFocusFlag(False);
763 ToolbarStyle *style = screen->getToolbarStyle();
764 BPen pen(style->l_text);
765 XDrawRectangle(display, frame.workspace_label, pen.gc(),
766 frame.workspace_label_w / 2, 0, 1,
768 // change the background of the window to that of an active window label
769 BTexture *texture = &(screen->getWindowStyle()->l_focus);
770 frame.wlabel = texture->render(frame.workspace_label_w, frame.label_h,
773 XSetWindowBackground(display, frame.workspace_label,
774 texture->color().pixel());
776 XSetWindowBackgroundPixmap(display, frame.workspace_label, frame.wlabel);
780 void Toolbar::buttonPressEvent(XButtonEvent *be) {
781 if (be->button == 1) {
782 if (be->window == frame.psbutton)
783 redrawPrevWorkspaceButton(True, True);
784 else if (be->window == frame.nsbutton)
785 redrawNextWorkspaceButton(True, True);
786 else if (be->window == frame.pwbutton)
787 redrawPrevWindowButton(True, True);
788 else if (be->window == frame.nwbutton)
789 redrawNextWindowButton(True, True);
790 #ifndef HAVE_STRFTIME
791 else if (be->window == frame.clock) {
792 XClearWindow(display, frame.clock);
793 checkClock(True, True);
795 #endif // HAVE_STRFTIME
797 Window w[1] = { frame.window };
798 screen->raiseWindows(w, 1);
800 } else if (be->button == 2 && (! on_top)) {
801 XLowerWindow(display, frame.window);
802 } else if (be->button == 3) {
803 if (toolbarmenu->isVisible()) {
808 x = be->x_root - (toolbarmenu->getWidth() / 2);
809 y = be->y_root - (toolbarmenu->getHeight() / 2);
813 else if (x + toolbarmenu->getWidth() > screen->getWidth())
814 x = screen->getWidth() - toolbarmenu->getWidth();
818 else if (y + toolbarmenu->getHeight() > screen->getHeight())
819 y = screen->getHeight() - toolbarmenu->getHeight();
821 toolbarmenu->move(x, y);
829 void Toolbar::buttonReleaseEvent(XButtonEvent *re) {
830 if (re->button == 1) {
831 if (re->window == frame.psbutton) {
832 redrawPrevWorkspaceButton(False, True);
834 if (re->x >= 0 && re->x < static_cast<signed>(frame.button_w) &&
835 re->y >= 0 && re->y < static_cast<signed>(frame.button_w))
836 if (screen->getCurrentWorkspace()->getID() > 0)
837 screen->changeWorkspaceID(screen->getCurrentWorkspace()->
840 screen->changeWorkspaceID(screen->getWorkspaceCount() - 1);
841 } else if (re->window == frame.nsbutton) {
842 redrawNextWorkspaceButton(False, True);
844 if (re->x >= 0 && re->x < static_cast<signed>(frame.button_w) &&
845 re->y >= 0 && re->y < static_cast<signed>(frame.button_w))
846 if (screen->getCurrentWorkspace()->getID() <
847 (screen->getWorkspaceCount() - 1))
848 screen->changeWorkspaceID(screen->getCurrentWorkspace()->
851 screen->changeWorkspaceID(0);
852 } else if (re->window == frame.pwbutton) {
853 redrawPrevWindowButton(False, True);
855 if (re->x >= 0 && re->x < static_cast<signed>(frame.button_w) &&
856 re->y >= 0 && re->y < static_cast<signed>(frame.button_w))
858 } else if (re->window == frame.nwbutton) {
859 redrawNextWindowButton(False, True);
861 if (re->x >= 0 && re->x < static_cast<signed>(frame.button_w) &&
862 re->y >= 0 && re->y < static_cast<signed>(frame.button_w))
864 } else if (re->window == frame.window_label)
865 screen->raiseFocus();
866 #ifndef HAVE_STRFTIME
867 else if (re->window == frame.clock) {
868 XClearWindow(display, frame.clock);
871 #endif // HAVE_STRFTIME
876 void Toolbar::enterNotifyEvent(XCrossingEvent *) {
881 if (! hide_timer->isTiming()) hide_timer->start();
883 if (hide_timer->isTiming()) hide_timer->stop();
887 void Toolbar::leaveNotifyEvent(XCrossingEvent *) {
892 if (hide_timer->isTiming()) hide_timer->stop();
893 } else if (! toolbarmenu->isVisible()) {
894 if (! hide_timer->isTiming()) hide_timer->start();
899 void Toolbar::exposeEvent(XExposeEvent *ee) {
900 if (ee->window == frame.clock) checkClock(True);
901 else if (ee->window == frame.workspace_label && (! editing))
902 redrawWorkspaceLabel();
903 else if (ee->window == frame.window_label) redrawWindowLabel();
904 else if (ee->window == frame.psbutton) redrawPrevWorkspaceButton();
905 else if (ee->window == frame.nsbutton) redrawNextWorkspaceButton();
906 else if (ee->window == frame.pwbutton) redrawPrevWindowButton();
907 else if (ee->window == frame.nwbutton) redrawNextWindowButton();
911 void Toolbar::keyPressEvent(XKeyEvent *ke) {
912 if (ke->window == frame.workspace_label && editing) {
913 if (new_workspace_name.empty()) {
919 XLookupString(ke, keychar, 1, &ks, 0);
921 // either we are told to end with a return or we hit 127 chars
922 if (ks == XK_Return || new_name_pos == 127) {
925 blackbox->setNoFocus(False);
926 if (blackbox->getFocusedWindow()) {
927 blackbox->getFocusedWindow()->setInputFocus();
929 blackbox->setFocusedWindow(0);
932 Workspace *wkspc = screen->getCurrentWorkspace();
933 wkspc->setName(new_workspace_name);
934 wkspc->getMenu()->hide();
936 screen->getWorkspacemenu()->changeItemLabel(wkspc->getID() + 2,
938 screen->getWorkspacemenu()->update();
940 new_workspace_name.erase();
943 // reset the background to that of the workspace label (its normal
945 BTexture *texture = &(screen->getToolbarStyle()->label);
946 frame.wlabel = texture->render(frame.workspace_label_w, frame.label_h,
949 XSetWindowBackground(display, frame.workspace_label,
950 texture->color().pixel());
952 XSetWindowBackgroundPixmap(display, frame.workspace_label,
955 } else if (! (ks == XK_Shift_L || ks == XK_Shift_R ||
956 ks == XK_Control_L || ks == XK_Control_R ||
957 ks == XK_Caps_Lock || ks == XK_Shift_Lock ||
958 ks == XK_Meta_L || ks == XK_Meta_R ||
959 ks == XK_Alt_L || ks == XK_Alt_R ||
960 ks == XK_Super_L || ks == XK_Super_R ||
961 ks == XK_Hyper_L || ks == XK_Hyper_R)) {
962 if (ks == XK_BackSpace) {
963 if (new_name_pos > 0) {
965 new_workspace_name.erase(new_name_pos);
967 new_workspace_name.resize(0);
970 new_workspace_name += (*keychar);
974 XClearWindow(display, frame.workspace_label);
977 tw = screen->getToolbarStyle()->font->measureString(new_workspace_name);
978 x = (frame.workspace_label_w - tw) / 2;
980 if (x < frame.bevel_w) x = frame.bevel_w;
982 ToolbarStyle *style = screen->getToolbarStyle();
983 style->font->drawString(frame.workspace_label, x, 1, style->l_text,
985 BPen pen(style->l_text);
986 XDrawRectangle(display, frame.workspace_label, pen.gc(), x + tw, 0, 1,
993 void Toolbar::timeout(void) {
996 clock_timer->setTimeout(aMinuteFromNow());
1000 void Toolbar::HideHandler::timeout(void) {
1001 toolbar->hidden = ! toolbar->hidden;
1002 if (toolbar->hidden)
1003 XMoveWindow(toolbar->display, toolbar->frame.window,
1004 toolbar->frame.x_hidden, toolbar->frame.y_hidden);
1006 XMoveWindow(toolbar->display, toolbar->frame.window,
1007 toolbar->frame.rect.x(), toolbar->frame.rect.y());
1011 void Toolbar::toggleAutoHide(void) {
1012 saveAutoHide(! doAutoHide());
1015 screen->getSlit()->reposition();
1017 if (do_auto_hide == False && hidden) {
1018 // force the slit to be visible
1019 if (hide_timer->isTiming()) hide_timer->stop();
1020 hide_handler.timeout();
1025 Toolbarmenu::Toolbarmenu(Toolbar *tb) : Basemenu(tb->screen) {
1028 setLabel(i18n(ToolbarSet, ToolbarToolbarTitle, "Toolbar"));
1031 placementmenu = new Placementmenu(this);
1033 insert(i18n(CommonSet, CommonPlacementTitle, "Placement"),
1035 insert(i18n(CommonSet, CommonAlwaysOnTop, "Always on top"), 1);
1036 insert(i18n(CommonSet, CommonAutoHide, "Auto hide"), 2);
1037 insert(i18n(ToolbarSet, ToolbarEditWkspcName,
1038 "Edit current workspace name"), 3);
1045 void Toolbarmenu::setValues() {
1046 setItemSelected(1, toolbar->isOnTop());
1047 setItemSelected(2, toolbar->doAutoHide());
1051 Toolbarmenu::~Toolbarmenu(void) {
1052 delete placementmenu;
1056 void Toolbarmenu::itemSelected(int button, unsigned int index) {
1060 BasemenuItem *item = find(index);
1063 switch (item->function()) {
1064 case 1: { // always on top
1065 toolbar->saveOnTop(! toolbar->isOnTop());
1066 setItemSelected(1, toolbar->isOnTop());
1068 if (toolbar->isOnTop()) getScreen()->raiseWindows((Window *) 0, 0);
1072 case 2: { // auto hide
1073 toolbar->toggleAutoHide();
1074 setItemSelected(2, toolbar->doAutoHide());
1079 case 3: { // edit current workspace name
1089 void Toolbarmenu::internal_hide(void) {
1090 Basemenu::internal_hide();
1091 if (toolbar->doAutoHide() && ! toolbar->isEditing())
1092 toolbar->hide_handler.timeout();
1096 void Toolbarmenu::reconfigure(void) {
1098 placementmenu->reconfigure();
1100 Basemenu::reconfigure();
1104 Toolbarmenu::Placementmenu::Placementmenu(Toolbarmenu *tm)
1105 : Basemenu(tm->toolbar->screen), toolbar(tm->toolbar) {
1106 setLabel(i18n(ToolbarSet, ToolbarToolbarPlacement, "Toolbar Placement"));
1108 setMinimumSublevels(3);
1110 insert(i18n(CommonSet, CommonPlacementTopLeft, "Top Left"),
1112 insert(i18n(CommonSet, CommonPlacementBottomLeft, "Bottom Left"),
1113 Toolbar::BottomLeft);
1114 insert(i18n(CommonSet, CommonPlacementTopCenter, "Top Center"),
1115 Toolbar::TopCenter);
1116 insert(i18n(CommonSet, CommonPlacementBottomCenter, "Bottom Center"),
1117 Toolbar::BottomCenter);
1118 insert(i18n(CommonSet, CommonPlacementTopRight, "Top Right"),
1120 insert(i18n(CommonSet, CommonPlacementBottomRight, "Bottom Right"),
1121 Toolbar::BottomRight);
1127 void Toolbarmenu::Placementmenu::setValues(void) {
1129 switch (toolbar->getPlacement()) {
1130 case Toolbar::BottomRight:
1132 case Toolbar::TopRight:
1134 case Toolbar::BottomCenter:
1136 case Toolbar::TopCenter:
1138 case Toolbar::BottomLeft:
1140 case Toolbar::TopLeft:
1143 setItemSelected(0, 0 == place);
1144 setItemSelected(1, 1 == place);
1145 setItemSelected(2, 2 == place);
1146 setItemSelected(3, 3 == place);
1147 setItemSelected(4, 4 == place);
1148 setItemSelected(5, 5 == place);
1152 void Toolbarmenu::Placementmenu::reconfigure(void) {
1154 Basemenu::reconfigure();
1158 void Toolbarmenu::Placementmenu::itemSelected(int button, unsigned int index) {
1162 BasemenuItem *item = find(index);
1165 toolbar->savePlacement(item->function());
1167 toolbar->reconfigure();
1169 // reposition the slit as well to make sure it doesn't intersect the
1171 getScreen()->getSlit()->reposition();
1175 void ToolbarStyle::doJustify(const std::string &text, int &start_pos,
1176 unsigned int max_length,
1177 unsigned int modifier) const {
1178 size_t text_len = text.size();
1179 unsigned int length;
1182 length = font->measureString(string(text, 0, text_len)) + modifier;
1183 } while (length > max_length && text_len-- > 0);
1187 start_pos += max_length - length;
1191 start_pos += (max_length - length) / 2;