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