]> Dogcows Code - chaz/openbox/blob - src/Slit.cc
sync with bb-cvs
[chaz/openbox] / 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 slitstr = "session.screen" + itostring(screen->getScreenNumber()) + ".slit.";
44 config = blackbox->getConfig();
45
46 load_rc();
47
48 display = screen->getBaseDisplay()->getXDisplay();
49 frame.window = frame.pixmap = None;
50
51 timer = new BTimer(blackbox, this);
52 timer->setTimeout(blackbox->getAutoRaiseDelay());
53
54 slitmenu = new Slitmenu(this);
55
56 XSetWindowAttributes attrib;
57 unsigned long create_mask = CWBackPixmap | CWBackPixel | CWBorderPixel |
58 CWColormap | CWOverrideRedirect | CWEventMask;
59 attrib.background_pixmap = None;
60 attrib.background_pixel = attrib.border_pixel =
61 screen->getBorderColor()->pixel();
62 attrib.colormap = screen->getColormap();
63 attrib.override_redirect = True;
64 attrib.event_mask = SubstructureRedirectMask | ButtonPressMask |
65 EnterWindowMask | LeaveWindowMask;
66
67 frame.rect.setSize(1, 1);
68
69 frame.window =
70 XCreateWindow(display, screen->getRootWindow(),
71 frame.rect.x(), frame.rect.y(),
72 frame.rect.width(), frame.rect.height(),
73 screen->getBorderWidth(), screen->getDepth(), InputOutput,
74 screen->getVisual(), create_mask, &attrib);
75 blackbox->saveSlitSearch(frame.window, this);
76
77 screen->addStrut(&strut);
78
79 reconfigure();
80 }
81
82
83 Slit::~Slit(void) {
84 delete timer;
85
86 delete slitmenu;
87
88 screen->removeStrut(&strut);
89 screen->updateAvailableArea();
90
91 screen->getImageControl()->removeImage(frame.pixmap);
92
93 blackbox->removeSlitSearch(frame.window);
94
95 XDestroyWindow(display, frame.window);
96 }
97
98
99 void Slit::addClient(Window w) {
100 if (! blackbox->validateWindow(w))
101 return;
102
103 SlitClient *client = new SlitClient;
104 client->client_window = w;
105
106 XWMHints *wmhints = XGetWMHints(display, w);
107
108 if (wmhints) {
109 if ((wmhints->flags & IconWindowHint) &&
110 (wmhints->icon_window != None)) {
111 // some dock apps use separate windows, we need to hide these
112 XMoveWindow(display, client->client_window, screen->getWidth() + 10,
113 screen->getHeight() + 10);
114 XMapWindow(display, client->client_window);
115
116 client->icon_window = wmhints->icon_window;
117 client->window = client->icon_window;
118 } else {
119 client->icon_window = None;
120 client->window = client->client_window;
121 }
122
123 XFree(wmhints);
124 } else {
125 client->icon_window = None;
126 client->window = client->client_window;
127 }
128
129 XWindowAttributes attrib;
130 if (XGetWindowAttributes(display, client->window, &attrib)) {
131 client->rect.setSize(attrib.width, attrib.height);
132 } else {
133 client->rect.setSize(64, 64);
134 }
135
136 Atom *proto;
137 int num_return = 0;
138 if (XGetWMProtocols(display, client->window, &proto, &num_return)) {
139 for (int i = 0; i < num_return; ++i) {
140 if (proto[i] ==
141 blackbox->getXAtom()->getAtom(XAtom::blackbox_structure_messages)) {
142 screen->addNetizen(new Netizen(screen, client->window));
143 }
144 }
145 }
146
147 XSetWindowBorderWidth(display, client->window, 0);
148
149 XGrabServer(display);
150 XSelectInput(display, frame.window, NoEventMask);
151 XSelectInput(display, client->window, NoEventMask);
152 XReparentWindow(display, client->window, frame.window, 0, 0);
153 XMapRaised(display, client->window);
154 XChangeSaveSet(display, client->window, SetModeInsert);
155 XSelectInput(display, frame.window, SubstructureRedirectMask |
156 ButtonPressMask | EnterWindowMask | LeaveWindowMask);
157 XSelectInput(display, client->window, StructureNotifyMask |
158 SubstructureNotifyMask | EnterWindowMask);
159
160 XUngrabServer(display);
161
162 clientList.push_back(client);
163
164 blackbox->saveSlitSearch(client->client_window, this);
165 blackbox->saveSlitSearch(client->icon_window, this);
166 reconfigure();
167 }
168
169
170 void Slit::removeClient(SlitClient *client, bool remap) {
171 blackbox->removeSlitSearch(client->client_window);
172 blackbox->removeSlitSearch(client->icon_window);
173 clientList.remove(client);
174
175 screen->removeNetizen(client->window);
176
177 if (remap && blackbox->validateWindow(client->window)) {
178 XGrabServer(display);
179 XSelectInput(display, frame.window, NoEventMask);
180 XSelectInput(display, client->window, NoEventMask);
181 XReparentWindow(display, client->window, screen->getRootWindow(),
182 client->rect.x(), client->rect.y());
183 XChangeSaveSet(display, client->window, SetModeDelete);
184 XSelectInput(display, frame.window, SubstructureRedirectMask |
185 ButtonPressMask | EnterWindowMask | LeaveWindowMask);
186 XUngrabServer(display);
187 }
188
189 delete client;
190 client = (SlitClient *) 0;
191 }
192
193
194 struct SlitClientMatch {
195 Window window;
196 SlitClientMatch(Window w): window(w) {}
197 inline bool operator()(const Slit::SlitClient* client) const {
198 return (client->window == window);
199 }
200 };
201
202
203 void Slit::removeClient(Window w, bool remap) {
204 SlitClientList::iterator it = clientList.begin();
205 const SlitClientList::iterator end = clientList.end();
206
207 it = std::find_if(it, end, SlitClientMatch(w));
208 if (it != end) {
209 removeClient(*it, remap);
210 reconfigure();
211 }
212 }
213
214
215 void Slit::saveOnTop(bool b) {
216 on_top = b;
217 config->setValue(slitstr + "onTop", on_top);
218 }
219
220 void Slit::saveAutoHide(bool b) {
221 do_auto_hide = b;
222 config->setValue(slitstr + "autoHide", do_auto_hide);
223 }
224
225 void Slit::savePlacement(int p) {
226 placement = p;
227 const char *pname;
228 switch (placement) {
229 case TopLeft: pname = "TopLeft"; break;
230 case CenterLeft: pname = "CenterLeft"; break;
231 case BottomLeft: pname = "BottomLeft"; break;
232 case TopCenter: pname = "TopCenter"; break;
233 case BottomCenter: pname = "BottomCenter"; break;
234 case TopRight: pname = "TopRight"; break;
235 case BottomRight: pname = "BottomRight"; break;
236 case CenterRight: default: pname = "CenterRight"; break;
237 }
238 config->setValue(slitstr + "placement", pname);
239 }
240
241 void Slit::saveDirection(int d) {
242 direction = d;
243 config->setValue(slitstr + "direction", (direction == Horizontal ?
244 "Horizontal" : "Vertical"));
245 }
246
247 void Slit::save_rc(void) {
248 saveOnTop(on_top);
249 saveAutoHide(do_auto_hide);
250 savePlacement(placement);
251 saveDirection(direction);
252 }
253
254 void Slit::load_rc(void) {
255 std::string s;
256
257 if (! config->getValue(slitstr + "onTop", on_top))
258 on_top = false;
259
260 if (! config->getValue(slitstr + "autoHide", do_auto_hide))
261 do_auto_hide = false;
262 hidden = do_auto_hide;
263
264 if (config->getValue(slitstr + "direction", s) && s == "Horizontal")
265 direction = Horizontal;
266 else
267 direction = Vertical;
268
269 if (config->getValue(slitstr + "placement", s)) {
270 if (s == "TopLeft")
271 placement = TopLeft;
272 else if (s == "CenterLeft")
273 placement = CenterLeft;
274 else if (s == "BottomLeft")
275 placement = BottomLeft;
276 else if (s == "TopCenter")
277 placement = TopCenter;
278 else if (s == "BottomCenter")
279 placement = BottomCenter;
280 else if (s == "TopRight")
281 placement = TopRight;
282 else if (s == "BottomRight")
283 placement = BottomRight;
284 else //if (s == "CenterRight")
285 placement = CenterRight;
286 } else
287 placement = CenterRight;
288 }
289
290
291 void Slit::reconfigure(void) {
292 SlitClientList::iterator it = clientList.begin();
293 const SlitClientList::iterator end = clientList.end();
294 SlitClient *client;
295
296 unsigned int width = 0, height = 0;
297
298 switch (direction) {
299 case Vertical:
300 for (; it != end; ++it) {
301 client = *it;
302 height += client->rect.height() + screen->getBevelWidth();
303
304 if (width < client->rect.width())
305 width = client->rect.width();
306 }
307
308 if (width < 1)
309 width = 1;
310 else
311 width += (screen->getBevelWidth() * 2);
312
313 if (height < 1)
314 height = 1;
315 else
316 height += screen->getBevelWidth();
317
318 break;
319
320 case Horizontal:
321 for (; it != end; ++it) {
322 client = *it;
323 width += client->rect.width() + screen->getBevelWidth();
324
325 if (height < client->rect.height())
326 height = client->rect.height();
327 }
328
329 if (width < 1)
330 width = 1;
331 else
332 width += screen->getBevelWidth();
333
334 if (height < 1)
335 height = 1;
336 else
337 height += (screen->getBevelWidth() * 2);
338
339 break;
340 }
341 frame.rect.setSize(width, height);
342
343 reposition();
344
345 XSetWindowBorderWidth(display ,frame.window, screen->getBorderWidth());
346 XSetWindowBorder(display, frame.window,
347 screen->getBorderColor()->pixel());
348
349 if (clientList.empty())
350 XUnmapWindow(display, frame.window);
351 else
352 XMapWindow(display, frame.window);
353
354 BTexture *texture = &(screen->getToolbarStyle()->toolbar);
355 frame.pixmap = texture->render(frame.rect.width(), frame.rect.height(),
356 frame.pixmap);
357 if (! frame.pixmap)
358 XSetWindowBackground(display, frame.window, texture->color().pixel());
359 else
360 XSetWindowBackgroundPixmap(display, frame.window, frame.pixmap);
361
362 XClearWindow(display, frame.window);
363
364 it = clientList.begin();
365
366 int x, y;
367
368 switch (direction) {
369 case Vertical:
370 x = 0;
371 y = screen->getBevelWidth();
372
373 for (; it != end; ++it) {
374 client = *it;
375 x = (frame.rect.width() - client->rect.width()) / 2;
376
377 XMoveResizeWindow(display, client->window, x, y,
378 client->rect.width(), client->rect.height());
379 XMapWindow(display, client->window);
380
381 // for ICCCM compliance
382 client->rect.setPos(x, y);
383
384 XEvent event;
385 event.type = ConfigureNotify;
386
387 event.xconfigure.display = display;
388 event.xconfigure.event = client->window;
389 event.xconfigure.window = client->window;
390 event.xconfigure.x = x;
391 event.xconfigure.y = y;
392 event.xconfigure.width = client->rect.width();
393 event.xconfigure.height = client->rect.height();
394 event.xconfigure.border_width = 0;
395 event.xconfigure.above = frame.window;
396 event.xconfigure.override_redirect = False;
397
398 XSendEvent(display, client->window, False, StructureNotifyMask, &event);
399
400 y += client->rect.height() + screen->getBevelWidth();
401 }
402
403 break;
404
405 case Horizontal:
406 x = screen->getBevelWidth();
407 y = 0;
408
409 for (; it != end; ++it) {
410 client = *it;
411 y = (frame.rect.height() - client->rect.height()) / 2;
412
413 XMoveResizeWindow(display, client->window, x, y,
414 client->rect.width(), client->rect.height());
415 XMapWindow(display, client->window);
416
417 // for ICCCM compliance
418 client->rect.setPos(x, y);
419
420 XEvent event;
421 event.type = ConfigureNotify;
422
423 event.xconfigure.display = display;
424 event.xconfigure.event = client->window;
425 event.xconfigure.window = client->window;
426 event.xconfigure.x = x;
427 event.xconfigure.y = y;
428 event.xconfigure.width = client->rect.width();
429 event.xconfigure.height = client->rect.height();
430 event.xconfigure.border_width = 0;
431 event.xconfigure.above = frame.window;
432 event.xconfigure.override_redirect = False;
433
434 XSendEvent(display, client->window, False, StructureNotifyMask, &event);
435
436 x += client->rect.width() + screen->getBevelWidth();
437 }
438 break;
439 }
440
441 slitmenu->reconfigure();
442 }
443
444
445 void Slit::updateStrut(void) {
446 strut.top = strut.bottom = strut.left = strut.right = 0;
447
448 if (! clientList.empty()) {
449 // when not hidden both borders are in use, when hidden only one is
450 unsigned int border_width = screen->getBorderWidth();
451 if (! do_auto_hide)
452 border_width *= 2;
453
454 switch (direction) {
455 case Vertical:
456 switch (placement) {
457 case TopCenter:
458 strut.top = getExposedHeight() + border_width;
459 break;
460 case BottomCenter:
461 strut.bottom = getExposedHeight() + border_width;
462 break;
463 case TopLeft:
464 case CenterLeft:
465 case BottomLeft:
466 strut.left = getExposedWidth() + border_width;
467 break;
468 case TopRight:
469 case CenterRight:
470 case BottomRight:
471 strut.right = getExposedWidth() + border_width;
472 break;
473 }
474 break;
475 case Horizontal:
476 switch (placement) {
477 case TopCenter:
478 case TopLeft:
479 case TopRight:
480 strut.top = frame.rect.top() + getExposedHeight() + border_width;
481 break;
482 case BottomCenter:
483 case BottomLeft:
484 case BottomRight:
485 int pos;
486 if (do_auto_hide)
487 pos = frame.y_hidden;
488 else
489 pos = frame.rect.y();
490 strut.bottom = (screen->getRect().bottom() - pos);
491 break;
492 case CenterLeft:
493 strut.left = getExposedWidth() + border_width;
494 break;
495 case CenterRight:
496 strut.right = getExposedWidth() + border_width;
497 break;
498 }
499 break;
500 }
501 }
502
503 // update area with new Strut info
504 screen->updateAvailableArea();
505 }
506
507
508 void Slit::reposition(void) {
509 int x = 0, y = 0;
510
511 switch (placement) {
512 case TopLeft:
513 case CenterLeft:
514 case BottomLeft:
515 x = 0;
516 frame.x_hidden = screen->getBevelWidth() - screen->getBorderWidth()
517 - frame.rect.width();
518
519 if (placement == TopLeft)
520 y = 0;
521 else if (placement == CenterLeft)
522 y = (screen->getHeight() - frame.rect.height()) / 2;
523 else
524 y = screen->getHeight() - frame.rect.height()
525 - (screen->getBorderWidth() * 2);
526
527 break;
528
529 case TopCenter:
530 case BottomCenter:
531 x = (screen->getWidth() - frame.rect.width()) / 2;
532 frame.x_hidden = x;
533
534 if (placement == TopCenter)
535 y = 0;
536 else
537 y = screen->getHeight() - frame.rect.height()
538 - (screen->getBorderWidth() * 2);
539
540 break;
541
542 case TopRight:
543 case CenterRight:
544 case BottomRight:
545 x = screen->getWidth() - frame.rect.width()
546 - (screen->getBorderWidth() * 2);
547 frame.x_hidden = screen->getWidth() - screen->getBevelWidth()
548 - screen->getBorderWidth();
549
550 if (placement == TopRight)
551 y = 0;
552 else if (placement == CenterRight)
553 y = (screen->getHeight() - frame.rect.height()) / 2;
554 else
555 y = screen->getHeight() - frame.rect.height()
556 - (screen->getBorderWidth() * 2);
557 break;
558 }
559
560 frame.rect.setPos(x, y);
561
562 // we have to add the border to the rect as it is not accounted for
563 Rect tbar_rect = screen->getToolbar()->getRect();
564 tbar_rect.setSize(tbar_rect.width() + (screen->getBorderWidth() * 2),
565 tbar_rect.height() + (screen->getBorderWidth() * 2));
566 Rect slit_rect = frame.rect;
567 slit_rect.setSize(slit_rect.width() + (screen->getBorderWidth() * 2),
568 slit_rect.height() + (screen->getBorderWidth() * 2));
569
570 if (! screen->doHideToolbar() && slit_rect.intersects(tbar_rect)) {
571 int delta = screen->getToolbar()->getExposedHeight() +
572 screen->getBorderWidth();
573 if (frame.rect.bottom() <= tbar_rect.bottom())
574 delta = -delta;
575
576 frame.rect.setY(frame.rect.y() + delta);
577 }
578
579 if (placement == TopCenter)
580 frame.y_hidden = 0 - frame.rect.height() + screen->getBorderWidth()
581 + screen->getBevelWidth();
582 else if (placement == BottomCenter)
583 frame.y_hidden = screen->getHeight() - screen->getBorderWidth()
584 - screen->getBevelWidth();
585 else
586 frame.y_hidden = frame.rect.y();
587
588 updateStrut();
589
590 if (hidden)
591 XMoveResizeWindow(display, frame.window,
592 frame.x_hidden, frame.y_hidden,
593 frame.rect.width(), frame.rect.height());
594 else
595 XMoveResizeWindow(display, frame.window,
596 frame.rect.x(), frame.rect.y(),
597 frame.rect.width(), frame.rect.height());
598 }
599
600
601 void Slit::shutdown(void) {
602 while (! clientList.empty())
603 removeClient(clientList.front());
604 }
605
606
607 void Slit::buttonPressEvent(const XButtonEvent *e) {
608 if (e->window != frame.window) return;
609
610 if (e->button == Button1 && (! on_top)) {
611 Window w[1] = { frame.window };
612 screen->raiseWindows(w, 1);
613 } else if (e->button == Button2 && (! on_top)) {
614 XLowerWindow(display, frame.window);
615 } else if (e->button == Button3) {
616 if (! slitmenu->isVisible()) {
617 int x, y;
618
619 x = e->x_root - (slitmenu->getWidth() / 2);
620 y = e->y_root - (slitmenu->getHeight() / 2);
621
622 if (x < 0)
623 x = 0;
624 else if (x + slitmenu->getWidth() > screen->getWidth())
625 x = screen->getWidth() - slitmenu->getWidth();
626
627 if (y < 0)
628 y = 0;
629 else if (y + slitmenu->getHeight() > screen->getHeight())
630 y = screen->getHeight() - slitmenu->getHeight();
631
632 slitmenu->move(x, y);
633 slitmenu->show();
634 } else {
635 slitmenu->hide();
636 }
637 }
638 }
639
640
641 void Slit::enterNotifyEvent(const XCrossingEvent *) {
642 if (! do_auto_hide)
643 return;
644
645 if (hidden) {
646 if (! timer->isTiming()) timer->start();
647 } else {
648 if (timer->isTiming()) timer->stop();
649 }
650 }
651
652
653 void Slit::leaveNotifyEvent(const XCrossingEvent *) {
654 if (! do_auto_hide)
655 return;
656
657 if (hidden) {
658 if (timer->isTiming()) timer->stop();
659 } else if (! slitmenu->isVisible()) {
660 if (! timer->isTiming()) timer->start();
661 }
662 }
663
664
665 void Slit::configureRequestEvent(const XConfigureRequestEvent *e) {
666 if (! blackbox->validateWindow(e->window))
667 return;
668
669 XWindowChanges xwc;
670
671 xwc.x = e->x;
672 xwc.y = e->y;
673 xwc.width = e->width;
674 xwc.height = e->height;
675 xwc.border_width = 0;
676 xwc.sibling = e->above;
677 xwc.stack_mode = e->detail;
678
679 XConfigureWindow(display, e->window, e->value_mask, &xwc);
680
681 SlitClientList::iterator it = clientList.begin();
682 const SlitClientList::iterator end = clientList.end();
683 for (; it != end; ++it) {
684 SlitClient *client = *it;
685 if (client->window == e->window &&
686 (static_cast<signed>(client->rect.width()) != e->width ||
687 static_cast<signed>(client->rect.height()) != e->height)) {
688 client->rect.setSize(e->width, e->height);
689
690 reconfigure();
691 return;
692 }
693 }
694 }
695
696
697 void Slit::timeout(void) {
698 hidden = ! hidden;
699 if (hidden)
700 XMoveWindow(display, frame.window, frame.x_hidden, frame.y_hidden);
701 else
702 XMoveWindow(display, frame.window, frame.rect.x(), frame.rect.y());
703 }
704
705
706 void Slit::toggleAutoHide(void) {
707 saveAutoHide(do_auto_hide ? False : True);
708
709 updateStrut();
710
711 if (do_auto_hide == False && hidden) {
712 // force the slit to be visible
713 if (timer->isTiming()) timer->stop();
714 timeout();
715 }
716 }
717
718
719 void Slit::unmapNotifyEvent(const XUnmapEvent *e) {
720 removeClient(e->window);
721 }
722
723
724 Slitmenu::Slitmenu(Slit *sl) : Basemenu(sl->screen) {
725 slit = sl;
726
727 setLabel(i18n(SlitSet, SlitSlitTitle, "Slit"));
728 setInternalMenu();
729
730 directionmenu = new Directionmenu(this);
731 placementmenu = new Placementmenu(this);
732
733 insert(i18n(CommonSet, CommonDirectionTitle, "Direction"),
734 directionmenu);
735 insert(i18n(CommonSet, CommonPlacementTitle, "Placement"),
736 placementmenu);
737 insert(i18n(CommonSet, CommonAlwaysOnTop, "Always on top"), 1);
738 insert(i18n(CommonSet, CommonAutoHide, "Auto hide"), 2);
739
740 update();
741
742 if (slit->isOnTop()) setItemSelected(2, True);
743 if (slit->doAutoHide()) setItemSelected(3, True);
744 }
745
746
747 Slitmenu::~Slitmenu(void) {
748 delete directionmenu;
749 delete placementmenu;
750 }
751
752
753 void Slitmenu::itemSelected(int button, unsigned int index) {
754 if (button != 1)
755 return;
756
757 BasemenuItem *item = find(index);
758 if (! item) return;
759
760 switch (item->function()) {
761 case 1: { // always on top
762 slit->saveOnTop(! slit->isOnTop());
763 setItemSelected(2, slit->isOnTop());
764
765 if (slit->isOnTop()) slit->screen->raiseWindows((Window *) 0, 0);
766 break;
767 }
768
769 case 2: { // auto hide
770 slit->toggleAutoHide();
771 setItemSelected(3, slit->doAutoHide());
772
773 break;
774 }
775 } // switch
776 }
777
778
779 void Slitmenu::internal_hide(void) {
780 Basemenu::internal_hide();
781 if (slit->doAutoHide())
782 slit->timeout();
783 }
784
785
786 void Slitmenu::reconfigure(void) {
787 directionmenu->reconfigure();
788 placementmenu->reconfigure();
789
790 Basemenu::reconfigure();
791 }
792
793
794 Slitmenu::Directionmenu::Directionmenu(Slitmenu *sm)
795 : Basemenu(sm->slit->screen), slit(sm->slit) {
796
797 setLabel(i18n(SlitSet, SlitSlitDirection, "Slit Direction"));
798 setInternalMenu();
799
800 insert(i18n(CommonSet, CommonDirectionHoriz, "Horizontal"),
801 Slit::Horizontal);
802 insert(i18n(CommonSet, CommonDirectionVert, "Vertical"),
803 Slit::Vertical);
804
805 update();
806 setValues();
807 }
808
809
810 void Slitmenu::Directionmenu::reconfigure(void) {
811 setValues();
812 Basemenu::reconfigure();
813 }
814
815
816 void Slitmenu::Directionmenu::setValues(void) {
817 const bool horiz = slit->getDirection() == Slit::Horizontal;
818 setItemSelected(0, horiz);
819 setItemSelected(1, ! horiz);
820 }
821
822
823 void Slitmenu::Directionmenu::itemSelected(int button, unsigned int index) {
824 if (button != 1)
825 return;
826
827 BasemenuItem *item = find(index);
828 if (! item) return;
829
830 slit->saveDirection(item->function());
831 hide();
832 slit->reconfigure();
833 }
834
835
836 Slitmenu::Placementmenu::Placementmenu(Slitmenu *sm)
837 : Basemenu(sm->slit->screen), slit(sm->slit) {
838
839 setLabel(i18n(SlitSet, SlitSlitPlacement, "Slit Placement"));
840 setMinimumSublevels(3);
841 setInternalMenu();
842
843 insert(i18n(CommonSet, CommonPlacementTopLeft, "Top Left"),
844 Slit::TopLeft);
845 insert(i18n(CommonSet, CommonPlacementCenterLeft, "Center Left"),
846 Slit::CenterLeft);
847 insert(i18n(CommonSet, CommonPlacementBottomLeft, "Bottom Left"),
848 Slit::BottomLeft);
849 insert(i18n(CommonSet, CommonPlacementTopCenter, "Top Center"),
850 Slit::TopCenter);
851 insert("");
852 insert(i18n(CommonSet, CommonPlacementBottomCenter, "Bottom Center"),
853 Slit::BottomCenter);
854 insert(i18n(CommonSet, CommonPlacementTopRight, "Top Right"),
855 Slit::TopRight);
856 insert(i18n(CommonSet, CommonPlacementCenterRight, "Center Right"),
857 Slit::CenterRight);
858 insert(i18n(CommonSet, CommonPlacementBottomRight, "Bottom Right"),
859 Slit::BottomRight);
860
861 update();
862
863 setValues();
864 }
865
866
867 void Slitmenu::Placementmenu::reconfigure(void) {
868 setValues();
869 Basemenu::reconfigure();
870 }
871
872
873 void Slitmenu::Placementmenu::setValues(void) {
874 int place = 0;
875 switch (slit->getPlacement()) {
876 case Slit::BottomRight:
877 place++;
878 case Slit::CenterRight:
879 place++;
880 case Slit::TopRight:
881 place++;
882 case Slit::BottomCenter:
883 place++;
884 case Slit::TopCenter:
885 place++;
886 case Slit::BottomLeft:
887 place++;
888 case Slit::CenterLeft:
889 place++;
890 case Slit::TopLeft:
891 break;
892 }
893 setItemSelected(0, 0 == place);
894 setItemSelected(1, 1 == place);
895 setItemSelected(2, 2 == place);
896 setItemSelected(3, 3 == place);
897 setItemSelected(5, 4 == place);
898 setItemSelected(6, 5 == place);
899 setItemSelected(7, 6 == place);
900 setItemSelected(8, 7 == place);
901 }
902
903
904 void Slitmenu::Placementmenu::itemSelected(int button, unsigned int index) {
905 if (button != 1)
906 return;
907
908 BasemenuItem *item = find(index);
909 if (! (item && item->function())) return;
910
911 slit->savePlacement(item->function());
912 hide();
913 slit->reconfigure();
914 }
915
This page took 0.073613 seconds and 4 git commands to generate.