version bump
[blackbox.git] / src / Toolbar.cc
blobe88b8f6bee1deab08c4e699534db84dc9ef88104
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)
45 timeval now;
46 gettimeofday(&now, 0);
47 return (std::max(1000l, ((((resolution - (now.tv_sec % resolution)) * 1000l))
48 - (now.tv_usec / 1000l))));
52 Toolbar::Toolbar(BScreen *scrn) {
53 _screen = scrn;
54 blackbox = _screen->blackbox();
56 // get the clock updating every minute
57 clock_timer = new bt::Timer(blackbox, this);
58 clock_timer->recurring(True);
60 const ToolbarOptions &options = _screen->resource().toolbarOptions();
62 const std::string &time_format = options.strftime_format;
63 if (time_format.find("%S") != std::string::npos
64 || time_format.find("%s") != std::string::npos
65 || time_format.find("%r") != std::string::npos
66 || time_format.find("%T") != std::string::npos) {
67 clock_timer_resolution = 1;
68 } else if (time_format.find("%M") != std::string::npos
69 || time_format.find("%R") != std::string::npos) {
70 clock_timer_resolution = 60;
71 } else {
72 clock_timer_resolution = 3600;
75 hide_timer = new bt::Timer(blackbox, this);
76 hide_timer->setTimeout(blackbox->resource().autoRaiseDelay());
78 setLayer(options.always_on_top
79 ? StackingList::LayerAbove
80 : StackingList::LayerNormal);
81 hidden = options.auto_hide;
83 new_name_pos = 0;
85 display = blackbox->XDisplay();
86 XSetWindowAttributes attrib;
87 unsigned long create_mask = CWColormap | CWOverrideRedirect | CWEventMask;
88 attrib.colormap = _screen->screenInfo().colormap();
89 attrib.override_redirect = True;
90 attrib.event_mask = ButtonPressMask | ButtonReleaseMask |
91 EnterWindowMask | LeaveWindowMask | ExposureMask;
93 frame.window =
94 XCreateWindow(display, _screen->screenInfo().rootWindow(), 0, 0, 1, 1, 0,
95 _screen->screenInfo().depth(), InputOutput,
96 _screen->screenInfo().visual(),
97 create_mask, &attrib);
98 blackbox->insertEventHandler(frame.window, this);
100 attrib.event_mask =
101 ButtonPressMask | ButtonReleaseMask | ExposureMask | EnterWindowMask;
103 frame.workspace_label =
104 XCreateWindow(display, frame.window, 0, 0, 1, 1, 0,
105 _screen->screenInfo().depth(), InputOutput,
106 _screen->screenInfo().visual(),
107 create_mask, &attrib);
108 blackbox->insertEventHandler(frame.workspace_label, this);
110 frame.window_label =
111 XCreateWindow(display, frame.window, 0, 0, 1, 1, 0,
112 _screen->screenInfo().depth(), InputOutput,
113 _screen->screenInfo().visual(),
114 create_mask, &attrib);
115 blackbox->insertEventHandler(frame.window_label, this);
117 frame.clock =
118 XCreateWindow(display, frame.window, 0, 0, 1, 1, 0,
119 _screen->screenInfo().depth(), InputOutput,
120 _screen->screenInfo().visual(),
121 create_mask, &attrib);
122 blackbox->insertEventHandler(frame.clock, this);
124 frame.psbutton =
125 XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0,
126 _screen->screenInfo().depth(), InputOutput,
127 _screen->screenInfo().visual(),
128 create_mask, &attrib);
129 blackbox->insertEventHandler(frame.psbutton, this);
131 frame.nsbutton =
132 XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0,
133 _screen->screenInfo().depth(), InputOutput,
134 _screen->screenInfo().visual(),
135 create_mask, &attrib);
136 blackbox->insertEventHandler(frame.nsbutton, this);
138 frame.pwbutton =
139 XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0,
140 _screen->screenInfo().depth(), InputOutput,
141 _screen->screenInfo().visual(),
142 create_mask, &attrib);
143 blackbox->insertEventHandler(frame.pwbutton, this);
145 frame.nwbutton =
146 XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0,
147 _screen->screenInfo().depth(), InputOutput,
148 _screen->screenInfo().visual(),
149 create_mask, &attrib);
150 blackbox->insertEventHandler(frame.nwbutton, this);
152 frame.base = frame.slabel = frame.wlabel = frame.clk = frame.button =
153 frame.pbutton = None;
155 _screen->addStrut(&strut);
157 reconfigure();
159 clock_timer->setTimeout(nextTimeout(clock_timer_resolution));
160 clock_timer->start();
162 XMapSubwindows(display, frame.window);
163 XMapWindow(display, frame.window);
167 Toolbar::~Toolbar(void) {
168 _screen->removeStrut(&strut);
170 XUnmapWindow(display, frame.window);
172 bt::PixmapCache::release(frame.base);
173 bt::PixmapCache::release(frame.slabel);
174 bt::PixmapCache::release(frame.wlabel);
175 bt::PixmapCache::release(frame.clk);
176 bt::PixmapCache::release(frame.button);
177 bt::PixmapCache::release(frame.pbutton);
179 blackbox->removeEventHandler(frame.window);
180 blackbox->removeEventHandler(frame.workspace_label);
181 blackbox->removeEventHandler(frame.window_label);
182 blackbox->removeEventHandler(frame.clock);
183 blackbox->removeEventHandler(frame.psbutton);
184 blackbox->removeEventHandler(frame.nsbutton);
185 blackbox->removeEventHandler(frame.pwbutton);
186 blackbox->removeEventHandler(frame.nwbutton);
188 // all children windows are destroyed by this call as well
189 XDestroyWindow(display, frame.window);
191 delete hide_timer;
192 delete clock_timer;
196 unsigned int Toolbar::exposedHeight(void) const {
197 const ToolbarOptions &options = _screen->resource().toolbarOptions();
198 const ToolbarStyle &style = _screen->resource().toolbarStyle();
199 return (options.auto_hide ? style.hidden_height : style.toolbar_height);
203 void Toolbar::reconfigure(void) {
204 ScreenResource &resource = _screen->resource();
205 const ToolbarOptions &options = resource.toolbarOptions();
206 const ToolbarStyle &style = resource.toolbarStyle();
208 unsigned int width = (_screen->screenInfo().width() *
209 options.width_percent) / 100;
211 const unsigned int border_width = style.toolbar.borderWidth();
212 const unsigned int extra =
213 style.frame_margin == 0 ? style.button.borderWidth() : 0;
214 frame.rect.setSize(width, style.toolbar_height);
216 int x, y;
217 switch (options.placement) {
218 case TopLeft:
219 case TopRight:
220 case TopCenter:
221 switch (options.placement) {
222 case TopLeft:
223 x = 0;
224 break;
225 case TopRight:
226 x = _screen->screenInfo().width() - frame.rect.width();
227 break;
228 default:
229 x = (_screen->screenInfo().width() - frame.rect.width()) / 2;
230 break;
232 y = 0;
233 frame.y_hidden = style.hidden_height - frame.rect.height();
234 break;
236 case BottomLeft:
237 case BottomRight:
238 case BottomCenter:
239 default:
240 switch (options.placement) {
241 case BottomLeft:
242 x = 0;
243 break;
244 case BottomRight:
245 x = _screen->screenInfo().width() - frame.rect.width();
246 break;
247 default:
248 x = (_screen->screenInfo().width() - frame.rect.width()) / 2;
249 break;
251 y = _screen->screenInfo().height() - frame.rect.height();
252 frame.y_hidden = _screen->screenInfo().height() - style.hidden_height;
253 break;
256 frame.rect.setPos(x, y);
258 updateStrut();
260 time_t ttmp = time(NULL);
262 unsigned int clock_w = 0u, label_w = 0u;
264 if (ttmp != -1) {
265 struct tm *tt = localtime(&ttmp);
266 if (tt) {
267 char t[1024];
268 int len = strftime(t, 1024, options.strftime_format.c_str(), tt);
269 if (len == 0) { // invalid time format found
270 // so use the default
271 const_cast<std::string &>(options.strftime_format) = "%I:%M %p";
272 len = strftime(t, 1024, options.strftime_format.c_str(), 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 * two 'w' are used to get the widest possible width
279 clock_w =
280 bt::textRect(_screen->screenNumber(), style.font,
281 bt::toUnicode(t)).width() +
282 bt::textRect(_screen->screenNumber(), style.font,
283 bt::toUnicode("ww")).width();
287 for (unsigned int i = 0; i < _screen->workspaceCount(); i++) {
288 width =
289 bt::textRect(_screen->screenNumber(), style.font,
290 _screen->resource().workspaceName(i)).width();
291 label_w = std::max(label_w, width);
294 label_w = clock_w = std::max(label_w, clock_w) + (style.label_margin * 2);
296 unsigned int window_label_w =
297 (frame.rect.width() - (border_width * 2)
298 - (clock_w + (style.button_width * 4) + label_w
299 + (style.frame_margin * 8))
300 + extra*6);
302 XMoveResizeWindow(display, frame.window, frame.rect.x(),
303 hidden ? frame.y_hidden : frame.rect.y(),
304 frame.rect.width(), frame.rect.height());
306 // workspace label
307 frame.slabel_rect.setRect(border_width + style.frame_margin,
308 border_width + style.frame_margin,
309 label_w,
310 style.label_height);
311 // previous workspace button
312 frame.ps_rect.setRect(border_width + (style.frame_margin * 2) + label_w
313 - extra,
314 border_width + style.frame_margin,
315 style.button_width,
316 style.button_width);
317 // next workspace button
318 frame.ns_rect.setRect(border_width + (style.frame_margin * 3)
319 + label_w + style.button_width - (extra * 2),
320 border_width + style.frame_margin,
321 style.button_width,
322 style.button_width);
323 // window label
324 frame.wlabel_rect.setRect(border_width + (style.frame_margin * 4)
325 + (style.button_width * 2) + label_w - (extra * 3),
326 border_width + style.frame_margin,
327 window_label_w,
328 style.label_height);
329 // previous window button
330 frame.pw_rect.setRect(border_width + (style.frame_margin * 5)
331 + (style.button_width * 2) + label_w
332 + window_label_w - (extra * 4),
333 border_width + style.frame_margin,
334 style.button_width,
335 style.button_width);
336 // next window button
337 frame.nw_rect.setRect(border_width + (style.frame_margin * 6)
338 + (style.button_width * 3) + label_w
339 + window_label_w - (extra * 5),
340 border_width + style.frame_margin,
341 style.button_width,
342 style.button_width);
343 // clock
344 frame.clock_rect.setRect(frame.rect.width() - clock_w - style.frame_margin
345 - border_width,
346 border_width + style.frame_margin,
347 clock_w,
348 style.label_height);
350 XMoveResizeWindow(display, frame.workspace_label,
351 frame.slabel_rect.x(), frame.slabel_rect.y(),
352 frame.slabel_rect.width(), frame.slabel_rect.height());
353 XMoveResizeWindow(display, frame.psbutton,
354 frame.ps_rect.x(), frame.ps_rect.y(),
355 frame.ps_rect.width(), frame.ps_rect.height());
356 XMoveResizeWindow(display, frame.nsbutton,
357 frame.ns_rect.x(), frame.ns_rect.y(),
358 frame.ns_rect.width(), frame.ns_rect.height());
359 XMoveResizeWindow(display, frame.window_label,
360 frame.wlabel_rect.x(), frame.wlabel_rect.y(),
361 frame.wlabel_rect.width(), frame.wlabel_rect.height());
362 XMoveResizeWindow(display, frame.pwbutton,
363 frame.pw_rect.x(), frame.pw_rect.y(),
364 frame.pw_rect.width(), frame.pw_rect.height());
365 XMoveResizeWindow(display, frame.nwbutton,
366 frame.nw_rect.x(), frame.nw_rect.y(),
367 frame.nw_rect.width(), frame.nw_rect.height());
368 XMoveResizeWindow(display, frame.clock,
369 frame.clock_rect.x(), frame.clock_rect.y(),
370 frame.clock_rect.width(), frame.clock_rect.height());
372 frame.base =
373 bt::PixmapCache::find(_screen->screenNumber(), style.toolbar,
374 frame.rect.width(), frame.rect.height(),
375 frame.base);
376 frame.slabel =
377 bt::PixmapCache::find(_screen->screenNumber(), style.slabel,
378 frame.slabel_rect.width(),
379 frame.slabel_rect.height(),
380 frame.slabel);
381 frame.wlabel =
382 bt::PixmapCache::find(_screen->screenNumber(), style.wlabel,
383 frame.wlabel_rect.width(),
384 frame.wlabel_rect.height(),
385 frame.wlabel);
386 frame.clk =
387 bt::PixmapCache::find(_screen->screenNumber(), style.clock,
388 frame.clock_rect.width(),
389 frame.clock_rect.height(),
390 frame.clk);
391 frame.button =
392 bt::PixmapCache::find(_screen->screenNumber(), style.button,
393 style.button_width, style.button_width,
394 frame.button);
395 frame.pbutton =
396 bt::PixmapCache::find(_screen->screenNumber(),
397 style.pressed,
398 style.button_width, style.button_width,
399 frame.pbutton);
401 XClearArea(display, frame.window, 0, 0,
402 frame.rect.width(), frame.rect.height(), True);
404 XClearArea(display, frame.workspace_label, 0, 0,
405 label_w, style.label_height, True);
406 XClearArea(display, frame.window_label, 0, 0,
407 window_label_w, style.label_height, True);
408 XClearArea(display, frame.clock, 0, 0,
409 clock_w, style.label_height, True);
411 XClearArea(display, frame.psbutton, 0, 0,
412 style.button_width, style.button_width, True);
413 XClearArea(display, frame.nsbutton, 0, 0,
414 style.button_width, style.button_width, True);
415 XClearArea(display, frame.pwbutton, 0, 0,
416 style.button_width, style.button_width, True);
417 XClearArea(display, frame.nwbutton, 0, 0,
418 style.button_width, style.button_width, True);
422 void Toolbar::updateStrut(void) {
423 // left and right are always 0
424 strut.top = strut.bottom = 0;
426 switch(_screen->resource().toolbarOptions().placement) {
427 case TopLeft:
428 case TopCenter:
429 case TopRight:
430 strut.top = exposedHeight();
431 break;
432 default:
433 strut.bottom = exposedHeight();
436 _screen->updateStrut();
440 void Toolbar::redrawClockLabel(void) {
441 const ToolbarOptions &options = _screen->resource().toolbarOptions();
442 const ToolbarStyle &style = _screen->resource().toolbarStyle();
444 bt::Rect u(0, 0, frame.clock_rect.width(), frame.clock_rect.height());
445 if (frame.clk == ParentRelative) {
446 bt::Rect t(-frame.clock_rect.x(), -frame.clock_rect.y(),
447 frame.rect.width(), frame.rect.height());
448 bt::drawTexture(_screen->screenNumber(), style.toolbar,
449 frame.clock, t, u, frame.base);
450 } else {
451 bt::drawTexture(_screen->screenNumber(), style.clock,
452 frame.clock, u, u, frame.clk);
455 time_t tmp = 0;
456 struct tm *tt = 0;
457 char str[1024];
458 if ((tmp = time(NULL)) == -1)
459 return; // should not happen
460 tt = localtime(&tmp);
461 if (! tt)
462 return; // ditto
463 if (! strftime(str, sizeof(str), options.strftime_format.c_str(), tt))
464 return; // ditto
466 bt::Pen pen(_screen->screenNumber(), style.clock_text);
467 bt::drawText(style.font, pen, frame.clock, u, style.alignment,
468 bt::toUnicode(str));
472 void Toolbar::redrawWindowLabel(void) {
473 const ToolbarStyle &style = _screen->resource().toolbarStyle();
475 bt::Rect u(0, 0, frame.wlabel_rect.width(), frame.wlabel_rect.height());
476 if (frame.wlabel == ParentRelative) {
477 bt::Rect t(-frame.wlabel_rect.x(), -frame.wlabel_rect.y(),
478 frame.rect.width(), frame.rect.height());
479 bt::drawTexture(_screen->screenNumber(), style.toolbar,
480 frame.window_label, t, u, frame.base);
481 } else {
482 bt::drawTexture(_screen->screenNumber(), style.wlabel,
483 frame.window_label, u, u, frame.wlabel);
486 BlackboxWindow *foc = _screen->blackbox()->focusedWindow();
487 if (! foc || foc->screen() != _screen)
488 return;
490 bt::Pen pen(_screen->screenNumber(), style.wlabel_text);
491 bt::drawText(style.font, pen, frame.window_label, u,
492 style.alignment,
493 bt::ellideText(foc->title(), u.width(), bt::toUnicode("..."),
494 _screen->screenNumber(), style.font));
498 void Toolbar::redrawWorkspaceLabel(void) {
499 const bt::ustring &name =
500 _screen->resource().workspaceName(_screen->currentWorkspace());
501 const ToolbarStyle &style = _screen->resource().toolbarStyle();
503 bt::Rect u(0, 0, frame.slabel_rect.width(), frame.slabel_rect.height());
504 if (frame.slabel == ParentRelative) {
505 bt::Rect t(-frame.slabel_rect.x(), -frame.slabel_rect.y(),
506 frame.rect.width(), frame.rect.height());
507 bt::drawTexture(_screen->screenNumber(), style.toolbar,
508 frame.workspace_label, t, u, frame.base);
509 } else {
510 bt::drawTexture(_screen->screenNumber(), style.slabel,
511 frame.workspace_label, u, u, frame.slabel);
514 bt::Pen pen(_screen->screenNumber(), style.slabel_text);
515 bt::drawText(style.font, pen, frame.workspace_label, u,
516 style.alignment, name);
520 void Toolbar::redrawPrevWorkspaceButton(bool pressed) {
521 const ToolbarStyle &style =
522 _screen->resource().toolbarStyle();
524 Pixmap p = pressed ? frame.pbutton : frame.button;
525 bt::Rect u(0, 0, style.button_width, style.button_width);
526 if (p == ParentRelative) {
527 bt::Rect t(-frame.ps_rect.x(), -frame.ps_rect.y(),
528 frame.rect.width(), frame.rect.height());
529 bt::drawTexture(_screen->screenNumber(), style.toolbar,
530 frame.psbutton, t, u, frame.base);
531 } else {
532 bt::drawTexture(_screen->screenNumber(),
533 pressed ? style.pressed : style.button,
534 frame.psbutton, u, u, p);
537 const bt::Pen pen(_screen->screenNumber(), style.foreground);
538 bt::drawBitmap(bt::Bitmap::leftArrow(_screen->screenNumber()),
539 pen, frame.psbutton, u);
543 void Toolbar::redrawNextWorkspaceButton(bool pressed) {
544 const ToolbarStyle &style =
545 _screen->resource().toolbarStyle();
547 Pixmap p = pressed ? frame.pbutton : frame.button;
548 bt::Rect u(0, 0, style.button_width, style.button_width);
549 if (p == ParentRelative) {
550 bt::Rect t(-frame.ns_rect.x(), -frame.ns_rect.y(),
551 frame.rect.width(), frame.rect.height());
552 bt::drawTexture(_screen->screenNumber(), style.toolbar,
553 frame.nsbutton, t, u, frame.base);
554 } else {
555 bt::drawTexture(_screen->screenNumber(),
556 pressed ? style.pressed : style.button,
557 frame.nsbutton, u, u, p);
560 const bt::Pen pen(_screen->screenNumber(), style.foreground);
561 bt::drawBitmap(bt::Bitmap::rightArrow(_screen->screenNumber()),
562 pen, frame.nsbutton, u);
566 void Toolbar::redrawPrevWindowButton(bool pressed) {
567 const ToolbarStyle &style =
568 _screen->resource().toolbarStyle();
570 Pixmap p = pressed ? frame.pbutton : frame.button;
571 bt::Rect u(0, 0, style.button_width, style.button_width);
572 if (p == ParentRelative) {
573 bt::Rect t(-frame.pw_rect.x(), -frame.pw_rect.y(),
574 frame.rect.width(), frame.rect.height());
575 bt::drawTexture(_screen->screenNumber(), style.toolbar,
576 frame.pwbutton, t, u, frame.base);
577 } else {
578 bt::drawTexture(_screen->screenNumber(),
579 pressed ? style.pressed : style.button,
580 frame.pwbutton, u, u, p);
583 const bt::Pen pen(_screen->screenNumber(), style.foreground);
584 bt::drawBitmap(bt::Bitmap::leftArrow(_screen->screenNumber()),
585 pen, frame.pwbutton, u);
589 void Toolbar::redrawNextWindowButton(bool pressed) {
590 const ToolbarStyle &style =
591 _screen->resource().toolbarStyle();
593 Pixmap p = pressed ? frame.pbutton : frame.button;
594 bt::Rect u(0, 0, style.button_width, style.button_width);
595 if (p == ParentRelative) {
596 bt::Rect t(-frame.nw_rect.x(), -frame.nw_rect.y(),
597 frame.rect.width(), frame.rect.height());
598 bt::drawTexture(_screen->screenNumber(), style.toolbar,
599 frame.nwbutton, t, u, frame.base);
600 } else {
601 bt::drawTexture(_screen->screenNumber(),
602 pressed ? style.pressed : style.button,
603 frame.nwbutton, u, u, p);
606 const bt::Pen pen(_screen->screenNumber(), style.foreground);
607 bt::drawBitmap(bt::Bitmap::rightArrow(_screen->screenNumber()),
608 pen, frame.nwbutton, u);
612 void Toolbar::buttonPressEvent(const XButtonEvent * const event) {
613 if (event->state == Mod1Mask) {
614 if (event->button == 1)
615 _screen->raiseWindow(this);
616 else if (event->button == 2)
617 _screen->lowerWindow(this);
618 return;
621 if (event->button == 1) {
622 if (event->window == frame.psbutton)
623 redrawPrevWorkspaceButton(True);
624 else if (event->window == frame.nsbutton)
625 redrawNextWorkspaceButton(True);
626 else if (event->window == frame.pwbutton)
627 redrawPrevWindowButton(True);
628 else if (event->window == frame.nwbutton)
629 redrawNextWindowButton(True);
630 return;
633 if (event->window == frame.window_label) {
634 BlackboxWindow *focus = blackbox->focusedWindow();
635 if (focus && focus->screen() == _screen) {
636 if (event->button == 2) {
637 _screen->lowerWindow(focus);
638 } else if (event->button == 3) {
639 Windowmenu *windowmenu = _screen->windowmenu(focus);
640 windowmenu->popup(event->x_root, event->y_root,
641 _screen->availableArea());
642 } else if (blackbox->resource().toolbarActionsWithMouseWheel() &&
643 blackbox->resource().shadeWindowWithMouseWheel() &&
644 focus->hasWindowFunction(WindowFunctionShade)) {
645 if ((event->button == 4) && !focus->isShaded()) {
646 focus->setShaded(true);
647 } else if ((event->button == 5) && focus->isShaded()) {
648 focus->setShaded(false);
652 return;
655 if ((event->window == frame.pwbutton) || (event->window == frame.nwbutton)) {
656 if (blackbox->resource().toolbarActionsWithMouseWheel()) {
657 if (event->button == 4)
658 _screen->nextFocus();
659 else if (event->button == 5)
660 _screen->prevFocus();
662 // XXX: current-workspace window-list menu with button 2 or 3 here..
663 return;
666 // XXX: workspace-menu with button 2 or 3 on workspace-items (prev/next/label) here
668 // default-handlers (scroll through workspaces, popup toolbar-menu)
669 if (event->button == 3) {
670 _screen->toolbarmenu()->popup(event->x_root, event->y_root,
671 _screen->availableArea());
672 return;
675 if (blackbox->resource().toolbarActionsWithMouseWheel()) {
676 if (event->button == 4)
677 _screen->nextWorkspace();
678 else if (event->button == 5)
679 _screen->prevWorkspace();
684 void Toolbar::buttonReleaseEvent(const XButtonEvent * const event) {
685 if (event->button == 1) {
686 const ToolbarStyle &style =
687 _screen->resource().toolbarStyle();
689 if (event->window == frame.psbutton) {
690 redrawPrevWorkspaceButton(False);
692 if (bt::within(event->x, event->y,
693 style.button_width, style.button_width)) {
694 _screen->prevWorkspace();
696 } else if (event->window == frame.nsbutton) {
697 redrawNextWorkspaceButton(False);
699 if (bt::within(event->x, event->y,
700 style.button_width, style.button_width)) {
701 _screen->nextWorkspace();
703 } else if (event->window == frame.pwbutton) {
704 redrawPrevWindowButton(False);
706 if (bt::within(event->x, event->y,
707 style.button_width, style.button_width))
708 _screen->prevFocus();
709 } else if (event->window == frame.nwbutton) {
710 redrawNextWindowButton(False);
712 if (bt::within(event->x, event->y,
713 style.button_width, style.button_width))
714 _screen->nextFocus();
715 } else if (event->window == frame.window_label)
716 _screen->raiseFocus();
721 void Toolbar::enterNotifyEvent(const XCrossingEvent * const /*unused*/) {
722 if (!_screen->resource().toolbarOptions().auto_hide)
723 return;
725 if (hidden) {
726 if (! hide_timer->isTiming())
727 hide_timer->start();
728 } else if (hide_timer->isTiming()) {
729 hide_timer->stop();
733 void Toolbar::leaveNotifyEvent(const XCrossingEvent * const /*unused*/) {
734 if (!_screen->resource().toolbarOptions().auto_hide)
735 return;
737 if (hidden) {
738 if (hide_timer->isTiming())
739 hide_timer->stop();
740 } else if (! hide_timer->isTiming()) {
741 hide_timer->start();
746 void Toolbar::exposeEvent(const XExposeEvent * const event) {
747 if (event->window == frame.clock) redrawClockLabel();
748 else if (event->window == frame.workspace_label) redrawWorkspaceLabel();
749 else if (event->window == frame.window_label) redrawWindowLabel();
750 else if (event->window == frame.psbutton) redrawPrevWorkspaceButton();
751 else if (event->window == frame.nsbutton) redrawNextWorkspaceButton();
752 else if (event->window == frame.pwbutton) redrawPrevWindowButton();
753 else if (event->window == frame.nwbutton) redrawNextWindowButton();
754 else if (event->window == frame.window) {
755 bt::Rect t(0, 0, frame.rect.width(), frame.rect.height());
756 bt::Rect r(event->x, event->y, event->width, event->height);
757 bt::drawTexture(_screen->screenNumber(),
758 _screen->resource().toolbarStyle().toolbar,
759 frame.window, t, r & t, frame.base);
764 void Toolbar::timeout(bt::Timer *timer) {
765 if (timer == clock_timer) {
766 redrawClockLabel();
768 clock_timer->setTimeout(nextTimeout(clock_timer_resolution));
769 } else if (timer == hide_timer) {
770 hidden = ! hidden;
771 if (hidden)
772 XMoveWindow(display, frame.window,
773 frame.rect.x(), frame.y_hidden);
774 else
775 XMoveWindow(display, frame.window,
776 frame.rect.x(), frame.rect.y());
777 } else {
778 // this should not happen
779 assert(0);
784 void Toolbar::toggleAutoHide(void) {
785 bool do_auto_hide = !_screen->resource().toolbarOptions().auto_hide;
787 updateStrut();
788 if (_screen->slit())
789 _screen->slit()->reposition();
791 if (!do_auto_hide && hidden) {
792 // force the toolbar to be visible
793 if (hide_timer->isTiming()) hide_timer->stop();
794 hide_timer->fireTimeout();
799 void Toolbar::setPlacement(Placement place) {
800 ToolbarOptions &options =
801 const_cast<ToolbarOptions &>(_screen->resource().toolbarOptions());
802 options.placement = place;
803 reconfigure();
805 // reposition the slit as well to make sure it doesn't intersect the
806 // toolbar
807 if (_screen->slit())
808 _screen->slit()->reposition();
810 _screen->saveResource();