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(const 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(const 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(const XCrossingEvent
*) {
881 if (! hide_timer
->isTiming()) hide_timer
->start();
883 if (hide_timer
->isTiming()) hide_timer
->stop();
887 void Toolbar::leaveNotifyEvent(const 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(const 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(const XKeyEvent
*ke
) {
912 if (ke
->window
== frame
.workspace_label
&& editing
) {
913 if (new_workspace_name
.empty()) {
919 XLookupString(const_cast<XKeyEvent
*>(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;