]> icculus.org git repositories - mikachu/openbox.git/blob - src/Slit.cc
Using some references instead of pointers for the menus.
[mikachu/openbox.git] / src / Slit.cc
1 // Slit.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 #ifdef    SLIT
34
35 #include <X11/keysym.h>
36
37 #include "i18n.h"
38 #include "openbox.h"
39 #include "Image.h"
40 #include "Screen.h"
41 #include "Slit.h"
42 #include "Toolbar.h"
43
44
45 Slit::Slit(BScreen *scr) {
46   screen = scr;
47   openbox = screen->getOpenbox();
48
49   on_top = screen->isSlitOnTop();
50   hidden = do_auto_hide = screen->doSlitAutoHide();
51
52   display = screen->getBaseDisplay()->getXDisplay();
53   frame.window = frame.pixmap = None;
54
55   timer = new BTimer(*openbox, *this);
56   timer->setTimeout(openbox->getAutoRaiseDelay());
57   timer->fireOnce(True);
58
59   clientList = new LinkedList<SlitClient>;
60
61   slitmenu = new Slitmenu(*this);
62
63   XSetWindowAttributes attrib;
64   unsigned long create_mask = CWBackPixmap | CWBackPixel | CWBorderPixel |
65                               CWColormap | CWOverrideRedirect | CWEventMask;
66   attrib.background_pixmap = None;
67   attrib.background_pixel = attrib.border_pixel =
68     screen->getBorderColor()->getPixel();
69   attrib.colormap = screen->getColormap();
70   attrib.override_redirect = True;
71   attrib.event_mask = SubstructureRedirectMask | ButtonPressMask |
72                       EnterWindowMask | LeaveWindowMask;
73
74   frame.x = frame.y = 0;
75   frame.width = frame.height = 1;
76
77   frame.window =
78     XCreateWindow(display, screen->getRootWindow(), frame.x, frame.y,
79                   frame.width, frame.height, screen->getBorderWidth(),
80                   screen->getDepth(), InputOutput, screen->getVisual(),
81                   create_mask, &attrib);
82   openbox->saveSlitSearch(frame.window, this);
83
84   reconfigure();
85 }
86
87
88 Slit::~Slit() {
89   openbox->grab();
90
91   if (timer->isTiming()) timer->stop();
92   delete timer;
93
94   delete clientList;
95   delete slitmenu;
96
97   screen->getImageControl()->removeImage(frame.pixmap);
98
99   openbox->removeSlitSearch(frame.window);
100
101   XDestroyWindow(display, frame.window);
102
103   openbox->ungrab();
104 }
105
106
107 void Slit::addClient(Window w) {
108   openbox->grab();
109
110   if (openbox->validateWindow(w)) {
111     SlitClient *client = new SlitClient;
112     client->client_window = w;
113
114     XWMHints *wmhints = XGetWMHints(display, w);
115
116     if (wmhints) {
117       if ((wmhints->flags & IconWindowHint) &&
118           (wmhints->icon_window != None)) {
119         XMoveWindow(display, client->client_window, screen->getWidth() + 10,
120                     screen->getHeight() + 10);
121         XMapWindow(display, client->client_window);
122
123         client->icon_window = wmhints->icon_window;
124         client->window = client->icon_window;
125       } else {
126         client->icon_window = None;
127         client->window = client->client_window;
128       }
129
130       XFree(wmhints);
131     } else {
132       client->icon_window = None;
133       client->window = client->client_window;
134     }
135
136     XWindowAttributes attrib;
137     if (XGetWindowAttributes(display, client->window, &attrib)) {
138       client->width = attrib.width;
139       client->height = attrib.height;
140     } else {
141       client->width = client->height = 64;
142     }
143
144     XSetWindowBorderWidth(display, client->window, 0);
145
146     XSelectInput(display, frame.window, NoEventMask);
147     XSelectInput(display, client->window, NoEventMask);
148
149     XReparentWindow(display, client->window, frame.window, 0, 0);
150     XMapRaised(display, client->window);
151     XChangeSaveSet(display, client->window, SetModeInsert);
152
153     XSelectInput(display, frame.window, SubstructureRedirectMask |
154                  ButtonPressMask | EnterWindowMask | LeaveWindowMask);
155     XSelectInput(display, client->window, StructureNotifyMask |
156                  SubstructureNotifyMask | EnterWindowMask);
157     XFlush(display);
158
159     clientList->insert(client);
160
161     openbox->saveSlitSearch(client->client_window, this);
162     openbox->saveSlitSearch(client->icon_window, this);
163     reconfigure();
164   }
165
166   openbox->ungrab();
167 }
168
169
170 void Slit::removeClient(SlitClient *client, Bool remap) {
171   openbox->removeSlitSearch(client->client_window);
172   openbox->removeSlitSearch(client->icon_window);
173   clientList->remove(client);
174
175   screen->removeNetizen(client->window);
176
177   if (remap && openbox->validateWindow(client->window)) {
178     XSelectInput(display, frame.window, NoEventMask);
179     XSelectInput(display, client->window, NoEventMask);
180     XReparentWindow(display, client->window, screen->getRootWindow(),
181                     client->x, client->y);
182     XChangeSaveSet(display, client->window, SetModeDelete);
183     XSelectInput(display, frame.window, SubstructureRedirectMask |
184                  ButtonPressMask | EnterWindowMask | LeaveWindowMask);
185     XFlush(display);
186   }
187
188   delete client;
189   client = (SlitClient *) 0;
190 }
191
192
193 void Slit::removeClient(Window w, Bool remap) {
194   openbox->grab();
195
196   Bool reconf = False;
197
198   LinkedListIterator<SlitClient> it(clientList);
199   for (SlitClient *tmp = it.current(); tmp; it++, tmp = it.current()) {
200     if (tmp->window == w) {
201       removeClient(tmp, remap);
202       reconf = True;
203
204       break;
205     }
206   }
207
208   if (reconf) reconfigure();
209
210   openbox->ungrab();
211 }
212
213
214 void Slit::reconfigure(void) {
215   frame.width = 0;
216   frame.height = 0;
217   LinkedListIterator<SlitClient> it(clientList);
218   SlitClient *client;
219
220   switch (screen->getSlitDirection()) {
221   case Vertical:
222     for (client = it.current(); client; it++, client = it.current()) {
223       frame.height += client->height + screen->getBevelWidth();
224
225       if (frame.width < client->width)
226         frame.width = client->width;
227     }
228
229     if (frame.width < 1)
230       frame.width = 1;
231     else
232       frame.width += (screen->getBevelWidth() * 2);
233
234     if (frame.height < 1)
235       frame.height = 1;
236     else
237       frame.height += screen->getBevelWidth();
238
239     break;
240
241   case Horizontal:
242     for (client = it.current(); client; it++, client = it.current()) {
243       frame.width += client->width + screen->getBevelWidth();
244
245       if (frame.height < client->height)
246         frame.height = client->height;
247     }
248
249     if (frame.width < 1)
250       frame.width = 1;
251     else
252       frame.width += screen->getBevelWidth();
253
254     if (frame.height < 1)
255       frame.height = 1;
256     else
257       frame.height += (screen->getBevelWidth() * 2);
258
259     break;
260   }
261
262   reposition();
263
264   XSetWindowBorderWidth(display ,frame.window, screen->getBorderWidth());
265   XSetWindowBorder(display, frame.window,
266                    screen->getBorderColor()->getPixel());
267
268   if (! clientList->count())
269     XUnmapWindow(display, frame.window);
270   else
271     XMapWindow(display, frame.window);
272
273   Pixmap tmp = frame.pixmap;
274   BImageControl *image_ctrl = screen->getImageControl();
275   BTexture *texture = &(screen->getToolbarStyle()->toolbar);
276   if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
277     frame.pixmap = None;
278     XSetWindowBackground(display, frame.window,
279                          texture->getColor()->getPixel());
280   } else {
281     frame.pixmap = image_ctrl->renderImage(frame.width, frame.height,
282                                            texture);
283     XSetWindowBackgroundPixmap(display, frame.window, frame.pixmap);
284   }
285   if (tmp) image_ctrl->removeImage(tmp);
286   XClearWindow(display, frame.window);
287
288   int x, y;
289   it.reset();
290
291   switch (screen->getSlitDirection()) {
292   case Vertical:
293     x = 0;
294     y = screen->getBevelWidth();
295
296     for (client = it.current(); client; it++, client = it.current()) {
297       x = (frame.width - client->width) / 2;
298
299       XMoveResizeWindow(display, client->window, x, y,
300                         client->width, client->height);
301       XMapWindow(display, client->window);
302
303       // for ICCCM compliance
304       client->x = x;
305       client->y = y;
306
307       XEvent event;
308       event.type = ConfigureNotify;
309
310       event.xconfigure.display = display;
311       event.xconfigure.event = client->window;
312       event.xconfigure.window = client->window;
313       event.xconfigure.x = x;
314       event.xconfigure.y = y;
315       event.xconfigure.width = client->width;
316       event.xconfigure.height = client->height;
317       event.xconfigure.border_width = 0;
318       event.xconfigure.above = frame.window;
319       event.xconfigure.override_redirect = False;
320
321       XSendEvent(display, client->window, False, StructureNotifyMask, &event);
322
323       y += client->height + screen->getBevelWidth();
324     }
325
326     break;
327
328   case Horizontal:
329     x = screen->getBevelWidth();
330     y = 0;
331
332     for (client = it.current(); client; it++, client = it.current()) {
333       y = (frame.height - client->height) / 2;
334
335       XMoveResizeWindow(display, client->window, x, y,
336                         client->width, client->height);
337       XMapWindow(display, client->window);
338
339       // for ICCCM compliance
340       client->x = x;
341       client->y = y;
342
343       XEvent event;
344       event.type = ConfigureNotify;
345
346       event.xconfigure.display = display;
347       event.xconfigure.event = client->window;
348       event.xconfigure.window = client->window;
349       event.xconfigure.x = x;
350       event.xconfigure.y = y;
351       event.xconfigure.width = client->width;
352       event.xconfigure.height = client->height;
353       event.xconfigure.border_width = 0;
354       event.xconfigure.above = frame.window;
355       event.xconfigure.override_redirect = False;
356
357       XSendEvent(display, client->window, False, StructureNotifyMask, &event);
358
359       x += client->width + screen->getBevelWidth();
360     }
361
362     break;
363   }
364
365   slitmenu->reconfigure();
366 }
367
368
369 void Slit::reposition(void) {
370   // place the slit in the appropriate place
371   switch (screen->getSlitPlacement()) {
372   case TopLeft:
373     frame.x = 0;
374     frame.y = 0;
375     if (screen->getSlitDirection() == Vertical) {
376       frame.x_hidden = screen->getBevelWidth() - screen->getBorderWidth()
377                        - frame.width;
378       frame.y_hidden = 0;
379     } else {
380       frame.x_hidden = 0;
381       frame.y_hidden = screen->getBevelWidth() - screen->getBorderWidth()
382                        - frame.height;
383     }
384     break;
385
386   case CenterLeft:
387     frame.x = 0;
388     frame.y = (screen->getHeight() - frame.height) / 2;
389     frame.x_hidden = screen->getBevelWidth() - screen->getBorderWidth()
390                      - frame.width;
391     frame.y_hidden = frame.y;
392     break;
393
394   case BottomLeft:
395     frame.x = 0;
396     frame.y = screen->getHeight() - frame.height
397       - (screen->getBorderWidth() * 2);
398     if (screen->getSlitDirection() == Vertical) {
399       frame.x_hidden = screen->getBevelWidth() - screen->getBorderWidth()
400                        - frame.width;
401       frame.y_hidden = frame.y;
402     } else {
403       frame.x_hidden = 0;
404       frame.y_hidden = screen->getHeight() - screen->getBevelWidth()
405                        - screen->getBorderWidth();
406     }
407     break;
408
409   case TopCenter:
410     frame.x = (screen->getWidth() - frame.width) / 2;
411     frame.y = 0;
412     frame.x_hidden = frame.x;
413     frame.y_hidden = screen->getBevelWidth() - screen->getBorderWidth()
414                      - frame.height;
415     break;
416
417   case BottomCenter:
418     frame.x = (screen->getWidth() - frame.width) / 2;
419     frame.y = screen->getHeight() - frame.height
420       - (screen->getBorderWidth() * 2);
421     frame.x_hidden = frame.x;
422     frame.y_hidden = screen->getHeight() - screen->getBevelWidth()
423                      - screen->getBorderWidth();
424     break;
425
426   case TopRight:
427     frame.x = screen->getWidth() - frame.width
428       - (screen->getBorderWidth() * 2);
429     frame.y = 0;
430     if (screen->getSlitDirection() == Vertical) {
431       frame.x_hidden = screen->getWidth() - screen->getBevelWidth()
432                        - screen->getBorderWidth();
433       frame.y_hidden = 0;
434     } else {
435       frame.x_hidden = frame.x;
436       frame.y_hidden = screen->getBevelWidth() - screen->getBorderWidth()
437                        - frame.height;
438     }
439     break;
440
441   case CenterRight:
442   default:
443     frame.x = screen->getWidth() - frame.width
444       - (screen->getBorderWidth() * 2);
445     frame.y = (screen->getHeight() - frame.height) / 2;
446     frame.x_hidden = screen->getWidth() - screen->getBevelWidth()
447                      - screen->getBorderWidth();
448     frame.y_hidden = frame.y;
449     break;
450
451   case BottomRight:
452     frame.x = screen->getWidth() - frame.width
453       - (screen->getBorderWidth() * 2);
454     frame.y = screen->getHeight() - frame.height
455       - (screen->getBorderWidth() * 2);
456     if (screen->getSlitDirection() == Vertical) {
457       frame.x_hidden = screen->getWidth() - screen->getBevelWidth()
458                        - screen->getBorderWidth();
459       frame.y_hidden = frame.y;
460     } else {
461       frame.x_hidden = frame.x;
462       frame.y_hidden = screen->getHeight() - screen->getBevelWidth()
463                        - screen->getBorderWidth();
464     }
465     break;
466   }
467
468   Toolbar *tbar = screen->getToolbar();
469   int sw = frame.width + (screen->getBorderWidth() * 2),
470       sh = frame.height + (screen->getBorderWidth() * 2),
471       tw = tbar->getWidth() + screen->getBorderWidth(),
472       th = tbar->getHeight() + screen->getBorderWidth();
473
474   if (tbar->getX() < frame.x + sw && tbar->getX() + tw > frame.x &&
475       tbar->getY() < frame.y + sh && tbar->getY() + th > frame.y) {
476     if (frame.y < th) {
477       frame.y += tbar->getExposedHeight();
478       if (screen->getSlitDirection() == Vertical)
479         frame.y_hidden += tbar->getExposedHeight();
480       else
481         frame.y_hidden = frame.y;
482     } else {
483       frame.y -= tbar->getExposedHeight();
484       if (screen->getSlitDirection() == Vertical)
485         frame.y_hidden -= tbar->getExposedHeight();
486       else
487         frame.y_hidden = frame.y;
488     }
489   }
490
491   if (hidden)
492     XMoveResizeWindow(display, frame.window, frame.x_hidden,
493                       frame.y_hidden, frame.width, frame.height);
494   else
495     XMoveResizeWindow(display, frame.window, frame.x,
496                       frame.y, frame.width, frame.height);
497 }
498
499
500 void Slit::shutdown(void) {
501   while (clientList->count())
502     removeClient(clientList->first());
503 }
504
505
506 void Slit::buttonPressEvent(XButtonEvent *e) {
507   if (e->window != frame.window) return;
508
509   if (e->button == Button1 && (! on_top)) {
510     Window w[1] = { frame.window };
511     screen->raiseWindows(w, 1);
512   } else if (e->button == Button2 && (! on_top)) {
513     XLowerWindow(display, frame.window);
514   } else if (e->button == Button3) {
515     if (! slitmenu->isVisible()) {
516       int x, y;
517
518       x = e->x_root - (slitmenu->getWidth() / 2);
519       y = e->y_root - (slitmenu->getHeight() / 2);
520
521       if (x < 0)
522         x = 0;
523       else if (x + slitmenu->getWidth() > screen->getWidth())
524         x = screen->getWidth() - slitmenu->getWidth();
525
526       if (y < 0)
527         y = 0;
528       else if (y + slitmenu->getHeight() > screen->getHeight())
529         y = screen->getHeight() - slitmenu->getHeight();
530
531       slitmenu->move(x, y);
532       slitmenu->show();
533     } else {
534       slitmenu->hide();
535     }
536   }
537 }
538
539
540 void Slit::enterNotifyEvent(XCrossingEvent *) {
541   if (! do_auto_hide)
542     return;
543
544   if (hidden) {
545     if (! timer->isTiming()) timer->start();
546   } else {
547     if (timer->isTiming()) timer->stop();
548   }
549 }
550
551
552 void Slit::leaveNotifyEvent(XCrossingEvent *) {
553   if (! do_auto_hide)
554     return;
555
556   if (hidden) {
557     if (timer->isTiming()) timer->stop();
558   } else if (! slitmenu->isVisible()) {
559     if (! timer->isTiming()) timer->start();
560   }
561 }
562
563
564 void Slit::configureRequestEvent(XConfigureRequestEvent *e) {
565   openbox->grab();
566
567   if (openbox->validateWindow(e->window)) {
568     Bool reconf = False;
569     XWindowChanges xwc;
570
571     xwc.x = e->x;
572     xwc.y = e->y;
573     xwc.width = e->width;
574     xwc.height = e->height;
575     xwc.border_width = 0;
576     xwc.sibling = e->above;
577     xwc.stack_mode = e->detail;
578
579     XConfigureWindow(display, e->window, e->value_mask, &xwc);
580
581     LinkedListIterator<SlitClient> it(clientList);
582     SlitClient *client = it.current();
583     for (; client; it++, client = it.current())
584       if (client->window == e->window)
585         if (client->width != ((unsigned) e->width) ||
586             client->height != ((unsigned) e->height)) {
587           client->width = (unsigned) e->width;
588           client->height = (unsigned) e->height;
589
590           reconf = True;
591
592           break;
593         }
594
595     if (reconf) reconfigure();
596
597   }
598
599   openbox->ungrab();
600 }
601
602
603 void Slit::timeout(void) {
604   hidden = ! hidden;
605   if (hidden)
606     XMoveWindow(display, frame.window, frame.x_hidden, frame.y_hidden);
607   else
608     XMoveWindow(display, frame.window, frame.x, frame.y);
609 }
610
611
612 Slitmenu::Slitmenu(Slit &sl) : Basemenu(*sl.screen), slit(sl) {
613   setLabel(i18n->getMessage(SlitSet, SlitSlitTitle, "Slit"));
614   setInternalMenu();
615
616   directionmenu = new Directionmenu(*this);
617   placementmenu = new Placementmenu(*this);
618
619   insert(i18n->getMessage(CommonSet, CommonDirectionTitle, "Direction"),
620          directionmenu);
621   insert(i18n->getMessage(CommonSet, CommonPlacementTitle, "Placement"),
622          placementmenu);
623   insert(i18n->getMessage(CommonSet, CommonAlwaysOnTop, "Always on top"), 1);
624   insert(i18n->getMessage(CommonSet, CommonAutoHide, "Auto hide"), 2);
625
626   update();
627
628   if (slit.isOnTop()) setItemSelected(2, True);
629   if (slit.doAutoHide()) setItemSelected(3, True);
630 }
631
632
633 Slitmenu::~Slitmenu(void) {
634   delete directionmenu;
635   delete placementmenu;
636 }
637
638
639 void Slitmenu::itemSelected(int button, int index) {
640   if (button != 1)
641     return;
642
643   BasemenuItem *item = find(index);
644   if (! item) return;
645
646   switch (item->function()) {
647   case 1: { // always on top
648     Bool change = ((slit.isOnTop()) ?  False : True);
649     slit.on_top = change;
650     setItemSelected(2, change);
651
652     if (slit.isOnTop()) slit.screen->raiseWindows((Window *) 0, 0);
653     break;
654   }
655
656   case 2: { // auto hide
657     Bool change = ((slit.doAutoHide()) ?  False : True);
658     slit.do_auto_hide = change;
659     setItemSelected(3, change);
660
661     break;
662   }
663   } // switch
664 }
665
666
667 void Slitmenu::internal_hide(void) {
668   Basemenu::internal_hide();
669   if (slit.doAutoHide())
670     slit.timeout();
671 }
672
673
674 void Slitmenu::reconfigure(void) {
675   directionmenu->reconfigure();
676   placementmenu->reconfigure();
677
678   Basemenu::reconfigure();
679 }
680
681
682 Slitmenu::Directionmenu::Directionmenu(Slitmenu &sm)
683   : Basemenu(*sm.slit.screen), slitmenu(sm) {
684   setLabel(i18n->getMessage(SlitSet, SlitSlitDirection, "Slit Direction"));
685   setInternalMenu();
686
687   insert(i18n->getMessage(CommonSet, CommonDirectionHoriz, "Horizontal"),
688          Slit::Horizontal);
689   insert(i18n->getMessage(CommonSet, CommonDirectionVert, "Vertical"),
690          Slit::Vertical);
691
692   update();
693
694   if (sm.slit.screen->getSlitDirection() == Slit::Horizontal)
695     setItemSelected(0, True);
696   else
697     setItemSelected(1, True);
698 }
699
700
701 void Slitmenu::Directionmenu::itemSelected(int button, int index) {
702   if (button != 1)
703     return;
704
705   BasemenuItem *item = find(index);
706   if (! item) return;
707
708   slitmenu.slit.screen->saveSlitDirection(item->function());
709
710   if (item->function() == Slit::Horizontal) {
711     setItemSelected(0, True);
712     setItemSelected(1, False);
713   } else {
714     setItemSelected(0, False);
715     setItemSelected(1, True);
716   }
717
718   hide();
719   slitmenu.slit.reconfigure();
720 }
721
722
723 Slitmenu::Placementmenu::Placementmenu(Slitmenu &sm)
724   : Basemenu(*sm.slit.screen), slitmenu(sm) {
725
726   setLabel(i18n->getMessage(SlitSet, SlitSlitPlacement, "Slit Placement"));
727   setMinimumSublevels(3);
728   setInternalMenu();
729
730   insert(i18n->getMessage(CommonSet, CommonPlacementTopLeft, "Top Left"),
731          Slit::TopLeft);
732   insert(i18n->getMessage(CommonSet, CommonPlacementCenterLeft, "Center Left"),
733          Slit::CenterLeft);
734   insert(i18n->getMessage(CommonSet, CommonPlacementBottomLeft, "Bottom Left"),
735          Slit::BottomLeft);
736   insert(i18n->getMessage(CommonSet, CommonPlacementTopCenter, "Top Center"),
737          Slit::TopCenter);
738   insert("");
739   insert(i18n->getMessage(CommonSet, CommonPlacementBottomCenter, 
740                           "Bottom Center"),
741          Slit::BottomCenter);
742   insert(i18n->getMessage(CommonSet, CommonPlacementTopRight, "Top Right"),
743          Slit::TopRight);
744   insert(i18n->getMessage(CommonSet, CommonPlacementCenterRight,
745                           "Center Right"),
746          Slit::CenterRight);
747   insert(i18n->getMessage(CommonSet, CommonPlacementBottomRight,
748                           "Bottom Right"),
749          Slit::BottomRight);
750
751   update();
752 }
753
754
755 void Slitmenu::Placementmenu::itemSelected(int button, int index) {
756   if (button != 1)
757     return;
758
759   BasemenuItem *item = find(index);
760   if (! (item && item->function())) return;
761
762   slitmenu.slit.screen->saveSlitPlacement(item->function());
763   hide();
764   slitmenu.slit.reconfigure();
765 }
766
767
768 #endif // SLIT