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