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"
62 #include "Workspace.hh"
63 #include "Clientmenu.hh"
64 #include "Workspacemenu.hh"
68 static long aMinuteFromNow(void) {
70 gettimeofday(&now
, 0);
71 return ((60 - (now
.tv_sec
% 60)) * 1000);
75 Toolbar::Toolbar(BScreen
*scrn
) {
77 blackbox
= screen
->getBlackbox();
78 toolbarstr
= "session.screen" + itostring(screen
->getScreenNumber()) +
80 config
= blackbox
->getConfig();
84 // get the clock updating every minute
85 clock_timer
= new BTimer(blackbox
, this);
86 clock_timer
->setTimeout(aMinuteFromNow());
87 clock_timer
->recurring(True
);
89 frame
.minute
= frame
.hour
= -1;
91 hide_handler
.toolbar
= this;
92 hide_timer
= new BTimer(blackbox
, &hide_handler
);
93 hide_timer
->setTimeout(blackbox
->getAutoRaiseDelay());
98 toolbarmenu
= new Toolbarmenu(this);
100 display
= blackbox
->getXDisplay();
101 XSetWindowAttributes attrib
;
102 unsigned long create_mask
= CWBackPixmap
| CWBackPixel
| CWBorderPixel
|
103 CWColormap
| CWOverrideRedirect
| CWEventMask
;
104 attrib
.background_pixmap
= None
;
105 attrib
.background_pixel
= attrib
.border_pixel
=
106 screen
->getBorderColor()->pixel();
107 attrib
.colormap
= screen
->getColormap();
108 attrib
.override_redirect
= True
;
109 attrib
.event_mask
= ButtonPressMask
| ButtonReleaseMask
|
110 EnterWindowMask
| LeaveWindowMask
;
113 XCreateWindow(display
, screen
->getRootWindow(), 0, 0, 1, 1, 0,
114 screen
->getDepth(), InputOutput
, screen
->getVisual(),
115 create_mask
, &attrib
);
116 blackbox
->saveToolbarSearch(frame
.window
, this);
118 attrib
.event_mask
= ButtonPressMask
| ButtonReleaseMask
| ExposureMask
|
119 KeyPressMask
| EnterWindowMask
;
121 frame
.workspace_label
=
122 XCreateWindow(display
, frame
.window
, 0, 0, 1, 1, 0, screen
->getDepth(),
123 InputOutput
, screen
->getVisual(), create_mask
, &attrib
);
124 blackbox
->saveToolbarSearch(frame
.workspace_label
, this);
127 XCreateWindow(display
, frame
.window
, 0, 0, 1, 1, 0, screen
->getDepth(),
128 InputOutput
, screen
->getVisual(), create_mask
, &attrib
);
129 blackbox
->saveToolbarSearch(frame
.window_label
, this);
132 XCreateWindow(display
, frame
.window
, 0, 0, 1, 1, 0, screen
->getDepth(),
133 InputOutput
, screen
->getVisual(), create_mask
, &attrib
);
134 blackbox
->saveToolbarSearch(frame
.clock
, this);
137 XCreateWindow(display
,frame
.window
, 0, 0, 1, 1, 0, screen
->getDepth(),
138 InputOutput
, screen
->getVisual(), create_mask
, &attrib
);
139 blackbox
->saveToolbarSearch(frame
.psbutton
, this);
142 XCreateWindow(display
,frame
.window
, 0, 0, 1, 1, 0, screen
->getDepth(),
143 InputOutput
, screen
->getVisual(), create_mask
, &attrib
);
144 blackbox
->saveToolbarSearch(frame
.nsbutton
, this);
147 XCreateWindow(display
,frame
.window
, 0, 0, 1, 1, 0, screen
->getDepth(),
148 InputOutput
, screen
->getVisual(), create_mask
, &attrib
);
149 blackbox
->saveToolbarSearch(frame
.pwbutton
, this);
152 XCreateWindow(display
,frame
.window
, 0, 0, 1, 1, 0, screen
->getDepth(),
153 InputOutput
, screen
->getVisual(), create_mask
, &attrib
);
154 blackbox
->saveToolbarSearch(frame
.nwbutton
, this);
156 frame
.base
= frame
.label
= frame
.wlabel
= frame
.clk
= frame
.button
=
157 frame
.pbutton
= None
;
164 Toolbar::~Toolbar(void) {
167 if (frame
.base
) screen
->getImageControl()->removeImage(frame
.base
);
168 if (frame
.label
) screen
->getImageControl()->removeImage(frame
.label
);
169 if (frame
.wlabel
) screen
->getImageControl()->removeImage(frame
.wlabel
);
170 if (frame
.clk
) screen
->getImageControl()->removeImage(frame
.clk
);
171 if (frame
.button
) screen
->getImageControl()->removeImage(frame
.button
);
172 if (frame
.pbutton
) screen
->getImageControl()->removeImage(frame
.pbutton
);
174 blackbox
->removeToolbarSearch(frame
.window
);
175 blackbox
->removeToolbarSearch(frame
.workspace_label
);
176 blackbox
->removeToolbarSearch(frame
.window_label
);
177 blackbox
->removeToolbarSearch(frame
.clock
);
178 blackbox
->removeToolbarSearch(frame
.psbutton
);
179 blackbox
->removeToolbarSearch(frame
.nsbutton
);
180 blackbox
->removeToolbarSearch(frame
.pwbutton
);
181 blackbox
->removeToolbarSearch(frame
.nwbutton
);
183 XDestroyWindow(display
, frame
.workspace_label
);
184 XDestroyWindow(display
, frame
.window_label
);
185 XDestroyWindow(display
, frame
.clock
);
187 XDestroyWindow(display
, frame
.window
);
195 void Toolbar::mapToolbar() {
196 if (!screen
->doHideToolbar()) {
197 //not hidden, so windows should not maximize over the toolbar
198 XMapSubwindows(display
, frame
.window
);
199 XMapWindow(display
, frame
.window
);
201 screen
->addStrut(&strut
);
206 void Toolbar::unmapToolbar() {
207 if (toolbarmenu
->isVisible())
209 //hidden so we can maximize over the toolbar
210 screen
->removeStrut(&strut
);
211 screen
->updateAvailableArea();
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 width
, height
;
294 width
= (screen
->getWidth() * width_percent
) / 100;
295 height
= screen
->getToolbarStyle()->font
->height();
297 frame
.bevel_w
= screen
->getBevelWidth();
298 frame
.button_w
= height
;
300 frame
.label_h
= height
;
301 height
+= (frame
.bevel_w
* 2);
303 frame
.rect
.setSize(width
, height
);
310 if (placement
== TopLeft
)
312 else if (placement
== TopRight
)
313 x
= screen
->getWidth() - frame
.rect
.width()
314 - (screen
->getBorderWidth() * 2);
316 x
= (screen
->getWidth() - frame
.rect
.width()) / 2;
321 frame
.y_hidden
= screen
->getBevelWidth() - screen
->getBorderWidth()
322 - frame
.rect
.height();
329 if (placement
== BottomLeft
)
331 else if (placement
== BottomRight
)
332 x
= screen
->getWidth() - frame
.rect
.width()
333 - (screen
->getBorderWidth() * 2);
335 x
= (screen
->getWidth() - frame
.rect
.width()) / 2;
337 y
= screen
->getHeight() - frame
.rect
.height()
338 - (screen
->getBorderWidth() * 2);
341 frame
.y_hidden
= screen
->getHeight() - screen
->getBevelWidth()
342 - screen
->getBorderWidth();
346 frame
.rect
.setPos(x
, y
);
351 time_t ttmp
= time(NULL
);
355 struct tm
*tt
= localtime(&ttmp
);
358 int len
= strftime(t
, 1024, screen
->getStrftimeFormat(), tt
);
359 if (len
== 0) { // invalid time format found
360 screen
->saveStrftimeFormat("%I:%M %p"); // so use the default
361 strftime(t
, 1024, screen
->getStrftimeFormat(), tt
);
363 // find the length of the rendered string and add room for two extra
364 // characters to it. This allows for variable width output of the fonts
365 BFont
*font
= screen
->getToolbarStyle()->font
;
366 frame
.clock_w
= font
->measureString(t
) + font
->maxCharWidth() * 2;
369 #else // !HAVE_STRFTIME
371 string s
= i18n(ToolbarSet
, ToolbarNoStrftimeLength
, "00:00000");
372 frame
.clock_w
= screen
->getToolbarStyle()->font
->measureString(s
);
374 #endif // HAVE_STRFTIME
376 frame
.workspace_label_w
= 0;
378 for (unsigned int i
= 0; i
< screen
->getWorkspaceCount(); i
++) {
379 const string
& workspace_name
= screen
->getWorkspace(i
)->getName();
380 width
= screen
->getToolbarStyle()->font
->measureString(workspace_name
);
381 if (width
> frame
.workspace_label_w
) frame
.workspace_label_w
= width
;
384 frame
.workspace_label_w
= frame
.clock_w
=
385 std::max(frame
.workspace_label_w
, frame
.clock_w
) + (frame
.bevel_w
* 4);
387 // XXX: where'd the +6 come from?
388 frame
.window_label_w
=
389 (frame
.rect
.width() - (frame
.clock_w
+ (frame
.button_w
* 4) +
390 frame
.workspace_label_w
+ (frame
.bevel_w
* 8) + 6));
393 XMoveResizeWindow(display
, frame
.window
, frame
.x_hidden
, frame
.y_hidden
,
394 frame
.rect
.width(), frame
.rect
.height());
396 XMoveResizeWindow(display
, frame
.window
, frame
.rect
.x(), frame
.rect
.y(),
397 frame
.rect
.width(), frame
.rect
.height());
400 XMoveResizeWindow(display
, frame
.workspace_label
, frame
.bevel_w
,
401 frame
.bevel_w
, frame
.workspace_label_w
,
403 XMoveResizeWindow(display
, frame
.psbutton
,
404 ((frame
.bevel_w
* 2) + frame
.workspace_label_w
+ 1),
405 frame
.bevel_w
+ 1, frame
.button_w
, frame
.button_w
);
406 XMoveResizeWindow(display
, frame
.nsbutton
,
407 ((frame
.bevel_w
* 3) + frame
.workspace_label_w
+
408 frame
.button_w
+ 2), frame
.bevel_w
+ 1, frame
.button_w
,
410 XMoveResizeWindow(display
, frame
.window_label
,
411 ((frame
.bevel_w
* 4) + (frame
.button_w
* 2) +
412 frame
.workspace_label_w
+ 3), frame
.bevel_w
,
413 frame
.window_label_w
, frame
.label_h
);
414 XMoveResizeWindow(display
, frame
.pwbutton
,
415 ((frame
.bevel_w
* 5) + (frame
.button_w
* 2) +
416 frame
.workspace_label_w
+ frame
.window_label_w
+ 4),
417 frame
.bevel_w
+ 1, frame
.button_w
, frame
.button_w
);
418 XMoveResizeWindow(display
, frame
.nwbutton
,
419 ((frame
.bevel_w
* 6) + (frame
.button_w
* 3) +
420 frame
.workspace_label_w
+ frame
.window_label_w
+ 5),
421 frame
.bevel_w
+ 1, frame
.button_w
, frame
.button_w
);
422 XMoveResizeWindow(display
, frame
.clock
,
423 frame
.rect
.width() - frame
.clock_w
- (frame
.bevel_w
* 2),
424 frame
.bevel_w
, frame
.clock_w
, frame
.label_h
);
426 ToolbarStyle
*style
= screen
->getToolbarStyle();
427 frame
.base
= style
->toolbar
.render(frame
.rect
.width(), frame
.rect
.height(),
430 XSetWindowBackground(display
, frame
.window
,
431 style
->toolbar
.color().pixel());
433 XSetWindowBackgroundPixmap(display
, frame
.window
, frame
.base
);
435 frame
.label
= style
->window
.render(frame
.window_label_w
, frame
.label_h
,
438 XSetWindowBackground(display
, frame
.window_label
,
439 style
->window
.color().pixel());
441 XSetWindowBackgroundPixmap(display
, frame
.window_label
, frame
.label
);
443 frame
.wlabel
= style
->label
.render(frame
.workspace_label_w
, frame
.label_h
,
446 XSetWindowBackground(display
, frame
.workspace_label
,
447 style
->label
.color().pixel());
449 XSetWindowBackgroundPixmap(display
, frame
.workspace_label
, frame
.wlabel
);
451 frame
.clk
= style
->clock
.render(frame
.clock_w
, frame
.label_h
, frame
.clk
);
453 XSetWindowBackground(display
, frame
.clock
, style
->clock
.color().pixel());
455 XSetWindowBackgroundPixmap(display
, frame
.clock
, frame
.clk
);
457 frame
.button
= style
->button
.render(frame
.button_w
, frame
.button_w
,
459 if (! frame
.button
) {
460 frame
.button_pixel
= style
->button
.color().pixel();
461 XSetWindowBackground(display
, frame
.psbutton
, frame
.button_pixel
);
462 XSetWindowBackground(display
, frame
.nsbutton
, frame
.button_pixel
);
463 XSetWindowBackground(display
, frame
.pwbutton
, frame
.button_pixel
);
464 XSetWindowBackground(display
, frame
.nwbutton
, frame
.button_pixel
);
466 XSetWindowBackgroundPixmap(display
, frame
.psbutton
, frame
.button
);
467 XSetWindowBackgroundPixmap(display
, frame
.nsbutton
, frame
.button
);
468 XSetWindowBackgroundPixmap(display
, frame
.pwbutton
, frame
.button
);
469 XSetWindowBackgroundPixmap(display
, frame
.nwbutton
, frame
.button
);
472 frame
.pbutton
= style
->pressed
.render(frame
.button_w
, frame
.button_w
,
475 frame
.pbutton_pixel
= style
->pressed
.color().pixel();
477 XSetWindowBorder(display
, frame
.window
,
478 screen
->getBorderColor()->pixel());
479 XSetWindowBorderWidth(display
, frame
.window
, screen
->getBorderWidth());
481 XClearWindow(display
, frame
.window
);
482 XClearWindow(display
, frame
.workspace_label
);
483 XClearWindow(display
, frame
.window_label
);
484 XClearWindow(display
, frame
.clock
);
485 XClearWindow(display
, frame
.psbutton
);
486 XClearWindow(display
, frame
.nsbutton
);
487 XClearWindow(display
, frame
.pwbutton
);
488 XClearWindow(display
, frame
.nwbutton
);
491 redrawWorkspaceLabel();
492 redrawPrevWorkspaceButton();
493 redrawNextWorkspaceButton();
494 redrawPrevWindowButton();
495 redrawNextWindowButton();
498 toolbarmenu
->reconfigure();
502 void Toolbar::updateStrut(void) {
503 // left and right are always 0
504 strut
.top
= strut
.bottom
= 0;
506 // when hidden only one border is visible
507 unsigned int border_width
= screen
->getBorderWidth();
511 if (! screen
->doHideToolbar()) {
516 strut
.top
= getExposedHeight() + border_width
;
519 strut
.bottom
= getExposedHeight() + border_width
;
523 screen
->updateAvailableArea();
528 void Toolbar::checkClock(bool redraw
) {
529 #else // !HAVE_STRFTIME
530 void Toolbar::checkClock(bool redraw
, bool date
) {
531 #endif // HAVE_STRFTIME
535 if ((tmp
= time(NULL
)) != -1) {
536 if (! (tt
= localtime(&tmp
))) return;
537 if (tt
->tm_min
!= frame
.minute
|| tt
->tm_hour
!= frame
.hour
) {
538 frame
.hour
= tt
->tm_hour
;
539 frame
.minute
= tt
->tm_min
;
540 XClearWindow(display
, frame
.clock
);
548 if (! strftime(t
, 1024, screen
->getStrftimeFormat(), tt
))
550 #else // !HAVE_STRFTIME
553 // format the date... with special consideration for y2k ;)
554 if (screen
->getDateFormat() == Blackbox::B_EuropeanDate
)
555 sprintf(t
, 18n(ToolbarSet
, ToolbarNoStrftimeDateFormatEu
,
557 tt
->tm_mday
, tt
->tm_mon
+ 1,
558 (tt
->tm_year
>= 100) ? tt
->tm_year
- 100 : tt
->tm_year
);
560 sprintf(t
, i18n(ToolbarSet
, ToolbarNoStrftimeDateFormat
,
562 tt
->tm_mon
+ 1, tt
->tm_mday
,
563 (tt
->tm_year
>= 100) ? tt
->tm_year
- 100 : tt
->tm_year
);
565 if (screen
->isClock24Hour())
566 sprintf(t
, i18n(ToolbarSet
, ToolbarNoStrftimeTimeFormat24
,
568 frame
.hour
, frame
.minute
);
570 sprintf(t
, i18n(ToolbarSet
, ToolbarNoStrftimeTimeFormat12
,
572 ((frame
.hour
> 12) ? frame
.hour
- 12 :
573 ((frame
.hour
== 0) ? 12 : frame
.hour
)), frame
.minute
,
574 ((frame
.hour
>= 12) ?
575 i18n(ToolbarSet
, ToolbarNoStrftimeTimeFormatP
, "p") :
576 i18n(ToolbarSet
, ToolbarNoStrftimeTimeFormatA
, "a")));
578 #endif // HAVE_STRFTIME
580 ToolbarStyle
*style
= screen
->getToolbarStyle();
582 int pos
= frame
.bevel_w
* 2; // this is modified by doJustify()
583 style
->doJustify(t
, pos
, frame
.clock_w
, frame
.bevel_w
* 4);
584 style
->font
->drawString(frame
.clock
, pos
, 1, style
->c_text
, t
);
589 void Toolbar::redrawWindowLabel(bool redraw
) {
590 BlackboxWindow
*foc
= screen
->getBlackbox()->getFocusedWindow();
592 XClearWindow(display
, frame
.window_label
);
597 XClearWindow(display
, frame
.window_label
);
599 if (foc
->getScreen() != screen
) return;
601 const char *title
= foc
->getTitle();
602 ToolbarStyle
*style
= screen
->getToolbarStyle();
604 int pos
= frame
.bevel_w
* 2; // modified by doJustify()
605 style
->doJustify(title
, pos
, frame
.window_label_w
, frame
.bevel_w
* 4);
606 style
->font
->drawString(frame
.window_label
, pos
, 1, style
->w_text
, title
);
610 void Toolbar::redrawWorkspaceLabel(bool redraw
) {
611 const string
& name
= screen
->getCurrentWorkspace()->getName();
614 XClearWindow(display
, frame
.workspace_label
);
616 ToolbarStyle
*style
= screen
->getToolbarStyle();
618 int pos
= frame
.bevel_w
* 2;
619 style
->doJustify(name
.c_str(), pos
, frame
.workspace_label_w
,
621 style
->font
->drawString(frame
.workspace_label
, pos
, 1, style
->l_text
, name
);
625 void Toolbar::drawArrow(Drawable surface
, bool left
) const {
626 ToolbarStyle
*style
= screen
->getToolbarStyle();
628 BPen
pen(style
->b_pic
);
630 int hh
= frame
.button_w
/ 2, hw
= frame
.button_w
/ 2;
632 const int bullet_size
= 3;
637 if (style
->left_button
.mask
!= None
) {
638 XSetClipMask(blackbox
->getXDisplay(), pen
.gc(), style
->left_button
.mask
);
639 XSetClipOrigin(blackbox
->getXDisplay(), pen
.gc(),
640 (frame
.button_w
- style
->left_button
.w
)/2,
641 (frame
.button_w
- style
->left_button
.h
)/2);
643 XFillRectangle(blackbox
->getXDisplay(), surface
, pen
.gc(),
644 (frame
.button_w
- style
->left_button
.w
)/2,
645 (frame
.button_w
- style
->left_button
.h
)/2,
646 style
->left_button
.w
, style
->left_button
.h
);
648 XSetClipMask(blackbox
->getXDisplay(), pen
.gc(), None
);
649 XSetClipOrigin(blackbox
->getXDisplay(), pen
.gc(), 0, 0);
651 #endif // BITMAPBUTTONS
652 pts
[0].x
= hw
- bullet_size
;
654 pts
[1].x
= 2 * bullet_size
;
655 pts
[1].y
= bullet_size
;
657 pts
[2].y
= -(2 * bullet_size
);
658 XFillPolygon(display
, surface
, pen
.gc(), pts
, 3, Convex
,
662 #endif // BITMAPBUTTONS
665 if (style
->right_button
.mask
!= None
) {
666 XSetClipMask(blackbox
->getXDisplay(), pen
.gc(),
667 style
->right_button
.mask
);
668 XSetClipOrigin(blackbox
->getXDisplay(), pen
.gc(),
669 (frame
.button_w
- style
->right_button
.w
)/2,
670 (frame
.button_w
- style
->right_button
.h
)/2);
672 XFillRectangle(blackbox
->getXDisplay(), surface
, pen
.gc(),
673 (frame
.button_w
- style
->right_button
.w
)/2,
674 (frame
.button_w
- style
->right_button
.h
)/2,
675 (frame
.button_w
+ style
->right_button
.w
)/2,
676 (frame
.button_w
+ style
->right_button
.h
)/2);
678 XSetClipMask(blackbox
->getXDisplay(), pen
.gc(), None
);
679 XSetClipOrigin(blackbox
->getXDisplay(), pen
.gc(), 0, 0);
681 #endif // BITMAPBUTTONS
682 pts
[0].x
= hw
- bullet_size
;
683 pts
[0].y
= hh
- bullet_size
;
684 pts
[1].x
= (2 * bullet_size
);
685 pts
[1].y
= bullet_size
;
686 pts
[2].x
= -(2 * bullet_size
);
687 pts
[2].y
= bullet_size
;
688 XFillPolygon(display
, surface
, pen
.gc(), pts
, 3, Convex
,
697 void Toolbar::redrawPrevWorkspaceButton(bool pressed
, bool redraw
) {
701 XSetWindowBackgroundPixmap(display
, frame
.psbutton
, frame
.pbutton
);
703 XSetWindowBackground(display
, frame
.psbutton
, frame
.pbutton_pixel
);
706 XSetWindowBackgroundPixmap(display
, frame
.psbutton
, frame
.button
);
708 XSetWindowBackground(display
, frame
.psbutton
, frame
.button_pixel
);
710 XClearWindow(display
, frame
.psbutton
);
713 drawArrow(frame
.psbutton
, True
);
717 void Toolbar::redrawNextWorkspaceButton(bool pressed
, bool redraw
) {
721 XSetWindowBackgroundPixmap(display
, frame
.nsbutton
, frame
.pbutton
);
723 XSetWindowBackground(display
, frame
.nsbutton
, frame
.pbutton_pixel
);
726 XSetWindowBackgroundPixmap(display
, frame
.nsbutton
, frame
.button
);
728 XSetWindowBackground(display
, frame
.nsbutton
, frame
.button_pixel
);
730 XClearWindow(display
, frame
.nsbutton
);
733 drawArrow(frame
.nsbutton
, False
);
737 void Toolbar::redrawPrevWindowButton(bool pressed
, bool redraw
) {
741 XSetWindowBackgroundPixmap(display
, frame
.pwbutton
, frame
.pbutton
);
743 XSetWindowBackground(display
, frame
.pwbutton
, frame
.pbutton_pixel
);
746 XSetWindowBackgroundPixmap(display
, frame
.pwbutton
, frame
.button
);
748 XSetWindowBackground(display
, frame
.pwbutton
, frame
.button_pixel
);
750 XClearWindow(display
, frame
.pwbutton
);
753 drawArrow(frame
.pwbutton
, True
);
757 void Toolbar::redrawNextWindowButton(bool pressed
, bool redraw
) {
761 XSetWindowBackgroundPixmap(display
, frame
.nwbutton
, frame
.pbutton
);
763 XSetWindowBackground(display
, frame
.nwbutton
, frame
.pbutton_pixel
);
766 XSetWindowBackgroundPixmap(display
, frame
.nwbutton
, frame
.button
);
768 XSetWindowBackground(display
, frame
.nwbutton
, frame
.button_pixel
);
770 XClearWindow(display
, frame
.nwbutton
);
773 drawArrow(frame
.nwbutton
, False
);
777 void Toolbar::edit(void) {
782 XGetInputFocus(display
, &window
, &foo
);
783 if (window
== frame
.workspace_label
)
786 XSetInputFocus(display
, frame
.workspace_label
,
787 RevertToPointerRoot
, CurrentTime
);
788 XClearWindow(display
, frame
.workspace_label
);
790 blackbox
->setNoFocus(True
);
791 if (blackbox
->getFocusedWindow())
792 blackbox
->getFocusedWindow()->setFocusFlag(False
);
794 ToolbarStyle
*style
= screen
->getToolbarStyle();
795 BPen
pen(style
->l_text
);
796 XDrawRectangle(display
, frame
.workspace_label
, pen
.gc(),
797 frame
.workspace_label_w
/ 2, 0, 1,
799 // change the background of the window to that of an active window label
800 BTexture
*texture
= &(screen
->getWindowStyle()->l_focus
);
801 frame
.wlabel
= texture
->render(frame
.workspace_label_w
, frame
.label_h
,
804 XSetWindowBackground(display
, frame
.workspace_label
,
805 texture
->color().pixel());
807 XSetWindowBackgroundPixmap(display
, frame
.workspace_label
, frame
.wlabel
);
811 void Toolbar::buttonPressEvent(const XButtonEvent
*be
) {
812 if (be
->button
== 1) {
813 if (be
->window
== frame
.psbutton
)
814 redrawPrevWorkspaceButton(True
, True
);
815 else if (be
->window
== frame
.nsbutton
)
816 redrawNextWorkspaceButton(True
, True
);
817 else if (be
->window
== frame
.pwbutton
)
818 redrawPrevWindowButton(True
, True
);
819 else if (be
->window
== frame
.nwbutton
)
820 redrawNextWindowButton(True
, True
);
821 #ifndef HAVE_STRFTIME
822 else if (be
->window
== frame
.clock
) {
823 XClearWindow(display
, frame
.clock
);
824 checkClock(True
, True
);
826 #endif // HAVE_STRFTIME
828 Window w
[1] = { frame
.window
};
829 screen
->raiseWindows(w
, 1);
831 } else if (be
->button
== 2 && (! on_top
)) {
832 XLowerWindow(display
, frame
.window
);
833 } else if (be
->button
== 3) {
834 if (toolbarmenu
->isVisible()) {
839 x
= be
->x_root
- (toolbarmenu
->getWidth() / 2);
840 y
= be
->y_root
- (toolbarmenu
->getHeight() / 2);
844 else if (x
+ toolbarmenu
->getWidth() > screen
->getWidth())
845 x
= screen
->getWidth() - toolbarmenu
->getWidth();
849 else if (y
+ toolbarmenu
->getHeight() > screen
->getHeight())
850 y
= screen
->getHeight() - toolbarmenu
->getHeight();
852 toolbarmenu
->move(x
, y
);
860 void Toolbar::buttonReleaseEvent(const XButtonEvent
*re
) {
861 if (re
->button
== 1) {
862 if (re
->window
== frame
.psbutton
) {
863 redrawPrevWorkspaceButton(False
, True
);
865 if (re
->x
>= 0 && re
->x
< static_cast<signed>(frame
.button_w
) &&
866 re
->y
>= 0 && re
->y
< static_cast<signed>(frame
.button_w
))
867 if (screen
->getCurrentWorkspace()->getID() > 0)
868 screen
->changeWorkspaceID(screen
->getCurrentWorkspace()->
871 screen
->changeWorkspaceID(screen
->getWorkspaceCount() - 1);
872 } else if (re
->window
== frame
.nsbutton
) {
873 redrawNextWorkspaceButton(False
, True
);
875 if (re
->x
>= 0 && re
->x
< static_cast<signed>(frame
.button_w
) &&
876 re
->y
>= 0 && re
->y
< static_cast<signed>(frame
.button_w
))
877 if (screen
->getCurrentWorkspace()->getID() <
878 (screen
->getWorkspaceCount() - 1))
879 screen
->changeWorkspaceID(screen
->getCurrentWorkspace()->
882 screen
->changeWorkspaceID(0);
883 } else if (re
->window
== frame
.pwbutton
) {
884 redrawPrevWindowButton(False
, True
);
886 if (re
->x
>= 0 && re
->x
< static_cast<signed>(frame
.button_w
) &&
887 re
->y
>= 0 && re
->y
< static_cast<signed>(frame
.button_w
))
889 } else if (re
->window
== frame
.nwbutton
) {
890 redrawNextWindowButton(False
, True
);
892 if (re
->x
>= 0 && re
->x
< static_cast<signed>(frame
.button_w
) &&
893 re
->y
>= 0 && re
->y
< static_cast<signed>(frame
.button_w
))
895 } else if (re
->window
== frame
.window_label
)
896 screen
->raiseFocus();
897 #ifndef HAVE_STRFTIME
898 else if (re
->window
== frame
.clock
) {
899 XClearWindow(display
, frame
.clock
);
902 #endif // HAVE_STRFTIME
907 void Toolbar::enterNotifyEvent(const XCrossingEvent
*) {
912 if (! hide_timer
->isTiming()) hide_timer
->start();
914 if (hide_timer
->isTiming()) hide_timer
->stop();
918 void Toolbar::leaveNotifyEvent(const XCrossingEvent
*) {
923 if (hide_timer
->isTiming()) hide_timer
->stop();
924 } else if (! toolbarmenu
->isVisible()) {
925 if (! hide_timer
->isTiming()) hide_timer
->start();
930 void Toolbar::exposeEvent(const XExposeEvent
*ee
) {
931 if (ee
->window
== frame
.clock
) checkClock(True
);
932 else if (ee
->window
== frame
.workspace_label
&& (! editing
))
933 redrawWorkspaceLabel();
934 else if (ee
->window
== frame
.window_label
) redrawWindowLabel();
935 else if (ee
->window
== frame
.psbutton
) redrawPrevWorkspaceButton();
936 else if (ee
->window
== frame
.nsbutton
) redrawNextWorkspaceButton();
937 else if (ee
->window
== frame
.pwbutton
) redrawPrevWindowButton();
938 else if (ee
->window
== frame
.nwbutton
) redrawNextWindowButton();
942 void Toolbar::keyPressEvent(const XKeyEvent
*ke
) {
943 if (ke
->window
== frame
.workspace_label
&& editing
) {
944 if (new_workspace_name
.empty()) {
950 XLookupString(const_cast<XKeyEvent
*>(ke
), keychar
, 1, &ks
, 0);
952 // either we are told to end with a return or we hit 127 chars
953 if (ks
== XK_Return
|| new_name_pos
== 127) {
956 blackbox
->setNoFocus(False
);
957 if (blackbox
->getFocusedWindow())
958 blackbox
->getFocusedWindow()->setInputFocus();
960 blackbox
->setFocusedWindow(0);
962 // the toolbar will be reconfigured when the change to the workspace name
963 // gets caught in the PropertyNotify event handler
964 screen
->getCurrentWorkspace()->setName(new_workspace_name
);
966 new_workspace_name
.erase();
969 // reset the background to that of the workspace label (its normal
971 BTexture
*texture
= &(screen
->getToolbarStyle()->label
);
972 frame
.wlabel
= texture
->render(frame
.workspace_label_w
, frame
.label_h
,
975 XSetWindowBackground(display
, frame
.workspace_label
,
976 texture
->color().pixel());
978 XSetWindowBackgroundPixmap(display
, frame
.workspace_label
,
980 } else if (! (ks
== XK_Shift_L
|| ks
== XK_Shift_R
||
981 ks
== XK_Control_L
|| ks
== XK_Control_R
||
982 ks
== XK_Caps_Lock
|| ks
== XK_Shift_Lock
||
983 ks
== XK_Meta_L
|| ks
== XK_Meta_R
||
984 ks
== XK_Alt_L
|| ks
== XK_Alt_R
||
985 ks
== XK_Super_L
|| ks
== XK_Super_R
||
986 ks
== XK_Hyper_L
|| ks
== XK_Hyper_R
)) {
987 if (ks
== XK_BackSpace
) {
988 if (new_name_pos
> 0) {
990 new_workspace_name
.erase(new_name_pos
);
992 new_workspace_name
.resize(0);
995 new_workspace_name
+= (*keychar
);
999 XClearWindow(display
, frame
.workspace_label
);
1002 tw
= screen
->getToolbarStyle()->font
->measureString(new_workspace_name
);
1003 x
= (frame
.workspace_label_w
- tw
) / 2;
1005 if (x
< frame
.bevel_w
) x
= frame
.bevel_w
;
1007 ToolbarStyle
*style
= screen
->getToolbarStyle();
1008 style
->font
->drawString(frame
.workspace_label
, x
, 1, style
->l_text
,
1009 new_workspace_name
);
1010 BPen
pen(style
->l_text
);
1011 XDrawRectangle(display
, frame
.workspace_label
, pen
.gc(), x
+ tw
, 0, 1,
1018 void Toolbar::timeout(void) {
1021 clock_timer
->setTimeout(aMinuteFromNow());
1025 void Toolbar::HideHandler::timeout(void) {
1026 toolbar
->hidden
= ! toolbar
->hidden
;
1027 if (toolbar
->hidden
)
1028 XMoveWindow(toolbar
->display
, toolbar
->frame
.window
,
1029 toolbar
->frame
.x_hidden
, toolbar
->frame
.y_hidden
);
1031 XMoveWindow(toolbar
->display
, toolbar
->frame
.window
,
1032 toolbar
->frame
.rect
.x(), toolbar
->frame
.rect
.y());
1036 void Toolbar::toggleAutoHide(void) {
1037 saveAutoHide(! doAutoHide());
1040 screen
->getSlit()->reposition();
1042 if (do_auto_hide
== False
&& hidden
) {
1043 // force the slit to be visible
1044 if (hide_timer
->isTiming()) hide_timer
->stop();
1045 hide_handler
.timeout();
1050 Toolbarmenu::Toolbarmenu(Toolbar
*tb
) : Basemenu(tb
->screen
) {
1053 setLabel(i18n(ToolbarSet
, ToolbarToolbarTitle
, "Toolbar"));
1056 placementmenu
= new Placementmenu(this);
1058 insert(i18n(CommonSet
, CommonPlacementTitle
, "Placement"),
1060 insert(i18n(CommonSet
, CommonAlwaysOnTop
, "Always on top"), 1);
1061 insert(i18n(CommonSet
, CommonAutoHide
, "Auto hide"), 2);
1062 insert(i18n(ToolbarSet
, ToolbarEditWkspcName
,
1063 "Edit current workspace name"), 3);
1070 void Toolbarmenu::setValues() {
1071 setItemSelected(1, toolbar
->isOnTop());
1072 setItemSelected(2, toolbar
->doAutoHide());
1076 Toolbarmenu::~Toolbarmenu(void) {
1077 delete placementmenu
;
1081 void Toolbarmenu::itemSelected(int button
, unsigned int index
) {
1085 BasemenuItem
*item
= find(index
);
1088 switch (item
->function()) {
1089 case 1: { // always on top
1090 toolbar
->saveOnTop(! toolbar
->isOnTop());
1091 setItemSelected(1, toolbar
->isOnTop());
1093 if (toolbar
->isOnTop()) getScreen()->raiseWindows((Window
*) 0, 0);
1097 case 2: { // auto hide
1098 toolbar
->toggleAutoHide();
1099 setItemSelected(2, toolbar
->doAutoHide());
1104 case 3: { // edit current workspace name
1114 void Toolbarmenu::internal_hide(void) {
1115 Basemenu::internal_hide();
1116 if (toolbar
->doAutoHide() && ! toolbar
->isEditing())
1117 toolbar
->hide_handler
.timeout();
1121 void Toolbarmenu::reconfigure(void) {
1123 placementmenu
->reconfigure();
1125 Basemenu::reconfigure();
1129 Toolbarmenu::Placementmenu::Placementmenu(Toolbarmenu
*tm
)
1130 : Basemenu(tm
->toolbar
->screen
), toolbar(tm
->toolbar
) {
1131 setLabel(i18n(ToolbarSet
, ToolbarToolbarPlacement
, "Toolbar Placement"));
1133 setMinimumSublevels(3);
1135 insert(i18n(CommonSet
, CommonPlacementTopLeft
, "Top Left"),
1137 insert(i18n(CommonSet
, CommonPlacementBottomLeft
, "Bottom Left"),
1138 Toolbar::BottomLeft
);
1139 insert(i18n(CommonSet
, CommonPlacementTopCenter
, "Top Center"),
1140 Toolbar::TopCenter
);
1141 insert(i18n(CommonSet
, CommonPlacementBottomCenter
, "Bottom Center"),
1142 Toolbar::BottomCenter
);
1143 insert(i18n(CommonSet
, CommonPlacementTopRight
, "Top Right"),
1145 insert(i18n(CommonSet
, CommonPlacementBottomRight
, "Bottom Right"),
1146 Toolbar::BottomRight
);
1152 void Toolbarmenu::Placementmenu::setValues(void) {
1154 switch (toolbar
->getPlacement()) {
1155 case Toolbar::BottomRight
:
1157 case Toolbar::TopRight
:
1159 case Toolbar::BottomCenter
:
1161 case Toolbar::TopCenter
:
1163 case Toolbar::BottomLeft
:
1165 case Toolbar::TopLeft
:
1168 setItemSelected(0, 0 == place
);
1169 setItemSelected(1, 1 == place
);
1170 setItemSelected(2, 2 == place
);
1171 setItemSelected(3, 3 == place
);
1172 setItemSelected(4, 4 == place
);
1173 setItemSelected(5, 5 == place
);
1177 void Toolbarmenu::Placementmenu::reconfigure(void) {
1179 Basemenu::reconfigure();
1183 void Toolbarmenu::Placementmenu::itemSelected(int button
, unsigned int index
) {
1187 BasemenuItem
*item
= find(index
);
1190 toolbar
->savePlacement(item
->function());
1192 toolbar
->reconfigure();
1194 // reposition the slit as well to make sure it doesn't intersect the
1196 getScreen()->getSlit()->reposition();
1200 void ToolbarStyle::doJustify(const std::string
&text
, int &start_pos
,
1201 unsigned int max_length
,
1202 unsigned int modifier
) const {
1203 size_t text_len
= text
.size();
1204 unsigned int length
;
1207 length
= font
->measureString(string(text
, 0, text_len
)) + modifier
;
1208 } while (length
> max_length
&& text_len
-- > 0);
1212 start_pos
+= max_length
- length
;
1216 start_pos
+= (max_length
- length
) / 2;