]> icculus.org git repositories - mikachu/openbox.git/blob - src/Toolbar.cc
Added a runtime option for hiding the toolbar totally. Will be cleaner
[mikachu/openbox.git] / src / Toolbar.cc
1 // Toolbar.cc for Openbox
2 // Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
3 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a
6 // copy of this software and associated documentation files (the "Software"),
7 // to deal in the Software without restriction, including without limitation
8 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 // and/or sell copies of the Software, and to permit persons to whom the
10 // Software is furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 // DEALINGS IN THE SOFTWARE.
22
23 // stupid macros needed to access some functions in version 2 of the GNU C
24 // library
25 #ifndef   _GNU_SOURCE
26 #define   _GNU_SOURCE
27 #endif // _GNU_SOURCE
28
29 #ifdef    HAVE_CONFIG_H
30 #  include "../config.h"
31 #endif // HAVE_CONFIG_H
32
33 #include "i18n.h"
34 #include "openbox.h"
35 #include "Clientmenu.h"
36 #include "Iconmenu.h"
37 #include "Rootmenu.h"
38 #include "Screen.h"
39 #include "Toolbar.h"
40 #include "Window.h"
41 #include "Workspace.h"
42 #include "Workspacemenu.h"
43
44 #include <X11/keysym.h>
45
46 #ifdef    STDC_HEADERS
47 #  include <string.h>
48 #endif // STDC_HEADERS
49
50 #ifdef    HAVE_STDIO_H
51 #  include <stdio.h>
52 #endif // HAVE_STDIO_H
53
54 #ifdef    TIME_WITH_SYS_TIME
55 # include <sys/time.h>
56 # include <time.h>
57 #else // !TIME_WITH_SYS_TIME
58 # ifdef    HAVE_SYS_TIME_H
59 #  include <sys/time.h>
60 # else // !HAVE_SYS_TIME_H
61 #  include <time.h>
62 # endif // HAVE_SYS_TIME_H
63 #endif // TIME_WITH_SYS_TIME
64
65
66 Toolbar::Toolbar(BScreen &scrn) : screen(scrn), openbox(scrn.getOpenbox()) {
67   // get the clock updating every minute
68   clock_timer = new BTimer(openbox, *this);
69   timeval now;
70   gettimeofday(&now, 0);
71   clock_timer->setTimeout((60 - (now.tv_sec % 60)) * 1000);
72   clock_timer->start();
73
74   hide_handler.toolbar = this;
75   hide_timer = new BTimer(openbox, hide_handler);
76   hide_timer->setTimeout(openbox.getAutoRaiseDelay());
77   hide_timer->fireOnce(True);
78
79   image_ctrl = screen.getImageControl();
80
81   on_top = screen.isToolbarOnTop();
82   hidden = do_auto_hide = screen.doToolbarAutoHide();
83
84   editing = False;
85   new_workspace_name = (char *) 0;
86   new_name_pos = 0;
87   frame.grab_x = frame.grab_y = 0;
88
89   toolbarmenu = new Toolbarmenu(*this);
90
91   display = openbox.getXDisplay();
92   XSetWindowAttributes attrib;
93   unsigned long create_mask = CWBackPixmap | CWBackPixel | CWBorderPixel |
94                               CWColormap | CWOverrideRedirect | CWEventMask;
95   attrib.background_pixmap = None;
96   attrib.background_pixel = attrib.border_pixel =
97     screen.getBorderColor()->getPixel();
98   attrib.colormap = screen.getColormap();
99   attrib.override_redirect = True;
100   attrib.event_mask = ButtonPressMask | ButtonReleaseMask |
101                       EnterWindowMask | LeaveWindowMask;
102
103   frame.window =
104     XCreateWindow(display, screen.getRootWindow(), 0, 0, 1, 1, 0,
105                   screen.getDepth(), InputOutput, screen.getVisual(),
106                   create_mask, &attrib);
107   openbox.saveToolbarSearch(frame.window, this);
108
109   attrib.event_mask = ButtonPressMask | ButtonReleaseMask | ExposureMask |
110                       KeyPressMask | EnterWindowMask;
111
112   frame.workspace_label =
113     XCreateWindow(display, frame.window, 0, 0, 1, 1, 0, screen.getDepth(),
114                   InputOutput, screen.getVisual(), create_mask, &attrib);
115   openbox.saveToolbarSearch(frame.workspace_label, this);
116
117   frame.window_label =
118     XCreateWindow(display, frame.window, 0, 0, 1, 1, 0, screen.getDepth(),
119                   InputOutput, screen.getVisual(), create_mask, &attrib);
120   openbox.saveToolbarSearch(frame.window_label, this);
121
122   frame.clock =
123     XCreateWindow(display, frame.window, 0, 0, 1, 1, 0, screen.getDepth(),
124                   InputOutput, screen.getVisual(), create_mask, &attrib);
125   openbox.saveToolbarSearch(frame.clock, this);
126
127   frame.psbutton =
128     XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen.getDepth(),
129                   InputOutput, screen.getVisual(), create_mask, &attrib);
130   openbox.saveToolbarSearch(frame.psbutton, this);
131
132   frame.nsbutton =
133     XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen.getDepth(),
134                   InputOutput, screen.getVisual(), create_mask, &attrib);
135   openbox.saveToolbarSearch(frame.nsbutton, this);
136
137   frame.pwbutton =
138     XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen.getDepth(),
139                   InputOutput, screen.getVisual(), create_mask, &attrib);
140   openbox.saveToolbarSearch(frame.pwbutton, this);
141
142   frame.nwbutton =
143     XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen.getDepth(),
144                   InputOutput, screen.getVisual(), create_mask, &attrib);
145   openbox.saveToolbarSearch(frame.nwbutton, this);
146
147   frame.base = frame.label = frame.wlabel = frame.clk = frame.button =
148     frame.pbutton = None;
149
150   reconfigure();
151   mapToolbar();
152 }
153
154 inline void Toolbar::mapToolbar(){
155   if(!screen.doToolbarHide()){
156     do_hide=false;//not hidden, so windows should not maximize over the toolbar
157     XMapSubwindows(display, frame.window);
158     XMapWindow(display, frame.window);
159   }else
160     do_hide=true;
161 }
162 inline void Toolbar::unMapToolbar(){
163   do_hide=true; //hidden so we can maximize over the toolbar
164   XUnmapWindow(display, frame.window);
165 }
166
167 Toolbar::~Toolbar(void) {
168   unMapToolbar();
169   if (frame.base) image_ctrl->removeImage(frame.base);
170   if (frame.label) image_ctrl->removeImage(frame.label);
171   if (frame.wlabel) image_ctrl->removeImage(frame.wlabel);
172   if (frame.clk) image_ctrl->removeImage(frame.clk);
173   if (frame.button) image_ctrl->removeImage(frame.button);
174   if (frame.pbutton) image_ctrl->removeImage(frame.pbutton);
175
176   openbox.removeToolbarSearch(frame.window);
177   openbox.removeToolbarSearch(frame.workspace_label);
178   openbox.removeToolbarSearch(frame.window_label);
179   openbox.removeToolbarSearch(frame.clock);
180   openbox.removeToolbarSearch(frame.psbutton);
181   openbox.removeToolbarSearch(frame.nsbutton);
182   openbox.removeToolbarSearch(frame.pwbutton);
183   openbox.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::reconfigure(void) {
198   frame.bevel_w = screen.getBevelWidth();
199   frame.width = screen.size().w() * screen.getToolbarWidthPercent() / 100;
200   
201   if (i18n->multibyte())
202     frame.height =
203       screen.getToolbarStyle()->fontset_extents->max_ink_extent.height;
204   else
205     frame.height = screen.getToolbarStyle()->font->ascent +
206                    screen.getToolbarStyle()->font->descent;
207   frame.button_w = frame.height;
208   frame.height += 2;
209   frame.label_h = frame.height;
210   frame.height += (frame.bevel_w * 2);
211   
212   switch (screen.getToolbarPlacement()) {
213   case TopLeft:
214     frame.x = 0;
215     frame.y = 0;
216     frame.x_hidden = 0;
217     frame.y_hidden = screen.getBevelWidth() - screen.getBorderWidth()
218                      - frame.height;
219     break;
220
221   case BottomLeft:
222     frame.x = 0;
223     frame.y = screen.size().h() - frame.height
224       - (screen.getBorderWidth() * 2);
225     frame.x_hidden = 0;
226     frame.y_hidden = screen.size().h() - screen.getBevelWidth()
227                      - screen.getBorderWidth();
228     break;
229
230   case TopCenter:
231     frame.x = (screen.size().w() - frame.width) / 2;
232     frame.y = 0;
233     frame.x_hidden = frame.x;
234     frame.y_hidden = screen.getBevelWidth() - screen.getBorderWidth()
235                      - frame.height;
236     break;
237
238   case BottomCenter:
239   default:
240     frame.x = (screen.size().w() - frame.width) / 2;
241     frame.y = screen.size().h() - frame.height
242       - (screen.getBorderWidth() * 2);
243     frame.x_hidden = frame.x;
244     frame.y_hidden = screen.size().h() - screen.getBevelWidth()
245                      - screen.getBorderWidth();
246     break;
247
248   case TopRight:
249     frame.x = screen.size().w() - frame.width
250       - (screen.getBorderWidth() * 2);
251     frame.y = 0;
252     frame.x_hidden = frame.x;
253     frame.y_hidden = screen.getBevelWidth() - screen.getBorderWidth()
254                      - frame.height;
255     break;
256
257   case BottomRight:
258     frame.x = screen.size().w() - frame.width
259       - (screen.getBorderWidth() * 2);
260     frame.y = screen.size().h() - frame.height
261       - (screen.getBorderWidth() * 2);
262     frame.x_hidden = frame.x;
263     frame.y_hidden = screen.size().h() - screen.getBevelWidth()
264                      - screen.getBorderWidth();
265     break;
266   }
267
268 #ifdef    HAVE_STRFTIME
269   time_t ttmp = time(NULL);
270   struct tm *tt = 0;
271
272   if (ttmp != -1) {
273     tt = localtime(&ttmp);
274     if (tt) {
275       char t[1025], *time_string = (char *) 0;
276       int len = strftime(t, 1024, screen.getStrftimeFormat(), tt);
277       t[len++-1] = ' ';   // add a space to the string for padding
278       t[len] = '\0';
279
280       if (i18n->multibyte()) {
281         XRectangle ink, logical;
282         XmbTextExtents(screen.getToolbarStyle()->fontset, t, len, &ink,
283                        &logical);
284         frame.clock_w = logical.width;
285
286         // ben's additional solution to pad some space beside the numbers
287         //frame.clock_w +=
288         //  screen.getToolbarStyle()->fontset_extents->max_logical_extent.width *
289         //  4;
290
291         // brad's solution, which is currently buggy, too big
292         //frame.clock_w =
293         //  screen.getToolbarStyle()->fontset_extents->max_logical_extent.width
294         //  * len;
295       } else {
296         frame.clock_w = XTextWidth(screen.getToolbarStyle()->font, t, len);
297         // ben's additional solution to pad some space beside the numbers
298         //frame.clock_w += screen.getToolbarStyle()->font->max_bounds.width * 4;
299         // brad's solution again, too big
300         //frame.clock_w = screen.getToolbarStyle()->font->max_bounds.width * len;
301       }
302       frame.clock_w += (frame.bevel_w * 4);
303       
304       delete [] time_string;
305     } else {
306       frame.clock_w = 0;
307     }
308   } else {
309     frame.clock_w = 0;
310   }
311 #else // !HAVE_STRFTIME
312   frame.clock_w =
313     XTextWidth(screen.getToolbarStyle()->font,
314                i18n->getMessage(ToolbarSet, ToolbarNoStrftimeLength,
315                                 "00:00000"),
316                strlen(i18n->getMessage(ToolbarSet, ToolbarNoStrftimeLength,
317                                        "00:00000"))) + (frame.bevel_w * 4);
318 #endif // HAVE_STRFTIME
319
320   int i;
321   unsigned int w = 0;
322   frame.workspace_label_w = 0;
323
324   for (i = 0; i < screen.getWorkspaceCount(); i++) {
325     if (i18n->multibyte()) {
326       XRectangle ink, logical;
327       XmbTextExtents(screen.getToolbarStyle()->fontset,
328                      screen.getWorkspace(i)->getName(),
329                      strlen(screen.getWorkspace(i)->getName()),
330                      &ink, &logical);
331       w = logical.width;
332     } else {
333       w = XTextWidth(screen.getToolbarStyle()->font,
334                      screen.getWorkspace(i)->getName(),
335                      strlen(screen.getWorkspace(i)->getName()));
336     }
337     w += (frame.bevel_w * 4);
338
339     if (w > frame.workspace_label_w) frame.workspace_label_w = w;
340   }
341
342   if (frame.workspace_label_w < frame.clock_w)
343     frame.workspace_label_w = frame.clock_w;
344   else if (frame.workspace_label_w > frame.clock_w)
345     frame.clock_w = frame.workspace_label_w;
346
347   frame.window_label_w =
348     (frame.width - (frame.clock_w + (frame.button_w * 4) +
349                     frame.workspace_label_w + (frame.bevel_w * 8) + 6));
350
351   if (hidden) {
352     XMoveResizeWindow(display, frame.window, frame.x_hidden, frame.y_hidden,
353                       frame.width, frame.height);
354   } else {
355     XMoveResizeWindow(display, frame.window, frame.x, frame.y,
356                       frame.width, frame.height);
357   }
358
359   XMoveResizeWindow(display, frame.workspace_label, frame.bevel_w,
360                     frame.bevel_w, frame.workspace_label_w,
361                     frame.label_h);
362   XMoveResizeWindow(display, frame.psbutton, (frame.bevel_w * 2) +
363                     frame.workspace_label_w + 1, frame.bevel_w + 1,
364                     frame.button_w, frame.button_w);
365   XMoveResizeWindow(display ,frame.nsbutton, (frame.bevel_w * 3) +
366                     frame.workspace_label_w + frame.button_w + 2,
367                     frame.bevel_w + 1, frame.button_w, frame.button_w);
368   XMoveResizeWindow(display, frame.window_label, (frame.bevel_w * 4) +
369                     (frame.button_w * 2) + frame.workspace_label_w + 3,
370                     frame.bevel_w, frame.window_label_w, frame.label_h);
371   XMoveResizeWindow(display, frame.pwbutton, (frame.bevel_w * 5) +
372                     (frame.button_w * 2) + frame.workspace_label_w +
373                     frame.window_label_w + 4, frame.bevel_w + 1,
374                     frame.button_w, frame.button_w);
375   XMoveResizeWindow(display, frame.nwbutton, (frame.bevel_w * 6) +
376                     (frame.button_w * 3) + frame.workspace_label_w +
377                     frame.window_label_w + 5, frame.bevel_w + 1,
378                     frame.button_w, frame.button_w);
379   XMoveResizeWindow(display, frame.clock, frame.width - frame.clock_w -
380                     frame.bevel_w, frame.bevel_w, frame.clock_w,
381                     frame.label_h);
382
383   Pixmap tmp = frame.base;
384   BTexture *texture = &(screen.getToolbarStyle()->toolbar);
385   if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
386     frame.base = None;
387     XSetWindowBackground(display, frame.window,
388                          texture->getColor()->getPixel());
389   } else {
390     frame.base =
391       image_ctrl->renderImage(frame.width, frame.height, texture);
392     XSetWindowBackgroundPixmap(display, frame.window, frame.base);
393   }
394   if (tmp) image_ctrl->removeImage(tmp);
395
396   tmp = frame.label;
397   texture = &(screen.getToolbarStyle()->window);
398   if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
399     frame.label = None;
400     XSetWindowBackground(display, frame.window_label,
401                          texture->getColor()->getPixel());
402   } else {
403     frame.label =
404       image_ctrl->renderImage(frame.window_label_w, frame.label_h, texture);
405     XSetWindowBackgroundPixmap(display, frame.window_label, frame.label);
406   }
407   if (tmp) image_ctrl->removeImage(tmp);
408
409   tmp = frame.wlabel;
410   texture = &(screen.getToolbarStyle()->label);
411   if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
412     frame.wlabel = None;
413     XSetWindowBackground(display, frame.workspace_label,
414                          texture->getColor()->getPixel());
415   } else {
416     frame.wlabel =
417       image_ctrl->renderImage(frame.workspace_label_w, frame.label_h, texture);
418     XSetWindowBackgroundPixmap(display, frame.workspace_label, frame.wlabel);
419   }
420   if (tmp) image_ctrl->removeImage(tmp);
421
422   tmp = frame.clk;
423   texture = &(screen.getToolbarStyle()->clock);
424   if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
425     frame.clk = None;
426     XSetWindowBackground(display, frame.clock,
427                          texture->getColor()->getPixel());
428   } else {
429     frame.clk =
430       image_ctrl->renderImage(frame.clock_w, frame.label_h, texture);
431     XSetWindowBackgroundPixmap(display, frame.clock, frame.clk);
432   }
433   if (tmp) image_ctrl->removeImage(tmp);
434
435   tmp = frame.button;
436   texture = &(screen.getToolbarStyle()->button);
437   if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
438     frame.button = None;
439
440     frame.button_pixel = texture->getColor()->getPixel();
441     XSetWindowBackground(display, frame.psbutton, frame.button_pixel);
442     XSetWindowBackground(display, frame.nsbutton, frame.button_pixel);
443     XSetWindowBackground(display, frame.pwbutton, frame.button_pixel);
444     XSetWindowBackground(display, frame.nwbutton, frame.button_pixel);
445   } else {
446     frame.button =
447       image_ctrl->renderImage(frame.button_w, frame.button_w, texture);
448
449     XSetWindowBackgroundPixmap(display, frame.psbutton, frame.button);
450     XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.button);
451     XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.button);
452     XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.button);
453   }
454   if (tmp) image_ctrl->removeImage(tmp);
455
456   tmp = frame.pbutton;
457   texture = &(screen.getToolbarStyle()->pressed);
458   if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
459     frame.pbutton = None;
460     frame.pbutton_pixel = texture->getColor()->getPixel();
461   } else {
462     frame.pbutton =
463       image_ctrl->renderImage(frame.button_w, frame.button_w, texture);
464   }
465   if (tmp) image_ctrl->removeImage(tmp);
466
467   XSetWindowBorder(display, frame.window,
468                    screen.getBorderColor()->getPixel());
469   XSetWindowBorderWidth(display, frame.window, screen.getBorderWidth());
470
471   XClearWindow(display, frame.window);
472   XClearWindow(display, frame.workspace_label);
473   XClearWindow(display, frame.window_label);
474   XClearWindow(display, frame.clock);
475   XClearWindow(display, frame.psbutton);
476   XClearWindow(display, frame.nsbutton);
477   XClearWindow(display, frame.pwbutton);
478   XClearWindow(display, frame.nwbutton);
479   
480   redrawWindowLabel();
481   redrawWorkspaceLabel();
482   redrawPrevWorkspaceButton();
483   redrawNextWorkspaceButton();
484   redrawPrevWindowButton();
485   redrawNextWindowButton();
486   checkClock(True);
487   
488   toolbarmenu->reconfigure();
489 }
490
491
492 #ifdef    HAVE_STRFTIME
493 void Toolbar::checkClock(Bool redraw) {
494 #else // !HAVE_STRFTIME
495 void Toolbar::checkClock(Bool redraw, Bool date) {
496 #endif // HAVE_STRFTIME
497   time_t tmp = 0;
498   struct tm *tt = 0;
499
500   if ((tmp = time(NULL)) != -1) {
501     if (! (tt = localtime(&tmp))) return;
502     if (tt->tm_min != frame.minute || tt->tm_hour != frame.hour) {
503       frame.hour = tt->tm_hour;
504       frame.minute = tt->tm_min;
505       XClearWindow(display, frame.clock);
506       redraw = True;
507     }
508   }
509
510   if (redraw) {
511 #ifdef    HAVE_STRFTIME
512     char t[1024];
513     if (! strftime(t, 1024, screen.getStrftimeFormat(), tt))
514       return;
515 #else // !HAVE_STRFTIME
516     char t[9];
517     if (date) {
518       // format the date... with special consideration for y2k ;)
519       if (screen.getDateFormat() == Openbox::B_EuropeanDate)
520         sprintf(t, 18n->getMessage(ToolbarSet, ToolbarNoStrftimeDateFormatEu,
521                                    "%02d.%02d.%02d"),
522                 tt->tm_mday, tt->tm_mon + 1,
523                 (tt->tm_year >= 100) ? tt->tm_year - 100 : tt->tm_year);
524       else
525         sprintf(t, i18n->getMessage(ToolbarSet, ToolbarNoStrftimeDateFormat,
526                                     "%02d/%02d/%02d"),
527                 tt->tm_mon + 1, tt->tm_mday,
528                 (tt->tm_year >= 100) ? tt->tm_year - 100 : tt->tm_year);
529     } else {
530       if (screen.isClock24Hour())
531         sprintf(t, i18n->getMessage(ToolbarSet, ToolbarNoStrftimeTimeFormat24,
532                                     "  %02d:%02d "),
533                 frame.hour, frame.minute);
534       else
535         sprintf(t, i18n->getMessage(ToolbarSet, ToolbarNoStrftimeTimeFormat12,
536                                     "%02d:%02d %sm"),
537                 ((frame.hour > 12) ? frame.hour - 12 :
538                  ((frame.hour == 0) ? 12 : frame.hour)), frame.minute,
539                 ((frame.hour >= 12) ?
540                  i18n->getMessage(ToolbarSet,
541                                   ToolbarNoStrftimeTimeFormatP, "p") :
542                  i18n->getMessage(ToolbarSet,
543                                   ToolbarNoStrftimeTimeFormatA, "a")));
544     }
545 #endif // HAVE_STRFTIME
546
547     int dx = (frame.bevel_w * 2), dlen = strlen(t);
548     unsigned int l;
549
550     if (i18n->multibyte()) {
551       XRectangle ink, logical;
552       XmbTextExtents(screen.getToolbarStyle()->fontset,
553                      t, dlen, &ink, &logical);
554       l = logical.width;
555     } else {
556       l = XTextWidth(screen.getToolbarStyle()->font, t, dlen);
557     }
558     
559     l += (frame.bevel_w * 4);
560     
561     if (l > frame.clock_w) {
562       for (; dlen >= 0; dlen--) {
563         if (i18n->multibyte()) {
564           XRectangle ink, logical;
565           XmbTextExtents(screen.getToolbarStyle()->fontset,
566                          t, dlen, &ink, &logical);
567           l = logical.width;
568         } else {
569           l = XTextWidth(screen.getToolbarStyle()->font, t, dlen);
570         }
571         l+= (frame.bevel_w * 4);
572         
573         if (l < frame.clock_w)
574           break;
575       }
576     }
577     switch (screen.getToolbarStyle()->justify) {
578     case BScreen::RightJustify:
579       dx += frame.clock_w - l;
580       break;
581
582     case BScreen::CenterJustify:
583       dx += (frame.clock_w - l) / 2;
584       break;
585     }
586
587     ToolbarStyle *style = screen.getToolbarStyle();
588     if (i18n->multibyte())
589       XmbDrawString(display, frame.clock, style->fontset, style->c_text_gc,
590                     dx, (1 - style->fontset_extents->max_ink_extent.y),
591                     t, dlen);
592     else
593       XDrawString(display, frame.clock, style->c_text_gc, dx,
594                   (style->font->ascent + 1), t, dlen);
595   }
596 }
597
598
599 void Toolbar::redrawWindowLabel(Bool redraw) {
600   if (screen.getOpenbox().getFocusedWindow()) {
601     if (redraw)
602       XClearWindow(display, frame.window_label);
603
604     OpenboxWindow *foc = screen.getOpenbox().getFocusedWindow();
605     if (foc->getScreen() != &screen) return;
606
607     int dx = (frame.bevel_w * 2), dlen = strlen(*foc->getTitle());
608     unsigned int l;
609
610     if (i18n->multibyte()) {
611       XRectangle ink, logical;
612       XmbTextExtents(screen.getToolbarStyle()->fontset, *foc->getTitle(),
613                      dlen, &ink, &logical);
614       l = logical.width;
615     } else {
616       l = XTextWidth(screen.getToolbarStyle()->font, *foc->getTitle(), dlen);
617     }
618     l += (frame.bevel_w * 4);
619
620     if (l > frame.window_label_w) {
621       for (; dlen >= 0; dlen--) {
622         if (i18n->multibyte()) {
623           XRectangle ink, logical;
624           XmbTextExtents(screen.getToolbarStyle()->fontset,
625                          *foc->getTitle(), dlen, &ink, &logical);
626           l = logical.width;
627         } else {
628           l = XTextWidth(screen.getToolbarStyle()->font,
629                          *foc->getTitle(), dlen);
630         }
631         l += (frame.bevel_w * 4);
632         
633         if (l < frame.window_label_w)
634           break;
635       }
636     }
637     switch (screen.getToolbarStyle()->justify) {
638     case BScreen::RightJustify:
639       dx += frame.window_label_w - l;
640       break;
641
642     case BScreen::CenterJustify:
643       dx += (frame.window_label_w - l) / 2;
644       break;
645     }
646
647     ToolbarStyle *style = screen.getToolbarStyle();
648     if (i18n->multibyte())
649       XmbDrawString(display, frame.window_label, style->fontset,
650                     style->w_text_gc, dx,
651                     (1 - style->fontset_extents->max_ink_extent.y),
652                     *foc->getTitle(), dlen);
653     else
654       XDrawString(display, frame.window_label, style->w_text_gc, dx,
655                   (style->font->ascent + 1), *foc->getTitle(), dlen);
656   } else {
657     XClearWindow(display, frame.window_label);
658   }
659 }
660  
661  
662 void Toolbar::redrawWorkspaceLabel(Bool redraw) {
663   if (screen.getCurrentWorkspace()->getName()) {
664     if (redraw)
665       XClearWindow(display, frame.workspace_label);
666     
667     int dx = (frame.bevel_w * 2), dlen =
668              strlen(screen.getCurrentWorkspace()->getName());
669     unsigned int l;
670     
671     if (i18n->multibyte()) {
672       XRectangle ink, logical;
673       XmbTextExtents(screen.getToolbarStyle()->fontset,
674                      screen.getCurrentWorkspace()->getName(), dlen,
675                      &ink, &logical);
676       l = logical.width;
677     } else {
678       l = XTextWidth(screen.getToolbarStyle()->font,
679                      screen.getCurrentWorkspace()->getName(), dlen);
680     }
681     l += (frame.bevel_w * 4);
682     
683     if (l > frame.workspace_label_w) {
684       for (; dlen >= 0; dlen--) {
685         if (i18n->multibyte()) {
686           XRectangle ink, logical;
687           XmbTextExtents(screen.getToolbarStyle()->fontset,
688                          screen.getCurrentWorkspace()->getName(), dlen,
689                          &ink, &logical);
690           l = logical.width;
691         } else {
692           l = XTextWidth(screen.getWindowStyle()->font,
693                          screen.getCurrentWorkspace()->getName(), dlen);
694         }
695         l += (frame.bevel_w * 4);
696         
697         if (l < frame.workspace_label_w)
698           break;
699       }
700     }
701     switch (screen.getToolbarStyle()->justify) {
702     case BScreen::RightJustify:
703       dx += frame.workspace_label_w - l;
704       break;
705
706     case BScreen::CenterJustify:
707       dx += (frame.workspace_label_w - l) / 2;
708       break;
709     }
710
711     ToolbarStyle *style = screen.getToolbarStyle();
712     if (i18n->multibyte())
713       XmbDrawString(display, frame.workspace_label, style->fontset,
714                     style->l_text_gc, dx,
715                     (1 - style->fontset_extents->max_ink_extent.y),
716                     (char *) screen.getCurrentWorkspace()->getName(), dlen);
717     else
718       XDrawString(display, frame.workspace_label, style->l_text_gc, dx,
719                   (style->font->ascent + 1),
720                   (char *) screen.getCurrentWorkspace()->getName(), dlen);
721   }
722 }
723
724
725 void Toolbar::redrawPrevWorkspaceButton(Bool pressed, Bool redraw) {
726   if (redraw) {
727     if (pressed) {
728       if (frame.pbutton)
729         XSetWindowBackgroundPixmap(display, frame.psbutton, frame.pbutton);
730       else
731         XSetWindowBackground(display, frame.psbutton, frame.pbutton_pixel);
732     } else {
733       if (frame.button)
734         XSetWindowBackgroundPixmap(display, frame.psbutton, frame.button);
735       else
736         XSetWindowBackground(display, frame.psbutton, frame.button_pixel);
737     }
738     XClearWindow(display, frame.psbutton);
739   }
740
741   int hh = frame.button_w / 2, hw = frame.button_w / 2;
742
743   XPoint pts[3];
744   pts[0].x = hw - 2; pts[0].y = hh;
745   pts[1].x = 4; pts[1].y = 2;
746   pts[2].x = 0; pts[2].y = -4;
747
748   XFillPolygon(display, frame.psbutton, screen.getToolbarStyle()->b_pic_gc,
749                pts, 3, Convex, CoordModePrevious);
750 }
751
752
753 void Toolbar::redrawNextWorkspaceButton(Bool pressed, Bool redraw) {
754   if (redraw) {
755     if (pressed) {
756       if (frame.pbutton)
757         XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.pbutton);
758       else
759         XSetWindowBackground(display, frame.nsbutton, frame.pbutton_pixel);
760     } else {
761       if (frame.button)
762         XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.button);
763       else
764         XSetWindowBackground(display, frame.nsbutton, frame.button_pixel);
765     }
766     XClearWindow(display, frame.nsbutton);
767   }
768
769   int hh = frame.button_w / 2, hw = frame.button_w / 2;
770
771   XPoint pts[3];
772   pts[0].x = hw - 2; pts[0].y = hh - 2;
773   pts[1].x = 4; pts[1].y =  2;
774   pts[2].x = -4; pts[2].y = 2;
775
776   XFillPolygon(display, frame.nsbutton, screen.getToolbarStyle()->b_pic_gc,
777                pts, 3, Convex, CoordModePrevious);
778 }
779
780
781 void Toolbar::redrawPrevWindowButton(Bool pressed, Bool redraw) {
782   if (redraw) {
783     if (pressed) {
784       if (frame.pbutton)
785         XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.pbutton);
786       else
787         XSetWindowBackground(display, frame.pwbutton, frame.pbutton_pixel);
788     } else {
789       if (frame.button)
790         XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.button);
791       else
792         XSetWindowBackground(display, frame.pwbutton, frame.button_pixel);
793     }
794     XClearWindow(display, frame.pwbutton);
795   }
796
797   int hh = frame.button_w / 2, hw = frame.button_w / 2;
798
799   XPoint pts[3];
800   pts[0].x = hw - 2; pts[0].y = hh;
801   pts[1].x = 4; pts[1].y = 2;
802   pts[2].x = 0; pts[2].y = -4;
803
804   XFillPolygon(display, frame.pwbutton, screen.getToolbarStyle()->b_pic_gc,
805                pts, 3, Convex, CoordModePrevious);
806 }
807
808
809 void Toolbar::redrawNextWindowButton(Bool pressed, Bool redraw) {
810   if (redraw) {
811     if (pressed) {
812       if (frame.pbutton)
813         XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.pbutton);
814       else
815         XSetWindowBackground(display, frame.nwbutton, frame.pbutton_pixel);
816     } else {
817       if (frame.button)
818         XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.button);
819       else
820         XSetWindowBackground(display, frame.nwbutton, frame.button_pixel);
821     }
822     XClearWindow(display, frame.nwbutton);
823   }
824
825   int hh = frame.button_w / 2, hw = frame.button_w / 2;
826
827   XPoint pts[3];
828   pts[0].x = hw - 2; pts[0].y = hh - 2;
829   pts[1].x = 4; pts[1].y =  2;
830   pts[2].x = -4; pts[2].y = 2;
831
832   XFillPolygon(display, frame.nwbutton, screen.getToolbarStyle()->b_pic_gc,
833                pts, 3, Convex, CoordModePrevious);
834 }
835
836
837 void Toolbar::edit(void) {
838   Window window;
839   int foo;
840
841   editing = True;
842   if (XGetInputFocus(display, &window, &foo) &&
843       window == frame.workspace_label)
844     return;
845
846   XSetInputFocus(display, frame.workspace_label,
847                  ((screen.isSloppyFocus()) ? RevertToPointerRoot :
848                   RevertToParent),
849                  CurrentTime);
850   XClearWindow(display, frame.workspace_label);
851
852   openbox.setNoFocus(True);
853   if (openbox.getFocusedWindow())
854     openbox.getFocusedWindow()->setFocusFlag(False);
855
856   XDrawRectangle(display, frame.workspace_label,
857                  screen.getWindowStyle()->l_text_focus_gc,
858                  frame.workspace_label_w / 2, 0, 1,
859                  frame.label_h - 1);
860   
861   // change the background of the window to that of an active window label
862   Pixmap tmp = frame.wlabel;
863   BTexture *texture = &(screen.getWindowStyle()->l_focus);
864   if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
865     frame.wlabel = None;
866     XSetWindowBackground(display, frame.workspace_label,
867                          texture->getColor()->getPixel());
868   } else {
869     frame.wlabel =
870       image_ctrl->renderImage(frame.workspace_label_w, frame.label_h, texture);
871     XSetWindowBackgroundPixmap(display, frame.workspace_label, frame.wlabel);
872   }
873   if (tmp) image_ctrl->removeImage(tmp);
874 }
875
876
877 void Toolbar::buttonPressEvent(XButtonEvent *be) {
878   if (be->button == 1) {
879     if (be->window == frame.psbutton)
880       redrawPrevWorkspaceButton(True, True);
881     else if (be->window == frame.nsbutton)
882       redrawNextWorkspaceButton(True, True);
883     else if (be->window == frame.pwbutton)
884       redrawPrevWindowButton(True, True);
885     else if (be->window == frame.nwbutton)
886       redrawNextWindowButton(True, True);
887 #ifndef   HAVE_STRFTIME
888     else if (be->window == frame.clock) {
889       XClearWindow(display, frame.clock);
890       checkClock(True, True);
891     }
892 #endif // HAVE_STRFTIME
893     else if (! on_top) {
894       Window w[1] = { frame.window };
895       screen.raiseWindows(w, 1);
896     }
897   } else if (be->button == 2 && (! on_top)) {
898     XLowerWindow(display, frame.window);
899   } else if (be->button == 3) {
900     if (! toolbarmenu->isVisible()) {
901       int x, y;
902
903       x = be->x_root - (toolbarmenu->getWidth() / 2);
904       y = be->y_root - (toolbarmenu->getHeight() / 2);
905
906       if (x < 0)
907         x = 0;
908       else if (x + toolbarmenu->getWidth() > screen.size().w())
909         x = screen.size().w() - toolbarmenu->getWidth();
910
911       if (y < 0)
912         y = 0;
913       else if (y + toolbarmenu->getHeight() > screen.size().h())
914         y = screen.size().h() - toolbarmenu->getHeight();
915
916       toolbarmenu->move(x, y);
917       toolbarmenu->show();
918     } else
919       toolbarmenu->hide();
920   }
921 }
922
923
924
925 void Toolbar::buttonReleaseEvent(XButtonEvent *re) {
926   if (re->button == 1) {
927     if (re->window == frame.psbutton) {
928       redrawPrevWorkspaceButton(False, True);
929
930       if (re->x >= 0 && re->x < (signed) frame.button_w &&
931           re->y >= 0 && re->y < (signed) frame.button_w)
932        if (screen.getCurrentWorkspace()->getWorkspaceID() > 0)
933           screen.changeWorkspaceID(screen.getCurrentWorkspace()->
934                                     getWorkspaceID() - 1);
935         else
936           screen.changeWorkspaceID(screen.getWorkspaceCount() - 1);
937     } else if (re->window == frame.nsbutton) {
938       redrawNextWorkspaceButton(False, True);
939
940       if (re->x >= 0 && re->x < (signed) frame.button_w &&
941           re->y >= 0 && re->y < (signed) frame.button_w)
942         if (screen.getCurrentWorkspace()->getWorkspaceID() <
943             screen.getWorkspaceCount() - 1)
944           screen.changeWorkspaceID(screen.getCurrentWorkspace()->
945                                     getWorkspaceID() + 1);
946         else
947           screen.changeWorkspaceID(0);
948     } else if (re->window == frame.pwbutton) {
949       redrawPrevWindowButton(False, True);
950
951       if (re->x >= 0 && re->x < (signed) frame.button_w &&
952           re->y >= 0 && re->y < (signed) frame.button_w)
953         screen.prevFocus();
954     } else if (re->window == frame.nwbutton) {
955       redrawNextWindowButton(False, True);
956
957       if (re->x >= 0 && re->x < (signed) frame.button_w &&
958           re->y >= 0 && re->y < (signed) frame.button_w)
959         screen.nextFocus();
960     } else if (re->window == frame.window_label)
961       screen.raiseFocus();
962 #ifndef   HAVE_STRFTIME
963     else if (re->window == frame.clock) {
964       XClearWindow(display, frame.clock);
965       checkClock(True);
966     }
967 #endif // HAVE_STRFTIME
968   }
969 }
970
971
972 void Toolbar::enterNotifyEvent(XCrossingEvent *) {
973   if (! do_auto_hide)
974     return;
975
976   if (hidden) {
977     if (! hide_timer->isTiming()) hide_timer->start();
978   } else {
979     if (hide_timer->isTiming()) hide_timer->stop();
980   }
981 }
982
983 void Toolbar::leaveNotifyEvent(XCrossingEvent *) {
984   if (! do_auto_hide)
985     return;
986
987   if (hidden) {
988     if (hide_timer->isTiming()) hide_timer->stop();
989   } else if (! toolbarmenu->isVisible()) {
990     if (! hide_timer->isTiming()) hide_timer->start();
991   }
992 }
993
994
995 void Toolbar::exposeEvent(XExposeEvent *ee) {
996   if (ee->window == frame.clock) checkClock(True);
997   else if (ee->window == frame.workspace_label && (! editing))
998     redrawWorkspaceLabel();
999   else if (ee->window == frame.window_label) redrawWindowLabel();
1000   else if (ee->window == frame.psbutton) redrawPrevWorkspaceButton();
1001   else if (ee->window == frame.nsbutton) redrawNextWorkspaceButton();
1002   else if (ee->window == frame.pwbutton) redrawPrevWindowButton();
1003   else if (ee->window == frame.nwbutton) redrawNextWindowButton();
1004 }
1005
1006
1007 void Toolbar::keyPressEvent(XKeyEvent *ke) {
1008   if (ke->window == frame.workspace_label && editing) {
1009     openbox.grab();
1010
1011     if (! new_workspace_name) {
1012       new_workspace_name = new char[128];
1013       new_name_pos = 0;
1014
1015       if (! new_workspace_name) return;
1016     }
1017
1018     KeySym ks;
1019     char keychar[1];
1020     XLookupString(ke, keychar, 1, &ks, 0);
1021
1022     // either we are told to end with a return or we hit the end of the buffer
1023     if (ks == XK_Return || new_name_pos == 127) {
1024       *(new_workspace_name + new_name_pos) = 0;
1025
1026       editing = False;
1027
1028       openbox.setNoFocus(False);
1029       if (openbox.getFocusedWindow()) {
1030         openbox.getFocusedWindow()->setInputFocus();
1031         openbox.getFocusedWindow()->setFocusFlag(True);
1032       } else {
1033         XSetInputFocus(display, PointerRoot, None, CurrentTime);
1034       }
1035       // check to make sure that new_name[0] != 0... otherwise we have a null
1036       // workspace name which causes serious problems, especially for the
1037       // Openbox::LoadRC() method.
1038       if (*new_workspace_name) {
1039         screen.getCurrentWorkspace()->setName(new_workspace_name);
1040         screen.getCurrentWorkspace()->getMenu()->hide();
1041         screen.getWorkspacemenu()->
1042           remove(screen.getCurrentWorkspace()->getWorkspaceID() + 2);
1043         screen.getWorkspacemenu()->
1044           insert(screen.getCurrentWorkspace()->getName(),
1045                  screen.getCurrentWorkspace()->getMenu(),
1046                  screen.getCurrentWorkspace()->getWorkspaceID() + 2);
1047         screen.getWorkspacemenu()->update();
1048       }
1049
1050       delete [] new_workspace_name;
1051       new_workspace_name = (char *) 0;
1052       new_name_pos = 0;
1053
1054       // reset the background to that of the workspace label (its normal
1055       // setting)
1056       Pixmap tmp = frame.wlabel;
1057       BTexture *texture = &(screen.getToolbarStyle()->label);
1058       if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
1059         frame.wlabel = None;
1060         XSetWindowBackground(display, frame.workspace_label,
1061                             texture->getColor()->getPixel());
1062       } else {
1063         frame.wlabel =
1064           image_ctrl->renderImage(frame.workspace_label_w, frame.label_h, texture);
1065         XSetWindowBackgroundPixmap(display, frame.workspace_label, frame.wlabel);
1066       }
1067       if (tmp) image_ctrl->removeImage(tmp);
1068   
1069       reconfigure();
1070     } else if (! (ks == XK_Shift_L || ks == XK_Shift_R ||
1071                   ks == XK_Control_L || ks == XK_Control_R ||
1072                   ks == XK_Caps_Lock || ks == XK_Shift_Lock ||
1073                   ks == XK_Meta_L || ks == XK_Meta_R ||
1074                   ks == XK_Alt_L || ks == XK_Alt_R ||
1075                   ks == XK_Super_L || ks == XK_Super_R ||
1076                   ks == XK_Hyper_L || ks == XK_Hyper_R)) {
1077       if (ks == XK_BackSpace) {
1078         if (new_name_pos > 0) {
1079           --new_name_pos;
1080           *(new_workspace_name + new_name_pos) = '\0';
1081         } else {
1082           *new_workspace_name = '\0';
1083         }
1084       } else {
1085         *(new_workspace_name + new_name_pos) = *keychar;
1086         ++new_name_pos;
1087         *(new_workspace_name + new_name_pos) = '\0';
1088       }
1089
1090       XClearWindow(display, frame.workspace_label);
1091       int l = strlen(new_workspace_name), tw, x;
1092
1093       if (i18n->multibyte()) {
1094         XRectangle ink, logical;
1095         XmbTextExtents(screen.getToolbarStyle()->fontset,
1096                        new_workspace_name, l, &ink, &logical);
1097         tw = logical.width;
1098       } else {
1099         tw = XTextWidth(screen.getToolbarStyle()->font,
1100                         new_workspace_name, l);
1101       }
1102       x = (frame.workspace_label_w - tw) / 2;
1103
1104       if (x < (signed) frame.bevel_w) x = frame.bevel_w;
1105
1106       WindowStyle *style = screen.getWindowStyle();
1107       if (i18n->multibyte())
1108         XmbDrawString(display, frame.workspace_label, style->fontset,
1109                       style->l_text_focus_gc, x,
1110                       (1 - style->fontset_extents->max_ink_extent.y),
1111                       new_workspace_name, l);
1112       else
1113         XDrawString(display, frame.workspace_label, style->l_text_focus_gc, x,
1114                     (style->font->ascent + 1),
1115                     new_workspace_name, l);
1116       
1117       XDrawRectangle(display, frame.workspace_label,
1118                      screen.getWindowStyle()->l_text_focus_gc, x + tw, 0, 1,
1119                      frame.label_h - 1);
1120     }
1121     
1122     openbox.ungrab();
1123   }
1124 }
1125
1126
1127 void Toolbar::timeout(void) {
1128   checkClock(True);
1129
1130   timeval now;
1131   gettimeofday(&now, 0);
1132   clock_timer->setTimeout((60 - (now.tv_sec % 60)) * 1000);
1133 }
1134
1135
1136 void Toolbar::HideHandler::timeout(void) {
1137   toolbar->hidden = ! toolbar->hidden;
1138   if (toolbar->hidden)
1139     XMoveWindow(toolbar->display, toolbar->frame.window,
1140                 toolbar->frame.x_hidden, toolbar->frame.y_hidden);
1141   else
1142     XMoveWindow(toolbar->display, toolbar->frame.window,
1143                 toolbar->frame.x, toolbar->frame.y);
1144 }
1145
1146
1147 Toolbarmenu::Toolbarmenu(Toolbar &tb) : Basemenu(tb.screen), toolbar(tb) {
1148   setLabel(i18n->getMessage(ToolbarSet, ToolbarToolbarTitle, "Toolbar"));
1149   setInternalMenu();
1150
1151   placementmenu = new Placementmenu(*this);
1152
1153   insert(i18n->getMessage(CommonSet, CommonPlacementTitle, "Placement"),
1154          placementmenu);
1155   insert(i18n->getMessage(CommonSet, CommonAlwaysOnTop, "Always on top"), 1);
1156   insert(i18n->getMessage(CommonSet, CommonAutoHide, "Auto hide"), 2);
1157   insert(i18n->getMessage(ToolbarSet, ToolbarEditWkspcName,
1158                           "Edit current workspace name"), 3);
1159
1160   update();
1161
1162   if (toolbar.isOnTop()) setItemSelected(1, True);
1163   if (toolbar.doAutoHide()) setItemSelected(2, True);
1164 }
1165
1166
1167 Toolbarmenu::~Toolbarmenu(void) {
1168   delete placementmenu;
1169 }
1170
1171
1172 void Toolbarmenu::itemSelected(int button, int index) {
1173   if (button != 1)
1174     return;
1175
1176   BasemenuItem *item = find(index);
1177   if (! item) return;
1178
1179   switch (item->function()) {
1180   case 1: { // always on top
1181     Bool change = ((toolbar.isOnTop()) ? False : True);
1182     toolbar.on_top = change;
1183     setItemSelected(1, change);
1184
1185     if (toolbar.isOnTop()) toolbar.screen.raiseWindows((Window *) 0, 0);
1186     break;
1187   }
1188
1189   case 2: { // auto hide
1190     Bool change = ((toolbar.doAutoHide()) ?  False : True);
1191     toolbar.do_auto_hide = change;
1192     setItemSelected(2, change);
1193
1194 #ifdef    SLIT
1195     toolbar.screen.getSlit()->reposition();
1196 #endif // SLIT
1197     break;
1198   }
1199
1200   case 3: { // edit current workspace name
1201     toolbar.edit();
1202     hide();
1203
1204     break;
1205   }
1206   } // switch
1207 }
1208
1209
1210 void Toolbarmenu::internal_hide(void) {
1211   Basemenu::internal_hide();
1212   if (toolbar.doAutoHide() && ! toolbar.isEditing())
1213     toolbar.hide_handler.timeout();
1214 }
1215
1216
1217 void Toolbarmenu::reconfigure(void) {
1218   placementmenu->reconfigure();
1219
1220   Basemenu::reconfigure();
1221 }
1222
1223
1224 Toolbarmenu::Placementmenu::Placementmenu(Toolbarmenu &tm)
1225   : Basemenu(tm.toolbar.screen), toolbarmenu(tm) {
1226   setLabel(i18n->getMessage(ToolbarSet, ToolbarToolbarPlacement,
1227                             "Toolbar Placement"));
1228   setInternalMenu();
1229   setMinimumSublevels(3);
1230
1231   insert(i18n->getMessage(CommonSet, CommonPlacementTopLeft,
1232                           "Top Left"), Toolbar::TopLeft);
1233   insert(i18n->getMessage(CommonSet, CommonPlacementBottomLeft,
1234                           "Bottom Left"), Toolbar::BottomLeft);
1235   insert(i18n->getMessage(CommonSet, CommonPlacementTopCenter,
1236                           "Top Center"), Toolbar::TopCenter);
1237   insert(i18n->getMessage(CommonSet, CommonPlacementBottomCenter,
1238                           "Bottom Center"), Toolbar::BottomCenter);
1239   insert(i18n->getMessage(CommonSet, CommonPlacementTopRight,
1240                           "Top Right"), Toolbar::TopRight);
1241   insert(i18n->getMessage(CommonSet, CommonPlacementBottomRight,
1242                           "Bottom Right"), Toolbar::BottomRight);
1243   update();
1244 }
1245
1246
1247 void Toolbarmenu::Placementmenu::itemSelected(int button, int index) {
1248   if (button != 1)
1249     return;
1250
1251   BasemenuItem *item = find(index);
1252   if (! item) return;
1253
1254   toolbarmenu.toolbar.screen.saveToolbarPlacement(item->function());
1255   hide();
1256   toolbarmenu.toolbar.reconfigure();
1257
1258 #ifdef    SLIT
1259   // reposition the slit as well to make sure it doesn't intersect the
1260   // toolbar
1261   toolbarmenu.toolbar.screen.getSlit()->reposition();
1262 #endif // SLIT
1263 }