]> icculus.org git repositories - mikachu/openbox.git/blob - src/Slit.cc
import from bb-cvs
[mikachu/openbox.git] / src / Slit.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // Slit.cc for Blackbox - an X11 Window manager
3 // Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
4 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a
7 // copy of this software and associated documentation files (the "Software"),
8 // to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 // and/or sell copies of the Software, and to permit persons to whom the
11 // Software is furnished to do so, subject to the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 // DEALINGS IN THE SOFTWARE.
23
24 #ifdef    HAVE_CONFIG_H
25 #  include "../config.h"
26 #endif // HAVE_CONFIG_H
27
28 extern "C" {
29 #include <X11/keysym.h>
30 }
31
32 #include "i18n.hh"
33 #include "blackbox.hh"
34 #include "Image.hh"
35 #include "Screen.hh"
36 #include "Slit.hh"
37 #include "Toolbar.hh"
38
39
40 Slit::Slit(BScreen *scr) {
41   screen = scr;
42   blackbox = screen->getBlackbox();
43
44   on_top = screen->isSlitOnTop();
45   hidden = do_auto_hide = screen->doSlitAutoHide();
46
47   display = screen->getBaseDisplay()->getXDisplay();
48   frame.window = frame.pixmap = None;
49
50   timer = new BTimer(blackbox, this);
51   timer->setTimeout(blackbox->getAutoRaiseDelay());
52
53   slitmenu = new Slitmenu(this);
54
55   XSetWindowAttributes attrib;
56   unsigned long create_mask = CWBackPixmap | CWBackPixel | CWBorderPixel |
57                               CWColormap | CWOverrideRedirect | CWEventMask;
58   attrib.background_pixmap = None;
59   attrib.background_pixel = attrib.border_pixel =
60     screen->getBorderColor()->pixel();
61   attrib.colormap = screen->getColormap();
62   attrib.override_redirect = True;
63   attrib.event_mask = SubstructureRedirectMask | ButtonPressMask |
64                       EnterWindowMask | LeaveWindowMask;
65
66   frame.rect.setSize(1, 1);
67
68   frame.window =
69     XCreateWindow(display, screen->getRootWindow(),
70                   frame.rect.x(), frame.rect.y(),
71                   frame.rect.width(), frame.rect.height(),
72                   screen->getBorderWidth(), screen->getDepth(), InputOutput,
73                   screen->getVisual(), create_mask, &attrib);
74   blackbox->saveSlitSearch(frame.window, this);
75
76   screen->addStrut(&strut);
77
78   reconfigure();
79 }
80
81
82 Slit::~Slit(void) {
83   delete timer;
84
85   delete slitmenu;
86
87   screen->getImageControl()->removeImage(frame.pixmap);
88
89   blackbox->removeSlitSearch(frame.window);
90
91   XDestroyWindow(display, frame.window);
92 }
93
94
95 void Slit::addClient(Window w) {
96   if (! blackbox->validateWindow(w))
97     return;
98
99   SlitClient *client = new SlitClient;
100   client->client_window = w;
101
102   XWMHints *wmhints = XGetWMHints(display, w);
103
104   if (wmhints) {
105     if ((wmhints->flags & IconWindowHint) &&
106         (wmhints->icon_window != None)) {
107       // some dock apps use separate windows, we need to hide these
108       XMoveWindow(display, client->client_window, screen->getWidth() + 10,
109                   screen->getHeight() + 10);
110       XMapWindow(display, client->client_window);
111
112       client->icon_window = wmhints->icon_window;
113       client->window = client->icon_window;
114     } else {
115       client->icon_window = None;
116       client->window = client->client_window;
117     }
118
119     XFree(wmhints);
120   } else {
121     client->icon_window = None;
122     client->window = client->client_window;
123   }
124
125   XWindowAttributes attrib;
126   if (XGetWindowAttributes(display, client->window, &attrib)) {
127     client->rect.setSize(attrib.width, attrib.height);
128   } else {
129     client->rect.setSize(64, 64);
130   }
131
132   XSetWindowBorderWidth(display, client->window, 0);
133
134   XGrabServer(display);
135   XSelectInput(display, frame.window, NoEventMask);
136   XSelectInput(display, client->window, NoEventMask);
137   XReparentWindow(display, client->window, frame.window, 0, 0);
138   XMapRaised(display, client->window);
139   XChangeSaveSet(display, client->window, SetModeInsert);
140   XSelectInput(display, frame.window, SubstructureRedirectMask |
141                ButtonPressMask | EnterWindowMask | LeaveWindowMask);
142   XSelectInput(display, client->window, StructureNotifyMask |
143                SubstructureNotifyMask | EnterWindowMask);
144
145   XUngrabServer(display);
146
147   clientList.push_back(client);
148
149   blackbox->saveSlitSearch(client->client_window, this);
150   blackbox->saveSlitSearch(client->icon_window, this);
151   reconfigure();
152 }
153
154
155 void Slit::removeClient(SlitClient *client, bool remap) {
156   blackbox->removeSlitSearch(client->client_window);
157   blackbox->removeSlitSearch(client->icon_window);
158   clientList.remove(client);
159
160   screen->removeNetizen(client->window);
161
162   if (remap && blackbox->validateWindow(client->window)) {
163     XGrabServer(display);
164     XSelectInput(display, frame.window, NoEventMask);
165     XSelectInput(display, client->window, NoEventMask);
166     XReparentWindow(display, client->window, screen->getRootWindow(),
167                     client->rect.x(), client->rect.y());
168     XChangeSaveSet(display, client->window, SetModeDelete);
169     XSelectInput(display, frame.window, SubstructureRedirectMask |
170                  ButtonPressMask | EnterWindowMask | LeaveWindowMask);
171     XUngrabServer(display);
172   }
173
174   delete client;
175   client = (SlitClient *) 0;
176 }
177
178
179 struct SlitClientMatch {
180   Window window;
181   SlitClientMatch(Window w): window(w) {}
182   inline bool operator()(const Slit::SlitClient* client) const {
183     return (client->window == window);
184   }
185 };
186
187
188 void Slit::removeClient(Window w, bool remap) {
189   SlitClientList::iterator it = clientList.begin();
190   const SlitClientList::iterator end = clientList.end();
191
192   it = std::find_if(it, end, SlitClientMatch(w));
193   if (it != end) {
194     removeClient(*it, remap);
195     reconfigure();
196   }
197 }
198
199
200 void Slit::reconfigure(void) {
201   SlitClientList::iterator it = clientList.begin();
202   const SlitClientList::iterator end = clientList.end();
203   SlitClient *client;
204
205   unsigned int width = 0, height = 0;
206
207   switch (screen->getSlitDirection()) {
208   case Vertical:
209     for (; it != end; ++it) {
210       client = *it;
211       height += client->rect.height() + screen->getBevelWidth();
212
213       if (width < client->rect.width())
214         width = client->rect.width();
215     }
216
217     if (width < 1)
218       width = 1;
219     else
220       width += (screen->getBevelWidth() * 2);
221
222     if (height < 1)
223       height = 1;
224     else
225       height += screen->getBevelWidth();
226
227     break;
228
229   case Horizontal:
230     for (; it != end; ++it) {
231       client = *it;
232       width += client->rect.width() + screen->getBevelWidth();
233
234       if (height < client->rect.height())
235         height = client->rect.height();
236     }
237
238     if (width < 1)
239       width = 1;
240     else
241       width += screen->getBevelWidth();
242
243     if (height < 1)
244       height = 1;
245     else
246       height += (screen->getBevelWidth() * 2);
247
248     break;
249   }
250   frame.rect.setSize(width, height);
251
252   reposition();
253
254   XSetWindowBorderWidth(display ,frame.window, screen->getBorderWidth());
255   XSetWindowBorder(display, frame.window,
256                    screen->getBorderColor()->pixel());
257
258   if (clientList.empty())
259     XUnmapWindow(display, frame.window);
260   else
261     XMapWindow(display, frame.window);
262
263   BTexture *texture = &(screen->getToolbarStyle()->toolbar);
264   frame.pixmap = texture->render(frame.rect.width(), frame.rect.height(),
265                                  frame.pixmap);
266   if (! frame.pixmap)
267     XSetWindowBackground(display, frame.window, texture->color().pixel());
268   else
269     XSetWindowBackgroundPixmap(display, frame.window, frame.pixmap);
270
271   XClearWindow(display, frame.window);
272
273   it = clientList.begin();
274
275   int x, y;
276
277   switch (screen->getSlitDirection()) {
278   case Vertical:
279     x = 0;
280     y = screen->getBevelWidth();
281
282     for (; it != end; ++it) {
283       client = *it;
284       x = (frame.rect.width() - client->rect.width()) / 2;
285
286       XMoveResizeWindow(display, client->window, x, y,
287                         client->rect.width(), client->rect.height());
288       XMapWindow(display, client->window);
289
290       // for ICCCM compliance
291       client->rect.setPos(x, y);
292
293       XEvent event;
294       event.type = ConfigureNotify;
295
296       event.xconfigure.display = display;
297       event.xconfigure.event = client->window;
298       event.xconfigure.window = client->window;
299       event.xconfigure.x = x;
300       event.xconfigure.y = y;
301       event.xconfigure.width = client->rect.width();
302       event.xconfigure.height = client->rect.height();
303       event.xconfigure.border_width = 0;
304       event.xconfigure.above = frame.window;
305       event.xconfigure.override_redirect = False;
306
307       XSendEvent(display, client->window, False, StructureNotifyMask, &event);
308
309       y += client->rect.height() + screen->getBevelWidth();
310     }
311
312     break;
313
314   case Horizontal:
315     x = screen->getBevelWidth();
316     y = 0;
317
318     for (; it != end; ++it) {
319       client = *it;
320       y = (frame.rect.height() - client->rect.height()) / 2;
321
322       XMoveResizeWindow(display, client->window, x, y,
323                         client->rect.width(), client->rect.height());
324       XMapWindow(display, client->window);
325
326       // for ICCCM compliance
327       client->rect.setPos(x, y);
328
329       XEvent event;
330       event.type = ConfigureNotify;
331
332       event.xconfigure.display = display;
333       event.xconfigure.event = client->window;
334       event.xconfigure.window = client->window;
335       event.xconfigure.x = x;
336       event.xconfigure.y = y;
337       event.xconfigure.width = client->rect.width();
338       event.xconfigure.height = client->rect.height();
339       event.xconfigure.border_width = 0;
340       event.xconfigure.above = frame.window;
341       event.xconfigure.override_redirect = False;
342
343       XSendEvent(display, client->window, False, StructureNotifyMask, &event);
344
345       x += client->rect.width() + screen->getBevelWidth();
346     }
347     break;
348   }
349
350   slitmenu->reconfigure();
351 }
352
353
354 void Slit::updateStrut(void) {
355   strut.top = strut.bottom = strut.left = strut.right = 0;
356
357   if (! clientList.empty()) {
358     switch (screen->getSlitDirection()) {
359     case Vertical:
360       switch (screen->getSlitPlacement()) {
361       case TopCenter:
362         strut.top = getY() + getExposedHeight() +
363                     (screen->getBorderWidth() * 2);
364         break;
365       case BottomCenter:
366         strut.bottom = screen->getHeight() - getY();
367         break;
368       case TopLeft:
369       case CenterLeft:
370       case BottomLeft:
371         strut.left = getExposedWidth() + (screen->getBorderWidth() * 2);
372         break;
373       case TopRight:
374       case CenterRight:
375       case BottomRight:
376         strut.right = getExposedWidth() + (screen->getBorderWidth() * 2);
377         break;
378       }
379       break;
380     case Horizontal:
381       switch (screen->getSlitPlacement()) {
382       case TopCenter:
383       case TopLeft:
384       case TopRight:
385         strut.top = getY() + getExposedHeight() +
386                     (screen->getBorderWidth() * 2);
387         break;
388       case BottomCenter:
389       case BottomLeft:
390       case BottomRight:
391         strut.bottom = screen->getHeight() - getY();
392         break;
393       case CenterLeft:
394         strut.left = getExposedWidth() + (screen->getBorderWidth() * 2);
395         break;
396       case CenterRight:
397         strut.right = getExposedWidth() + (screen->getBorderWidth() * 2);
398         break;
399       }
400       break;
401     }
402   }
403
404   // update area with new Strut info
405   screen->updateAvailableArea();
406 }
407
408
409 void Slit::reposition(void) {
410   // place the slit in the appropriate place
411   switch (screen->getSlitPlacement()) {
412   case TopLeft:
413     frame.rect.setPos(0, 0);
414
415     if (screen->getSlitDirection() == Vertical) {
416       frame.x_hidden = screen->getBevelWidth() - screen->getBorderWidth()
417                        - frame.rect.width();
418       frame.y_hidden = 0;
419     } else {
420       frame.x_hidden = 0;
421       frame.y_hidden = screen->getBevelWidth() - screen->getBorderWidth()
422                        - frame.rect.height();
423     }
424     break;
425
426   case CenterLeft:
427     frame.rect.setPos(0, (screen->getHeight() - frame.rect.height()) / 2);
428
429     frame.x_hidden = screen->getBevelWidth() - screen->getBorderWidth()
430                      - frame.rect.width();
431     frame.y_hidden = frame.rect.y();
432     break;
433
434   case BottomLeft:
435     frame.rect.setPos(0, (screen->getHeight() - frame.rect.height()
436                           - (screen->getBorderWidth() * 2)));
437
438     if (screen->getSlitDirection() == Vertical) {
439       frame.x_hidden = screen->getBevelWidth() - screen->getBorderWidth()
440                        - frame.rect.width();
441       frame.y_hidden = frame.rect.y();
442     } else {
443       frame.x_hidden = 0;
444       frame.y_hidden = screen->getHeight() - screen->getBevelWidth()
445                        - screen->getBorderWidth();
446     }
447     break;
448
449   case TopCenter:
450     frame.rect.setPos((screen->getWidth() - frame.rect.width()) / 2, 0);
451
452     frame.x_hidden = frame.rect.x();
453     frame.y_hidden = screen->getBevelWidth() - screen->getBorderWidth()
454                      - frame.rect.height();
455     break;
456
457   case BottomCenter:
458     frame.rect.setPos((screen->getWidth() - frame.rect.width()) / 2,
459                       (screen->getHeight() - frame.rect.height()
460                        - (screen->getBorderWidth() * 2)));
461     frame.x_hidden = frame.rect.x();
462     frame.y_hidden = screen->getHeight() - screen->getBevelWidth()
463                      - screen->getBorderWidth();
464     break;
465
466   case TopRight:
467     frame.rect.setPos((screen->getWidth() - frame.rect.width()
468                        - (screen->getBorderWidth() * 2)), 0);
469
470     if (screen->getSlitDirection() == Vertical) {
471       frame.x_hidden = screen->getWidth() - screen->getBevelWidth()
472                        - screen->getBorderWidth();
473       frame.y_hidden = 0;
474     } else {
475       frame.x_hidden = frame.rect.x();
476       frame.y_hidden = screen->getBevelWidth() - screen->getBorderWidth()
477                        - frame.rect.height();
478     }
479     break;
480
481   case CenterRight:
482   default:
483     frame.rect.setPos((screen->getWidth() - frame.rect.width()
484                        - (screen->getBorderWidth() * 2)),
485                       (screen->getHeight() - frame.rect.height()) / 2);
486
487     frame.x_hidden = screen->getWidth() - screen->getBevelWidth()
488                      - screen->getBorderWidth();
489     frame.y_hidden = frame.rect.y();
490     break;
491
492   case BottomRight:
493     frame.rect.setPos((screen->getWidth() - frame.rect.width()
494                        - (screen->getBorderWidth() * 2)),
495                       (screen->getHeight() - frame.rect.height()
496                        - (screen->getBorderWidth() * 2)));
497
498     if (screen->getSlitDirection() == Vertical) {
499       frame.x_hidden = screen->getWidth() - screen->getBevelWidth()
500                        - screen->getBorderWidth();
501       frame.y_hidden = frame.rect.y();
502     } else {
503       frame.x_hidden = frame.rect.x();
504       frame.y_hidden = screen->getHeight() - screen->getBevelWidth()
505                        - screen->getBorderWidth();
506     }
507     break;
508   }
509
510   Rect tbar_rect = screen->getToolbar()->getRect();
511   tbar_rect.setSize(tbar_rect.width() + (screen->getBorderWidth() * 2),
512                     tbar_rect.height() + (screen->getBorderWidth() * 2));
513   Rect slit_rect = frame.rect;
514   slit_rect.setSize(slit_rect.width() + (screen->getBorderWidth() * 2),
515                     slit_rect.height() + (screen->getBorderWidth() * 2));
516
517   if (slit_rect.intersects(tbar_rect)) {
518     Toolbar *tbar = screen->getToolbar();
519     frame.y_hidden = frame.rect.y();
520
521     int delta = tbar->getExposedHeight() + (screen->getBorderWidth() * 2);
522     if (frame.rect.bottom() <= tbar_rect.bottom()) {
523       delta = -delta;
524     }
525     frame.rect.setY(frame.rect.y() + delta);
526     if (screen->getSlitDirection() == Vertical)
527       frame.y_hidden += delta;
528   }
529
530   updateStrut();
531
532   if (hidden)
533     XMoveResizeWindow(display, frame.window, frame.x_hidden,
534                       frame.y_hidden, frame.rect.width(), frame.rect.height());
535   else
536     XMoveResizeWindow(display, frame.window, frame.rect.x(), frame.rect.y(),
537                       frame.rect.width(), frame.rect.height());
538 }
539
540
541 void Slit::shutdown(void) {
542   while (! clientList.empty())
543     removeClient(clientList.front());
544 }
545
546
547 void Slit::buttonPressEvent(XButtonEvent *e) {
548   if (e->window != frame.window) return;
549
550   if (e->button == Button1 && (! on_top)) {
551     Window w[1] = { frame.window };
552     screen->raiseWindows(w, 1);
553   } else if (e->button == Button2 && (! on_top)) {
554     XLowerWindow(display, frame.window);
555   } else if (e->button == Button3) {
556     if (! slitmenu->isVisible()) {
557       int x, y;
558
559       x = e->x_root - (slitmenu->getWidth() / 2);
560       y = e->y_root - (slitmenu->getHeight() / 2);
561
562       if (x < 0)
563         x = 0;
564       else if (x + slitmenu->getWidth() > screen->getWidth())
565         x = screen->getWidth() - slitmenu->getWidth();
566
567       if (y < 0)
568         y = 0;
569       else if (y + slitmenu->getHeight() > screen->getHeight())
570         y = screen->getHeight() - slitmenu->getHeight();
571
572       slitmenu->move(x, y);
573       slitmenu->show();
574     } else {
575       slitmenu->hide();
576     }
577   }
578 }
579
580
581 void Slit::enterNotifyEvent(XCrossingEvent *) {
582   if (! do_auto_hide)
583     return;
584
585   if (hidden) {
586     if (! timer->isTiming()) timer->start();
587   } else {
588     if (timer->isTiming()) timer->stop();
589   }
590 }
591
592
593 void Slit::leaveNotifyEvent(XCrossingEvent *) {
594   if (! do_auto_hide)
595     return;
596
597   if (hidden) {
598     if (timer->isTiming()) timer->stop();
599   } else if (! slitmenu->isVisible()) {
600     if (! timer->isTiming()) timer->start();
601   }
602 }
603
604
605 void Slit::configureRequestEvent(XConfigureRequestEvent *e) {
606   if (! blackbox->validateWindow(e->window))
607     return;
608
609   XWindowChanges xwc;
610
611   xwc.x = e->x;
612   xwc.y = e->y;
613   xwc.width = e->width;
614   xwc.height = e->height;
615   xwc.border_width = 0;
616   xwc.sibling = e->above;
617   xwc.stack_mode = e->detail;
618
619   XConfigureWindow(display, e->window, e->value_mask, &xwc);
620
621   SlitClientList::iterator it = clientList.begin();
622   const SlitClientList::iterator end = clientList.end();
623   for (; it != end; ++it) {
624     SlitClient *client = *it;
625     if (client->window == e->window &&
626         (static_cast<signed>(client->rect.width()) != e->width ||
627          static_cast<signed>(client->rect.height()) != e->height)) {
628       client->rect.setSize(e->width, e->height);
629
630       reconfigure();
631       return;
632     }
633   }
634 }
635
636
637 void Slit::timeout(void) {
638   hidden = ! hidden;
639   if (hidden)
640     XMoveWindow(display, frame.window, frame.x_hidden, frame.y_hidden);
641   else
642     XMoveWindow(display, frame.window, frame.rect.x(), frame.rect.y());
643 }
644
645
646 void Slit::toggleAutoHide(void) {
647   do_auto_hide = (do_auto_hide) ?  False : True;
648
649   updateStrut();
650
651   if (do_auto_hide == False && hidden) {
652     // force the slit to be visible
653     if (timer->isTiming()) timer->stop();
654     timeout();
655   }
656 }
657
658
659 void Slit::unmapNotifyEvent(XUnmapEvent *e) {
660   removeClient(e->window);
661 }
662
663
664 Slitmenu::Slitmenu(Slit *sl) : Basemenu(sl->screen) {
665   slit = sl;
666
667   setLabel(i18n(SlitSet, SlitSlitTitle, "Slit"));
668   setInternalMenu();
669
670   directionmenu = new Directionmenu(this);
671   placementmenu = new Placementmenu(this);
672
673   insert(i18n(CommonSet, CommonDirectionTitle, "Direction"),
674          directionmenu);
675   insert(i18n(CommonSet, CommonPlacementTitle, "Placement"),
676          placementmenu);
677   insert(i18n(CommonSet, CommonAlwaysOnTop, "Always on top"), 1);
678   insert(i18n(CommonSet, CommonAutoHide, "Auto hide"), 2);
679
680   update();
681
682   if (slit->isOnTop()) setItemSelected(2, True);
683   if (slit->doAutoHide()) setItemSelected(3, True);
684 }
685
686
687 Slitmenu::~Slitmenu(void) {
688   delete directionmenu;
689   delete placementmenu;
690 }
691
692
693 void Slitmenu::itemSelected(int button, unsigned int index) {
694   if (button != 1)
695     return;
696
697   BasemenuItem *item = find(index);
698   if (! item) return;
699
700   switch (item->function()) {
701   case 1: { // always on top
702     slit->on_top = ((slit->isOnTop()) ?  False : True);
703     setItemSelected(2, slit->on_top);
704
705     if (slit->isOnTop()) slit->screen->raiseWindows((Window *) 0, 0);
706     break;
707   }
708
709   case 2: { // auto hide
710     slit->toggleAutoHide();
711     setItemSelected(3, slit->do_auto_hide);
712
713     break;
714   }
715   } // switch
716 }
717
718
719 void Slitmenu::internal_hide(void) {
720   Basemenu::internal_hide();
721   if (slit->doAutoHide())
722     slit->timeout();
723 }
724
725
726 void Slitmenu::reconfigure(void) {
727   directionmenu->reconfigure();
728   placementmenu->reconfigure();
729
730   Basemenu::reconfigure();
731 }
732
733
734 Slitmenu::Directionmenu::Directionmenu(Slitmenu *sm)
735   : Basemenu(sm->slit->screen) {
736
737   setLabel(i18n(SlitSet, SlitSlitDirection, "Slit Direction"));
738   setInternalMenu();
739
740   insert(i18n(CommonSet, CommonDirectionHoriz, "Horizontal"),
741          Slit::Horizontal);
742   insert(i18n(CommonSet, CommonDirectionVert, "Vertical"),
743          Slit::Vertical);
744
745   update();
746
747   if (getScreen()->getSlitDirection() == Slit::Horizontal)
748     setItemSelected(0, True);
749   else
750     setItemSelected(1, True);
751 }
752
753
754 void Slitmenu::Directionmenu::itemSelected(int button, unsigned int index) {
755   if (button != 1)
756     return;
757
758   BasemenuItem *item = find(index);
759   if (! item) return;
760
761   getScreen()->saveSlitDirection(item->function());
762
763   if (item->function() == Slit::Horizontal) {
764     setItemSelected(0, True);
765     setItemSelected(1, False);
766   } else {
767     setItemSelected(0, False);
768     setItemSelected(1, True);
769   }
770
771   hide();
772   getScreen()->getSlit()->reconfigure();
773 }
774
775
776 Slitmenu::Placementmenu::Placementmenu(Slitmenu *sm)
777   : Basemenu(sm->slit->screen) {
778
779   setLabel(i18n(SlitSet, SlitSlitPlacement, "Slit Placement"));
780   setMinimumSublevels(3);
781   setInternalMenu();
782
783   insert(i18n(CommonSet, CommonPlacementTopLeft, "Top Left"),
784          Slit::TopLeft);
785   insert(i18n(CommonSet, CommonPlacementCenterLeft, "Center Left"),
786          Slit::CenterLeft);
787   insert(i18n(CommonSet, CommonPlacementBottomLeft, "Bottom Left"),
788          Slit::BottomLeft);
789   insert(i18n(CommonSet, CommonPlacementTopCenter, "Top Center"),
790          Slit::TopCenter);
791   insert("");
792   insert(i18n(CommonSet, CommonPlacementBottomCenter, "Bottom Center"),
793          Slit::BottomCenter);
794   insert(i18n(CommonSet, CommonPlacementTopRight, "Top Right"),
795          Slit::TopRight);
796   insert(i18n(CommonSet, CommonPlacementCenterRight, "Center Right"),
797          Slit::CenterRight);
798   insert(i18n(CommonSet, CommonPlacementBottomRight, "Bottom Right"),
799          Slit::BottomRight);
800
801   update();
802 }
803
804
805 void Slitmenu::Placementmenu::itemSelected(int button, unsigned int index) {
806   if (button != 1)
807     return;
808
809   BasemenuItem *item = find(index);
810   if (! (item && item->function())) return;
811
812   getScreen()->saveSlitPlacement(item->function());
813   hide();
814   getScreen()->getSlit()->reconfigure();
815 }
816