aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias Gumz <akira@fluxbox.org>2015-01-21 20:59:42 (GMT)
committerMathias Gumz <akira@fluxbox.org>2015-01-21 20:59:42 (GMT)
commit145cf94ea67a7d58ccd0a90dae8cba8c38a3275a (patch)
tree6b7bb923bbf956982b5c638672548b27e20ef41c
parentf64727caff069f830dfadb63786df0eba7b3bdb4 (diff)
downloadfluxbox-145cf94ea67a7d58ccd0a90dae8cba8c38a3275a.zip
fluxbox-145cf94ea67a7d58ccd0a90dae8cba8c38a3275a.tar.bz2
Refactor: bundle related members together
Also: try to avoid unsigned/signed problems in drawing code.
-rw-r--r--src/FbTk/Menu.cc351
-rw-r--r--src/FbTk/Menu.hh80
2 files changed, 211 insertions, 220 deletions
diff --git a/src/FbTk/Menu.cc b/src/FbTk/Menu.cc
index 061d739..8076946 100644
--- a/src/FbTk/Menu.cc
+++ b/src/FbTk/Menu.cc
@@ -40,22 +40,9 @@
40#include <X11/keysym.h> 40#include <X11/keysym.h>
41 41
42#include <algorithm> 42#include <algorithm>
43 43#include <cstdio>
44#ifdef HAVE_CSTDIO 44#include <cstdlib>
45 #include <cstdio> 45#include <cstring>
46#else
47 #include <stdio.h>
48#endif
49#ifdef HAVE_CSTDLIB
50 #include <cstdlib>
51#else
52 #include <stdlib.h>
53#endif
54#ifdef HAVE_CSTRING
55 #include <cstring>
56#else
57 #include <string.h>
58#endif
59 46
60#ifdef DEBUG 47#ifdef DEBUG
61#include <iostream> 48#include <iostream>
@@ -88,6 +75,7 @@ namespace FbTk {
88Menu* s_shown = 0; // if there's a menu open at all 75Menu* s_shown = 0; // if there's a menu open at all
89Menu* s_focused = 0; // holds currently focused menu 76Menu* s_focused = 0; // holds currently focused menu
90 77
78
91Menu* Menu::shownMenu() { return s_shown; } 79Menu* Menu::shownMenu() { return s_shown; }
92Menu* Menu::focused() { return s_focused; } 80Menu* Menu::focused() { return s_focused; }
93 81
@@ -101,21 +89,22 @@ Menu::Menu(FbTk::ThemeProxy<MenuTheme> &tm, ImageControl &imgctrl):
101 m_theme(tm), 89 m_theme(tm),
102 m_parent(0), 90 m_parent(0),
103 m_image_ctrl(imgctrl), 91 m_image_ctrl(imgctrl),
104 m_screen_x(0),
105 m_screen_y(0),
106 m_screen_width(DisplayWidth(FbTk::App::instance()->display(), tm->screenNum())),
107 m_screen_height(DisplayHeight(FbTk::App::instance()->display(), tm->screenNum())),
108 m_alignment(ALIGNDONTCARE), 92 m_alignment(ALIGNDONTCARE),
109 m_active_index(-1), 93 m_active_index(-1),
110 m_shape(0), 94 m_shape(0),
111 m_need_update(true) { 95 m_need_update(true) {
112 96
97 Display* disp = FbTk::App::instance()->display();
98 m_screen.x = 0;
99 m_screen.y = 0;
100 m_screen.width = DisplayWidth(disp, tm->screenNum());
101 m_screen.height = DisplayHeight(disp, tm->screenNum());
102
113 // setup timers 103 // setup timers
114 RefCount<Command<void> > show_cmd(new SimpleCommand<Menu>(*this, &Menu::openSubmenu)); 104 RefCount<Command<void> > show_cmd(new SimpleCommand<Menu>(*this, &Menu::openSubmenu));
115 m_submenu_timer.setCommand(show_cmd); 105 m_submenu_timer.setCommand(show_cmd);
116 m_submenu_timer.fireOnce(true); 106 m_submenu_timer.fireOnce(true);
117 107
118
119 RefCount<Command<void> > hide_cmd(new SimpleCommand<Menu>(*this, &Menu::closeMenu)); 108 RefCount<Command<void> > hide_cmd(new SimpleCommand<Menu>(*this, &Menu::closeMenu));
120 m_hide_timer.setCommand(hide_cmd); 109 m_hide_timer.setCommand(hide_cmd);
121 m_hide_timer.fireOnce(true); 110 m_hide_timer.fireOnce(true);
@@ -123,34 +112,26 @@ Menu::Menu(FbTk::ThemeProxy<MenuTheme> &tm, ImageControl &imgctrl):
123 // make sure we get updated when the theme is reloaded 112 // make sure we get updated when the theme is reloaded
124 m_tracker.join(tm.reconfigSig(), MemFun(*this, &Menu::themeReconfigured)); 113 m_tracker.join(tm.reconfigSig(), MemFun(*this, &Menu::themeReconfigured));
125 114
126 m_title_vis = true; 115 m_internal_menu = false;
127 116 m_state.moving = m_state.closing = m_state.torn = m_state.visible = false;
128 m_internal_menu =
129 m_moving =
130 m_closing =
131 m_torn =
132 m_visible = false;
133
134 117
135 m_type_ahead.init(m_items); 118 m_type_ahead.init(m_items);
136 119
137 m_x_move = 120 m_x_move = m_y_move = 0;
138 m_y_move = 0;
139
140 m_which_sub = -1; 121 m_which_sub = -1;
141 122
142 m_frame_pixmap = 123 m_hilite_pixmap = None;
143 m_title_pixmap =
144 m_hilite_pixmap = None;
145 124
146 m_item_w = m_frame_h = 125 m_title.visible = true;
147 theme()->titleFont().height() + theme()->bevelWidth() * 2; 126 m_title.pixmap = None;
148 127
149 m_columns = 128 m_frame.pixmap = None;
150 m_rows_per_column = 129 m_frame.height = theme()->titleFont().height() + theme()->bevelWidth() * 2;
151 m_min_columns = 0; 130
131 m_item_w = m_frame.height;
132
133 m_columns = m_rows_per_column = m_min_columns = 0;
152 134
153 FbTk::EventManager &evm = *FbTk::EventManager::instance();
154 long event_mask = ButtonPressMask | ButtonReleaseMask | 135 long event_mask = ButtonPressMask | ButtonReleaseMask |
155 ButtonMotionMask | KeyPressMask | ExposureMask | FocusChangeMask; 136 ButtonMotionMask | KeyPressMask | ExposureMask | FocusChangeMask;
156 137
@@ -164,52 +145,50 @@ Menu::Menu(FbTk::ThemeProxy<MenuTheme> &tm, ImageControl &imgctrl):
164 // initialize 'shape' here AFTER we created m_window aka fbwindow() 145 // initialize 'shape' here AFTER we created m_window aka fbwindow()
165 m_shape.reset(new Shape(fbwindow(), tm->shapePlaces())); 146 m_shape.reset(new Shape(fbwindow(), tm->shapePlaces()));
166 147
148 FbTk::EventManager &evm = *FbTk::EventManager::instance();
167 evm.add(*this, m_window); 149 evm.add(*this, m_window);
168 150
169 // strip focus change mask from attrib, since we should only use it with main window 151 // strip focus change mask from attrib, since we should only use it with
152 // main window
170 event_mask ^= FocusChangeMask; 153 event_mask ^= FocusChangeMask;
171
172 event_mask |= EnterWindowMask | LeaveWindowMask; 154 event_mask |= EnterWindowMask | LeaveWindowMask;
173 155
174 //create menu title 156 //create menu title
175 m_title = FbTk::FbWindow(m_window, // parent 157 m_title.win = FbTk::FbWindow(m_window,
176 0, 0, width(), theme()->titleHeight(), // pos and size 158 0, 0, width(), theme()->titleHeight(),
177 event_mask, // mask 159 event_mask,
178 false, // override redirect 160 false, // override redirect
179 true); // save under 161 true); // save under
180 162
181 evm.add(*this, m_title); 163 evm.add(*this, m_title.win);
182 m_title.setRenderer(*this); 164 m_title.win.setRenderer(*this);
183 165
184 event_mask |= PointerMotionMask; 166 event_mask |= PointerMotionMask;
185 m_frame = FbTk::FbWindow(m_window, // parent 167 m_frame.win = FbTk::FbWindow(m_window,
186 0, theme()->titleHeight(), // pos 168 0, theme()->titleHeight(),
187 width(), m_frame_h ? m_frame_h : 1, // size 169 width(), m_frame.height ? m_frame.height : 1,
188 event_mask, // mask 170 event_mask,
189 false, // override redirect 171 false, // override redirect
190 true); // save under 172 true); // save under
191 evm.add(*this, m_frame); 173 evm.add(*this, m_frame.win);
192 m_frame.setRenderer(*this); 174 m_frame.win.setRenderer(*this);
193 175 m_title.win.raise();
194 m_title.raise();
195
196 reconfigure(); 176 reconfigure();
197} 177}
198 178
199Menu::~Menu() { 179Menu::~Menu() {
200 180
201 m_window.hide(); 181 m_window.hide();
182 removeAll();
202 183
203 if (s_shown && s_shown->window() == window()) 184 if (s_shown && s_shown->window() == window())
204 s_shown = 0; 185 s_shown = 0;
205 186
206 removeAll(); 187 if (m_title.pixmap)
207 188 m_image_ctrl.removeImage(m_title.pixmap);
208 if (m_title_pixmap)
209 m_image_ctrl.removeImage(m_title_pixmap);
210 189
211 if (m_frame_pixmap) 190 if (m_frame.pixmap)
212 m_image_ctrl.removeImage(m_frame_pixmap); 191 m_image_ctrl.removeImage(m_frame.pixmap);
213 192
214 if (m_hilite_pixmap) 193 if (m_hilite_pixmap)
215 m_image_ctrl.removeImage(m_hilite_pixmap); 194 m_image_ctrl.removeImage(m_hilite_pixmap);
@@ -231,6 +210,7 @@ int Menu::insertSubmenu(const FbString &label, Menu *submenu, int pos) {
231} 210}
232 211
233int Menu::insertItem(MenuItem *item, int pos) { 212int Menu::insertItem(MenuItem *item, int pos) {
213
234 if (item == 0) 214 if (item == 0)
235 return m_items.size(); 215 return m_items.size();
236 if (pos == -1) { 216 if (pos == -1) {
@@ -287,19 +267,13 @@ int Menu::remove(unsigned int index) {
287 if (index != m_items.size()) 267 if (index != m_items.size())
288 fixMenuItemIndices(); 268 fixMenuItemIndices();
289 269
290 if (item->submenu() != 0) { 270 Menu* sm = item->submenu();
291 Menu *tmp = item->submenu(); 271 if (sm) {
292 // if menu is internal we should just hide it instead 272 if (! sm->m_internal_menu) {
293 // if destroying it 273 delete sm;
294 if (! tmp->m_internal_menu) {
295 delete tmp;
296 } 274 }
297 // We can't internal_hide here, as the child may be deleted!
298// } else
299// tmp->internal_hide();
300 } 275 }
301 276
302
303 delete item; 277 delete item;
304 } 278 }
305 279
@@ -407,8 +381,8 @@ void Menu::enableTitle() {
407} 381}
408 382
409void Menu::updateMenu() { 383void Menu::updateMenu() {
410 if (m_title_vis) { 384 if (m_title.visible) {
411 m_item_w = theme()->titleFont().textWidth(m_label); 385 m_item_w = theme()->titleFont().textWidth(m_title.label);
412 m_item_w += (theme()->bevelWidth() * 2); 386 m_item_w += (theme()->bevelWidth() * 2);
413 } else 387 } else
414 m_item_w = 1; 388 m_item_w = 1;
@@ -443,7 +417,7 @@ void Menu::updateMenu() {
443 m_columns = 1; 417 m_columns = 1;
444 418
445 while (theme()->itemHeight() * (m_items.size() + 1) / m_columns + 419 while (theme()->itemHeight() * (m_items.size() + 1) / m_columns +
446 theme()->titleHeight() + theme()->borderWidth() > m_screen_height) { 420 theme()->titleHeight() + theme()->borderWidth() > m_screen.height) {
447 m_columns++; 421 m_columns++;
448 } 422 }
449 423
@@ -458,13 +432,13 @@ void Menu::updateMenu() {
458 } 432 }
459 433
460 int itmp = (theme()->itemHeight() * m_rows_per_column); 434 int itmp = (theme()->itemHeight() * m_rows_per_column);
461 m_frame_h = itmp < 1 ? 1 : itmp; 435 m_frame.height = itmp < 1 ? 1 : itmp;
462 436
463 unsigned int new_width = (m_columns * m_item_w); 437 unsigned int new_width = (m_columns * m_item_w);
464 unsigned int new_height = m_frame_h; 438 unsigned int new_height = m_frame.height;
465 439
466 if (m_title_vis) 440 if (m_title.visible)
467 new_height += theme()->titleHeight() + ((m_frame_h > 0)?m_title.borderWidth():0); 441 new_height += theme()->titleHeight() + ((m_frame.height > 0)?m_title.win.borderWidth():0);
468 442
469 443
470 if (new_width == 0) 444 if (new_width == 0)
@@ -483,8 +457,8 @@ void Menu::updateMenu() {
483 if (!isVisible()) 457 if (!isVisible())
484 return; 458 return;
485 459
486 if (m_frame.alpha() != alpha()) 460 if (m_frame.win.alpha() != alpha())
487 m_frame.setAlpha(alpha()); 461 m_frame.win.setAlpha(alpha());
488 462
489 renderMenuPixmap(m_hilite_pixmap, NULL, 463 renderMenuPixmap(m_hilite_pixmap, NULL,
490 m_item_w, theme()->itemHeight(), 464 m_item_w, theme()->itemHeight(),
@@ -513,24 +487,24 @@ void Menu::updateMenu() {
513 } 487 }
514 } 488 }
515 489
516 if (m_title_vis) { 490 if (m_title.visible) {
517 m_title.moveResize(-m_title.borderWidth(), -m_title.borderWidth(), 491 m_title.win.moveResize(-m_title.win.borderWidth(), -m_title.win.borderWidth(),
518 width() + m_title.borderWidth(), theme()->titleHeight()); 492 width() + m_title.win.borderWidth(), theme()->titleHeight());
519 } 493 }
520 494
521 m_frame.moveResize(0, ((m_title_vis) ? m_title.y() + m_title.height() + 495 m_frame.win.moveResize(0, ((m_title.visible) ? m_title.win.y() + m_title.win.height() +
522 m_title.borderWidth()*2 : 0), 496 m_title.win.borderWidth()*2 : 0),
523 width(), m_frame_h); 497 width(), m_frame.height);
524 498
525 if (m_title_vis && m_need_update) { 499 if (m_title.visible && m_need_update) {
526 renderMenuPixmap(m_title_pixmap, &m_title, 500 renderMenuPixmap(m_title.pixmap, &m_title.win,
527 width(), theme()->titleHeight(), 501 width(), theme()->titleHeight(),
528 theme()->titleTexture(), m_image_ctrl); 502 theme()->titleTexture(), m_image_ctrl);
529 } 503 }
530 504
531 if (m_need_update) { 505 if (m_need_update) {
532 renderMenuPixmap(m_frame_pixmap, &m_frame, 506 renderMenuPixmap(m_frame.pixmap, &m_frame.win,
533 width(), m_frame_h, 507 width(), m_frame.height,
534 theme()->frameTexture(), m_image_ctrl); 508 theme()->frameTexture(), m_image_ctrl);
535 } 509 }
536 510
@@ -545,7 +519,7 @@ void Menu::show() {
545 if (isVisible() || m_items.empty()) 519 if (isVisible() || m_items.empty())
546 return; 520 return;
547 521
548 m_visible = true; 522 m_state.visible = true;
549 523
550 if (m_need_update) 524 if (m_need_update)
551 updateMenu(); 525 updateMenu();
@@ -573,7 +547,7 @@ void Menu::hide(bool force) {
573 Menu *p = this; 547 Menu *p = this;
574 while (p && p->isVisible()) { 548 while (p && p->isVisible()) {
575 Menu *tmp = p->m_parent; 549 Menu *tmp = p->m_parent;
576 if (force || !p->m_torn) 550 if (force || !p->m_state.torn)
577 p->internal_hide(); 551 p->internal_hide();
578 else 552 else
579 p->m_parent = 0; 553 p->m_parent = 0;
@@ -598,8 +572,8 @@ void Menu::grabInputFocus() {
598 572
599 573
600void Menu::clearWindow() { 574void Menu::clearWindow() {
601 m_title.clear(); 575 m_title.win.clear();
602 m_frame.clear(); 576 m_frame.win.clear();
603 577
604 // clear foreground bits of frame items 578 // clear foreground bits of frame items
605 for (size_t i = 0; i < m_items.size(); i++) { 579 for (size_t i = 0; i < m_items.size(); i++) {
@@ -636,7 +610,7 @@ void Menu::internal_hide(bool first) {
636 s_shown = 0; 610 s_shown = 0;
637 } 611 }
638 612
639 m_torn = m_visible = m_closing = false; 613 m_state.torn = m_state.visible = m_state.closing = false;
640 m_which_sub = -1; 614 m_which_sub = -1;
641 615
642 if (first && m_parent && m_parent->isVisible() && 616 if (first && m_parent && m_parent->isVisible() &&
@@ -654,8 +628,8 @@ void Menu::move(int x, int y) {
654 628
655 m_window.move(x, y); 629 m_window.move(x, y);
656 // potentially transparent children 630 // potentially transparent children
657 m_title.parentMoved(); 631 m_title.win.parentMoved();
658 m_frame.parentMoved(); 632 m_frame.win.parentMoved();
659 633
660 if (!isVisible()) 634 if (!isVisible())
661 return; 635 return;
@@ -673,7 +647,7 @@ void Menu::redrawTitle(FbDrawable &drawable) {
673 647
674 const FbTk::Font &font = theme()->titleFont(); 648 const FbTk::Font &font = theme()->titleFont();
675 int dx = theme()->bevelWidth(); 649 int dx = theme()->bevelWidth();
676 unsigned int l = font.textWidth(m_label) + theme()->bevelWidth()*2; 650 int l = static_cast<int>(font.textWidth(m_title.label) + theme()->bevelWidth()*2);
677 651
678 switch (theme()->titleFontJustify()) { 652 switch (theme()->titleFontJustify()) {
679 case FbTk::RIGHT: 653 case FbTk::RIGHT:
@@ -689,7 +663,7 @@ void Menu::redrawTitle(FbDrawable &drawable) {
689 663
690 // difference between height based on font, and style-set height 664 // difference between height based on font, and style-set height
691 int height_offset = theme()->titleHeight() - (font.height() + 2*theme()->bevelWidth()); 665 int height_offset = theme()->titleHeight() - (font.height() + 2*theme()->bevelWidth());
692 font.drawText(drawable, screenNumber(), theme()->titleTextGC().gc(), m_label, 666 font.drawText(drawable, screenNumber(), theme()->titleTextGC().gc(), m_title.label,
693 dx, font.ascent() + theme()->bevelWidth() + height_offset/2); // position 667 dx, font.ascent() + theme()->bevelWidth() + height_offset/2); // position
694} 668}
695 669
@@ -713,7 +687,7 @@ void Menu::drawSubmenu(unsigned int index) {
713 if (item->submenu()->m_parent != this) 687 if (item->submenu()->m_parent != this)
714 item->submenu()->m_parent = this; 688 item->submenu()->m_parent = this;
715 689
716 item->submenu()->setScreen(m_screen_x, m_screen_y, m_screen_width, m_screen_height); 690 item->submenu()->setScreen(m_screen.x, m_screen.y, m_screen.width, m_screen.height);
717 691
718 // ensure we do not divide by 0 and thus cause a SIGFPE 692 // ensure we do not divide by 0 and thus cause a SIGFPE
719 if (m_rows_per_column == 0) { 693 if (m_rows_per_column == 0) {
@@ -724,49 +698,49 @@ void Menu::drawSubmenu(unsigned int index) {
724 return; 698 return;
725 } 699 }
726 700
701 int bw = m_window.borderWidth();
702 int h = static_cast<int>(height());
703 int title_bw = m_title.win.borderWidth();
704 int title_height = (m_title.visible ? theme()->titleHeight() + title_bw : 0);
705
706 int subm_title_height = (item->submenu()->m_title.visible) ?
707 item->submenu()->theme()->titleHeight() + bw : 0;
708 int subm_height = static_cast<int>(item->submenu()->height());
709 int subm_width = static_cast<int>(item->submenu()->width());
710 int subm_bw = item->submenu()->fbwindow().borderWidth();
711
727 int column = index / m_rows_per_column; 712 int column = index / m_rows_per_column;
728 int row = index - (column * m_rows_per_column); 713 int row = index - (column * m_rows_per_column);
729 int new_x = x() + ((m_item_w * (column + 1)) + m_window.borderWidth()); 714 int new_x = x() + ((m_item_w * (column + 1)) + bw);
730 int new_y; 715 int new_y = y() + title_height - subm_title_height;
731 716
732 if (m_alignment == ALIGNTOP) { 717 if (m_alignment != ALIGNTOP) {
733 new_y = (y() + ((m_title_vis) ? theme()->titleHeight() + m_title.borderWidth() : 0) - 718 new_y = new_y + (theme()->itemHeight() * row);
734 ((item->submenu()->m_title_vis) ?
735 item->submenu()->theme()->titleHeight() + m_window.borderWidth() : 0));
736 } else {
737 new_y = (y() + (theme()->itemHeight() * row) +
738 ((m_title_vis) ? theme()->titleHeight() + m_window.borderWidth() : 0) -
739 ((item->submenu()->m_title_vis) ?
740 item->submenu()->theme()->titleHeight() + m_window.borderWidth() : 0));
741 } 719 }
742 720
743 if (m_alignment == ALIGNBOTTOM && 721 if (m_alignment == ALIGNBOTTOM && (new_y + subm_height) > (y() + h)) {
744 (new_y + item->submenu()->height()) > (y() + height())) { 722 new_y = (y() + h - subm_height);
745 new_y = (y() + height() - item->submenu()->height());
746 } 723 }
747 724
748 int borderw = item->submenu()->fbwindow().borderWidth(); 725 if ((new_x + subm_width + 2*subm_bw) > (m_screen.x + static_cast<int>(m_screen.width))) {
749 726 new_x = x() - subm_width - bw;
750 if ((new_x + item->submenu()->width()) + 2*borderw > m_screen_x + m_screen_width) {
751 new_x = x() - item->submenu()->width() - m_window.borderWidth();
752 } 727 }
753 728
754 if (new_x < m_screen_x) 729 if (new_x < m_screen.x)
755 new_x = m_screen_x; 730 new_x = m_screen.x;
756 731
757 if ((new_y + item->submenu()->height()) > m_screen_y + m_screen_height) { 732 if ((new_y + subm_height) > (m_screen.y + static_cast<int>(m_screen.height))) {
758 new_y = m_screen_y + m_screen_height - item->submenu()->height() - 733 new_y = m_screen.y + static_cast<int>(m_screen.height) - subm_height - 2*bw;
759 m_window.borderWidth() * 2;
760 } 734 }
761 735
762 item->submenu()->m_moving = m_moving; 736 item->submenu()->m_state.moving = m_state.moving;
763 m_which_sub = index; 737 m_which_sub = index;
764 738
765 if (new_y < m_screen_y) 739 if (new_y < m_screen.y)
766 new_y = m_screen_y; 740 new_y = m_screen.y;
767 741
768 item->submenu()->move(new_x, new_y); 742 item->submenu()->move(new_x, new_y);
769 if (! m_moving) 743 if (! m_state.moving)
770 clearItem(index); 744 clearItem(index);
771 745
772 if (! item->submenu()->isVisible() && item->submenu()->numberOfItems() > 0) { 746 if (! item->submenu()->isVisible() && item->submenu()->numberOfItems() > 0) {
@@ -817,8 +791,7 @@ int Menu::drawItem(FbDrawable &drawable, unsigned int index,
817} 791}
818 792
819void Menu::setLabel(const FbTk::BiDiString &labelstr) { 793void Menu::setLabel(const FbTk::BiDiString &labelstr) {
820 //make sure we don't send 0 to std::string 794 m_title.label = labelstr;
821 m_label = labelstr;
822 reconfigure(); 795 reconfigure();
823} 796}
824 797
@@ -890,13 +863,14 @@ void Menu::handleEvent(XEvent &event) {
890} 863}
891 864
892void Menu::buttonPressEvent(XButtonEvent &be) { 865void Menu::buttonPressEvent(XButtonEvent &be) {
893 if (be.window == m_title) { 866
867 m_state.closing = false;
868 if (be.window == m_title.win) {
894 grabInputFocus(); 869 grabInputFocus();
895 m_closing = (be.button == 3); 870 m_state.closing = (be.button == 3);
896 } else 871 }
897 m_closing = false;
898 872
899 if (be.window == m_frame && m_item_w != 0) { 873 if (be.window == m_frame.win && m_item_w != 0) {
900 874
901 int column = (be.x / m_item_w); 875 int column = (be.x / m_item_w);
902 int i = (be.y / theme()->itemHeight()); 876 int i = (be.y / theme()->itemHeight());
@@ -918,9 +892,9 @@ void Menu::buttonPressEvent(XButtonEvent &be) {
918 892
919 893
920void Menu::buttonReleaseEvent(XButtonEvent &re) { 894void Menu::buttonReleaseEvent(XButtonEvent &re) {
921 if (re.window == m_title) { 895 if (re.window == m_title.win) {
922 if (m_moving) { 896 if (m_state.moving) {
923 m_moving = false; 897 m_state.moving = false;
924 898
925 if (validIndex(m_which_sub) && 899 if (validIndex(m_which_sub) &&
926 m_items[m_which_sub]->submenu()->isVisible()) 900 m_items[m_which_sub]->submenu()->isVisible())
@@ -928,16 +902,16 @@ void Menu::buttonReleaseEvent(XButtonEvent &re) {
928 902
929 if (alpha() < 255) { 903 if (alpha() < 255) {
930 // update these since we've (probably) moved 904 // update these since we've (probably) moved
931 m_title.parentMoved(); 905 m_title.win.parentMoved();
932 m_frame.parentMoved(); 906 m_frame.win.parentMoved();
933 clearWindow(); 907 clearWindow();
934 } 908 }
935 } 909 }
936 910
937 if (re.button == 3 && m_closing) 911 if (re.button == 3 && m_state.closing)
938 internal_hide(); 912 internal_hide();
939 913
940 } else if (re.window == m_frame) { 914 } else if (re.window == m_frame.win) {
941 915
942 int column = (re.x / m_item_w); 916 int column = (re.x / m_item_w);
943 int i = (re.y / theme()->itemHeight()); 917 int i = (re.y / theme()->itemHeight());
@@ -963,15 +937,15 @@ void Menu::buttonReleaseEvent(XButtonEvent &re) {
963 937
964void Menu::motionNotifyEvent(XMotionEvent &me) { 938void Menu::motionNotifyEvent(XMotionEvent &me) {
965 // if draging the with the titlebar: 939 // if draging the with the titlebar:
966 if (me.window == m_title && (me.state & Button1Mask)) { 940 if (me.window == m_title.win && (me.state & Button1Mask)) {
967 stopHide(); 941 stopHide();
968 942
969 if (! m_moving) { 943 if (! m_state.moving) { // if not m_moving: start m_moving operation
970 // if not m_moving: start m_moving operation 944
971 m_moving = m_torn = true; 945 m_state.moving = m_state.torn = true;
972 if (m_parent) 946 if (m_parent)
973 m_parent->m_which_sub = -1; 947 m_parent->m_which_sub = -1;
974 // clear current highlighted item 948
975 clearItem(m_active_index); 949 clearItem(m_active_index);
976 950
977 if (validIndex(m_which_sub) && 951 if (validIndex(m_which_sub) &&
@@ -983,7 +957,7 @@ void Menu::motionNotifyEvent(XMotionEvent &me) {
983 m_window.move(me.x_root - m_x_move, me.y_root - m_y_move); 957 m_window.move(me.x_root - m_x_move, me.y_root - m_y_move);
984 } 958 }
985 959
986 } else if (!(me.state & Button1Mask) && me.window == m_frame) { 960 } else if (!(me.state & Button1Mask) && me.window == m_frame.win) {
987 stopHide(); 961 stopHide();
988 int column = (me.x / m_item_w); 962 int column = (me.x / m_item_w);
989 int i = (me.y / theme()->itemHeight()); 963 int i = (me.y / theme()->itemHeight());
@@ -1039,9 +1013,9 @@ void Menu::exposeEvent(XExposeEvent &ee) {
1039 if (!isVisible()) 1013 if (!isVisible())
1040 return; 1014 return;
1041 1015
1042 if (ee.window == m_title) { 1016 if (ee.window == m_title.win) {
1043 m_title.clearArea(ee.x, ee.y, ee.width, ee.height); 1017 m_title.win.clearArea(ee.x, ee.y, ee.width, ee.height);
1044 } else if (ee.window == m_frame) { 1018 } else if (ee.window == m_frame.win) {
1045 1019
1046 // find where to clear 1020 // find where to clear
1047 // this is a compilicated algorithm... lets do it step by step... 1021 // this is a compilicated algorithm... lets do it step by step...
@@ -1120,7 +1094,7 @@ void Menu::keyPressEvent(XKeyEvent &event) {
1120 break; 1094 break;
1121 case XK_Escape: // close menu 1095 case XK_Escape: // close menu
1122 m_type_ahead.reset(); 1096 m_type_ahead.reset();
1123 m_torn = false; 1097 m_state.torn = false;
1124 hide(true); 1098 hide(true);
1125 break; 1099 break;
1126 case XK_BackSpace: 1100 case XK_BackSpace:
@@ -1173,7 +1147,7 @@ void Menu::keyPressEvent(XKeyEvent &event) {
1173} 1147}
1174 1148
1175void Menu::leaveNotifyEvent(XCrossingEvent &ce) { 1149void Menu::leaveNotifyEvent(XCrossingEvent &ce) {
1176 m_closing = false; 1150 m_state.closing = false;
1177 // if there's a submenu open, highlight its index and stop hide 1151 // if there's a submenu open, highlight its index and stop hide
1178 if (validIndex(m_which_sub) && m_active_index != m_which_sub && 1152 if (validIndex(m_which_sub) && m_active_index != m_which_sub &&
1179 m_items[m_which_sub]->submenu()->isVisible()) { 1153 m_items[m_which_sub]->submenu()->isVisible()) {
@@ -1190,22 +1164,22 @@ void Menu::reconfigure() {
1190 1164
1191 if (FbTk::Transparent::haveComposite()) { 1165 if (FbTk::Transparent::haveComposite()) {
1192 m_window.setOpaque(alpha()); 1166 m_window.setOpaque(alpha());
1193 m_title.setAlpha(255); 1167 m_title.win.setAlpha(255);
1194 m_frame.setAlpha(255); 1168 m_frame.win.setAlpha(255);
1195 } else { 1169 } else {
1196 m_window.setOpaque(255); 1170 m_window.setOpaque(255);
1197 m_title.setAlpha(alpha()); 1171 m_title.win.setAlpha(alpha());
1198 m_frame.setAlpha(alpha()); 1172 m_frame.win.setAlpha(alpha());
1199 } 1173 }
1200 1174
1201 m_need_update = true; // redraw items 1175 m_need_update = true; // redraw items
1202 1176
1203 m_window.setBorderColor(theme()->borderColor()); 1177 m_window.setBorderColor(theme()->borderColor());
1204 m_title.setBorderColor(theme()->borderColor()); 1178 m_title.win.setBorderColor(theme()->borderColor());
1205 m_frame.setBorderColor(theme()->borderColor()); 1179 m_frame.win.setBorderColor(theme()->borderColor());
1206 1180
1207 m_window.setBorderWidth(theme()->borderWidth()); 1181 m_window.setBorderWidth(theme()->borderWidth());
1208 m_title.setBorderWidth(theme()->borderWidth()); 1182 m_title.win.setBorderWidth(theme()->borderWidth());
1209 1183
1210 updateMenu(); 1184 updateMenu();
1211} 1185}
@@ -1257,17 +1231,17 @@ void Menu::themeReconfigured() {
1257} 1231}
1258 1232
1259void Menu::setScreen(int x, int y, unsigned int w, unsigned int h) { 1233void Menu::setScreen(int x, int y, unsigned int w, unsigned int h) {
1260 m_screen_x = x; 1234 m_screen.x = x;
1261 m_screen_y = y; 1235 m_screen.y = y;
1262 m_screen_width = w; 1236 m_screen.width = w;
1263 m_screen_height = h; 1237 m_screen.height = h;
1264} 1238}
1265 1239
1266// Render the foreground objects of given window onto given pixmap 1240// Render the foreground objects of given window onto given pixmap
1267void Menu::renderForeground(FbWindow &win, FbDrawable &drawable) { 1241void Menu::renderForeground(FbWindow &win, FbDrawable &drawable) {
1268 if (&win == &m_frame) { 1242 if (&win == &m_frame.win) {
1269 redrawFrame(drawable); 1243 redrawFrame(drawable);
1270 } else if (&win == &m_title) { 1244 } else if (&win == &m_title.win) {
1271 redrawTitle(drawable); 1245 redrawTitle(drawable);
1272 } 1246 }
1273} 1247}
@@ -1302,19 +1276,19 @@ void Menu::clearItem(int index, bool clear, int search_index) {
1302 find(index)) - m_matches.begin(); 1276 find(index)) - m_matches.begin();
1303 1277
1304 // don't highlight if moving, doesn't work with alpha on 1278 // don't highlight if moving, doesn't work with alpha on
1305 if (highlight && !m_moving) { 1279 if (highlight && !m_state.moving) {
1306 highlightItem(index); 1280 highlightItem(index);
1307 if (search_index < static_cast<int>(m_matches.size())) 1281 if (search_index < static_cast<int>(m_matches.size()))
1308 drawLine(index, m_type_ahead.stringSize()); 1282 drawLine(index, m_type_ahead.stringSize());
1309 return; 1283 return;
1310 } else if (clear) 1284 } else if (clear)
1311 m_frame.clearArea(item_x, item_y, item_w, item_h); 1285 m_frame.win.clearArea(item_x, item_y, item_w, item_h);
1312 1286
1313 MenuItem* item = m_items[index]; 1287 MenuItem* item = m_items[index];
1314 if (!item) 1288 if (!item)
1315 return; 1289 return;
1316 1290
1317 item->draw(m_frame, theme(), highlight, 1291 item->draw(m_frame.win, theme(), highlight,
1318 true, false, item_x, item_y, 1292 true, false, item_x, item_y,
1319 item_w, item_h); 1293 item_w, item_h);
1320 1294
@@ -1340,12 +1314,12 @@ void Menu::highlightItem(int index) {
1340 unsigned int item_h = theme()->itemHeight(); 1314 unsigned int item_h = theme()->itemHeight();
1341 int item_x = (column * m_item_w); 1315 int item_x = (column * m_item_w);
1342 int item_y = (row * item_h); 1316 int item_y = (row * item_h);
1317 FbPixmap buffer = FbPixmap(m_frame.win, item_w, item_h, m_frame.win.depth());
1318 bool parent_rel = (m_hilite_pixmap == ParentRelative);
1319 Pixmap pixmap = parent_rel ? m_frame.pixmap : m_hilite_pixmap;
1320 int pixmap_x = parent_rel ? item_x : 0;
1321 int pixmap_y = parent_rel ? item_y : 0;
1343 1322
1344 FbPixmap buffer = FbPixmap(m_frame, item_w, item_h, m_frame.depth());
1345
1346 bool parent_rel = m_hilite_pixmap == ParentRelative;
1347 Pixmap pixmap = parent_rel ? m_frame_pixmap : m_hilite_pixmap;
1348 int pixmap_x = parent_rel ? item_x : 0, pixmap_y = parent_rel ? item_y : 0;
1349 if (pixmap) { 1323 if (pixmap) {
1350 buffer.copyArea(pixmap, 1324 buffer.copyArea(pixmap,
1351 theme()->hiliteGC().gc(), pixmap_x, pixmap_y, 1325 theme()->hiliteGC().gc(), pixmap_x, pixmap_y,
@@ -1355,11 +1329,10 @@ void Menu::highlightItem(int index) {
1355 buffer.fillRectangle(theme()->hiliteGC().gc(), 1329 buffer.fillRectangle(theme()->hiliteGC().gc(),
1356 0, 0, item_w, item_h); 1330 0, 0, item_w, item_h);
1357 } 1331 }
1358 m_frame.updateTransparent(item_x, item_y, item_w, item_h, buffer.drawable(), true);
1359 1332
1333 m_frame.win.updateTransparent(item_x, item_y, item_w, item_h, buffer.drawable(), true);
1360 drawItem(buffer, index, true, true); 1334 drawItem(buffer, index, true, true);
1361 1335 m_frame.win.copyArea(buffer.drawable(), theme()->hiliteGC().gc(),
1362 m_frame.copyArea(buffer.drawable(), theme()->hiliteGC().gc(),
1363 0, 0, 1336 0, 0,
1364 item_x, item_y, 1337 item_x, item_y,
1365 item_w, item_h); 1338 item_w, item_h);
@@ -1406,8 +1379,20 @@ void Menu::drawLine(int index, int size){
1406 int item_y = (row * theme()->itemHeight()); 1379 int item_y = (row * theme()->itemHeight());
1407 1380
1408 FbTk::MenuItem *item = find(index); 1381 FbTk::MenuItem *item = find(index);
1409 item->drawLine(m_frame, theme(), size, item_x, item_y, m_item_w); 1382 item->drawLine(m_frame.win, theme(), size, item_x, item_y, m_item_w);
1410} 1383}
1411 1384
1385void Menu::setTitleVisibility(bool b) {
1386 m_title.visible = b;
1387 m_need_update = true;
1388 if (!b)
1389 titleWindow().lower();
1390 else
1391 titleWindow().raise();
1392}
1393
1394
1395
1396
1412 1397
1413} // end namespace FbTk 1398} // end namespace FbTk
diff --git a/src/FbTk/Menu.hh b/src/FbTk/Menu.hh
index 27d5b12..9716a89 100644
--- a/src/FbTk/Menu.hh
+++ b/src/FbTk/Menu.hh
@@ -83,7 +83,7 @@ public:
83 83
84 void disableTitle(); 84 void disableTitle();
85 void enableTitle(); 85 void enableTitle();
86 bool isTitleVisible() const { return m_title_vis; } 86 bool isTitleVisible() const { return m_title.visible; }
87 87
88 void setScreen(int x, int y, unsigned int w, unsigned int h); 88 void setScreen(int x, int y, unsigned int w, unsigned int h);
89 89
@@ -117,22 +117,23 @@ public:
117 @name accessors 117 @name accessors
118 */ 118 */
119 //@{ 119 //@{
120 bool isTorn() const { return m_torn; } 120 bool isTorn() const { return m_state.torn; }
121 bool isVisible() const { return m_visible; } 121 bool isVisible() const { return m_state.visible; }
122 bool isMoving() const { return m_moving; } 122 bool isMoving() const { return m_state.moving; }
123 int screenNumber() const { return m_window.screenNumber(); } 123 int screenNumber() const { return m_window.screenNumber(); }
124 Window window() const { return m_window.window(); } 124 Window window() const { return m_window.window(); }
125 FbWindow &fbwindow() { return m_window; } 125 FbWindow &fbwindow() { return m_window; }
126 const FbWindow &fbwindow() const { return m_window; } 126 const FbWindow &fbwindow() const { return m_window; }
127 FbWindow &titleWindow() { return m_title; } 127 FbWindow &titleWindow() { return m_title.win; }
128 FbWindow &frameWindow() { return m_frame; } 128 FbWindow &frameWindow() { return m_frame.win; }
129 const FbTk::BiDiString &label() const { return m_label; } 129
130 int x() const { return m_window.x(); } 130 const FbTk::BiDiString &label() const { return m_title.label; }
131 int y() const { return m_window.y(); } 131 int x() const { return m_window.x(); }
132 unsigned int width() const { return m_window.width(); } 132 int y() const { return m_window.y(); }
133 unsigned int height() const { return m_window.height(); } 133 unsigned int width() const { return m_window.width(); }
134 size_t numberOfItems() const { return m_items.size(); } 134 unsigned int height() const { return m_window.height(); }
135 int currentSubmenu() const { return m_which_sub; } 135 size_t numberOfItems() const { return m_items.size(); }
136 int currentSubmenu() const { return m_which_sub; }
136 137
137 bool isItemSelected(unsigned int index) const; 138 bool isItemSelected(unsigned int index) const;
138 bool isItemEnabled(unsigned int index) const; 139 bool isItemEnabled(unsigned int index) const;
@@ -159,13 +160,7 @@ public:
159protected: 160protected:
160 161
161 void themeReconfigured(); 162 void themeReconfigured();
162 void setTitleVisibility(bool b) { 163 void setTitleVisibility(bool b);
163 m_title_vis = b; m_need_update = true;
164 if (!b)
165 titleWindow().lower();
166 else
167 titleWindow().raise();
168 }
169 164
170 // renders item onto pm 165 // renders item onto pm
171 int drawItem(FbDrawable &pm, unsigned int index, 166 int drawItem(FbDrawable &pm, unsigned int index,
@@ -199,16 +194,21 @@ private:
199 void drawLine(int index, int size); 194 void drawLine(int index, int size);
200 void fixMenuItemIndices(); 195 void fixMenuItemIndices();
201 196
202 int m_screen_x, m_screen_y; 197 struct Rect {
203 unsigned int m_screen_width, m_screen_height; 198 int x, y;
204 bool m_moving; ///< if we're moving/draging or not 199 unsigned int width, height;
205 bool m_closing; ///< if we're right clicking on the menu title 200 } m_screen;
206 bool m_visible; ///< menu visibility 201
207 bool m_torn; ///< torn from parent 202 struct State {
208 bool m_internal_menu; ///< whether we should destroy this menu or if it's managed somewhere else 203 bool moving;
209 bool m_title_vis; ///< title visibility 204 bool closing; // right click title
205 bool visible;
206 bool torn; // torn from parent
207 } m_state;
210 208
209 bool m_internal_menu; ///< whether we should destroy this menu or if it's managed somewhere else
211 int m_which_sub; 210 int m_which_sub;
211
212 Alignment m_alignment; 212 Alignment m_alignment;
213 213
214 // the menu window 214 // the menu window
@@ -216,14 +216,20 @@ private:
216 Pixmap m_hilite_pixmap; 216 Pixmap m_hilite_pixmap;
217 217
218 // the title 218 // the title
219 FbTk::FbWindow m_title; 219 struct Title {
220 Pixmap m_title_pixmap; 220 FbTk::FbWindow win;
221 FbTk::BiDiString m_label; 221 Pixmap pixmap;
222 FbTk::BiDiString label;
223 bool visible;
224 } m_title;
222 225
223 // area for the menuitems 226 // area for the menuitems
224 FbTk::FbWindow m_frame; 227 struct Frame {
225 Pixmap m_frame_pixmap; 228 FbTk::FbWindow win;
226 unsigned int m_frame_h; 229 Pixmap pixmap;
230 unsigned int height;
231 } m_frame;
232
227 233
228 int m_x_move; 234 int m_x_move;
229 int m_y_move; 235 int m_y_move;