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();
80 // get the clock updating every minute
81 clock_timer
= new BTimer(blackbox
, this);
82 clock_timer
->setTimeout(aMinuteFromNow());
83 clock_timer
->recurring(True
);
85 frame
.minute
= frame
.hour
= -1;
87 hide_handler
.toolbar
= this;
88 hide_timer
= new BTimer(blackbox
, &hide_handler
);
89 hide_timer
->setTimeout(blackbox
->getAutoRaiseDelay());
91 on_top
= screen
->isToolbarOnTop();
92 hidden
= do_auto_hide
= screen
->doToolbarAutoHide();
96 frame
.grab_x
= frame
.grab_y
= 0;
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
;
159 screen
->addStrut(&strut
);
163 XMapSubwindows(display
, frame
.window
);
164 XMapWindow(display
, frame
.window
);
168 Toolbar::~Toolbar(void) {
169 XUnmapWindow(display
, frame
.window
);
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::reconfigure(void) {
200 unsigned int height
= 0,
201 width
= (screen
->getWidth() * screen
->getToolbarWidthPercent()) / 100;
203 if (i18n
.multibyte())
204 height
= screen
->getToolbarStyle()->fontset_extents
->max_ink_extent
.height
;
206 height
= screen
->getToolbarStyle()->font
->ascent
+
207 screen
->getToolbarStyle()->font
->descent
;
209 frame
.bevel_w
= screen
->getBevelWidth();
210 frame
.button_w
= height
;
212 frame
.label_h
= height
;
213 height
+= (frame
.bevel_w
* 2);
215 frame
.rect
.setSize(width
, height
);
218 switch (screen
->getToolbarPlacement()) {
222 if (screen
->getToolbarPlacement() == TopLeft
)
224 else if (screen
->getToolbarPlacement() == TopRight
)
225 x
= screen
->getWidth() - frame
.rect
.width()
226 - (screen
->getBorderWidth() * 2);
228 x
= (screen
->getWidth() - frame
.rect
.width()) / 2;
233 frame
.y_hidden
= screen
->getBevelWidth() - screen
->getBorderWidth()
234 - frame
.rect
.height();
241 if (screen
->getToolbarPlacement() == BottomLeft
)
243 else if (screen
->getToolbarPlacement() == BottomRight
)
244 x
= screen
->getWidth() - frame
.rect
.width()
245 - (screen
->getBorderWidth() * 2);
247 x
= (screen
->getWidth() - frame
.rect
.width()) / 2;
249 y
= screen
->getHeight() - frame
.rect
.height()
250 - (screen
->getBorderWidth() * 2);
253 frame
.y_hidden
= screen
->getHeight() - screen
->getBevelWidth()
254 - screen
->getBorderWidth();
258 frame
.rect
.setPos(x
, y
);
263 time_t ttmp
= time(NULL
);
267 struct tm
*tt
= localtime(&ttmp
);
270 int len
= strftime(t
, 1024, screen
->getStrftimeFormat(), tt
);
271 if (len
== 0) { // invalid time format found
272 screen
->saveStrftimeFormat("%I:%M %p"); // so use the default
273 len
= strftime(t
, 1024, screen
->getStrftimeFormat(), tt
);
275 // find the length of the rendered string and add room for two extra
276 // characters to it. This allows for variable width output of the fonts
277 if (i18n
.multibyte()) {
278 XRectangle ink
, logical
;
279 XmbTextExtents(screen
->getToolbarStyle()->fontset
, t
, len
,
281 XFontSetExtents
* extents
= screen
->getToolbarStyle()->fontset_extents
;
282 frame
.clock_w
= logical
.width
+
283 (extents
->max_logical_extent
.width
* 2);
285 XFontStruct
* font
= screen
->getToolbarStyle()->font
;
286 frame
.clock_w
= XTextWidth(font
, t
, len
) +
287 ((font
->max_bounds
.rbearing
- font
->min_bounds
.lbearing
) * 2);
291 #else // !HAVE_STRFTIME
293 XTextWidth(screen
->getToolbarStyle()->font
,
294 i18n(ToolbarSet
, ToolbarNoStrftimeLength
, "00:00000"),
295 strlen(i18n(ToolbarSet
, ToolbarNoStrftimeLength
,
297 #endif // HAVE_STRFTIME
299 frame
.workspace_label_w
= 0;
301 for (unsigned int i
= 0; i
< screen
->getWorkspaceCount(); i
++) {
302 const string
& workspace_name
= screen
->getWorkspace(i
)->getName();
303 if (i18n
.multibyte()) {
304 XRectangle ink
, logical
;
305 XmbTextExtents(screen
->getToolbarStyle()->fontset
,
306 workspace_name
.c_str(), workspace_name
.length(),
308 width
= logical
.width
;
310 width
= XTextWidth(screen
->getToolbarStyle()->font
,
311 workspace_name
.c_str(), workspace_name
.length());
314 if (width
> frame
.workspace_label_w
) frame
.workspace_label_w
= width
;
317 frame
.workspace_label_w
= frame
.clock_w
=
318 std::max(frame
.workspace_label_w
, frame
.clock_w
) + (frame
.bevel_w
* 4);
320 // XXX: where'd the +6 come from?
321 frame
.window_label_w
=
322 (frame
.rect
.width() - (frame
.clock_w
+ (frame
.button_w
* 4) +
323 frame
.workspace_label_w
+ (frame
.bevel_w
* 8) + 6));
326 XMoveResizeWindow(display
, frame
.window
, frame
.x_hidden
, frame
.y_hidden
,
327 frame
.rect
.width(), frame
.rect
.height());
329 XMoveResizeWindow(display
, frame
.window
, frame
.rect
.x(), frame
.rect
.y(),
330 frame
.rect
.width(), frame
.rect
.height());
333 XMoveResizeWindow(display
, frame
.workspace_label
, frame
.bevel_w
,
334 frame
.bevel_w
, frame
.workspace_label_w
,
336 XMoveResizeWindow(display
, frame
.psbutton
,
337 ((frame
.bevel_w
* 2) + frame
.workspace_label_w
+ 1),
338 frame
.bevel_w
+ 1, frame
.button_w
, frame
.button_w
);
339 XMoveResizeWindow(display
, frame
.nsbutton
,
340 ((frame
.bevel_w
* 3) + frame
.workspace_label_w
+
341 frame
.button_w
+ 2), frame
.bevel_w
+ 1, frame
.button_w
,
343 XMoveResizeWindow(display
, frame
.window_label
,
344 ((frame
.bevel_w
* 4) + (frame
.button_w
* 2) +
345 frame
.workspace_label_w
+ 3), frame
.bevel_w
,
346 frame
.window_label_w
, frame
.label_h
);
347 XMoveResizeWindow(display
, frame
.pwbutton
,
348 ((frame
.bevel_w
* 5) + (frame
.button_w
* 2) +
349 frame
.workspace_label_w
+ frame
.window_label_w
+ 4),
350 frame
.bevel_w
+ 1, frame
.button_w
, frame
.button_w
);
351 XMoveResizeWindow(display
, frame
.nwbutton
,
352 ((frame
.bevel_w
* 6) + (frame
.button_w
* 3) +
353 frame
.workspace_label_w
+ frame
.window_label_w
+ 5),
354 frame
.bevel_w
+ 1, frame
.button_w
, frame
.button_w
);
355 XMoveResizeWindow(display
, frame
.clock
,
356 frame
.rect
.width() - frame
.clock_w
- (frame
.bevel_w
* 2),
357 frame
.bevel_w
, frame
.clock_w
, frame
.label_h
);
359 ToolbarStyle
*style
= screen
->getToolbarStyle();
360 frame
.base
= style
->toolbar
.render(frame
.rect
.width(), frame
.rect
.height(),
363 XSetWindowBackground(display
, frame
.window
,
364 style
->toolbar
.color().pixel());
366 XSetWindowBackgroundPixmap(display
, frame
.window
, frame
.base
);
368 frame
.label
= style
->window
.render(frame
.window_label_w
, frame
.label_h
,
371 XSetWindowBackground(display
, frame
.window_label
,
372 style
->window
.color().pixel());
374 XSetWindowBackgroundPixmap(display
, frame
.window_label
, frame
.label
);
376 frame
.wlabel
= style
->label
.render(frame
.workspace_label_w
, frame
.label_h
,
379 XSetWindowBackground(display
, frame
.workspace_label
,
380 style
->label
.color().pixel());
382 XSetWindowBackgroundPixmap(display
, frame
.workspace_label
, frame
.wlabel
);
384 frame
.clk
= style
->clock
.render(frame
.clock_w
, frame
.label_h
, frame
.clk
);
386 XSetWindowBackground(display
, frame
.clock
, style
->clock
.color().pixel());
388 XSetWindowBackgroundPixmap(display
, frame
.clock
, frame
.clk
);
390 frame
.button
= style
->button
.render(frame
.button_w
, frame
.button_w
,
392 if (! frame
.button
) {
393 frame
.button_pixel
= style
->button
.color().pixel();
394 XSetWindowBackground(display
, frame
.psbutton
, frame
.button_pixel
);
395 XSetWindowBackground(display
, frame
.nsbutton
, frame
.button_pixel
);
396 XSetWindowBackground(display
, frame
.pwbutton
, frame
.button_pixel
);
397 XSetWindowBackground(display
, frame
.nwbutton
, frame
.button_pixel
);
399 XSetWindowBackgroundPixmap(display
, frame
.psbutton
, frame
.button
);
400 XSetWindowBackgroundPixmap(display
, frame
.nsbutton
, frame
.button
);
401 XSetWindowBackgroundPixmap(display
, frame
.pwbutton
, frame
.button
);
402 XSetWindowBackgroundPixmap(display
, frame
.nwbutton
, frame
.button
);
405 frame
.pbutton
= style
->pressed
.render(frame
.button_w
, frame
.button_w
,
408 frame
.pbutton_pixel
= style
->pressed
.color().pixel();
410 XSetWindowBorder(display
, frame
.window
,
411 screen
->getBorderColor()->pixel());
412 XSetWindowBorderWidth(display
, frame
.window
, screen
->getBorderWidth());
414 XClearWindow(display
, frame
.window
);
415 XClearWindow(display
, frame
.workspace_label
);
416 XClearWindow(display
, frame
.window_label
);
417 XClearWindow(display
, frame
.clock
);
418 XClearWindow(display
, frame
.psbutton
);
419 XClearWindow(display
, frame
.nsbutton
);
420 XClearWindow(display
, frame
.pwbutton
);
421 XClearWindow(display
, frame
.nwbutton
);
424 redrawWorkspaceLabel();
425 redrawPrevWorkspaceButton();
426 redrawNextWorkspaceButton();
427 redrawPrevWindowButton();
428 redrawNextWindowButton();
431 toolbarmenu
->reconfigure();
435 void Toolbar::updateStrut(void) {
436 // left and right are always 0
437 strut
.top
= strut
.bottom
= 0;
439 switch(screen
->getToolbarPlacement()) {
443 strut
.top
= getExposedHeight() + (screen
->getBorderWidth() * 2);
446 strut
.bottom
= getExposedHeight() + (screen
->getBorderWidth() * 2);
449 screen
->updateAvailableArea();
454 void Toolbar::checkClock(bool redraw
) {
455 #else // !HAVE_STRFTIME
456 void Toolbar::checkClock(bool redraw
, bool date
) {
457 #endif // HAVE_STRFTIME
461 if ((tmp
= time(NULL
)) != -1) {
462 if (! (tt
= localtime(&tmp
))) return;
463 if (tt
->tm_min
!= frame
.minute
|| tt
->tm_hour
!= frame
.hour
) {
464 frame
.hour
= tt
->tm_hour
;
465 frame
.minute
= tt
->tm_min
;
466 XClearWindow(display
, frame
.clock
);
474 if (! strftime(t
, 1024, screen
->getStrftimeFormat(), tt
))
476 #else // !HAVE_STRFTIME
479 // format the date... with special consideration for y2k ;)
480 if (screen
->getDateFormat() == Blackbox::B_EuropeanDate
)
481 sprintf(t
, 18n(ToolbarSet
, ToolbarNoStrftimeDateFormatEu
,
483 tt
->tm_mday
, tt
->tm_mon
+ 1,
484 (tt
->tm_year
>= 100) ? tt
->tm_year
- 100 : tt
->tm_year
);
486 sprintf(t
, i18n(ToolbarSet
, ToolbarNoStrftimeDateFormat
,
488 tt
->tm_mon
+ 1, tt
->tm_mday
,
489 (tt
->tm_year
>= 100) ? tt
->tm_year
- 100 : tt
->tm_year
);
491 if (screen
->isClock24Hour())
492 sprintf(t
, i18n(ToolbarSet
, ToolbarNoStrftimeTimeFormat24
,
494 frame
.hour
, frame
.minute
);
496 sprintf(t
, i18n(ToolbarSet
, ToolbarNoStrftimeTimeFormat12
,
498 ((frame
.hour
> 12) ? frame
.hour
- 12 :
499 ((frame
.hour
== 0) ? 12 : frame
.hour
)), frame
.minute
,
500 ((frame
.hour
>= 12) ?
501 i18n(ToolbarSet
, ToolbarNoStrftimeTimeFormatP
, "p") :
502 i18n(ToolbarSet
, ToolbarNoStrftimeTimeFormatA
, "a")));
504 #endif // HAVE_STRFTIME
506 ToolbarStyle
*style
= screen
->getToolbarStyle();
508 int pos
= frame
.bevel_w
* 2, // this is modified by doJustify()
509 dlen
= style
->doJustify(t
, pos
, frame
.clock_w
,
510 frame
.bevel_w
* 4, i18n
.multibyte());
511 BPen
pen(style
->c_text
, style
->font
);
512 if (i18n
.multibyte())
513 XmbDrawString(display
, frame
.clock
, style
->fontset
, pen
.gc(),
514 pos
, (1 - style
->fontset_extents
->max_ink_extent
.y
),
517 XDrawString(display
, frame
.clock
, pen
.gc(), pos
,
518 (style
->font
->ascent
+ 1), t
, dlen
);
523 void Toolbar::redrawWindowLabel(bool redraw
) {
524 BlackboxWindow
*foc
= screen
->getBlackbox()->getFocusedWindow();
526 XClearWindow(display
, frame
.window_label
);
531 XClearWindow(display
, frame
.window_label
);
533 if (foc
->getScreen() != screen
) return;
535 const char *title
= foc
->getTitle();
536 ToolbarStyle
*style
= screen
->getToolbarStyle();
538 int pos
= frame
.bevel_w
* 2, // modified by doJustify()
539 dlen
= style
->doJustify(title
, pos
, frame
.window_label_w
,
540 frame
.bevel_w
* 4, i18n
.multibyte());
541 BPen
pen(style
->w_text
, style
->font
);
542 if (i18n
.multibyte())
543 XmbDrawString(display
, frame
.window_label
, style
->fontset
, pen
.gc(), pos
,
544 (1 - style
->fontset_extents
->max_ink_extent
.y
),
547 XDrawString(display
, frame
.window_label
, pen
.gc(), pos
,
548 (style
->font
->ascent
+ 1), title
, dlen
);
552 void Toolbar::redrawWorkspaceLabel(bool redraw
) {
553 const string
& name
= screen
->getCurrentWorkspace()->getName();
556 XClearWindow(display
, frame
.workspace_label
);
558 ToolbarStyle
*style
= screen
->getToolbarStyle();
560 int pos
= frame
.bevel_w
* 2,
561 dlen
= style
->doJustify(name
.c_str(), pos
, frame
.workspace_label_w
,
562 frame
.bevel_w
* 4, i18n
.multibyte());
563 BPen
pen(style
->l_text
, style
->font
);
564 if (i18n
.multibyte())
565 XmbDrawString(display
, frame
.workspace_label
, style
->fontset
, pen
.gc(),
566 pos
, (1 - style
->fontset_extents
->max_ink_extent
.y
),
569 XDrawString(display
, frame
.workspace_label
, pen
.gc(), pos
,
570 (style
->font
->ascent
+ 1),
575 void Toolbar::redrawPrevWorkspaceButton(bool pressed
, bool redraw
) {
579 XSetWindowBackgroundPixmap(display
, frame
.psbutton
, frame
.pbutton
);
581 XSetWindowBackground(display
, frame
.psbutton
, frame
.pbutton_pixel
);
584 XSetWindowBackgroundPixmap(display
, frame
.psbutton
, frame
.button
);
586 XSetWindowBackground(display
, frame
.psbutton
, frame
.button_pixel
);
588 XClearWindow(display
, frame
.psbutton
);
591 int hh
= frame
.button_w
/ 2, hw
= frame
.button_w
/ 2;
594 pts
[0].x
= hw
- 2; pts
[0].y
= hh
;
595 pts
[1].x
= 4; pts
[1].y
= 2;
596 pts
[2].x
= 0; pts
[2].y
= -4;
598 ToolbarStyle
*style
= screen
->getToolbarStyle();
599 BPen
pen(style
->b_pic
, style
->font
);
600 XFillPolygon(display
, frame
.psbutton
, pen
.gc(),
601 pts
, 3, Convex
, CoordModePrevious
);
605 void Toolbar::redrawNextWorkspaceButton(bool pressed
, bool redraw
) {
609 XSetWindowBackgroundPixmap(display
, frame
.nsbutton
, frame
.pbutton
);
611 XSetWindowBackground(display
, frame
.nsbutton
, frame
.pbutton_pixel
);
614 XSetWindowBackgroundPixmap(display
, frame
.nsbutton
, frame
.button
);
616 XSetWindowBackground(display
, frame
.nsbutton
, frame
.button_pixel
);
618 XClearWindow(display
, frame
.nsbutton
);
621 int hh
= frame
.button_w
/ 2, hw
= frame
.button_w
/ 2;
624 pts
[0].x
= hw
- 2; pts
[0].y
= hh
- 2;
625 pts
[1].x
= 4; pts
[1].y
= 2;
626 pts
[2].x
= -4; pts
[2].y
= 2;
628 ToolbarStyle
*style
= screen
->getToolbarStyle();
629 BPen
pen(style
->b_pic
, style
->font
);
630 XFillPolygon(display
, frame
.nsbutton
, pen
.gc(),
631 pts
, 3, Convex
, CoordModePrevious
);
635 void Toolbar::redrawPrevWindowButton(bool pressed
, bool redraw
) {
639 XSetWindowBackgroundPixmap(display
, frame
.pwbutton
, frame
.pbutton
);
641 XSetWindowBackground(display
, frame
.pwbutton
, frame
.pbutton_pixel
);
644 XSetWindowBackgroundPixmap(display
, frame
.pwbutton
, frame
.button
);
646 XSetWindowBackground(display
, frame
.pwbutton
, frame
.button_pixel
);
648 XClearWindow(display
, frame
.pwbutton
);
651 int hh
= frame
.button_w
/ 2, hw
= frame
.button_w
/ 2;
654 pts
[0].x
= hw
- 2; pts
[0].y
= hh
;
655 pts
[1].x
= 4; pts
[1].y
= 2;
656 pts
[2].x
= 0; pts
[2].y
= -4;
658 ToolbarStyle
*style
= screen
->getToolbarStyle();
659 BPen
pen(style
->b_pic
, style
->font
);
660 XFillPolygon(display
, frame
.pwbutton
, pen
.gc(),
661 pts
, 3, Convex
, CoordModePrevious
);
665 void Toolbar::redrawNextWindowButton(bool pressed
, bool redraw
) {
669 XSetWindowBackgroundPixmap(display
, frame
.nwbutton
, frame
.pbutton
);
671 XSetWindowBackground(display
, frame
.nwbutton
, frame
.pbutton_pixel
);
674 XSetWindowBackgroundPixmap(display
, frame
.nwbutton
, frame
.button
);
676 XSetWindowBackground(display
, frame
.nwbutton
, frame
.button_pixel
);
678 XClearWindow(display
, frame
.nwbutton
);
681 int hh
= frame
.button_w
/ 2, hw
= frame
.button_w
/ 2;
684 pts
[0].x
= hw
- 2; pts
[0].y
= hh
- 2;
685 pts
[1].x
= 4; pts
[1].y
= 2;
686 pts
[2].x
= -4; pts
[2].y
= 2;
688 ToolbarStyle
*style
= screen
->getToolbarStyle();
689 BPen
pen(style
->b_pic
, style
->font
);
690 XFillPolygon(display
, frame
.nwbutton
, pen
.gc(), pts
, 3, Convex
,
695 void Toolbar::edit(void) {
700 XGetInputFocus(display
, &window
, &foo
);
701 if (window
== frame
.workspace_label
)
704 XSetInputFocus(display
, frame
.workspace_label
,
705 RevertToPointerRoot
, CurrentTime
);
706 XClearWindow(display
, frame
.workspace_label
);
708 blackbox
->setNoFocus(True
);
709 if (blackbox
->getFocusedWindow())
710 blackbox
->getFocusedWindow()->setFocusFlag(False
);
712 ToolbarStyle
*style
= screen
->getToolbarStyle();
713 BPen
pen(style
->l_text
, style
->font
);
714 XDrawRectangle(display
, frame
.workspace_label
, pen
.gc(),
715 frame
.workspace_label_w
/ 2, 0, 1,
717 // change the background of the window to that of an active window label
718 BTexture
*texture
= &(screen
->getWindowStyle()->l_focus
);
719 frame
.wlabel
= texture
->render(frame
.workspace_label_w
, frame
.label_h
,
722 XSetWindowBackground(display
, frame
.workspace_label
,
723 texture
->color().pixel());
725 XSetWindowBackgroundPixmap(display
, frame
.workspace_label
, frame
.wlabel
);
729 void Toolbar::buttonPressEvent(XButtonEvent
*be
) {
730 if (be
->button
== 1) {
731 if (be
->window
== frame
.psbutton
)
732 redrawPrevWorkspaceButton(True
, True
);
733 else if (be
->window
== frame
.nsbutton
)
734 redrawNextWorkspaceButton(True
, True
);
735 else if (be
->window
== frame
.pwbutton
)
736 redrawPrevWindowButton(True
, True
);
737 else if (be
->window
== frame
.nwbutton
)
738 redrawNextWindowButton(True
, True
);
739 #ifndef HAVE_STRFTIME
740 else if (be
->window
== frame
.clock
) {
741 XClearWindow(display
, frame
.clock
);
742 checkClock(True
, True
);
744 #endif // HAVE_STRFTIME
746 Window w
[1] = { frame
.window
};
747 screen
->raiseWindows(w
, 1);
749 } else if (be
->button
== 2 && (! on_top
)) {
750 XLowerWindow(display
, frame
.window
);
751 } else if (be
->button
== 3) {
752 if (toolbarmenu
->isVisible()) {
757 x
= be
->x_root
- (toolbarmenu
->getWidth() / 2);
758 y
= be
->y_root
- (toolbarmenu
->getHeight() / 2);
762 else if (x
+ toolbarmenu
->getWidth() > screen
->getWidth())
763 x
= screen
->getWidth() - toolbarmenu
->getWidth();
767 else if (y
+ toolbarmenu
->getHeight() > screen
->getHeight())
768 y
= screen
->getHeight() - toolbarmenu
->getHeight();
770 toolbarmenu
->move(x
, y
);
778 void Toolbar::buttonReleaseEvent(XButtonEvent
*re
) {
779 if (re
->button
== 1) {
780 if (re
->window
== frame
.psbutton
) {
781 redrawPrevWorkspaceButton(False
, True
);
783 if (re
->x
>= 0 && re
->x
< static_cast<signed>(frame
.button_w
) &&
784 re
->y
>= 0 && re
->y
< static_cast<signed>(frame
.button_w
))
785 if (screen
->getCurrentWorkspace()->getID() > 0)
786 screen
->changeWorkspaceID(screen
->getCurrentWorkspace()->
789 screen
->changeWorkspaceID(screen
->getWorkspaceCount() - 1);
790 } else if (re
->window
== frame
.nsbutton
) {
791 redrawNextWorkspaceButton(False
, True
);
793 if (re
->x
>= 0 && re
->x
< static_cast<signed>(frame
.button_w
) &&
794 re
->y
>= 0 && re
->y
< static_cast<signed>(frame
.button_w
))
795 if (screen
->getCurrentWorkspace()->getID() <
796 (screen
->getWorkspaceCount() - 1))
797 screen
->changeWorkspaceID(screen
->getCurrentWorkspace()->
800 screen
->changeWorkspaceID(0);
801 } else if (re
->window
== frame
.pwbutton
) {
802 redrawPrevWindowButton(False
, True
);
804 if (re
->x
>= 0 && re
->x
< static_cast<signed>(frame
.button_w
) &&
805 re
->y
>= 0 && re
->y
< static_cast<signed>(frame
.button_w
))
807 } else if (re
->window
== frame
.nwbutton
) {
808 redrawNextWindowButton(False
, True
);
810 if (re
->x
>= 0 && re
->x
< static_cast<signed>(frame
.button_w
) &&
811 re
->y
>= 0 && re
->y
< static_cast<signed>(frame
.button_w
))
813 } else if (re
->window
== frame
.window_label
)
814 screen
->raiseFocus();
815 #ifndef HAVE_STRFTIME
816 else if (re
->window
== frame
.clock
) {
817 XClearWindow(display
, frame
.clock
);
820 #endif // HAVE_STRFTIME
825 void Toolbar::enterNotifyEvent(XCrossingEvent
*) {
830 if (! hide_timer
->isTiming()) hide_timer
->start();
832 if (hide_timer
->isTiming()) hide_timer
->stop();
836 void Toolbar::leaveNotifyEvent(XCrossingEvent
*) {
841 if (hide_timer
->isTiming()) hide_timer
->stop();
842 } else if (! toolbarmenu
->isVisible()) {
843 if (! hide_timer
->isTiming()) hide_timer
->start();
848 void Toolbar::exposeEvent(XExposeEvent
*ee
) {
849 if (ee
->window
== frame
.clock
) checkClock(True
);
850 else if (ee
->window
== frame
.workspace_label
&& (! editing
))
851 redrawWorkspaceLabel();
852 else if (ee
->window
== frame
.window_label
) redrawWindowLabel();
853 else if (ee
->window
== frame
.psbutton
) redrawPrevWorkspaceButton();
854 else if (ee
->window
== frame
.nsbutton
) redrawNextWorkspaceButton();
855 else if (ee
->window
== frame
.pwbutton
) redrawPrevWindowButton();
856 else if (ee
->window
== frame
.nwbutton
) redrawNextWindowButton();
860 void Toolbar::keyPressEvent(XKeyEvent
*ke
) {
861 if (ke
->window
== frame
.workspace_label
&& editing
) {
862 if (new_workspace_name
.empty()) {
868 XLookupString(ke
, keychar
, 1, &ks
, 0);
870 // either we are told to end with a return or we hit 127 chars
871 if (ks
== XK_Return
|| new_name_pos
== 127) {
874 blackbox
->setNoFocus(False
);
875 if (blackbox
->getFocusedWindow()) {
876 blackbox
->getFocusedWindow()->setInputFocus();
878 blackbox
->setFocusedWindow(0);
881 Workspace
*wkspc
= screen
->getCurrentWorkspace();
882 wkspc
->setName(new_workspace_name
);
883 wkspc
->getMenu()->hide();
885 screen
->getWorkspacemenu()->changeItemLabel(wkspc
->getID() + 2,
887 screen
->getWorkspacemenu()->update();
889 new_workspace_name
.erase();
892 // reset the background to that of the workspace label (its normal
894 BTexture
*texture
= &(screen
->getToolbarStyle()->label
);
895 frame
.wlabel
= texture
->render(frame
.workspace_label_w
, frame
.label_h
,
898 XSetWindowBackground(display
, frame
.workspace_label
,
899 texture
->color().pixel());
901 XSetWindowBackgroundPixmap(display
, frame
.workspace_label
,
904 } else if (! (ks
== XK_Shift_L
|| ks
== XK_Shift_R
||
905 ks
== XK_Control_L
|| ks
== XK_Control_R
||
906 ks
== XK_Caps_Lock
|| ks
== XK_Shift_Lock
||
907 ks
== XK_Meta_L
|| ks
== XK_Meta_R
||
908 ks
== XK_Alt_L
|| ks
== XK_Alt_R
||
909 ks
== XK_Super_L
|| ks
== XK_Super_R
||
910 ks
== XK_Hyper_L
|| ks
== XK_Hyper_R
)) {
911 if (ks
== XK_BackSpace
) {
912 if (new_name_pos
> 0) {
914 new_workspace_name
.erase(new_name_pos
);
916 new_workspace_name
.resize(0);
919 new_workspace_name
+= (*keychar
);
923 XClearWindow(display
, frame
.workspace_label
);
924 unsigned int l
= new_workspace_name
.length(), tw
, x
;
926 if (i18n
.multibyte()) {
927 XRectangle ink
, logical
;
928 XmbTextExtents(screen
->getToolbarStyle()->fontset
,
929 new_workspace_name
.c_str(), l
, &ink
, &logical
);
932 tw
= XTextWidth(screen
->getToolbarStyle()->font
,
933 new_workspace_name
.c_str(), l
);
935 x
= (frame
.workspace_label_w
- tw
) / 2;
937 if (x
< frame
.bevel_w
) x
= frame
.bevel_w
;
939 ToolbarStyle
*style
= screen
->getToolbarStyle();
940 BPen
pen(style
->l_text
, style
->font
);
941 if (i18n
.multibyte())
942 XmbDrawString(display
, frame
.workspace_label
, style
->fontset
,
944 (1 - style
->fontset_extents
->max_ink_extent
.y
),
945 new_workspace_name
.c_str(), l
);
947 XDrawString(display
, frame
.workspace_label
, pen
.gc(), x
,
948 (style
->font
->ascent
+ 1),
949 new_workspace_name
.c_str(), l
);
950 XDrawRectangle(display
, frame
.workspace_label
, pen
.gc(), x
+ tw
, 0, 1,
957 void Toolbar::timeout(void) {
960 clock_timer
->setTimeout(aMinuteFromNow());
964 void Toolbar::HideHandler::timeout(void) {
965 toolbar
->hidden
= ! toolbar
->hidden
;
967 XMoveWindow(toolbar
->display
, toolbar
->frame
.window
,
968 toolbar
->frame
.x_hidden
, toolbar
->frame
.y_hidden
);
970 XMoveWindow(toolbar
->display
, toolbar
->frame
.window
,
971 toolbar
->frame
.rect
.x(), toolbar
->frame
.rect
.y());
975 void Toolbar::toggleAutoHide(void) {
976 do_auto_hide
= (do_auto_hide
) ? False
: True
;
979 screen
->getSlit()->reposition();
981 if (do_auto_hide
== False
&& hidden
) {
982 // force the slit to be visible
983 if (hide_timer
->isTiming()) hide_timer
->stop();
984 hide_handler
.timeout();
989 Toolbarmenu::Toolbarmenu(Toolbar
*tb
) : Basemenu(tb
->screen
) {
992 setLabel(i18n(ToolbarSet
, ToolbarToolbarTitle
, "Toolbar"));
995 placementmenu
= new Placementmenu(this);
997 insert(i18n(CommonSet
, CommonPlacementTitle
, "Placement"),
999 insert(i18n(CommonSet
, CommonAlwaysOnTop
, "Always on top"), 1);
1000 insert(i18n(CommonSet
, CommonAutoHide
, "Auto hide"), 2);
1001 insert(i18n(ToolbarSet
, ToolbarEditWkspcName
,
1002 "Edit current workspace name"), 3);
1006 if (toolbar
->isOnTop()) setItemSelected(1, True
);
1007 if (toolbar
->doAutoHide()) setItemSelected(2, True
);
1011 Toolbarmenu::~Toolbarmenu(void) {
1012 delete placementmenu
;
1016 void Toolbarmenu::itemSelected(int button
, unsigned int index
) {
1020 BasemenuItem
*item
= find(index
);
1023 switch (item
->function()) {
1024 case 1: { // always on top
1025 toolbar
->on_top
= ((toolbar
->isOnTop()) ? False
: True
);;
1026 setItemSelected(1, toolbar
->on_top
);
1028 if (toolbar
->isOnTop()) getScreen()->raiseWindows((Window
*) 0, 0);
1032 case 2: { // auto hide
1033 toolbar
->toggleAutoHide();
1034 setItemSelected(2, toolbar
->do_auto_hide
);
1039 case 3: { // edit current workspace name
1049 void Toolbarmenu::internal_hide(void) {
1050 Basemenu::internal_hide();
1051 if (toolbar
->doAutoHide() && ! toolbar
->isEditing())
1052 toolbar
->hide_handler
.timeout();
1056 void Toolbarmenu::reconfigure(void) {
1057 placementmenu
->reconfigure();
1059 Basemenu::reconfigure();
1063 Toolbarmenu::Placementmenu::Placementmenu(Toolbarmenu
*tm
)
1064 : Basemenu(tm
->toolbar
->screen
) {
1065 setLabel(i18n(ToolbarSet
, ToolbarToolbarPlacement
, "Toolbar Placement"));
1067 setMinimumSublevels(3);
1069 insert(i18n(CommonSet
, CommonPlacementTopLeft
, "Top Left"),
1071 insert(i18n(CommonSet
, CommonPlacementBottomLeft
, "Bottom Left"),
1072 Toolbar::BottomLeft
);
1073 insert(i18n(CommonSet
, CommonPlacementTopCenter
, "Top Center"),
1074 Toolbar::TopCenter
);
1075 insert(i18n(CommonSet
, CommonPlacementBottomCenter
, "Bottom Center"),
1076 Toolbar::BottomCenter
);
1077 insert(i18n(CommonSet
, CommonPlacementTopRight
, "Top Right"),
1079 insert(i18n(CommonSet
, CommonPlacementBottomRight
, "Bottom Right"),
1080 Toolbar::BottomRight
);
1085 void Toolbarmenu::Placementmenu::itemSelected(int button
, unsigned int index
) {
1089 BasemenuItem
*item
= find(index
);
1092 getScreen()->saveToolbarPlacement(item
->function());
1094 getScreen()->getToolbar()->reconfigure();
1096 // reposition the slit as well to make sure it doesn't intersect the
1098 getScreen()->getSlit()->reposition();
1102 int ToolbarStyle::doJustify(const char *text
, int &start_pos
,
1103 unsigned int max_length
, unsigned int modifier
,
1104 bool multibyte
) const {
1105 size_t text_len
= strlen(text
);
1106 unsigned int length
;
1110 XRectangle ink
, logical
;
1111 XmbTextExtents(fontset
, text
, text_len
, &ink
, &logical
);
1112 length
= logical
.width
;
1114 length
= XTextWidth(font
, text
, text_len
);
1117 } while (length
> max_length
&& text_len
-- > 0);
1121 start_pos
+= max_length
- length
;
1125 start_pos
+= (max_length
- length
) / 2;