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