1 // -*- mode: C++; indent-tabs-mode: nil; -*-
2 // Toolbar.cc for Blackbox - an X11 Window manager
3 // Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
4 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
6 // Permission is hereby granted, free of charge, to any person obtaining a
7 // copy of this software and associated documentation files (the "Software"),
8 // to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 // and/or sell copies of the Software, and to permit persons to whom the
11 // Software is furnished to do so, subject to the following conditions:
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 // DEALINGS IN THE SOFTWARE.
25 # include "../config.h"
26 #endif // HAVE_CONFIG_H
29 #include <X11/keysym.h>
33 #endif // HAVE_STRING_H
37 #endif // HAVE_STDIO_H
39 #ifdef TIME_WITH_SYS_TIME
40 # include <sys/time.h>
42 #else // !TIME_WITH_SYS_TIME
43 # ifdef HAVE_SYS_TIME_H
44 # include <sys/time.h>
45 # else // !HAVE_SYS_TIME_H
47 # endif // HAVE_SYS_TIME_H
48 #endif // TIME_WITH_SYS_TIME
55 #include "blackbox.hh"
56 #include "Clientmenu.hh"
58 #include "Iconmenu.hh"
60 #include "Rootmenu.hh"
64 #include "Workspace.hh"
65 #include "Workspacemenu.hh"
69 static long aMinuteFromNow(void) {
71 gettimeofday(&now
, 0);
72 return ((60 - (now
.tv_sec
% 60)) * 1000);
76 Toolbar::Toolbar(BScreen
*scrn
) {
78 blackbox
= screen
->getBlackbox();
79 toolbarstr
= (string
)"session.screen" + itostring(screen
->getScreenNumber())
81 config
= blackbox
->getConfig();
85 // get the clock updating every minute
86 clock_timer
= new BTimer(blackbox
, this);
87 clock_timer
->setTimeout(aMinuteFromNow());
88 clock_timer
->recurring(True
);
90 frame
.minute
= frame
.hour
= -1;
92 hide_handler
.toolbar
= this;
93 hide_timer
= new BTimer(blackbox
, &hide_handler
);
94 hide_timer
->setTimeout(blackbox
->getAutoRaiseDelay());
98 frame
.grab_x
= frame
.grab_y
= 0;
100 toolbarmenu
= new Toolbarmenu(this);
102 display
= blackbox
->getXDisplay();
103 XSetWindowAttributes attrib
;
104 unsigned long create_mask
= CWBackPixmap
| CWBackPixel
| CWBorderPixel
|
105 CWColormap
| CWOverrideRedirect
| CWEventMask
;
106 attrib
.background_pixmap
= None
;
107 attrib
.background_pixel
= attrib
.border_pixel
=
108 screen
->getBorderColor()->pixel();
109 attrib
.colormap
= screen
->getColormap();
110 attrib
.override_redirect
= True
;
111 attrib
.event_mask
= ButtonPressMask
| ButtonReleaseMask
|
112 EnterWindowMask
| LeaveWindowMask
;
115 XCreateWindow(display
, screen
->getRootWindow(), 0, 0, 1, 1, 0,
116 screen
->getDepth(), InputOutput
, screen
->getVisual(),
117 create_mask
, &attrib
);
118 blackbox
->saveToolbarSearch(frame
.window
, this);
120 attrib
.event_mask
= ButtonPressMask
| ButtonReleaseMask
| ExposureMask
|
121 KeyPressMask
| EnterWindowMask
;
123 frame
.workspace_label
=
124 XCreateWindow(display
, frame
.window
, 0, 0, 1, 1, 0, screen
->getDepth(),
125 InputOutput
, screen
->getVisual(), create_mask
, &attrib
);
126 blackbox
->saveToolbarSearch(frame
.workspace_label
, this);
129 XCreateWindow(display
, frame
.window
, 0, 0, 1, 1, 0, screen
->getDepth(),
130 InputOutput
, screen
->getVisual(), create_mask
, &attrib
);
131 blackbox
->saveToolbarSearch(frame
.window_label
, this);
134 XCreateWindow(display
, frame
.window
, 0, 0, 1, 1, 0, screen
->getDepth(),
135 InputOutput
, screen
->getVisual(), create_mask
, &attrib
);
136 blackbox
->saveToolbarSearch(frame
.clock
, this);
139 XCreateWindow(display
,frame
.window
, 0, 0, 1, 1, 0, screen
->getDepth(),
140 InputOutput
, screen
->getVisual(), create_mask
, &attrib
);
141 blackbox
->saveToolbarSearch(frame
.psbutton
, this);
144 XCreateWindow(display
,frame
.window
, 0, 0, 1, 1, 0, screen
->getDepth(),
145 InputOutput
, screen
->getVisual(), create_mask
, &attrib
);
146 blackbox
->saveToolbarSearch(frame
.nsbutton
, this);
149 XCreateWindow(display
,frame
.window
, 0, 0, 1, 1, 0, screen
->getDepth(),
150 InputOutput
, screen
->getVisual(), create_mask
, &attrib
);
151 blackbox
->saveToolbarSearch(frame
.pwbutton
, this);
154 XCreateWindow(display
,frame
.window
, 0, 0, 1, 1, 0, screen
->getDepth(),
155 InputOutput
, screen
->getVisual(), create_mask
, &attrib
);
156 blackbox
->saveToolbarSearch(frame
.nwbutton
, this);
158 frame
.base
= frame
.label
= frame
.wlabel
= frame
.clk
= frame
.button
=
159 frame
.pbutton
= None
;
161 screen
->addStrut(&strut
);
168 Toolbar::~Toolbar(void) {
171 if (frame
.base
) screen
->getImageControl()->removeImage(frame
.base
);
172 if (frame
.label
) screen
->getImageControl()->removeImage(frame
.label
);
173 if (frame
.wlabel
) screen
->getImageControl()->removeImage(frame
.wlabel
);
174 if (frame
.clk
) screen
->getImageControl()->removeImage(frame
.clk
);
175 if (frame
.button
) screen
->getImageControl()->removeImage(frame
.button
);
176 if (frame
.pbutton
) screen
->getImageControl()->removeImage(frame
.pbutton
);
178 blackbox
->removeToolbarSearch(frame
.window
);
179 blackbox
->removeToolbarSearch(frame
.workspace_label
);
180 blackbox
->removeToolbarSearch(frame
.window_label
);
181 blackbox
->removeToolbarSearch(frame
.clock
);
182 blackbox
->removeToolbarSearch(frame
.psbutton
);
183 blackbox
->removeToolbarSearch(frame
.nsbutton
);
184 blackbox
->removeToolbarSearch(frame
.pwbutton
);
185 blackbox
->removeToolbarSearch(frame
.nwbutton
);
187 XDestroyWindow(display
, frame
.workspace_label
);
188 XDestroyWindow(display
, frame
.window_label
);
189 XDestroyWindow(display
, frame
.clock
);
191 XDestroyWindow(display
, frame
.window
);
199 void Toolbar::mapToolbar() {
200 if (!screen
->doHideToolbar()) {
201 //not hidden, so windows should not maximize over the toolbar
202 XMapSubwindows(display
, frame
.window
);
203 XMapWindow(display
, frame
.window
);
209 void Toolbar::unmapToolbar() {
210 if (toolbarmenu
->isVisible())
212 //hidden so we can maximize over the toolbar
213 XUnmapWindow(display
, frame
.window
);
218 void Toolbar::saveOnTop(bool b
) {
220 config
->setValue(toolbarstr
+ "onTop", on_top
);
224 void Toolbar::saveAutoHide(bool b
) {
226 config
->setValue(toolbarstr
+ "autoHide", do_auto_hide
);
230 void Toolbar::saveWidthPercent(unsigned int w
) {
232 config
->setValue(toolbarstr
+ "widthPercent", width_percent
);
236 void Toolbar::savePlacement(int p
) {
240 case TopLeft
: pname
= "TopLeft"; break;
241 case BottomLeft
: pname
= "BottomLeft"; break;
242 case TopCenter
: pname
= "TopCenter"; break;
243 case TopRight
: pname
= "TopRight"; break;
244 case BottomRight
: pname
= "BottomRight"; break;
245 case BottomCenter
: default: pname
= "BottomCenter"; break;
247 config
->setValue(toolbarstr
+ "placement", pname
);
251 void Toolbar::save_rc(void) {
253 saveAutoHide(do_auto_hide
);
254 saveWidthPercent(width_percent
);
255 savePlacement(placement
);
259 void Toolbar::load_rc(void) {
262 if (! config
->getValue(toolbarstr
+ "onTop", on_top
))
265 if (! config
->getValue(toolbarstr
+ "autoHide", do_auto_hide
))
266 do_auto_hide
= false;
267 hidden
= do_auto_hide
;
269 if (! config
->getValue(toolbarstr
+ "widthPercent", width_percent
) ||
270 width_percent
== 0 || width_percent
> 100)
273 if (config
->getValue(toolbarstr
+ "placement", s
)) {
276 else if (s
== "BottomLeft")
277 placement
= BottomLeft
;
278 else if (s
== "TopCenter")
279 placement
= TopCenter
;
280 else if (s
== "TopRight")
281 placement
= TopRight
;
282 else if (s
== "BottomRight")
283 placement
= BottomRight
;
284 else //if (s == "BottomCenter")
285 placement
= BottomCenter
;
287 placement
= BottomCenter
;
291 void Toolbar::reconfigure(void) {
292 unsigned int height
= 0,
293 width
= (screen
->getWidth() * width_percent
) / 100;
295 if (i18n
.multibyte())
296 height
= screen
->getToolbarStyle()->fontset_extents
->max_ink_extent
.height
;
298 height
= screen
->getToolbarStyle()->font
->ascent
+
299 screen
->getToolbarStyle()->font
->descent
;
301 frame
.bevel_w
= screen
->getBevelWidth();
302 frame
.button_w
= height
;
304 frame
.label_h
= height
;
305 height
+= (frame
.bevel_w
* 2);
307 frame
.rect
.setSize(width
, height
);
314 if (placement
== TopLeft
)
316 else if (placement
== TopRight
)
317 x
= screen
->getWidth() - frame
.rect
.width()
318 - (screen
->getBorderWidth() * 2);
320 x
= (screen
->getWidth() - frame
.rect
.width()) / 2;
325 frame
.y_hidden
= screen
->getBevelWidth() - screen
->getBorderWidth()
326 - frame
.rect
.height();
333 if (placement
== BottomLeft
)
335 else if (placement
== BottomRight
)
336 x
= screen
->getWidth() - frame
.rect
.width()
337 - (screen
->getBorderWidth() * 2);
339 x
= (screen
->getWidth() - frame
.rect
.width()) / 2;
341 y
= screen
->getHeight() - frame
.rect
.height()
342 - (screen
->getBorderWidth() * 2);
345 frame
.y_hidden
= screen
->getHeight() - screen
->getBevelWidth()
346 - screen
->getBorderWidth();
350 frame
.rect
.setPos(x
, y
);
355 time_t ttmp
= time(NULL
);
359 struct tm
*tt
= localtime(&ttmp
);
362 int len
= strftime(t
, 1024, screen
->getStrftimeFormat(), tt
);
363 if (len
== 0) { // invalid time format found
364 screen
->saveStrftimeFormat("%I:%M %p"); // so use the default
365 len
= strftime(t
, 1024, screen
->getStrftimeFormat(), tt
);
367 // find the length of the rendered string and add room for two extra
368 // characters to it. This allows for variable width output of the fonts
369 if (i18n
.multibyte()) {
370 XRectangle ink
, logical
;
371 XmbTextExtents(screen
->getToolbarStyle()->fontset
, t
, len
,
373 XFontSetExtents
* extents
= screen
->getToolbarStyle()->fontset_extents
;
374 frame
.clock_w
= logical
.width
+
375 (extents
->max_logical_extent
.width
* 2);
377 XFontStruct
* font
= screen
->getToolbarStyle()->font
;
378 frame
.clock_w
= XTextWidth(font
, t
, len
) +
379 ((font
->max_bounds
.rbearing
- font
->min_bounds
.lbearing
) * 2);
383 #else // !HAVE_STRFTIME
385 XTextWidth(screen
->getToolbarStyle()->font
,
386 i18n(ToolbarSet
, ToolbarNoStrftimeLength
, "00:00000"),
387 strlen(i18n(ToolbarSet
, ToolbarNoStrftimeLength
,
389 #endif // HAVE_STRFTIME
391 frame
.workspace_label_w
= 0;
393 for (unsigned int i
= 0; i
< screen
->getWorkspaceCount(); i
++) {
394 const string
& workspace_name
= screen
->getWorkspace(i
)->getName();
395 if (i18n
.multibyte()) {
396 XRectangle ink
, logical
;
397 XmbTextExtents(screen
->getToolbarStyle()->fontset
,
398 workspace_name
.c_str(), workspace_name
.length(),
400 width
= logical
.width
;
402 width
= XTextWidth(screen
->getToolbarStyle()->font
,
403 workspace_name
.c_str(), workspace_name
.length());
406 if (width
> frame
.workspace_label_w
) frame
.workspace_label_w
= width
;
409 frame
.workspace_label_w
= frame
.clock_w
=
410 std::max(frame
.workspace_label_w
, frame
.clock_w
) + (frame
.bevel_w
* 4);
412 // XXX: where'd the +6 come from?
413 frame
.window_label_w
=
414 (frame
.rect
.width() - (frame
.clock_w
+ (frame
.button_w
* 4) +
415 frame
.workspace_label_w
+ (frame
.bevel_w
* 8) + 6));
418 XMoveResizeWindow(display
, frame
.window
, frame
.x_hidden
, frame
.y_hidden
,
419 frame
.rect
.width(), frame
.rect
.height());
421 XMoveResizeWindow(display
, frame
.window
, frame
.rect
.x(), frame
.rect
.y(),
422 frame
.rect
.width(), frame
.rect
.height());
425 XMoveResizeWindow(display
, frame
.workspace_label
, frame
.bevel_w
,
426 frame
.bevel_w
, frame
.workspace_label_w
,
428 XMoveResizeWindow(display
, frame
.psbutton
,
429 ((frame
.bevel_w
* 2) + frame
.workspace_label_w
+ 1),
430 frame
.bevel_w
+ 1, frame
.button_w
, frame
.button_w
);
431 XMoveResizeWindow(display
, frame
.nsbutton
,
432 ((frame
.bevel_w
* 3) + frame
.workspace_label_w
+
433 frame
.button_w
+ 2), frame
.bevel_w
+ 1, frame
.button_w
,
435 XMoveResizeWindow(display
, frame
.window_label
,
436 ((frame
.bevel_w
* 4) + (frame
.button_w
* 2) +
437 frame
.workspace_label_w
+ 3), frame
.bevel_w
,
438 frame
.window_label_w
, frame
.label_h
);
439 XMoveResizeWindow(display
, frame
.pwbutton
,
440 ((frame
.bevel_w
* 5) + (frame
.button_w
* 2) +
441 frame
.workspace_label_w
+ frame
.window_label_w
+ 4),
442 frame
.bevel_w
+ 1, frame
.button_w
, frame
.button_w
);
443 XMoveResizeWindow(display
, frame
.nwbutton
,
444 ((frame
.bevel_w
* 6) + (frame
.button_w
* 3) +
445 frame
.workspace_label_w
+ frame
.window_label_w
+ 5),
446 frame
.bevel_w
+ 1, frame
.button_w
, frame
.button_w
);
447 XMoveResizeWindow(display
, frame
.clock
,
448 frame
.rect
.width() - frame
.clock_w
- (frame
.bevel_w
* 2),
449 frame
.bevel_w
, frame
.clock_w
, frame
.label_h
);
451 ToolbarStyle
*style
= screen
->getToolbarStyle();
452 frame
.base
= style
->toolbar
.render(frame
.rect
.width(), frame
.rect
.height(),
455 XSetWindowBackground(display
, frame
.window
,
456 style
->toolbar
.color().pixel());
458 XSetWindowBackgroundPixmap(display
, frame
.window
, frame
.base
);
460 frame
.label
= style
->window
.render(frame
.window_label_w
, frame
.label_h
,
463 XSetWindowBackground(display
, frame
.window_label
,
464 style
->window
.color().pixel());
466 XSetWindowBackgroundPixmap(display
, frame
.window_label
, frame
.label
);
468 frame
.wlabel
= style
->label
.render(frame
.workspace_label_w
, frame
.label_h
,
471 XSetWindowBackground(display
, frame
.workspace_label
,
472 style
->label
.color().pixel());
474 XSetWindowBackgroundPixmap(display
, frame
.workspace_label
, frame
.wlabel
);
476 frame
.clk
= style
->clock
.render(frame
.clock_w
, frame
.label_h
, frame
.clk
);
478 XSetWindowBackground(display
, frame
.clock
, style
->clock
.color().pixel());
480 XSetWindowBackgroundPixmap(display
, frame
.clock
, frame
.clk
);
482 frame
.button
= style
->button
.render(frame
.button_w
, frame
.button_w
,
484 if (! frame
.button
) {
485 frame
.button_pixel
= style
->button
.color().pixel();
486 XSetWindowBackground(display
, frame
.psbutton
, frame
.button_pixel
);
487 XSetWindowBackground(display
, frame
.nsbutton
, frame
.button_pixel
);
488 XSetWindowBackground(display
, frame
.pwbutton
, frame
.button_pixel
);
489 XSetWindowBackground(display
, frame
.nwbutton
, frame
.button_pixel
);
491 XSetWindowBackgroundPixmap(display
, frame
.psbutton
, frame
.button
);
492 XSetWindowBackgroundPixmap(display
, frame
.nsbutton
, frame
.button
);
493 XSetWindowBackgroundPixmap(display
, frame
.pwbutton
, frame
.button
);
494 XSetWindowBackgroundPixmap(display
, frame
.nwbutton
, frame
.button
);
497 frame
.pbutton
= style
->pressed
.render(frame
.button_w
, frame
.button_w
,
500 frame
.pbutton_pixel
= style
->pressed
.color().pixel();
502 XSetWindowBorder(display
, frame
.window
,
503 screen
->getBorderColor()->pixel());
504 XSetWindowBorderWidth(display
, frame
.window
, screen
->getBorderWidth());
506 XClearWindow(display
, frame
.window
);
507 XClearWindow(display
, frame
.workspace_label
);
508 XClearWindow(display
, frame
.window_label
);
509 XClearWindow(display
, frame
.clock
);
510 XClearWindow(display
, frame
.psbutton
);
511 XClearWindow(display
, frame
.nsbutton
);
512 XClearWindow(display
, frame
.pwbutton
);
513 XClearWindow(display
, frame
.nwbutton
);
516 redrawWorkspaceLabel();
517 redrawPrevWorkspaceButton();
518 redrawNextWorkspaceButton();
519 redrawPrevWindowButton();
520 redrawNextWindowButton();
523 toolbarmenu
->reconfigure();
527 void Toolbar::updateStrut(void) {
528 // left and right are always 0
529 strut
.top
= strut
.bottom
= 0;
531 // when hidden only one border is visible
532 unsigned int border_width
= screen
->getBorderWidth();
536 if (! screen
->doHideToolbar()) {
541 strut
.top
= getExposedHeight() + border_width
;
544 strut
.bottom
= getExposedHeight() + border_width
;
548 screen
->updateAvailableArea();
553 void Toolbar::checkClock(bool redraw
) {
554 #else // !HAVE_STRFTIME
555 void Toolbar::checkClock(bool redraw
, bool date
) {
556 #endif // HAVE_STRFTIME
560 if ((tmp
= time(NULL
)) != -1) {
561 if (! (tt
= localtime(&tmp
))) return;
562 if (tt
->tm_min
!= frame
.minute
|| tt
->tm_hour
!= frame
.hour
) {
563 frame
.hour
= tt
->tm_hour
;
564 frame
.minute
= tt
->tm_min
;
565 XClearWindow(display
, frame
.clock
);
573 if (! strftime(t
, 1024, screen
->getStrftimeFormat(), tt
))
575 #else // !HAVE_STRFTIME
578 // format the date... with special consideration for y2k ;)
579 if (screen
->getDateFormat() == Blackbox::B_EuropeanDate
)
580 sprintf(t
, 18n(ToolbarSet
, ToolbarNoStrftimeDateFormatEu
,
582 tt
->tm_mday
, tt
->tm_mon
+ 1,
583 (tt
->tm_year
>= 100) ? tt
->tm_year
- 100 : tt
->tm_year
);
585 sprintf(t
, i18n(ToolbarSet
, ToolbarNoStrftimeDateFormat
,
587 tt
->tm_mon
+ 1, tt
->tm_mday
,
588 (tt
->tm_year
>= 100) ? tt
->tm_year
- 100 : tt
->tm_year
);
590 if (screen
->isClock24Hour())
591 sprintf(t
, i18n(ToolbarSet
, ToolbarNoStrftimeTimeFormat24
,
593 frame
.hour
, frame
.minute
);
595 sprintf(t
, i18n(ToolbarSet
, ToolbarNoStrftimeTimeFormat12
,
597 ((frame
.hour
> 12) ? frame
.hour
- 12 :
598 ((frame
.hour
== 0) ? 12 : frame
.hour
)), frame
.minute
,
599 ((frame
.hour
>= 12) ?
600 i18n(ToolbarSet
, ToolbarNoStrftimeTimeFormatP
, "p") :
601 i18n(ToolbarSet
, ToolbarNoStrftimeTimeFormatA
, "a")));
603 #endif // HAVE_STRFTIME
605 ToolbarStyle
*style
= screen
->getToolbarStyle();
607 int pos
= frame
.bevel_w
* 2, // this is modified by doJustify()
608 dlen
= style
->doJustify(t
, pos
, frame
.clock_w
,
609 frame
.bevel_w
* 4, i18n
.multibyte());
610 BPen
pen(style
->c_text
, style
->font
);
611 if (i18n
.multibyte())
612 XmbDrawString(display
, frame
.clock
, style
->fontset
, pen
.gc(),
613 pos
, (1 - style
->fontset_extents
->max_ink_extent
.y
),
616 XDrawString(display
, frame
.clock
, pen
.gc(), pos
,
617 (style
->font
->ascent
+ 1), t
, dlen
);
622 void Toolbar::redrawWindowLabel(bool redraw
) {
623 BlackboxWindow
*foc
= screen
->getBlackbox()->getFocusedWindow();
625 XClearWindow(display
, frame
.window_label
);
630 XClearWindow(display
, frame
.window_label
);
632 if (foc
->getScreen() != screen
) return;
634 const char *title
= foc
->getTitle();
635 ToolbarStyle
*style
= screen
->getToolbarStyle();
637 int pos
= frame
.bevel_w
* 2, // modified by doJustify()
638 dlen
= style
->doJustify(title
, pos
, frame
.window_label_w
,
639 frame
.bevel_w
* 4, i18n
.multibyte());
640 BPen
pen(style
->w_text
, style
->font
);
641 if (i18n
.multibyte())
642 XmbDrawString(display
, frame
.window_label
, style
->fontset
, pen
.gc(), pos
,
643 (1 - style
->fontset_extents
->max_ink_extent
.y
),
646 XDrawString(display
, frame
.window_label
, pen
.gc(), pos
,
647 (style
->font
->ascent
+ 1), title
, dlen
);
651 void Toolbar::redrawWorkspaceLabel(bool redraw
) {
652 const string
& name
= screen
->getCurrentWorkspace()->getName();
655 XClearWindow(display
, frame
.workspace_label
);
657 ToolbarStyle
*style
= screen
->getToolbarStyle();
659 int pos
= frame
.bevel_w
* 2,
660 dlen
= style
->doJustify(name
.c_str(), pos
, frame
.workspace_label_w
,
661 frame
.bevel_w
* 4, i18n
.multibyte());
662 BPen
pen(style
->l_text
, style
->font
);
663 if (i18n
.multibyte())
664 XmbDrawString(display
, frame
.workspace_label
, style
->fontset
, pen
.gc(),
665 pos
, (1 - style
->fontset_extents
->max_ink_extent
.y
),
668 XDrawString(display
, frame
.workspace_label
, pen
.gc(), pos
,
669 (style
->font
->ascent
+ 1),
674 void Toolbar::redrawPrevWorkspaceButton(bool pressed
, bool redraw
) {
678 XSetWindowBackgroundPixmap(display
, frame
.psbutton
, frame
.pbutton
);
680 XSetWindowBackground(display
, frame
.psbutton
, frame
.pbutton_pixel
);
683 XSetWindowBackgroundPixmap(display
, frame
.psbutton
, frame
.button
);
685 XSetWindowBackground(display
, frame
.psbutton
, frame
.button_pixel
);
687 XClearWindow(display
, frame
.psbutton
);
690 int hh
= frame
.button_w
/ 2, hw
= frame
.button_w
/ 2;
693 pts
[0].x
= hw
- 2; pts
[0].y
= hh
;
694 pts
[1].x
= 4; pts
[1].y
= 2;
695 pts
[2].x
= 0; pts
[2].y
= -4;
697 ToolbarStyle
*style
= screen
->getToolbarStyle();
698 BPen
pen(style
->b_pic
, style
->font
);
699 XFillPolygon(display
, frame
.psbutton
, pen
.gc(),
700 pts
, 3, Convex
, CoordModePrevious
);
704 void Toolbar::redrawNextWorkspaceButton(bool pressed
, bool redraw
) {
708 XSetWindowBackgroundPixmap(display
, frame
.nsbutton
, frame
.pbutton
);
710 XSetWindowBackground(display
, frame
.nsbutton
, frame
.pbutton_pixel
);
713 XSetWindowBackgroundPixmap(display
, frame
.nsbutton
, frame
.button
);
715 XSetWindowBackground(display
, frame
.nsbutton
, frame
.button_pixel
);
717 XClearWindow(display
, frame
.nsbutton
);
720 int hh
= frame
.button_w
/ 2, hw
= frame
.button_w
/ 2;
723 pts
[0].x
= hw
- 2; pts
[0].y
= hh
- 2;
724 pts
[1].x
= 4; pts
[1].y
= 2;
725 pts
[2].x
= -4; pts
[2].y
= 2;
727 ToolbarStyle
*style
= screen
->getToolbarStyle();
728 BPen
pen(style
->b_pic
, style
->font
);
729 XFillPolygon(display
, frame
.nsbutton
, pen
.gc(),
730 pts
, 3, Convex
, CoordModePrevious
);
734 void Toolbar::redrawPrevWindowButton(bool pressed
, bool redraw
) {
738 XSetWindowBackgroundPixmap(display
, frame
.pwbutton
, frame
.pbutton
);
740 XSetWindowBackground(display
, frame
.pwbutton
, frame
.pbutton_pixel
);
743 XSetWindowBackgroundPixmap(display
, frame
.pwbutton
, frame
.button
);
745 XSetWindowBackground(display
, frame
.pwbutton
, frame
.button_pixel
);
747 XClearWindow(display
, frame
.pwbutton
);
750 int hh
= frame
.button_w
/ 2, hw
= frame
.button_w
/ 2;
753 pts
[0].x
= hw
- 2; pts
[0].y
= hh
;
754 pts
[1].x
= 4; pts
[1].y
= 2;
755 pts
[2].x
= 0; pts
[2].y
= -4;
757 ToolbarStyle
*style
= screen
->getToolbarStyle();
758 BPen
pen(style
->b_pic
, style
->font
);
759 XFillPolygon(display
, frame
.pwbutton
, pen
.gc(),
760 pts
, 3, Convex
, CoordModePrevious
);
764 void Toolbar::redrawNextWindowButton(bool pressed
, bool redraw
) {
768 XSetWindowBackgroundPixmap(display
, frame
.nwbutton
, frame
.pbutton
);
770 XSetWindowBackground(display
, frame
.nwbutton
, frame
.pbutton_pixel
);
773 XSetWindowBackgroundPixmap(display
, frame
.nwbutton
, frame
.button
);
775 XSetWindowBackground(display
, frame
.nwbutton
, frame
.button_pixel
);
777 XClearWindow(display
, frame
.nwbutton
);
780 int hh
= frame
.button_w
/ 2, hw
= frame
.button_w
/ 2;
783 pts
[0].x
= hw
- 2; pts
[0].y
= hh
- 2;
784 pts
[1].x
= 4; pts
[1].y
= 2;
785 pts
[2].x
= -4; pts
[2].y
= 2;
787 ToolbarStyle
*style
= screen
->getToolbarStyle();
788 BPen
pen(style
->b_pic
, style
->font
);
789 XFillPolygon(display
, frame
.nwbutton
, pen
.gc(), pts
, 3, Convex
,
794 void Toolbar::edit(void) {
799 XGetInputFocus(display
, &window
, &foo
);
800 if (window
== frame
.workspace_label
)
803 XSetInputFocus(display
, frame
.workspace_label
,
804 RevertToPointerRoot
, CurrentTime
);
805 XClearWindow(display
, frame
.workspace_label
);
807 blackbox
->setNoFocus(True
);
808 if (blackbox
->getFocusedWindow())
809 blackbox
->getFocusedWindow()->setFocusFlag(False
);
811 ToolbarStyle
*style
= screen
->getToolbarStyle();
812 BPen
pen(style
->l_text
, style
->font
);
813 XDrawRectangle(display
, frame
.workspace_label
, pen
.gc(),
814 frame
.workspace_label_w
/ 2, 0, 1,
816 // change the background of the window to that of an active window label
817 BTexture
*texture
= &(screen
->getWindowStyle()->l_focus
);
818 frame
.wlabel
= texture
->render(frame
.workspace_label_w
, frame
.label_h
,
821 XSetWindowBackground(display
, frame
.workspace_label
,
822 texture
->color().pixel());
824 XSetWindowBackgroundPixmap(display
, frame
.workspace_label
, frame
.wlabel
);
828 void Toolbar::buttonPressEvent(XButtonEvent
*be
) {
829 if (be
->button
== 1) {
830 if (be
->window
== frame
.psbutton
)
831 redrawPrevWorkspaceButton(True
, True
);
832 else if (be
->window
== frame
.nsbutton
)
833 redrawNextWorkspaceButton(True
, True
);
834 else if (be
->window
== frame
.pwbutton
)
835 redrawPrevWindowButton(True
, True
);
836 else if (be
->window
== frame
.nwbutton
)
837 redrawNextWindowButton(True
, True
);
838 #ifndef HAVE_STRFTIME
839 else if (be
->window
== frame
.clock
) {
840 XClearWindow(display
, frame
.clock
);
841 checkClock(True
, True
);
843 #endif // HAVE_STRFTIME
845 Window w
[1] = { frame
.window
};
846 screen
->raiseWindows(w
, 1);
848 } else if (be
->button
== 2 && (! on_top
)) {
849 XLowerWindow(display
, frame
.window
);
850 } else if (be
->button
== 3) {
851 if (toolbarmenu
->isVisible()) {
856 x
= be
->x_root
- (toolbarmenu
->getWidth() / 2);
857 y
= be
->y_root
- (toolbarmenu
->getHeight() / 2);
861 else if (x
+ toolbarmenu
->getWidth() > screen
->getWidth())
862 x
= screen
->getWidth() - toolbarmenu
->getWidth();
866 else if (y
+ toolbarmenu
->getHeight() > screen
->getHeight())
867 y
= screen
->getHeight() - toolbarmenu
->getHeight();
869 toolbarmenu
->move(x
, y
);
877 void Toolbar::buttonReleaseEvent(XButtonEvent
*re
) {
878 if (re
->button
== 1) {
879 if (re
->window
== frame
.psbutton
) {
880 redrawPrevWorkspaceButton(False
, True
);
882 if (re
->x
>= 0 && re
->x
< static_cast<signed>(frame
.button_w
) &&
883 re
->y
>= 0 && re
->y
< static_cast<signed>(frame
.button_w
))
884 if (screen
->getCurrentWorkspace()->getID() > 0)
885 screen
->changeWorkspaceID(screen
->getCurrentWorkspace()->
888 screen
->changeWorkspaceID(screen
->getWorkspaceCount() - 1);
889 } else if (re
->window
== frame
.nsbutton
) {
890 redrawNextWorkspaceButton(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
))
894 if (screen
->getCurrentWorkspace()->getID() <
895 (screen
->getWorkspaceCount() - 1))
896 screen
->changeWorkspaceID(screen
->getCurrentWorkspace()->
899 screen
->changeWorkspaceID(0);
900 } else if (re
->window
== frame
.pwbutton
) {
901 redrawPrevWindowButton(False
, True
);
903 if (re
->x
>= 0 && re
->x
< static_cast<signed>(frame
.button_w
) &&
904 re
->y
>= 0 && re
->y
< static_cast<signed>(frame
.button_w
))
906 } else if (re
->window
== frame
.nwbutton
) {
907 redrawNextWindowButton(False
, True
);
909 if (re
->x
>= 0 && re
->x
< static_cast<signed>(frame
.button_w
) &&
910 re
->y
>= 0 && re
->y
< static_cast<signed>(frame
.button_w
))
912 } else if (re
->window
== frame
.window_label
)
913 screen
->raiseFocus();
914 #ifndef HAVE_STRFTIME
915 else if (re
->window
== frame
.clock
) {
916 XClearWindow(display
, frame
.clock
);
919 #endif // HAVE_STRFTIME
924 void Toolbar::enterNotifyEvent(XCrossingEvent
*) {
929 if (! hide_timer
->isTiming()) hide_timer
->start();
931 if (hide_timer
->isTiming()) hide_timer
->stop();
935 void Toolbar::leaveNotifyEvent(XCrossingEvent
*) {
940 if (hide_timer
->isTiming()) hide_timer
->stop();
941 } else if (! toolbarmenu
->isVisible()) {
942 if (! hide_timer
->isTiming()) hide_timer
->start();
947 void Toolbar::exposeEvent(XExposeEvent
*ee
) {
948 if (ee
->window
== frame
.clock
) checkClock(True
);
949 else if (ee
->window
== frame
.workspace_label
&& (! editing
))
950 redrawWorkspaceLabel();
951 else if (ee
->window
== frame
.window_label
) redrawWindowLabel();
952 else if (ee
->window
== frame
.psbutton
) redrawPrevWorkspaceButton();
953 else if (ee
->window
== frame
.nsbutton
) redrawNextWorkspaceButton();
954 else if (ee
->window
== frame
.pwbutton
) redrawPrevWindowButton();
955 else if (ee
->window
== frame
.nwbutton
) redrawNextWindowButton();
959 void Toolbar::keyPressEvent(XKeyEvent
*ke
) {
960 if (ke
->window
== frame
.workspace_label
&& editing
) {
961 if (new_workspace_name
.empty()) {
967 XLookupString(ke
, keychar
, 1, &ks
, 0);
969 // either we are told to end with a return or we hit 127 chars
970 if (ks
== XK_Return
|| new_name_pos
== 127) {
973 blackbox
->setNoFocus(False
);
974 if (blackbox
->getFocusedWindow()) {
975 blackbox
->getFocusedWindow()->setInputFocus();
977 blackbox
->setFocusedWindow(0);
980 Workspace
*wkspc
= screen
->getCurrentWorkspace();
981 wkspc
->setName(new_workspace_name
);
982 wkspc
->getMenu()->hide();
984 screen
->getWorkspacemenu()->changeItemLabel(wkspc
->getID() + 2,
986 screen
->getWorkspacemenu()->update();
988 new_workspace_name
.erase();
991 // reset the background to that of the workspace label (its normal
993 BTexture
*texture
= &(screen
->getToolbarStyle()->label
);
994 frame
.wlabel
= texture
->render(frame
.workspace_label_w
, frame
.label_h
,
997 XSetWindowBackground(display
, frame
.workspace_label
,
998 texture
->color().pixel());
1000 XSetWindowBackgroundPixmap(display
, frame
.workspace_label
,
1003 } else if (! (ks
== XK_Shift_L
|| ks
== XK_Shift_R
||
1004 ks
== XK_Control_L
|| ks
== XK_Control_R
||
1005 ks
== XK_Caps_Lock
|| ks
== XK_Shift_Lock
||
1006 ks
== XK_Meta_L
|| ks
== XK_Meta_R
||
1007 ks
== XK_Alt_L
|| ks
== XK_Alt_R
||
1008 ks
== XK_Super_L
|| ks
== XK_Super_R
||
1009 ks
== XK_Hyper_L
|| ks
== XK_Hyper_R
)) {
1010 if (ks
== XK_BackSpace
) {
1011 if (new_name_pos
> 0) {
1013 new_workspace_name
.erase(new_name_pos
);
1015 new_workspace_name
.resize(0);
1018 new_workspace_name
+= (*keychar
);
1022 XClearWindow(display
, frame
.workspace_label
);
1023 unsigned int l
= new_workspace_name
.length(), tw
, x
;
1025 if (i18n
.multibyte()) {
1026 XRectangle ink
, logical
;
1027 XmbTextExtents(screen
->getToolbarStyle()->fontset
,
1028 new_workspace_name
.c_str(), l
, &ink
, &logical
);
1031 tw
= XTextWidth(screen
->getToolbarStyle()->font
,
1032 new_workspace_name
.c_str(), l
);
1034 x
= (frame
.workspace_label_w
- tw
) / 2;
1036 if (x
< frame
.bevel_w
) x
= frame
.bevel_w
;
1038 ToolbarStyle
*style
= screen
->getToolbarStyle();
1039 BPen
pen(style
->l_text
, style
->font
);
1040 if (i18n
.multibyte())
1041 XmbDrawString(display
, frame
.workspace_label
, style
->fontset
,
1043 (1 - style
->fontset_extents
->max_ink_extent
.y
),
1044 new_workspace_name
.c_str(), l
);
1046 XDrawString(display
, frame
.workspace_label
, pen
.gc(), x
,
1047 (style
->font
->ascent
+ 1),
1048 new_workspace_name
.c_str(), l
);
1049 XDrawRectangle(display
, frame
.workspace_label
, pen
.gc(), x
+ tw
, 0, 1,
1056 void Toolbar::timeout(void) {
1059 clock_timer
->setTimeout(aMinuteFromNow());
1063 void Toolbar::HideHandler::timeout(void) {
1064 toolbar
->hidden
= ! toolbar
->hidden
;
1065 if (toolbar
->hidden
)
1066 XMoveWindow(toolbar
->display
, toolbar
->frame
.window
,
1067 toolbar
->frame
.x_hidden
, toolbar
->frame
.y_hidden
);
1069 XMoveWindow(toolbar
->display
, toolbar
->frame
.window
,
1070 toolbar
->frame
.rect
.x(), toolbar
->frame
.rect
.y());
1074 void Toolbar::toggleAutoHide(void) {
1075 saveAutoHide(! doAutoHide());
1078 screen
->getSlit()->reposition();
1080 if (do_auto_hide
== False
&& hidden
) {
1081 // force the slit to be visible
1082 if (hide_timer
->isTiming()) hide_timer
->stop();
1083 hide_handler
.timeout();
1088 Toolbarmenu::Toolbarmenu(Toolbar
*tb
) : Basemenu(tb
->screen
) {
1091 setLabel(i18n(ToolbarSet
, ToolbarToolbarTitle
, "Toolbar"));
1094 placementmenu
= new Placementmenu(this);
1096 insert(i18n(CommonSet
, CommonPlacementTitle
, "Placement"),
1098 insert(i18n(CommonSet
, CommonAlwaysOnTop
, "Always on top"), 1);
1099 insert(i18n(CommonSet
, CommonAutoHide
, "Auto hide"), 2);
1100 insert(i18n(ToolbarSet
, ToolbarEditWkspcName
,
1101 "Edit current workspace name"), 3);
1108 void Toolbarmenu::setValues() {
1109 setItemSelected(1, toolbar
->isOnTop());
1110 setItemSelected(2, toolbar
->doAutoHide());
1114 Toolbarmenu::~Toolbarmenu(void) {
1115 delete placementmenu
;
1119 void Toolbarmenu::itemSelected(int button
, unsigned int index
) {
1123 BasemenuItem
*item
= find(index
);
1126 switch (item
->function()) {
1127 case 1: { // always on top
1128 toolbar
->saveOnTop(! toolbar
->isOnTop());
1129 setItemSelected(1, toolbar
->isOnTop());
1131 if (toolbar
->isOnTop()) getScreen()->raiseWindows((Window
*) 0, 0);
1135 case 2: { // auto hide
1136 toolbar
->toggleAutoHide();
1137 setItemSelected(2, toolbar
->doAutoHide());
1142 case 3: { // edit current workspace name
1152 void Toolbarmenu::internal_hide(void) {
1153 Basemenu::internal_hide();
1154 if (toolbar
->doAutoHide() && ! toolbar
->isEditing())
1155 toolbar
->hide_handler
.timeout();
1159 void Toolbarmenu::reconfigure(void) {
1161 placementmenu
->reconfigure();
1163 Basemenu::reconfigure();
1167 Toolbarmenu::Placementmenu::Placementmenu(Toolbarmenu
*tm
)
1168 : Basemenu(tm
->toolbar
->screen
), toolbar(tm
->toolbar
) {
1169 setLabel(i18n(ToolbarSet
, ToolbarToolbarPlacement
, "Toolbar Placement"));
1171 setMinimumSublevels(3);
1173 insert(i18n(CommonSet
, CommonPlacementTopLeft
, "Top Left"),
1175 insert(i18n(CommonSet
, CommonPlacementBottomLeft
, "Bottom Left"),
1176 Toolbar::BottomLeft
);
1177 insert(i18n(CommonSet
, CommonPlacementTopCenter
, "Top Center"),
1178 Toolbar::TopCenter
);
1179 insert(i18n(CommonSet
, CommonPlacementBottomCenter
, "Bottom Center"),
1180 Toolbar::BottomCenter
);
1181 insert(i18n(CommonSet
, CommonPlacementTopRight
, "Top Right"),
1183 insert(i18n(CommonSet
, CommonPlacementBottomRight
, "Bottom Right"),
1184 Toolbar::BottomRight
);
1190 void Toolbarmenu::Placementmenu::setValues(void) {
1192 switch (toolbar
->getPlacement()) {
1193 case Toolbar::BottomRight
:
1195 case Toolbar::TopRight
:
1197 case Toolbar::BottomCenter
:
1199 case Toolbar::TopCenter
:
1201 case Toolbar::BottomLeft
:
1203 case Toolbar::TopLeft
:
1206 setItemSelected(0, 0 == place
);
1207 setItemSelected(1, 1 == place
);
1208 setItemSelected(2, 2 == place
);
1209 setItemSelected(3, 3 == place
);
1210 setItemSelected(4, 4 == place
);
1211 setItemSelected(5, 5 == place
);
1215 void Toolbarmenu::Placementmenu::reconfigure(void) {
1217 Basemenu::reconfigure();
1221 void Toolbarmenu::Placementmenu::itemSelected(int button
, unsigned int index
) {
1225 BasemenuItem
*item
= find(index
);
1228 toolbar
->savePlacement(item
->function());
1230 toolbar
->reconfigure();
1232 // reposition the slit as well to make sure it doesn't intersect the
1234 getScreen()->getSlit()->reposition();
1238 int ToolbarStyle::doJustify(const char *text
, int &start_pos
,
1239 unsigned int max_length
, unsigned int modifier
,
1240 bool multibyte
) const {
1241 size_t text_len
= strlen(text
);
1242 unsigned int length
;
1246 XRectangle ink
, logical
;
1247 XmbTextExtents(fontset
, text
, text_len
, &ink
, &logical
);
1248 length
= logical
.width
;
1250 length
= XTextWidth(font
, text
, text_len
);
1253 } while (length
> max_length
&& text_len
-- > 0);
1257 start_pos
+= max_length
- length
;
1261 start_pos
+= (max_length
- length
) / 2;