correctly set size/state on construction... this fixes bug 1108138
[blackbox.git] / src / Toolbar.cc
blob2847bb780f868e64095f3a2338e5c7518e9ea5b0
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // Toolbar.cc for Blackbox - an X11 Window manager
3 // Copyright (c) 2001 - 2005 Sean 'Shaleh' Perry <shaleh@debian.org>
4 // Copyright (c) 1997 - 2000, 2002 - 2005
5 // Bradley T Hughes <bhughes at trolltech.com>
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a
8 // copy of this software and associated documentation files (the "Software"),
9 // to deal in the Software without restriction, including without limitation
10 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 // and/or sell copies of the Software, and to permit persons to whom the
12 // Software is furnished to do so, subject to the following conditions:
14 // The above copyright notice and this permission notice shall be included in
15 // all copies or substantial portions of the Software.
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 // DEALINGS IN THE SOFTWARE.
25 #include "Toolbar.hh"
26 #include "Iconmenu.hh"
27 #include "Screen.hh"
28 #include "Slit.hh"
29 #include "Toolbarmenu.hh"
30 #include "Window.hh"
31 #include "Windowmenu.hh"
32 #include "Workspacemenu.hh"
34 #include <Pen.hh>
35 #include <PixmapCache.hh>
36 #include <Unicode.hh>
38 #include <X11/Xutil.h>
39 #include <sys/time.h>
40 #include <assert.h>
43 long nextTimeout(int resolution) {
44 timeval now;
45 gettimeofday(&now, 0);
46 return (std::max(1000l, ((resolution - (now.tv_sec % resolution)) * 1000))
47 - (now.tv_usec / 1000));
51 Toolbar::Toolbar(BScreen *scrn) {
52 _screen = scrn;
53 blackbox = _screen->blackbox();
55 // get the clock updating every minute
56 clock_timer = new bt::Timer(blackbox, this);
57 clock_timer->recurring(True);
59 const ToolbarOptions &options = _screen->resource().toolbarOptions();
61 const std::string &time_format = options.strftime_format;
62 if (time_format.find("%S") != std::string::npos
63 || time_format.find("%s") != std::string::npos
64 || time_format.find("%r") != std::string::npos
65 || time_format.find("%T") != std::string::npos) {
66 clock_timer_resolution = 1;
67 } else if (time_format.find("%M") != std::string::npos
68 || time_format.find("%R") != std::string::npos) {
69 clock_timer_resolution = 60;
70 } else {
71 clock_timer_resolution = 3600;
74 hide_timer = new bt::Timer(blackbox, this);
75 hide_timer->setTimeout(blackbox->resource().autoRaiseDelay());
77 setLayer(options.always_on_top
78 ? StackingList::LayerAbove
79 : StackingList::LayerNormal);
80 hidden = options.auto_hide;
82 new_name_pos = 0;
84 display = blackbox->XDisplay();
85 XSetWindowAttributes attrib;
86 unsigned long create_mask = CWColormap | CWOverrideRedirect | CWEventMask;
87 attrib.colormap = _screen->screenInfo().colormap();
88 attrib.override_redirect = True;
89 attrib.event_mask = ButtonPressMask | ButtonReleaseMask |
90 EnterWindowMask | LeaveWindowMask | ExposureMask;
92 frame.window =
93 XCreateWindow(display, _screen->screenInfo().rootWindow(), 0, 0, 1, 1, 0,
94 _screen->screenInfo().depth(), InputOutput,
95 _screen->screenInfo().visual(),
96 create_mask, &attrib);
97 blackbox->insertEventHandler(frame.window, this);
99 attrib.event_mask =
100 ButtonPressMask | ButtonReleaseMask | ExposureMask | EnterWindowMask;
102 frame.workspace_label =
103 XCreateWindow(display, frame.window, 0, 0, 1, 1, 0,
104 _screen->screenInfo().depth(), InputOutput,
105 _screen->screenInfo().visual(),
106 create_mask, &attrib);
107 blackbox->insertEventHandler(frame.workspace_label, this);
109 frame.window_label =
110 XCreateWindow(display, frame.window, 0, 0, 1, 1, 0,
111 _screen->screenInfo().depth(), InputOutput,
112 _screen->screenInfo().visual(),
113 create_mask, &attrib);
114 blackbox->insertEventHandler(frame.window_label, this);
116 frame.clock =
117 XCreateWindow(display, frame.window, 0, 0, 1, 1, 0,
118 _screen->screenInfo().depth(), InputOutput,
119 _screen->screenInfo().visual(),
120 create_mask, &attrib);
121 blackbox->insertEventHandler(frame.clock, this);
123 frame.psbutton =
124 XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0,
125 _screen->screenInfo().depth(), InputOutput,
126 _screen->screenInfo().visual(),
127 create_mask, &attrib);
128 blackbox->insertEventHandler(frame.psbutton, this);
130 frame.nsbutton =
131 XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0,
132 _screen->screenInfo().depth(), InputOutput,
133 _screen->screenInfo().visual(),
134 create_mask, &attrib);
135 blackbox->insertEventHandler(frame.nsbutton, this);
137 frame.pwbutton =
138 XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0,
139 _screen->screenInfo().depth(), InputOutput,
140 _screen->screenInfo().visual(),
141 create_mask, &attrib);
142 blackbox->insertEventHandler(frame.pwbutton, this);
144 frame.nwbutton =
145 XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0,
146 _screen->screenInfo().depth(), InputOutput,
147 _screen->screenInfo().visual(),
148 create_mask, &attrib);
149 blackbox->insertEventHandler(frame.nwbutton, this);
151 frame.base = frame.slabel = frame.wlabel = frame.clk = frame.button =
152 frame.pbutton = None;
154 _screen->addStrut(&strut);
156 reconfigure();
158 clock_timer->setTimeout(nextTimeout(clock_timer_resolution));
159 clock_timer->start();
161 XMapSubwindows(display, frame.window);
162 XMapWindow(display, frame.window);
166 Toolbar::~Toolbar(void) {
167 _screen->removeStrut(&strut);
169 XUnmapWindow(display, frame.window);
171 bt::PixmapCache::release(frame.base);
172 bt::PixmapCache::release(frame.slabel);
173 bt::PixmapCache::release(frame.wlabel);
174 bt::PixmapCache::release(frame.clk);
175 bt::PixmapCache::release(frame.button);
176 bt::PixmapCache::release(frame.pbutton);
178 blackbox->removeEventHandler(frame.window);
179 blackbox->removeEventHandler(frame.workspace_label);
180 blackbox->removeEventHandler(frame.window_label);
181 blackbox->removeEventHandler(frame.clock);
182 blackbox->removeEventHandler(frame.psbutton);
183 blackbox->removeEventHandler(frame.nsbutton);
184 blackbox->removeEventHandler(frame.pwbutton);
185 blackbox->removeEventHandler(frame.nwbutton);
187 // all children windows are destroyed by this call as well
188 XDestroyWindow(display, frame.window);
190 delete hide_timer;
191 delete clock_timer;
195 unsigned int Toolbar::exposedHeight(void) const {
196 const ToolbarOptions &options = _screen->resource().toolbarOptions();
197 const ToolbarStyle &style = _screen->resource().toolbarStyle();
198 return (options.auto_hide ? style.hidden_height : style.toolbar_height);
202 void Toolbar::reconfigure(void) {
203 ScreenResource &resource = _screen->resource();
204 const ToolbarOptions &options = resource.toolbarOptions();
205 const ToolbarStyle &style = resource.toolbarStyle();
207 unsigned int width = (_screen->screenInfo().width() *
208 options.width_percent) / 100;
210 const unsigned int border_width = style.toolbar.borderWidth();
211 const unsigned int extra =
212 style.frame_margin == 0 ? style.button.borderWidth() : 0;
213 frame.rect.setSize(width, style.toolbar_height);
215 int x, y;
216 switch (options.placement) {
217 case TopLeft:
218 case TopRight:
219 case TopCenter:
220 switch (options.placement) {
221 case TopLeft:
222 x = 0;
223 break;
224 case TopRight:
225 x = _screen->screenInfo().width() - frame.rect.width();
226 break;
227 default:
228 x = (_screen->screenInfo().width() - frame.rect.width()) / 2;
229 break;
231 y = 0;
232 frame.y_hidden = style.hidden_height - frame.rect.height();
233 break;
235 case BottomLeft:
236 case BottomRight:
237 case BottomCenter:
238 default:
239 switch (options.placement) {
240 case BottomLeft:
241 x = 0;
242 break;
243 case BottomRight:
244 x = _screen->screenInfo().width() - frame.rect.width();
245 break;
246 default:
247 x = (_screen->screenInfo().width() - frame.rect.width()) / 2;
248 break;
250 y = _screen->screenInfo().height() - frame.rect.height();
251 frame.y_hidden = _screen->screenInfo().height() - style.hidden_height;
252 break;
255 frame.rect.setPos(x, y);
257 updateStrut();
259 time_t ttmp = time(NULL);
261 unsigned int clock_w = 0u, label_w = 0u;
263 if (ttmp != -1) {
264 struct tm *tt = localtime(&ttmp);
265 if (tt) {
266 char t[1024];
267 int len = strftime(t, 1024, options.strftime_format.c_str(), tt);
268 if (len == 0) { // invalid time format found
269 // so use the default
270 const_cast<std::string &>(options.strftime_format) = "%I:%M %p";
271 len = strftime(t, 1024, options.strftime_format.c_str(), tt);
274 * find the length of the rendered string and add room for two extra
275 * characters to it. This allows for variable width output of the fonts.
276 * two 'w' are used to get the widest possible width
278 clock_w =
279 bt::textRect(_screen->screenNumber(), style.font,
280 bt::toUnicode(t)).width() +
281 bt::textRect(_screen->screenNumber(), style.font,
282 bt::toUnicode("ww")).width();
286 for (unsigned int i = 0; i < _screen->workspaceCount(); i++) {
287 width =
288 bt::textRect(_screen->screenNumber(), style.font,
289 _screen->resource().workspaceName(i)).width();
290 label_w = std::max(label_w, width);
293 label_w = clock_w = std::max(label_w, clock_w) + (style.label_margin * 2);
295 unsigned int window_label_w =
296 (frame.rect.width() - (border_width * 2)
297 - (clock_w + (style.button_width * 4) + label_w
298 + (style.frame_margin * 8))
299 + extra*6);
301 XMoveResizeWindow(display, frame.window, frame.rect.x(),
302 hidden ? frame.y_hidden : frame.rect.y(),
303 frame.rect.width(), frame.rect.height());
305 // workspace label
306 frame.slabel_rect.setRect(border_width + style.frame_margin,
307 border_width + style.frame_margin,
308 label_w,
309 style.label_height);
310 // previous workspace button
311 frame.ps_rect.setRect(border_width + (style.frame_margin * 2) + label_w
312 - extra,
313 border_width + style.frame_margin,
314 style.button_width,
315 style.button_width);
316 // next workspace button
317 frame.ns_rect.setRect(border_width + (style.frame_margin * 3)
318 + label_w + style.button_width - (extra * 2),
319 border_width + style.frame_margin,
320 style.button_width,
321 style.button_width);
322 // window label
323 frame.wlabel_rect.setRect(border_width + (style.frame_margin * 4)
324 + (style.button_width * 2) + label_w - (extra * 3),
325 border_width + style.frame_margin,
326 window_label_w,
327 style.label_height);
328 // previous window button
329 frame.pw_rect.setRect(border_width + (style.frame_margin * 5)
330 + (style.button_width * 2) + label_w
331 + window_label_w - (extra * 4),
332 border_width + style.frame_margin,
333 style.button_width,
334 style.button_width);
335 // next window button
336 frame.nw_rect.setRect(border_width + (style.frame_margin * 6)
337 + (style.button_width * 3) + label_w
338 + window_label_w - (extra * 5),
339 border_width + style.frame_margin,
340 style.button_width,
341 style.button_width);
342 // clock
343 frame.clock_rect.setRect(frame.rect.width() - clock_w - style.frame_margin
344 - border_width,
345 border_width + style.frame_margin,
346 clock_w,
347 style.label_height);
349 XMoveResizeWindow(display, frame.workspace_label,
350 frame.slabel_rect.x(), frame.slabel_rect.y(),
351 frame.slabel_rect.width(), frame.slabel_rect.height());
352 XMoveResizeWindow(display, frame.psbutton,
353 frame.ps_rect.x(), frame.ps_rect.y(),
354 frame.ps_rect.width(), frame.ps_rect.height());
355 XMoveResizeWindow(display, frame.nsbutton,
356 frame.ns_rect.x(), frame.ns_rect.y(),
357 frame.ns_rect.width(), frame.ns_rect.height());
358 XMoveResizeWindow(display, frame.window_label,
359 frame.wlabel_rect.x(), frame.wlabel_rect.y(),
360 frame.wlabel_rect.width(), frame.wlabel_rect.height());
361 XMoveResizeWindow(display, frame.pwbutton,
362 frame.pw_rect.x(), frame.pw_rect.y(),
363 frame.pw_rect.width(), frame.pw_rect.height());
364 XMoveResizeWindow(display, frame.nwbutton,
365 frame.nw_rect.x(), frame.nw_rect.y(),
366 frame.nw_rect.width(), frame.nw_rect.height());
367 XMoveResizeWindow(display, frame.clock,
368 frame.clock_rect.x(), frame.clock_rect.y(),
369 frame.clock_rect.width(), frame.clock_rect.height());
371 frame.base =
372 bt::PixmapCache::find(_screen->screenNumber(), style.toolbar,
373 frame.rect.width(), frame.rect.height(),
374 frame.base);
375 frame.slabel =
376 bt::PixmapCache::find(_screen->screenNumber(), style.slabel,
377 frame.slabel_rect.width(),
378 frame.slabel_rect.height(),
379 frame.slabel);
380 frame.wlabel =
381 bt::PixmapCache::find(_screen->screenNumber(), style.wlabel,
382 frame.wlabel_rect.width(),
383 frame.wlabel_rect.height(),
384 frame.wlabel);
385 frame.clk =
386 bt::PixmapCache::find(_screen->screenNumber(), style.clock,
387 frame.clock_rect.width(),
388 frame.clock_rect.height(),
389 frame.clk);
390 frame.button =
391 bt::PixmapCache::find(_screen->screenNumber(), style.button,
392 style.button_width, style.button_width,
393 frame.button);
394 frame.pbutton =
395 bt::PixmapCache::find(_screen->screenNumber(),
396 style.pressed,
397 style.button_width, style.button_width,
398 frame.pbutton);
400 XClearArea(display, frame.window, 0, 0,
401 frame.rect.width(), frame.rect.height(), True);
403 XClearArea(display, frame.workspace_label, 0, 0,
404 label_w, style.label_height, True);
405 XClearArea(display, frame.window_label, 0, 0,
406 window_label_w, style.label_height, True);
407 XClearArea(display, frame.clock, 0, 0,
408 clock_w, style.label_height, True);
410 XClearArea(display, frame.psbutton, 0, 0,
411 style.button_width, style.button_width, True);
412 XClearArea(display, frame.nsbutton, 0, 0,
413 style.button_width, style.button_width, True);
414 XClearArea(display, frame.pwbutton, 0, 0,
415 style.button_width, style.button_width, True);
416 XClearArea(display, frame.nwbutton, 0, 0,
417 style.button_width, style.button_width, True);
421 void Toolbar::updateStrut(void) {
422 // left and right are always 0
423 strut.top = strut.bottom = 0;
425 switch(_screen->resource().toolbarOptions().placement) {
426 case TopLeft:
427 case TopCenter:
428 case TopRight:
429 strut.top = exposedHeight();
430 break;
431 default:
432 strut.bottom = exposedHeight();
435 _screen->updateStrut();
439 void Toolbar::redrawClockLabel(void) {
440 const ToolbarOptions &options = _screen->resource().toolbarOptions();
441 const ToolbarStyle &style = _screen->resource().toolbarStyle();
443 bt::Rect u(0, 0, frame.clock_rect.width(), frame.clock_rect.height());
444 if (frame.clk == ParentRelative) {
445 bt::Rect t(-frame.clock_rect.x(), -frame.clock_rect.y(),
446 frame.rect.width(), frame.rect.height());
447 bt::drawTexture(_screen->screenNumber(), style.toolbar,
448 frame.clock, t, u, frame.base);
449 } else {
450 bt::drawTexture(_screen->screenNumber(), style.clock,
451 frame.clock, u, u, frame.clk);
454 time_t tmp = 0;
455 struct tm *tt = 0;
456 char str[1024];
457 if ((tmp = time(NULL)) == -1)
458 return; // should not happen
459 tt = localtime(&tmp);
460 if (! tt)
461 return; // ditto
462 if (! strftime(str, 1024, options.strftime_format.c_str(), tt))
463 return; // ditto
465 bt::Pen pen(_screen->screenNumber(), style.clock_text);
466 bt::drawText(style.font, pen, frame.clock, u, style.alignment,
467 bt::toUnicode(str));
471 void Toolbar::redrawWindowLabel(void) {
472 const ToolbarStyle &style = _screen->resource().toolbarStyle();
474 bt::Rect u(0, 0, frame.wlabel_rect.width(), frame.wlabel_rect.height());
475 if (frame.wlabel == ParentRelative) {
476 bt::Rect t(-frame.wlabel_rect.x(), -frame.wlabel_rect.y(),
477 frame.rect.width(), frame.rect.height());
478 bt::drawTexture(_screen->screenNumber(), style.toolbar,
479 frame.window_label, t, u, frame.base);
480 } else {
481 bt::drawTexture(_screen->screenNumber(), style.wlabel,
482 frame.window_label, u, u, frame.wlabel);
485 BlackboxWindow *foc = _screen->blackbox()->focusedWindow();
486 if (! foc || foc->screen() != _screen)
487 return;
489 bt::Pen pen(_screen->screenNumber(), style.wlabel_text);
490 bt::drawText(style.font, pen, frame.window_label, u,
491 style.alignment,
492 bt::ellideText(foc->title(), u.width(), bt::toUnicode("..."),
493 _screen->screenNumber(), style.font));
497 void Toolbar::redrawWorkspaceLabel(void) {
498 const bt::ustring &name =
499 _screen->resource().workspaceName(_screen->currentWorkspace());
500 const ToolbarStyle &style = _screen->resource().toolbarStyle();
502 bt::Rect u(0, 0, frame.slabel_rect.width(), frame.slabel_rect.height());
503 if (frame.slabel == ParentRelative) {
504 bt::Rect t(-frame.slabel_rect.x(), -frame.slabel_rect.y(),
505 frame.rect.width(), frame.rect.height());
506 bt::drawTexture(_screen->screenNumber(), style.toolbar,
507 frame.workspace_label, t, u, frame.base);
508 } else {
509 bt::drawTexture(_screen->screenNumber(), style.slabel,
510 frame.workspace_label, u, u, frame.slabel);
513 bt::Pen pen(_screen->screenNumber(), style.slabel_text);
514 bt::drawText(style.font, pen, frame.workspace_label, u,
515 style.alignment, name);
519 void Toolbar::redrawPrevWorkspaceButton(bool pressed) {
520 const ToolbarStyle &style =
521 _screen->resource().toolbarStyle();
523 Pixmap p = pressed ? frame.pbutton : frame.button;
524 bt::Rect u(0, 0, style.button_width, style.button_width);
525 if (p == ParentRelative) {
526 bt::Rect t(-frame.ps_rect.x(), -frame.ps_rect.y(),
527 frame.rect.width(), frame.rect.height());
528 bt::drawTexture(_screen->screenNumber(), style.toolbar,
529 frame.psbutton, t, u, frame.base);
530 } else {
531 bt::drawTexture(_screen->screenNumber(),
532 pressed ? style.pressed : style.button,
533 frame.psbutton, u, u, p);
536 const bt::Pen pen(_screen->screenNumber(), style.foreground);
537 bt::drawBitmap(bt::Bitmap::leftArrow(_screen->screenNumber()),
538 pen, frame.psbutton, u);
542 void Toolbar::redrawNextWorkspaceButton(bool pressed) {
543 const ToolbarStyle &style =
544 _screen->resource().toolbarStyle();
546 Pixmap p = pressed ? frame.pbutton : frame.button;
547 bt::Rect u(0, 0, style.button_width, style.button_width);
548 if (p == ParentRelative) {
549 bt::Rect t(-frame.ns_rect.x(), -frame.ns_rect.y(),
550 frame.rect.width(), frame.rect.height());
551 bt::drawTexture(_screen->screenNumber(), style.toolbar,
552 frame.nsbutton, t, u, frame.base);
553 } else {
554 bt::drawTexture(_screen->screenNumber(),
555 pressed ? style.pressed : style.button,
556 frame.nsbutton, u, u, p);
559 const bt::Pen pen(_screen->screenNumber(), style.foreground);
560 bt::drawBitmap(bt::Bitmap::rightArrow(_screen->screenNumber()),
561 pen, frame.nsbutton, u);
565 void Toolbar::redrawPrevWindowButton(bool pressed) {
566 const ToolbarStyle &style =
567 _screen->resource().toolbarStyle();
569 Pixmap p = pressed ? frame.pbutton : frame.button;
570 bt::Rect u(0, 0, style.button_width, style.button_width);
571 if (p == ParentRelative) {
572 bt::Rect t(-frame.pw_rect.x(), -frame.pw_rect.y(),
573 frame.rect.width(), frame.rect.height());
574 bt::drawTexture(_screen->screenNumber(), style.toolbar,
575 frame.pwbutton, t, u, frame.base);
576 } else {
577 bt::drawTexture(_screen->screenNumber(),
578 pressed ? style.pressed : style.button,
579 frame.pwbutton, u, u, p);
582 const bt::Pen pen(_screen->screenNumber(), style.foreground);
583 bt::drawBitmap(bt::Bitmap::leftArrow(_screen->screenNumber()),
584 pen, frame.pwbutton, u);
588 void Toolbar::redrawNextWindowButton(bool pressed) {
589 const ToolbarStyle &style =
590 _screen->resource().toolbarStyle();
592 Pixmap p = pressed ? frame.pbutton : frame.button;
593 bt::Rect u(0, 0, style.button_width, style.button_width);
594 if (p == ParentRelative) {
595 bt::Rect t(-frame.nw_rect.x(), -frame.nw_rect.y(),
596 frame.rect.width(), frame.rect.height());
597 bt::drawTexture(_screen->screenNumber(), style.toolbar,
598 frame.nwbutton, t, u, frame.base);
599 } else {
600 bt::drawTexture(_screen->screenNumber(),
601 pressed ? style.pressed : style.button,
602 frame.nwbutton, u, u, p);
605 const bt::Pen pen(_screen->screenNumber(), style.foreground);
606 bt::drawBitmap(bt::Bitmap::rightArrow(_screen->screenNumber()),
607 pen, frame.nwbutton, u);
611 void Toolbar::buttonPressEvent(const XButtonEvent * const event) {
612 if (event->button == 1) {
613 _screen->raiseWindow(this);
614 if (event->window == frame.psbutton)
615 redrawPrevWorkspaceButton(True);
616 else if (event->window == frame.nsbutton)
617 redrawNextWorkspaceButton(True);
618 else if (event->window == frame.pwbutton)
619 redrawPrevWindowButton(True);
620 else if (event->window == frame.nwbutton)
621 redrawNextWindowButton(True);
622 } else if (event->button == 2) {
623 _screen->lowerWindow(this);
624 } else if (event->button == 3) {
625 BlackboxWindow *focus = blackbox->focusedWindow();
626 if (event->window == frame.window_label &&
627 focus && focus->screen() == _screen) {
628 Windowmenu *windowmenu = _screen->windowmenu(focus);
629 windowmenu->popup(event->x_root, event->y_root,
630 _screen->availableArea());
631 } else {
632 _screen->toolbarmenu()->popup(event->x_root, event->y_root,
633 _screen->availableArea());
639 void Toolbar::buttonReleaseEvent(const XButtonEvent * const event) {
640 if (event->button == 1) {
641 const ToolbarStyle &style =
642 _screen->resource().toolbarStyle();
644 if (event->window == frame.psbutton) {
645 redrawPrevWorkspaceButton(False);
647 if (bt::within(event->x, event->y,
648 style.button_width, style.button_width)) {
649 int new_workspace;
650 if (_screen->currentWorkspace() > 0)
651 new_workspace = _screen->currentWorkspace() - 1;
652 else
653 new_workspace = _screen->workspaceCount() - 1;
654 _screen->setCurrentWorkspace(new_workspace);
656 } else if (event->window == frame.nsbutton) {
657 redrawNextWorkspaceButton(False);
659 if (bt::within(event->x, event->y,
660 style.button_width, style.button_width))
661 if (_screen->currentWorkspace() < _screen->workspaceCount() - 1)
662 _screen->setCurrentWorkspace(_screen->currentWorkspace() + 1);
663 else
664 _screen->setCurrentWorkspace(0);
665 } else if (event->window == frame.pwbutton) {
666 redrawPrevWindowButton(False);
668 if (bt::within(event->x, event->y,
669 style.button_width, style.button_width))
670 _screen->prevFocus();
671 } else if (event->window == frame.nwbutton) {
672 redrawNextWindowButton(False);
674 if (bt::within(event->x, event->y,
675 style.button_width, style.button_width))
676 _screen->nextFocus();
677 } else if (event->window == frame.window_label)
678 _screen->raiseFocus();
683 void Toolbar::enterNotifyEvent(const XCrossingEvent * const /*unused*/) {
684 if (!_screen->resource().toolbarOptions().auto_hide)
685 return;
687 if (hidden) {
688 if (! hide_timer->isTiming())
689 hide_timer->start();
690 } else if (hide_timer->isTiming()) {
691 hide_timer->stop();
695 void Toolbar::leaveNotifyEvent(const XCrossingEvent * const /*unused*/) {
696 if (!_screen->resource().toolbarOptions().auto_hide)
697 return;
699 if (hidden) {
700 if (hide_timer->isTiming())
701 hide_timer->stop();
702 } else if (! hide_timer->isTiming()) {
703 hide_timer->start();
708 void Toolbar::exposeEvent(const XExposeEvent * const event) {
709 if (event->window == frame.clock) redrawClockLabel();
710 else if (event->window == frame.workspace_label) redrawWorkspaceLabel();
711 else if (event->window == frame.window_label) redrawWindowLabel();
712 else if (event->window == frame.psbutton) redrawPrevWorkspaceButton();
713 else if (event->window == frame.nsbutton) redrawNextWorkspaceButton();
714 else if (event->window == frame.pwbutton) redrawPrevWindowButton();
715 else if (event->window == frame.nwbutton) redrawNextWindowButton();
716 else if (event->window == frame.window) {
717 bt::Rect t(0, 0, frame.rect.width(), frame.rect.height());
718 bt::Rect r(event->x, event->y, event->width, event->height);
719 bt::drawTexture(_screen->screenNumber(),
720 _screen->resource().toolbarStyle().toolbar,
721 frame.window, t, r & t, frame.base);
726 void Toolbar::timeout(bt::Timer *timer) {
727 if (timer == clock_timer) {
728 redrawClockLabel();
730 clock_timer->setTimeout(nextTimeout(clock_timer_resolution));
731 } else if (timer == hide_timer) {
732 hidden = ! hidden;
733 if (hidden)
734 XMoveWindow(display, frame.window,
735 frame.rect.x(), frame.y_hidden);
736 else
737 XMoveWindow(display, frame.window,
738 frame.rect.x(), frame.rect.y());
739 } else {
740 // this should not happen
741 assert(0);
746 void Toolbar::toggleAutoHide(void) {
747 bool do_auto_hide = !_screen->resource().toolbarOptions().auto_hide;
749 updateStrut();
750 if (_screen->slit())
751 _screen->slit()->reposition();
753 if (!do_auto_hide && hidden) {
754 // force the toolbar to be visible
755 if (hide_timer->isTiming()) hide_timer->stop();
756 hide_timer->fireTimeout();
761 void Toolbar::setPlacement(Placement place) {
762 ToolbarOptions &options =
763 const_cast<ToolbarOptions &>(_screen->resource().toolbarOptions());
764 options.placement = place;
765 reconfigure();
767 // reposition the slit as well to make sure it doesn't intersect the
768 // toolbar
769 if (_screen->slit())
770 _screen->slit()->reposition();
772 _screen->saveResource();