]> Dogcows Code - chaz/openbox/blob - src/Toolbar.cc
make arrows larger, match th size of the other bullets. make all bullets' sizes quick...
[chaz/openbox] / src / Toolbar.cc
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)
5 //
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:
12 //
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
15 //
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.
23
24 #ifdef HAVE_CONFIG_H
25 # include "../config.h"
26 #endif // HAVE_CONFIG_H
27
28 extern "C" {
29 #include <X11/keysym.h>
30
31 #ifdef HAVE_STRING_H
32 # include <string.h>
33 #endif // HAVE_STRING_H
34
35 #ifdef HAVE_STDIO_H
36 # include <stdio.h>
37 #endif // HAVE_STDIO_H
38
39 #ifdef TIME_WITH_SYS_TIME
40 # include <sys/time.h>
41 # include <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
46 # include <time.h>
47 # endif // HAVE_SYS_TIME_H
48 #endif // TIME_WITH_SYS_TIME
49 }
50
51 #include <string>
52 using std::string;
53
54 #include "i18n.hh"
55 #include "blackbox.hh"
56 #include "Clientmenu.hh"
57 #include "Font.hh"
58 #include "GCCache.hh"
59 #include "Iconmenu.hh"
60 #include "Image.hh"
61 #include "Rootmenu.hh"
62 #include "Screen.hh"
63 #include "Toolbar.hh"
64 #include "Window.hh"
65 #include "Workspace.hh"
66 #include "Workspacemenu.hh"
67 #include "Slit.hh"
68
69
70 static long aMinuteFromNow(void) {
71 timeval now;
72 gettimeofday(&now, 0);
73 return ((60 - (now.tv_sec % 60)) * 1000);
74 }
75
76
77 Toolbar::Toolbar(BScreen *scrn) {
78 screen = scrn;
79 blackbox = screen->getBlackbox();
80 toolbarstr = "session.screen" + itostring(screen->getScreenNumber()) +
81 ".toolbar.";
82 config = blackbox->getConfig();
83
84 load_rc();
85
86 // get the clock updating every minute
87 clock_timer = new BTimer(blackbox, this);
88 clock_timer->setTimeout(aMinuteFromNow());
89 clock_timer->recurring(True);
90 clock_timer->start();
91 frame.minute = frame.hour = -1;
92
93 hide_handler.toolbar = this;
94 hide_timer = new BTimer(blackbox, &hide_handler);
95 hide_timer->setTimeout(blackbox->getAutoRaiseDelay());
96
97 editing = False;
98 new_name_pos = 0;
99
100 toolbarmenu = new Toolbarmenu(this);
101
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;
113
114 frame.window =
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);
119
120 attrib.event_mask = ButtonPressMask | ButtonReleaseMask | ExposureMask |
121 KeyPressMask | EnterWindowMask;
122
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);
127
128 frame.window_label =
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);
132
133 frame.clock =
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);
137
138 frame.psbutton =
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);
142
143 frame.nsbutton =
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);
147
148 frame.pwbutton =
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);
152
153 frame.nwbutton =
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);
157
158 frame.base = frame.label = frame.wlabel = frame.clk = frame.button =
159 frame.pbutton = None;
160
161 reconfigure();
162 mapToolbar();
163 }
164
165
166 Toolbar::~Toolbar(void) {
167 unmapToolbar();
168
169 if (frame.base) screen->getImageControl()->removeImage(frame.base);
170 if (frame.label) screen->getImageControl()->removeImage(frame.label);
171 if (frame.wlabel) screen->getImageControl()->removeImage(frame.wlabel);
172 if (frame.clk) screen->getImageControl()->removeImage(frame.clk);
173 if (frame.button) screen->getImageControl()->removeImage(frame.button);
174 if (frame.pbutton) screen->getImageControl()->removeImage(frame.pbutton);
175
176 blackbox->removeToolbarSearch(frame.window);
177 blackbox->removeToolbarSearch(frame.workspace_label);
178 blackbox->removeToolbarSearch(frame.window_label);
179 blackbox->removeToolbarSearch(frame.clock);
180 blackbox->removeToolbarSearch(frame.psbutton);
181 blackbox->removeToolbarSearch(frame.nsbutton);
182 blackbox->removeToolbarSearch(frame.pwbutton);
183 blackbox->removeToolbarSearch(frame.nwbutton);
184
185 XDestroyWindow(display, frame.workspace_label);
186 XDestroyWindow(display, frame.window_label);
187 XDestroyWindow(display, frame.clock);
188
189 XDestroyWindow(display, frame.window);
190
191 delete hide_timer;
192 delete clock_timer;
193 delete toolbarmenu;
194 }
195
196
197 void Toolbar::mapToolbar() {
198 if (!screen->doHideToolbar()) {
199 //not hidden, so windows should not maximize over the toolbar
200 XMapSubwindows(display, frame.window);
201 XMapWindow(display, frame.window);
202 }
203 screen->addStrut(&strut);
204 updateStrut();
205 }
206
207
208 void Toolbar::unmapToolbar() {
209 if (toolbarmenu->isVisible())
210 toolbarmenu->hide();
211 //hidden so we can maximize over the toolbar
212 screen->removeStrut(&strut);
213 screen->updateAvailableArea();
214
215 XUnmapWindow(display, frame.window);
216 updateStrut();
217 }
218
219
220 void Toolbar::saveOnTop(bool b) {
221 on_top = b;
222 config->setValue(toolbarstr + "onTop", on_top);
223 }
224
225
226 void Toolbar::saveAutoHide(bool b) {
227 do_auto_hide = b;
228 config->setValue(toolbarstr + "autoHide", do_auto_hide);
229 }
230
231
232 void Toolbar::saveWidthPercent(unsigned int w) {
233 width_percent = w;
234 config->setValue(toolbarstr + "widthPercent", width_percent);
235 }
236
237
238 void Toolbar::savePlacement(int p) {
239 placement = p;
240 const char *pname;
241 switch (placement) {
242 case TopLeft: pname = "TopLeft"; break;
243 case BottomLeft: pname = "BottomLeft"; break;
244 case TopCenter: pname = "TopCenter"; break;
245 case TopRight: pname = "TopRight"; break;
246 case BottomRight: pname = "BottomRight"; break;
247 case BottomCenter: default: pname = "BottomCenter"; break;
248 }
249 config->setValue(toolbarstr + "placement", pname);
250 }
251
252
253 void Toolbar::save_rc(void) {
254 saveOnTop(on_top);
255 saveAutoHide(do_auto_hide);
256 saveWidthPercent(width_percent);
257 savePlacement(placement);
258 }
259
260
261 void Toolbar::load_rc(void) {
262 string s;
263
264 if (! config->getValue(toolbarstr + "onTop", on_top))
265 on_top = false;
266
267 if (! config->getValue(toolbarstr + "autoHide", do_auto_hide))
268 do_auto_hide = false;
269 hidden = do_auto_hide;
270
271 if (! config->getValue(toolbarstr + "widthPercent", width_percent) ||
272 width_percent == 0 || width_percent > 100)
273 width_percent = 66;
274
275 if (config->getValue(toolbarstr + "placement", s)) {
276 if (s == "TopLeft")
277 placement = TopLeft;
278 else if (s == "BottomLeft")
279 placement = BottomLeft;
280 else if (s == "TopCenter")
281 placement = TopCenter;
282 else if (s == "TopRight")
283 placement = TopRight;
284 else if (s == "BottomRight")
285 placement = BottomRight;
286 else //if (s == "BottomCenter")
287 placement = BottomCenter;
288 } else
289 placement = BottomCenter;
290 }
291
292
293 void Toolbar::reconfigure(void) {
294 unsigned int width, height;
295
296 width = (screen->getWidth() * width_percent) / 100;
297 height = screen->getToolbarStyle()->font->height();
298
299 frame.bevel_w = screen->getBevelWidth();
300 frame.button_w = height;
301 height += 2;
302 frame.label_h = height;
303 height += (frame.bevel_w * 2);
304
305 frame.rect.setSize(width, height);
306
307 int x, y;
308 switch (placement) {
309 case TopLeft:
310 case TopRight:
311 case TopCenter:
312 if (placement == TopLeft)
313 x = 0;
314 else if (placement == TopRight)
315 x = screen->getWidth() - frame.rect.width()
316 - (screen->getBorderWidth() * 2);
317 else
318 x = (screen->getWidth() - frame.rect.width()) / 2;
319
320 y = 0;
321
322 frame.x_hidden = x;
323 frame.y_hidden = screen->getBevelWidth() - screen->getBorderWidth()
324 - frame.rect.height();
325 break;
326
327 case BottomLeft:
328 case BottomRight:
329 case BottomCenter:
330 default:
331 if (placement == BottomLeft)
332 x = 0;
333 else if (placement == BottomRight)
334 x = screen->getWidth() - frame.rect.width()
335 - (screen->getBorderWidth() * 2);
336 else
337 x = (screen->getWidth() - frame.rect.width()) / 2;
338
339 y = screen->getHeight() - frame.rect.height()
340 - (screen->getBorderWidth() * 2);
341
342 frame.x_hidden = x;
343 frame.y_hidden = screen->getHeight() - screen->getBevelWidth()
344 - screen->getBorderWidth();
345 break;
346 }
347
348 frame.rect.setPos(x, y);
349
350 updateStrut();
351
352 #ifdef HAVE_STRFTIME
353 time_t ttmp = time(NULL);
354
355 frame.clock_w = 0;
356 if (ttmp != -1) {
357 struct tm *tt = localtime(&ttmp);
358 if (tt) {
359 char t[1024];
360 int len = strftime(t, 1024, screen->getStrftimeFormat(), tt);
361 if (len == 0) { // invalid time format found
362 screen->saveStrftimeFormat("%I:%M %p"); // so use the default
363 strftime(t, 1024, screen->getStrftimeFormat(), tt);
364 }
365 // find the length of the rendered string and add room for two extra
366 // characters to it. This allows for variable width output of the fonts
367 BFont *font = screen->getToolbarStyle()->font;
368 frame.clock_w = font->measureString(t) + font->maxCharWidth() * 2;
369 }
370 }
371 #else // !HAVE_STRFTIME
372 {
373 string s = i18n(ToolbarSet, ToolbarNoStrftimeLength, "00:00000");
374 frame.clock_w = screen->getToolbarStyle()->font->measureString(s);
375 }
376 #endif // HAVE_STRFTIME
377
378 frame.workspace_label_w = 0;
379
380 for (unsigned int i = 0; i < screen->getWorkspaceCount(); i++) {
381 const string& workspace_name = screen->getWorkspace(i)->getName();
382 width = screen->getToolbarStyle()->font->measureString(workspace_name);
383 if (width > frame.workspace_label_w) frame.workspace_label_w = width;
384 }
385
386 frame.workspace_label_w = frame.clock_w =
387 std::max(frame.workspace_label_w, frame.clock_w) + (frame.bevel_w * 4);
388
389 // XXX: where'd the +6 come from?
390 frame.window_label_w =
391 (frame.rect.width() - (frame.clock_w + (frame.button_w * 4) +
392 frame.workspace_label_w + (frame.bevel_w * 8) + 6));
393
394 if (hidden) {
395 XMoveResizeWindow(display, frame.window, frame.x_hidden, frame.y_hidden,
396 frame.rect.width(), frame.rect.height());
397 } else {
398 XMoveResizeWindow(display, frame.window, frame.rect.x(), frame.rect.y(),
399 frame.rect.width(), frame.rect.height());
400 }
401
402 XMoveResizeWindow(display, frame.workspace_label, frame.bevel_w,
403 frame.bevel_w, frame.workspace_label_w,
404 frame.label_h);
405 XMoveResizeWindow(display, frame.psbutton,
406 ((frame.bevel_w * 2) + frame.workspace_label_w + 1),
407 frame.bevel_w + 1, frame.button_w, frame.button_w);
408 XMoveResizeWindow(display, frame.nsbutton,
409 ((frame.bevel_w * 3) + frame.workspace_label_w +
410 frame.button_w + 2), frame.bevel_w + 1, frame.button_w,
411 frame.button_w);
412 XMoveResizeWindow(display, frame.window_label,
413 ((frame.bevel_w * 4) + (frame.button_w * 2) +
414 frame.workspace_label_w + 3), frame.bevel_w,
415 frame.window_label_w, frame.label_h);
416 XMoveResizeWindow(display, frame.pwbutton,
417 ((frame.bevel_w * 5) + (frame.button_w * 2) +
418 frame.workspace_label_w + frame.window_label_w + 4),
419 frame.bevel_w + 1, frame.button_w, frame.button_w);
420 XMoveResizeWindow(display, frame.nwbutton,
421 ((frame.bevel_w * 6) + (frame.button_w * 3) +
422 frame.workspace_label_w + frame.window_label_w + 5),
423 frame.bevel_w + 1, frame.button_w, frame.button_w);
424 XMoveResizeWindow(display, frame.clock,
425 frame.rect.width() - frame.clock_w - (frame.bevel_w * 2),
426 frame.bevel_w, frame.clock_w, frame.label_h);
427
428 ToolbarStyle *style = screen->getToolbarStyle();
429 frame.base = style->toolbar.render(frame.rect.width(), frame.rect.height(),
430 frame.base);
431 if (! frame.base)
432 XSetWindowBackground(display, frame.window,
433 style->toolbar.color().pixel());
434 else
435 XSetWindowBackgroundPixmap(display, frame.window, frame.base);
436
437 frame.label = style->window.render(frame.window_label_w, frame.label_h,
438 frame.label);
439 if (! frame.label)
440 XSetWindowBackground(display, frame.window_label,
441 style->window.color().pixel());
442 else
443 XSetWindowBackgroundPixmap(display, frame.window_label, frame.label);
444
445 frame.wlabel = style->label.render(frame.workspace_label_w, frame.label_h,
446 frame.wlabel);
447 if (! frame.wlabel)
448 XSetWindowBackground(display, frame.workspace_label,
449 style->label.color().pixel());
450 else
451 XSetWindowBackgroundPixmap(display, frame.workspace_label, frame.wlabel);
452
453 frame.clk = style->clock.render(frame.clock_w, frame.label_h, frame.clk);
454 if (! frame.clk)
455 XSetWindowBackground(display, frame.clock, style->clock.color().pixel());
456 else
457 XSetWindowBackgroundPixmap(display, frame.clock, frame.clk);
458
459 frame.button = style->button.render(frame.button_w, frame.button_w,
460 frame.button);
461 if (! frame.button) {
462 frame.button_pixel = style->button.color().pixel();
463 XSetWindowBackground(display, frame.psbutton, frame.button_pixel);
464 XSetWindowBackground(display, frame.nsbutton, frame.button_pixel);
465 XSetWindowBackground(display, frame.pwbutton, frame.button_pixel);
466 XSetWindowBackground(display, frame.nwbutton, frame.button_pixel);
467 } else {
468 XSetWindowBackgroundPixmap(display, frame.psbutton, frame.button);
469 XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.button);
470 XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.button);
471 XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.button);
472 }
473
474 frame.pbutton = style->pressed.render(frame.button_w, frame.button_w,
475 frame.pbutton);
476 if (! frame.pbutton)
477 frame.pbutton_pixel = style->pressed.color().pixel();
478
479 XSetWindowBorder(display, frame.window,
480 screen->getBorderColor()->pixel());
481 XSetWindowBorderWidth(display, frame.window, screen->getBorderWidth());
482
483 XClearWindow(display, frame.window);
484 XClearWindow(display, frame.workspace_label);
485 XClearWindow(display, frame.window_label);
486 XClearWindow(display, frame.clock);
487 XClearWindow(display, frame.psbutton);
488 XClearWindow(display, frame.nsbutton);
489 XClearWindow(display, frame.pwbutton);
490 XClearWindow(display, frame.nwbutton);
491
492 redrawWindowLabel();
493 redrawWorkspaceLabel();
494 redrawPrevWorkspaceButton();
495 redrawNextWorkspaceButton();
496 redrawPrevWindowButton();
497 redrawNextWindowButton();
498 checkClock(True);
499
500 toolbarmenu->reconfigure();
501 }
502
503
504 void Toolbar::updateStrut(void) {
505 // left and right are always 0
506 strut.top = strut.bottom = 0;
507
508 // when hidden only one border is visible
509 unsigned int border_width = screen->getBorderWidth();
510 if (! do_auto_hide)
511 border_width *= 2;
512
513 if (! screen->doHideToolbar()) {
514 switch(placement) {
515 case TopLeft:
516 case TopCenter:
517 case TopRight:
518 strut.top = getExposedHeight() + border_width;
519 break;
520 default:
521 strut.bottom = getExposedHeight() + border_width;
522 }
523 }
524
525 screen->updateAvailableArea();
526 }
527
528
529 #ifdef HAVE_STRFTIME
530 void Toolbar::checkClock(bool redraw) {
531 #else // !HAVE_STRFTIME
532 void Toolbar::checkClock(bool redraw, bool date) {
533 #endif // HAVE_STRFTIME
534 time_t tmp = 0;
535 struct tm *tt = 0;
536
537 if ((tmp = time(NULL)) != -1) {
538 if (! (tt = localtime(&tmp))) return;
539 if (tt->tm_min != frame.minute || tt->tm_hour != frame.hour) {
540 frame.hour = tt->tm_hour;
541 frame.minute = tt->tm_min;
542 XClearWindow(display, frame.clock);
543 redraw = True;
544 }
545 }
546
547 if (redraw) {
548 #ifdef HAVE_STRFTIME
549 char t[1024];
550 if (! strftime(t, 1024, screen->getStrftimeFormat(), tt))
551 return;
552 #else // !HAVE_STRFTIME
553 char t[9];
554 if (date) {
555 // format the date... with special consideration for y2k ;)
556 if (screen->getDateFormat() == Blackbox::B_EuropeanDate)
557 sprintf(t, 18n(ToolbarSet, ToolbarNoStrftimeDateFormatEu,
558 "%02d.%02d.%02d"),
559 tt->tm_mday, tt->tm_mon + 1,
560 (tt->tm_year >= 100) ? tt->tm_year - 100 : tt->tm_year);
561 else
562 sprintf(t, i18n(ToolbarSet, ToolbarNoStrftimeDateFormat,
563 "%02d/%02d/%02d"),
564 tt->tm_mon + 1, tt->tm_mday,
565 (tt->tm_year >= 100) ? tt->tm_year - 100 : tt->tm_year);
566 } else {
567 if (screen->isClock24Hour())
568 sprintf(t, i18n(ToolbarSet, ToolbarNoStrftimeTimeFormat24,
569 " %02d:%02d "),
570 frame.hour, frame.minute);
571 else
572 sprintf(t, i18n(ToolbarSet, ToolbarNoStrftimeTimeFormat12,
573 "%02d:%02d %sm"),
574 ((frame.hour > 12) ? frame.hour - 12 :
575 ((frame.hour == 0) ? 12 : frame.hour)), frame.minute,
576 ((frame.hour >= 12) ?
577 i18n(ToolbarSet, ToolbarNoStrftimeTimeFormatP, "p") :
578 i18n(ToolbarSet, ToolbarNoStrftimeTimeFormatA, "a")));
579 }
580 #endif // HAVE_STRFTIME
581
582 ToolbarStyle *style = screen->getToolbarStyle();
583
584 int pos = frame.bevel_w * 2; // this is modified by doJustify()
585 style->doJustify(t, pos, frame.clock_w, frame.bevel_w * 4);
586 style->font->drawString(frame.clock, pos, 1, style->c_text, t);
587 }
588 }
589
590
591 void Toolbar::redrawWindowLabel(bool redraw) {
592 BlackboxWindow *foc = screen->getBlackbox()->getFocusedWindow();
593 if (! foc) {
594 XClearWindow(display, frame.window_label);
595 return;
596 }
597
598 if (redraw)
599 XClearWindow(display, frame.window_label);
600
601 if (foc->getScreen() != screen) return;
602
603 const char *title = foc->getTitle();
604 ToolbarStyle *style = screen->getToolbarStyle();
605
606 int pos = frame.bevel_w * 2; // modified by doJustify()
607 style->doJustify(title, pos, frame.window_label_w, frame.bevel_w * 4);
608 style->font->drawString(frame.window_label, pos, 1, style->w_text, title);
609 }
610
611
612 void Toolbar::redrawWorkspaceLabel(bool redraw) {
613 const string& name = screen->getCurrentWorkspace()->getName();
614
615 if (redraw)
616 XClearWindow(display, frame.workspace_label);
617
618 ToolbarStyle *style = screen->getToolbarStyle();
619
620 int pos = frame.bevel_w * 2;
621 style->doJustify(name.c_str(), pos, frame.workspace_label_w,
622 frame.bevel_w * 4);
623 style->font->drawString(frame.workspace_label, pos, 1, style->l_text, name);
624 }
625
626
627 void Toolbar::drawArrow(Drawable surface, bool left) const {
628 int hh = frame.button_w / 2, hw = frame.button_w / 2;
629 XPoint pts[3];
630 const int bullet_size = 3;
631
632 if (left) {
633 pts[0].x = hw - bullet_size;
634 pts[0].y = hh;
635 pts[1].x = 2 * bullet_size;
636 pts[1].y = bullet_size;
637 pts[2].x = 0;
638 pts[2].y = -(2 * bullet_size);
639 } else {
640 pts[0].x = hw - bullet_size;
641 pts[0].y = hh - bullet_size;
642 pts[1].x = (2 * bullet_size);
643 pts[1].y = bullet_size;
644 pts[2].x = -(2 * bullet_size);
645 pts[2].y = bullet_size;
646 }
647
648 BPen pen(screen->getToolbarStyle()->b_pic);
649 XFillPolygon(display, surface, pen.gc(), pts, 3, Convex, CoordModePrevious);
650 }
651
652
653 void Toolbar::redrawPrevWorkspaceButton(bool pressed, bool redraw) {
654 if (redraw) {
655 if (pressed) {
656 if (frame.pbutton)
657 XSetWindowBackgroundPixmap(display, frame.psbutton, frame.pbutton);
658 else
659 XSetWindowBackground(display, frame.psbutton, frame.pbutton_pixel);
660 } else {
661 if (frame.button)
662 XSetWindowBackgroundPixmap(display, frame.psbutton, frame.button);
663 else
664 XSetWindowBackground(display, frame.psbutton, frame.button_pixel);
665 }
666 XClearWindow(display, frame.psbutton);
667 }
668
669 drawArrow(frame.psbutton, True);
670 }
671
672
673 void Toolbar::redrawNextWorkspaceButton(bool pressed, bool redraw) {
674 if (redraw) {
675 if (pressed) {
676 if (frame.pbutton)
677 XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.pbutton);
678 else
679 XSetWindowBackground(display, frame.nsbutton, frame.pbutton_pixel);
680 } else {
681 if (frame.button)
682 XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.button);
683 else
684 XSetWindowBackground(display, frame.nsbutton, frame.button_pixel);
685 }
686 XClearWindow(display, frame.nsbutton);
687 }
688
689 drawArrow(frame.nsbutton, False);
690 }
691
692
693 void Toolbar::redrawPrevWindowButton(bool pressed, bool redraw) {
694 if (redraw) {
695 if (pressed) {
696 if (frame.pbutton)
697 XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.pbutton);
698 else
699 XSetWindowBackground(display, frame.pwbutton, frame.pbutton_pixel);
700 } else {
701 if (frame.button)
702 XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.button);
703 else
704 XSetWindowBackground(display, frame.pwbutton, frame.button_pixel);
705 }
706 XClearWindow(display, frame.pwbutton);
707 }
708
709 drawArrow(frame.pwbutton, True);
710 }
711
712
713 void Toolbar::redrawNextWindowButton(bool pressed, bool redraw) {
714 if (redraw) {
715 if (pressed) {
716 if (frame.pbutton)
717 XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.pbutton);
718 else
719 XSetWindowBackground(display, frame.nwbutton, frame.pbutton_pixel);
720 } else {
721 if (frame.button)
722 XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.button);
723 else
724 XSetWindowBackground(display, frame.nwbutton, frame.button_pixel);
725 }
726 XClearWindow(display, frame.nwbutton);
727 }
728
729 drawArrow(frame.nwbutton, False);
730 }
731
732
733 void Toolbar::edit(void) {
734 Window window;
735 int foo;
736
737 editing = True;
738 XGetInputFocus(display, &window, &foo);
739 if (window == frame.workspace_label)
740 return;
741
742 XSetInputFocus(display, frame.workspace_label,
743 RevertToPointerRoot, CurrentTime);
744 XClearWindow(display, frame.workspace_label);
745
746 blackbox->setNoFocus(True);
747 if (blackbox->getFocusedWindow())
748 blackbox->getFocusedWindow()->setFocusFlag(False);
749
750 ToolbarStyle *style = screen->getToolbarStyle();
751 BPen pen(style->l_text);
752 XDrawRectangle(display, frame.workspace_label, pen.gc(),
753 frame.workspace_label_w / 2, 0, 1,
754 frame.label_h - 1);
755 // change the background of the window to that of an active window label
756 BTexture *texture = &(screen->getWindowStyle()->l_focus);
757 frame.wlabel = texture->render(frame.workspace_label_w, frame.label_h,
758 frame.wlabel);
759 if (! frame.wlabel)
760 XSetWindowBackground(display, frame.workspace_label,
761 texture->color().pixel());
762 else
763 XSetWindowBackgroundPixmap(display, frame.workspace_label, frame.wlabel);
764 }
765
766
767 void Toolbar::buttonPressEvent(const XButtonEvent *be) {
768 if (be->button == 1) {
769 if (be->window == frame.psbutton)
770 redrawPrevWorkspaceButton(True, True);
771 else if (be->window == frame.nsbutton)
772 redrawNextWorkspaceButton(True, True);
773 else if (be->window == frame.pwbutton)
774 redrawPrevWindowButton(True, True);
775 else if (be->window == frame.nwbutton)
776 redrawNextWindowButton(True, True);
777 #ifndef HAVE_STRFTIME
778 else if (be->window == frame.clock) {
779 XClearWindow(display, frame.clock);
780 checkClock(True, True);
781 }
782 #endif // HAVE_STRFTIME
783 else if (! on_top) {
784 Window w[1] = { frame.window };
785 screen->raiseWindows(w, 1);
786 }
787 } else if (be->button == 2 && (! on_top)) {
788 XLowerWindow(display, frame.window);
789 } else if (be->button == 3) {
790 if (toolbarmenu->isVisible()) {
791 toolbarmenu->hide();
792 } else {
793 int x, y;
794
795 x = be->x_root - (toolbarmenu->getWidth() / 2);
796 y = be->y_root - (toolbarmenu->getHeight() / 2);
797
798 if (x < 0)
799 x = 0;
800 else if (x + toolbarmenu->getWidth() > screen->getWidth())
801 x = screen->getWidth() - toolbarmenu->getWidth();
802
803 if (y < 0)
804 y = 0;
805 else if (y + toolbarmenu->getHeight() > screen->getHeight())
806 y = screen->getHeight() - toolbarmenu->getHeight();
807
808 toolbarmenu->move(x, y);
809 toolbarmenu->show();
810 }
811 }
812 }
813
814
815
816 void Toolbar::buttonReleaseEvent(const XButtonEvent *re) {
817 if (re->button == 1) {
818 if (re->window == frame.psbutton) {
819 redrawPrevWorkspaceButton(False, True);
820
821 if (re->x >= 0 && re->x < static_cast<signed>(frame.button_w) &&
822 re->y >= 0 && re->y < static_cast<signed>(frame.button_w))
823 if (screen->getCurrentWorkspace()->getID() > 0)
824 screen->changeWorkspaceID(screen->getCurrentWorkspace()->
825 getID() - 1);
826 else
827 screen->changeWorkspaceID(screen->getWorkspaceCount() - 1);
828 } else if (re->window == frame.nsbutton) {
829 redrawNextWorkspaceButton(False, True);
830
831 if (re->x >= 0 && re->x < static_cast<signed>(frame.button_w) &&
832 re->y >= 0 && re->y < static_cast<signed>(frame.button_w))
833 if (screen->getCurrentWorkspace()->getID() <
834 (screen->getWorkspaceCount() - 1))
835 screen->changeWorkspaceID(screen->getCurrentWorkspace()->
836 getID() + 1);
837 else
838 screen->changeWorkspaceID(0);
839 } else if (re->window == frame.pwbutton) {
840 redrawPrevWindowButton(False, True);
841
842 if (re->x >= 0 && re->x < static_cast<signed>(frame.button_w) &&
843 re->y >= 0 && re->y < static_cast<signed>(frame.button_w))
844 screen->prevFocus();
845 } else if (re->window == frame.nwbutton) {
846 redrawNextWindowButton(False, True);
847
848 if (re->x >= 0 && re->x < static_cast<signed>(frame.button_w) &&
849 re->y >= 0 && re->y < static_cast<signed>(frame.button_w))
850 screen->nextFocus();
851 } else if (re->window == frame.window_label)
852 screen->raiseFocus();
853 #ifndef HAVE_STRFTIME
854 else if (re->window == frame.clock) {
855 XClearWindow(display, frame.clock);
856 checkClock(True);
857 }
858 #endif // HAVE_STRFTIME
859 }
860 }
861
862
863 void Toolbar::enterNotifyEvent(const XCrossingEvent *) {
864 if (! do_auto_hide)
865 return;
866
867 if (hidden) {
868 if (! hide_timer->isTiming()) hide_timer->start();
869 } else {
870 if (hide_timer->isTiming()) hide_timer->stop();
871 }
872 }
873
874 void Toolbar::leaveNotifyEvent(const XCrossingEvent *) {
875 if (! do_auto_hide)
876 return;
877
878 if (hidden) {
879 if (hide_timer->isTiming()) hide_timer->stop();
880 } else if (! toolbarmenu->isVisible()) {
881 if (! hide_timer->isTiming()) hide_timer->start();
882 }
883 }
884
885
886 void Toolbar::exposeEvent(const XExposeEvent *ee) {
887 if (ee->window == frame.clock) checkClock(True);
888 else if (ee->window == frame.workspace_label && (! editing))
889 redrawWorkspaceLabel();
890 else if (ee->window == frame.window_label) redrawWindowLabel();
891 else if (ee->window == frame.psbutton) redrawPrevWorkspaceButton();
892 else if (ee->window == frame.nsbutton) redrawNextWorkspaceButton();
893 else if (ee->window == frame.pwbutton) redrawPrevWindowButton();
894 else if (ee->window == frame.nwbutton) redrawNextWindowButton();
895 }
896
897
898 void Toolbar::keyPressEvent(const XKeyEvent *ke) {
899 if (ke->window == frame.workspace_label && editing) {
900 if (new_workspace_name.empty()) {
901 new_name_pos = 0;
902 }
903
904 KeySym ks;
905 char keychar[1];
906 XLookupString(const_cast<XKeyEvent*>(ke), keychar, 1, &ks, 0);
907
908 // either we are told to end with a return or we hit 127 chars
909 if (ks == XK_Return || new_name_pos == 127) {
910 editing = False;
911
912 blackbox->setNoFocus(False);
913 if (blackbox->getFocusedWindow()) {
914 blackbox->getFocusedWindow()->setInputFocus();
915 } else {
916 blackbox->setFocusedWindow(0);
917 }
918
919 Workspace *wkspc = screen->getCurrentWorkspace();
920 wkspc->setName(new_workspace_name);
921 wkspc->getMenu()->hide();
922
923 screen->getWorkspacemenu()->changeItemLabel(wkspc->getID() + 2,
924 wkspc->getName());
925 screen->getWorkspacemenu()->update();
926
927 new_workspace_name.erase();
928 new_name_pos = 0;
929
930 // reset the background to that of the workspace label (its normal
931 // setting)
932 BTexture *texture = &(screen->getToolbarStyle()->label);
933 frame.wlabel = texture->render(frame.workspace_label_w, frame.label_h,
934 frame.wlabel);
935 if (! frame.wlabel)
936 XSetWindowBackground(display, frame.workspace_label,
937 texture->color().pixel());
938 else
939 XSetWindowBackgroundPixmap(display, frame.workspace_label,
940 frame.wlabel);
941 reconfigure();
942 } else if (! (ks == XK_Shift_L || ks == XK_Shift_R ||
943 ks == XK_Control_L || ks == XK_Control_R ||
944 ks == XK_Caps_Lock || ks == XK_Shift_Lock ||
945 ks == XK_Meta_L || ks == XK_Meta_R ||
946 ks == XK_Alt_L || ks == XK_Alt_R ||
947 ks == XK_Super_L || ks == XK_Super_R ||
948 ks == XK_Hyper_L || ks == XK_Hyper_R)) {
949 if (ks == XK_BackSpace) {
950 if (new_name_pos > 0) {
951 --new_name_pos;
952 new_workspace_name.erase(new_name_pos);
953 } else {
954 new_workspace_name.resize(0);
955 }
956 } else {
957 new_workspace_name += (*keychar);
958 ++new_name_pos;
959 }
960
961 XClearWindow(display, frame.workspace_label);
962 unsigned int tw, x;
963
964 tw = screen->getToolbarStyle()->font->measureString(new_workspace_name);
965 x = (frame.workspace_label_w - tw) / 2;
966
967 if (x < frame.bevel_w) x = frame.bevel_w;
968
969 ToolbarStyle *style = screen->getToolbarStyle();
970 style->font->drawString(frame.workspace_label, x, 1, style->l_text,
971 new_workspace_name);
972 BPen pen(style->l_text);
973 XDrawRectangle(display, frame.workspace_label, pen.gc(), x + tw, 0, 1,
974 frame.label_h - 1);
975 }
976 }
977 }
978
979
980 void Toolbar::timeout(void) {
981 checkClock(True);
982
983 clock_timer->setTimeout(aMinuteFromNow());
984 }
985
986
987 void Toolbar::HideHandler::timeout(void) {
988 toolbar->hidden = ! toolbar->hidden;
989 if (toolbar->hidden)
990 XMoveWindow(toolbar->display, toolbar->frame.window,
991 toolbar->frame.x_hidden, toolbar->frame.y_hidden);
992 else
993 XMoveWindow(toolbar->display, toolbar->frame.window,
994 toolbar->frame.rect.x(), toolbar->frame.rect.y());
995 }
996
997
998 void Toolbar::toggleAutoHide(void) {
999 saveAutoHide(! doAutoHide());
1000
1001 updateStrut();
1002 screen->getSlit()->reposition();
1003
1004 if (do_auto_hide == False && hidden) {
1005 // force the slit to be visible
1006 if (hide_timer->isTiming()) hide_timer->stop();
1007 hide_handler.timeout();
1008 }
1009 }
1010
1011
1012 Toolbarmenu::Toolbarmenu(Toolbar *tb) : Basemenu(tb->screen) {
1013 toolbar = tb;
1014
1015 setLabel(i18n(ToolbarSet, ToolbarToolbarTitle, "Toolbar"));
1016 setInternalMenu();
1017
1018 placementmenu = new Placementmenu(this);
1019
1020 insert(i18n(CommonSet, CommonPlacementTitle, "Placement"),
1021 placementmenu);
1022 insert(i18n(CommonSet, CommonAlwaysOnTop, "Always on top"), 1);
1023 insert(i18n(CommonSet, CommonAutoHide, "Auto hide"), 2);
1024 insert(i18n(ToolbarSet, ToolbarEditWkspcName,
1025 "Edit current workspace name"), 3);
1026
1027 update();
1028 setValues();
1029 }
1030
1031
1032 void Toolbarmenu::setValues() {
1033 setItemSelected(1, toolbar->isOnTop());
1034 setItemSelected(2, toolbar->doAutoHide());
1035 }
1036
1037
1038 Toolbarmenu::~Toolbarmenu(void) {
1039 delete placementmenu;
1040 }
1041
1042
1043 void Toolbarmenu::itemSelected(int button, unsigned int index) {
1044 if (button != 1)
1045 return;
1046
1047 BasemenuItem *item = find(index);
1048 if (! item) return;
1049
1050 switch (item->function()) {
1051 case 1: { // always on top
1052 toolbar->saveOnTop(! toolbar->isOnTop());
1053 setItemSelected(1, toolbar->isOnTop());
1054
1055 if (toolbar->isOnTop()) getScreen()->raiseWindows((Window *) 0, 0);
1056 break;
1057 }
1058
1059 case 2: { // auto hide
1060 toolbar->toggleAutoHide();
1061 setItemSelected(2, toolbar->doAutoHide());
1062
1063 break;
1064 }
1065
1066 case 3: { // edit current workspace name
1067 toolbar->edit();
1068 hide();
1069
1070 break;
1071 }
1072 } // switch
1073 }
1074
1075
1076 void Toolbarmenu::internal_hide(void) {
1077 Basemenu::internal_hide();
1078 if (toolbar->doAutoHide() && ! toolbar->isEditing())
1079 toolbar->hide_handler.timeout();
1080 }
1081
1082
1083 void Toolbarmenu::reconfigure(void) {
1084 setValues();
1085 placementmenu->reconfigure();
1086
1087 Basemenu::reconfigure();
1088 }
1089
1090
1091 Toolbarmenu::Placementmenu::Placementmenu(Toolbarmenu *tm)
1092 : Basemenu(tm->toolbar->screen), toolbar(tm->toolbar) {
1093 setLabel(i18n(ToolbarSet, ToolbarToolbarPlacement, "Toolbar Placement"));
1094 setInternalMenu();
1095 setMinimumSublevels(3);
1096
1097 insert(i18n(CommonSet, CommonPlacementTopLeft, "Top Left"),
1098 Toolbar::TopLeft);
1099 insert(i18n(CommonSet, CommonPlacementBottomLeft, "Bottom Left"),
1100 Toolbar::BottomLeft);
1101 insert(i18n(CommonSet, CommonPlacementTopCenter, "Top Center"),
1102 Toolbar::TopCenter);
1103 insert(i18n(CommonSet, CommonPlacementBottomCenter, "Bottom Center"),
1104 Toolbar::BottomCenter);
1105 insert(i18n(CommonSet, CommonPlacementTopRight, "Top Right"),
1106 Toolbar::TopRight);
1107 insert(i18n(CommonSet, CommonPlacementBottomRight, "Bottom Right"),
1108 Toolbar::BottomRight);
1109 update();
1110 setValues();
1111 }
1112
1113
1114 void Toolbarmenu::Placementmenu::setValues(void) {
1115 int place = 0;
1116 switch (toolbar->getPlacement()) {
1117 case Toolbar::BottomRight:
1118 place++;
1119 case Toolbar::TopRight:
1120 place++;
1121 case Toolbar::BottomCenter:
1122 place++;
1123 case Toolbar::TopCenter:
1124 place++;
1125 case Toolbar::BottomLeft:
1126 place++;
1127 case Toolbar::TopLeft:
1128 break;
1129 }
1130 setItemSelected(0, 0 == place);
1131 setItemSelected(1, 1 == place);
1132 setItemSelected(2, 2 == place);
1133 setItemSelected(3, 3 == place);
1134 setItemSelected(4, 4 == place);
1135 setItemSelected(5, 5 == place);
1136 }
1137
1138
1139 void Toolbarmenu::Placementmenu::reconfigure(void) {
1140 setValues();
1141 Basemenu::reconfigure();
1142 }
1143
1144
1145 void Toolbarmenu::Placementmenu::itemSelected(int button, unsigned int index) {
1146 if (button != 1)
1147 return;
1148
1149 BasemenuItem *item = find(index);
1150 if (! item) return;
1151
1152 toolbar->savePlacement(item->function());
1153 hide();
1154 toolbar->reconfigure();
1155
1156 // reposition the slit as well to make sure it doesn't intersect the
1157 // toolbar
1158 getScreen()->getSlit()->reposition();
1159 }
1160
1161
1162 void ToolbarStyle::doJustify(const std::string &text, int &start_pos,
1163 unsigned int max_length,
1164 unsigned int modifier) const {
1165 size_t text_len = text.size();
1166 unsigned int length;
1167
1168 do {
1169 length = font->measureString(string(text, 0, text_len)) + modifier;
1170 } while (length > max_length && text_len-- > 0);
1171
1172 switch (justify) {
1173 case RightJustify:
1174 start_pos += max_length - length;
1175 break;
1176
1177 case CenterJustify:
1178 start_pos += (max_length - length) / 2;
1179 break;
1180
1181 case LeftJustify:
1182 default:
1183 break;
1184 }
1185 }
This page took 0.091623 seconds and 5 git commands to generate.