aboutsummaryrefslogtreecommitdiff
path: root/src/FbTk/Menu.cc
diff options
context:
space:
mode:
authorfluxgen <fluxgen>2004-06-07 20:28:50 (GMT)
committerfluxgen <fluxgen>2004-06-07 20:28:50 (GMT)
commit34edd2640a35cb825a647e8d37db6cbc8e6afea1 (patch)
tree4845b4d0353b5d9a4d7bd1d2f4a5a8c30a3bb824 /src/FbTk/Menu.cc
parent5530ce6450d0d96f504d000a0cfe4fb29c6c323c (diff)
downloadfluxbox_pavel-34edd2640a35cb825a647e8d37db6cbc8e6afea1.zip
fluxbox_pavel-34edd2640a35cb825a647e8d37db6cbc8e6afea1.tar.bz2
improved transparent rendering and fixed drawing of menu items in MenuItem class
Diffstat (limited to 'src/FbTk/Menu.cc')
-rw-r--r--src/FbTk/Menu.cc512
1 files changed, 268 insertions, 244 deletions
diff --git a/src/FbTk/Menu.cc b/src/FbTk/Menu.cc
index 8736edf..f0e5c59 100644
--- a/src/FbTk/Menu.cc
+++ b/src/FbTk/Menu.cc
@@ -1,5 +1,5 @@
1// Menu.cc for FbTk - Fluxbox Toolkit 1// Menu.cc for FbTk - Fluxbox Toolkit
2// Copyright (c) 2001 - 2003 Henrik Kinnunen (fluxgen at users.sourceforge.net) 2// Copyright (c) 2001 - 2004 Henrik Kinnunen (fluxgen at users.sourceforge.net)
3// 3//
4// Basemenu.cc for blackbox - an X11 Window manager 4// Basemenu.cc for blackbox - an X11 Window manager
5// Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net) 5// Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net)
@@ -22,7 +22,7 @@
22// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23// DEALINGS IN THE SOFTWARE. 23// DEALINGS IN THE SOFTWARE.
24 24
25// $Id: Menu.cc,v 1.61 2004/06/07 11:46:05 rathnor Exp $ 25// $Id: Menu.cc,v 1.62 2004/06/07 20:28:50 fluxgen Exp $
26 26
27//use GNU extensions 27//use GNU extensions
28#ifndef _GNU_SOURCE 28#ifndef _GNU_SOURCE
@@ -31,6 +31,10 @@
31 31
32#include "Menu.hh" 32#include "Menu.hh"
33 33
34#ifdef HAVE_CONFIG_H
35#include "config.h"
36#endif //HAVE_CONFIG_H
37
34#include "MenuItem.hh" 38#include "MenuItem.hh"
35#include "ImageControl.hh" 39#include "ImageControl.hh"
36#include "MenuTheme.hh" 40#include "MenuTheme.hh"
@@ -56,6 +60,28 @@ static Menu *shown = 0;
56 60
57Menu *Menu::s_focused = 0; 61Menu *Menu::s_focused = 0;
58 62
63static Pixmap getRootPixmap(int screen_num) {
64 Pixmap root_pm = 0;
65 // get root pixmap for transparency
66 Display *disp = FbTk::App::instance()->display();
67 Atom real_type;
68 int real_format;
69 unsigned long items_read, items_left;
70 unsigned int *data;
71 if (XGetWindowProperty(disp, RootWindow(disp, screen_num),
72 XInternAtom(disp, "_XROOTPMAP_ID", false),
73 0L, 1L,
74 false, XA_PIXMAP, &real_type,
75 &real_format, &items_read, &items_left,
76 (unsigned char **) &data) == Success &&
77 items_read) {
78 root_pm = (Pixmap) (*data);
79 XFree(data);
80 }
81
82 return root_pm;
83}
84
59Menu::Menu(MenuTheme &tm, ImageControl &imgctrl): 85Menu::Menu(MenuTheme &tm, ImageControl &imgctrl):
60 m_theme(tm), 86 m_theme(tm),
61 m_parent(0), 87 m_parent(0),
@@ -135,23 +161,30 @@ Menu::Menu(MenuTheme &tm, ImageControl &imgctrl):
135 161
136 event_mask |= EnterWindowMask | LeaveWindowMask; 162 event_mask |= EnterWindowMask | LeaveWindowMask;
137 //create menu title 163 //create menu title
138 menu.title = FbTk::FbWindow(menu.window, 164 menu.title = FbTk::FbWindow(menu.window, // parent
139 0, 0, width(), menu.title_h, 165 0, 0, width(), menu.title_h, // pos and size
140 event_mask); 166 event_mask, // mask
167 false, // override redirect
168 true); // save under
141 169
142 evm.add(*this, menu.title); 170 evm.add(*this, menu.title);
143 171
144 event_mask |= PointerMotionMask; 172 event_mask |= PointerMotionMask;
145 menu.frame = FbTk::FbWindow(menu.window, 173 menu.frame = FbTk::FbWindow(menu.window, // parent
146 0, menu.title_h, 174 0, menu.title_h, // pos
147 width(), menu.frame_h ? menu.frame_h : 1, 175 width(), menu.frame_h ? menu.frame_h : 1, // size
148 event_mask, false, true); 176 event_mask, // mask
177 false, // override redirect
178 true); // save under
149 evm.add(*this, menu.frame); 179 evm.add(*this, menu.frame);
180
181
150 // update style 182 // update style
151 reconfigure(); 183 // reconfigure();
152} 184}
153 185
154Menu::~Menu() { 186Menu::~Menu() {
187
155 menu.window.hide(); 188 menu.window.hide();
156 189
157 if (shown && shown->window() == window()) 190 if (shown && shown->window() == window())
@@ -361,35 +394,34 @@ void Menu::update(int active_index) {
361 if (m_border_width > 20) 394 if (m_border_width > 20)
362 m_border_width = 20; 395 m_border_width = 20;
363 396
364 menu.item_h = m_theme.frameFont().height() + menu.bevel_w; 397 if (theme().titleHeight() != 0)
365 menu.title_h = m_theme.titleFont().height() + menu.bevel_w*2; 398 menu.title_h = std::max(theme().titleHeight(), theme().titleFont().height() + menu.bevel_w*2);
399 else
400 menu.title_h = theme().titleFont().height() + menu.bevel_w*2;
401
402 if (theme().itemHeight() != 0)
403 menu.item_h = std::max(theme().itemHeight(), theme().frameFont().height() + menu.bevel_w);
404 else
405 menu.item_h = theme().frameFont().height() + menu.bevel_w;
406
366 407
367 if (title_vis) { 408 if (title_vis) {
368 menu.item_w = m_theme.titleFont().textWidth(menu.label.c_str(), 409 menu.item_w = theme().titleFont().textWidth(menu.label.c_str(),
369 menu.label.size()); 410 menu.label.size());
370 411
371 menu.item_w += (menu.bevel_w * 2); 412 menu.item_w += (menu.bevel_w * 2);
372 } else 413 } else
373 menu.item_w = 1; 414 menu.item_w = 1;
374 415
375 int ii = 0; 416 unsigned int ii = 0;
376 Menuitems::iterator it = menuitems.begin(); 417 Menuitems::iterator it = menuitems.begin();
377 Menuitems::iterator it_end = menuitems.end(); 418 Menuitems::iterator it_end = menuitems.end();
378 for (; it != it_end; ++it) { 419 for (; it != it_end; ++it) {
379 MenuItem *itmp = (*it); 420 ii = (*it)->width(theme());
380 421 menu.item_w = (ii > menu.item_w ? ii : menu.item_w);
381 const char *s = itmp->label().c_str();
382 int l = itmp->label().size();
383
384 ii = m_theme.frameFont().textWidth(s, l);
385
386
387 ii += (menu.bevel_w * 2) + (menu.item_h * 2);
388
389 menu.item_w = ((menu.item_w < (unsigned int) ii) ? ii : menu.item_w);
390 } 422 }
391 423
392 if (menuitems.size()) { 424 if (!menuitems.empty()) {
393 menu.sublevels = 1; 425 menu.sublevels = 1;
394 426
395 while (menu.item_h * (menuitems.size() + 1) / menu.sublevels + 427 while (menu.item_h * (menuitems.size() + 1) / menu.sublevels +
@@ -425,10 +457,10 @@ void Menu::update(int active_index) {
425 457
426 menu.window.resize(new_width, new_height); 458 menu.window.resize(new_width, new_height);
427 459
428 Pixmap tmp; 460 Pixmap tmp = 0;
429 if (title_vis) { 461 if (title_vis && m_need_update) {
430 tmp = menu.title_pixmap; 462 tmp = menu.title_pixmap;
431 const FbTk::Texture &tex = m_theme.titleTexture(); 463 const FbTk::Texture &tex = theme().titleTexture();
432 if (!tex.usePixmap()) { 464 if (!tex.usePixmap()) {
433 menu.title_pixmap = None; 465 menu.title_pixmap = None;
434 menu.title.setBackgroundColor(tex.color()); 466 menu.title.setBackgroundColor(tex.color());
@@ -444,19 +476,21 @@ void Menu::update(int active_index) {
444 } 476 }
445 477
446 tmp = menu.frame_pixmap; 478 tmp = menu.frame_pixmap;
447 const FbTk::Texture &frame_tex = m_theme.frameTexture(); 479 const FbTk::Texture &frame_tex = theme().frameTexture();
448 if (!frame_tex.usePixmap()) { 480 if (m_need_update) {
449 menu.frame_pixmap = None; 481 if (!frame_tex.usePixmap()) {
450 } else { 482 menu.frame_pixmap = None;
451 menu.frame_pixmap = 483 } else {
452 m_image_ctrl.renderImage(width(), menu.frame_h, frame_tex); 484 menu.frame_pixmap =
453 } 485 m_image_ctrl.renderImage(width(), menu.frame_h, frame_tex);
486 }
454 487
455 if (tmp) 488 if (tmp)
456 m_image_ctrl.removeImage(tmp); 489 m_image_ctrl.removeImage(tmp);
457 490
491 }
458 tmp = menu.hilite_pixmap; 492 tmp = menu.hilite_pixmap;
459 const FbTk::Texture &hilite_tex = m_theme.hiliteTexture(); 493 const FbTk::Texture &hilite_tex = theme().hiliteTexture();
460 if (!hilite_tex.usePixmap()) { 494 if (!hilite_tex.usePixmap()) {
461 menu.hilite_pixmap = None; 495 menu.hilite_pixmap = None;
462 } else 496 } else
@@ -495,62 +529,86 @@ void Menu::update(int active_index) {
495 menu.frame.width(), menu.frame.height(), 529 menu.frame.width(), menu.frame.height(),
496 menu.frame.depth()); 530 menu.frame.depth());
497 531
532 m_real_frame_pm = FbTk::FbPixmap(menu.frame.window(),
533 menu.frame.width(), menu.frame.height(),
534 menu.frame.depth());
535
536 menu.frame.setBackgroundPixmap(m_real_frame_pm.drawable());
498 if (m_frame_pm.drawable() == 0) { 537 if (m_frame_pm.drawable() == 0) {
499 _FB_USES_NLS; 538 _FB_USES_NLS;
500 cerr<<"FbTk::Menu: "<<_FBTKTEXT(Error, CreatePixmap, "Error creating pixmap", "Couldn't create a pixmap - image - for some reason")<<" ("<< 539 cerr<<"FbTk::Menu: "<<_FBTKTEXT(Error, CreatePixmap, "Error creating pixmap", "Couldn't create a pixmap - image - for some reason")<<" ("<<
501 menu.frame.window()<<", "<<menu.frame.width()<<", "<< 540 menu.frame.window()<<", "<<menu.frame.width()<<", "<<
502 menu.frame.height()<< 541 menu.frame.height()<<
503 ", "<<menu.frame.depth()<<") !"<<endl; 542 ", "<<menu.frame.depth()<<") !"<<endl;
504 } else if (menu.sublevels > 0 && menu.persub * menu.sublevels != menuitems.size()) { 543 } else if (menu.sublevels > 0 && menu.persub * menu.sublevels != (int)menuitems.size()) {
505 544
506 // TODO: fill only that part of the menuframe with the 545 // TODO: fill only that part of the menuframe with the
507 // pixmap/color, that has actually NO buttons on it 546 // pixmap/color, that has actually NO buttons on it
508 FbTk::GContext def_gc(menu.frame.window()); 547 GContext def_gc(menu.frame);
509 if (menu.frame_pixmap == 0) { 548 if (menu.frame_pixmap == 0) {
510 def_gc.setForeground(m_theme.frameTexture().color()); 549 def_gc.setForeground(m_theme.frameTexture().color());
511 m_frame_pm.fillRectangle(def_gc.gc(), 550 m_frame_pm.fillRectangle(def_gc.gc(),
512 0, 0, 551 0, 0,
513 width(), menu.frame_h); 552 width(), menu.frame_h);
514 553 m_real_frame_pm.fillRectangle(def_gc.gc(),
554 0, 0,
555 width(), menu.frame_h);
515 } else { 556 } else {
516 m_frame_pm.copyArea(menu.frame_pixmap, def_gc.gc(), 557 m_frame_pm.copyArea(menu.frame_pixmap, def_gc.gc(),
517 0, 0, 558 0, 0,
518 0, 0, 559 0, 0,
519 width(), menu.frame_h); 560 width(), menu.frame_h);
561
562 m_real_frame_pm.copyArea(menu.frame_pixmap,
563 def_gc.gc(),
564 0, 0,
565 0, 0,
566 width(), menu.frame_h);
520 } 567 }
568
521 } 569 }
570
522 } 571 }
523 572
524 menu.frame.setBackgroundPixmap(m_frame_pm.drawable()); 573 // if menu visible and title visible
525
526 // clearWindow();
527
528 if (title_vis && visible) 574 if (title_vis && visible)
529 redrawTitle(); 575 redrawTitle();
530 576
531 if (active_index >= 0) { 577 if (active_index >= 0 && visible) {
532 for (unsigned int i = 0; visible && i < menuitems.size(); i++) { 578 renderTransp(0, 0,
579 m_real_frame_pm.width(), m_real_frame_pm.height());
580 for (unsigned int i = 0; i < menuitems.size(); i++) {
533 if (i == (unsigned int)which_sub) { 581 if (i == (unsigned int)which_sub) {
534 drawItem(i, true, true, false); 582 drawItem(i, true, // highlight
583 true, // clear
584 false); // render_trans
535 } else 585 } else
536 drawItem(i, (static_cast<signed>(i) == active_index && isItemEnabled(i)), true, false); 586 drawItem(i,
587 // high light
588 (static_cast<signed>(i) == active_index && isItemEnabled(i)),
589 true, // clear
590 false); // render transparent
537 } 591 }
538 592
539 if (m_parent && visible) 593 if (m_parent)
540 m_parent->drawSubmenu(m_parent->which_sub); 594 m_parent->drawSubmenu(m_parent->which_sub);
595 /*
596 renderTransp(0, active_index*menu.item_h,
597 width(), menu.item_h);
598 */
541 599
542 menu.frame.clearArea(0, active_index * menu.item_h, 600 }
543 width(), menu.item_h);
544 menu.frame.updateTransparent(0, active_index * menu.item_h,
545 width(), menu.item_h);
546 601
602 if (m_need_update) {
603 for (unsigned int i = 0; i < menuitems.size(); i++) {
604 if (i == (unsigned int)which_sub) {
605 drawItem(i, true, true, false);
606 } else
607 drawItem(i, (static_cast<signed>(i) == active_index && isItemEnabled(i)), true, true);
608 }
547 } 609 }
548 610
549 menu.window.clear();
550 renderTransFrame();
551
552 m_need_update = false; 611 m_need_update = false;
553 menu.window.showSubwindows();
554} 612}
555 613
556 614
@@ -559,7 +617,6 @@ void Menu::show() {
559 update(); 617 update();
560 menu.window.showSubwindows(); 618 menu.window.showSubwindows();
561 menu.window.show(); 619 menu.window.show();
562 //!! TODO, this should probably be done explicit if one don't want to raise
563 raise(); 620 raise();
564 visible = true; 621 visible = true;
565 622
@@ -596,7 +653,11 @@ void Menu::grabInputFocus() {
596 653
597void Menu::clearWindow() { 654void Menu::clearWindow() {
598 menu.window.clear(); 655 menu.window.clear();
599 menu.title.clear(); 656 redrawTitle();
657
658 renderTransp(0, 0,
659 m_real_frame_pm.width(), m_real_frame_pm.height());
660
600 menu.frame.clear(); 661 menu.frame.clear();
601} 662}
602 663
@@ -627,9 +688,14 @@ void Menu::move(int x, int y) {
627 if (which_sub != -1) 688 if (which_sub != -1)
628 drawSubmenu(which_sub); 689 drawSubmenu(which_sub);
629 690
691 redrawTitle();
630 if (!(m_parent && m_parent->moving) && !torn) { 692 if (!(m_parent && m_parent->moving) && !torn) {
631 redrawTitle(); 693
632 renderTransFrame(); 694 renderTransp(0, 0,
695 m_real_frame_pm.width(), m_real_frame_pm.height());
696 } else if (!moving) {
697 renderTransp(0, 0,
698 m_real_frame_pm.width(), m_real_frame_pm.height());
633 } 699 }
634} 700}
635 701
@@ -652,15 +718,18 @@ void Menu::redrawTitle() {
652 default: 718 default:
653 break; 719 break;
654 } 720 }
721
722 if (menu.title.alpha() != alpha())
723 menu.title.setAlpha(alpha());
724
655 menu.title.clear(); 725 menu.title.clear();
726 menu.title.updateTransparent();
656 font.drawText(menu.title.window(), // drawable 727 font.drawText(menu.title.window(), // drawable
657 screenNumber(), 728 screenNumber(),
658 m_theme.titleTextGC().gc(), // graphic context 729 m_theme.titleTextGC().gc(), // graphic context
659 text, len, // text string with lenght 730 text, len, // text string with lenght
660 dx, font.ascent() + menu.bevel_w); // position 731 dx, font.ascent() + menu.bevel_w); // position
661 732
662 menu.title.updateTransparent();
663
664} 733}
665 734
666 735
@@ -697,7 +766,7 @@ void Menu::drawSubmenu(unsigned int index) {
697 (menu.item_h * i) + 766 (menu.item_h * i) +
698 ((title_vis) ? menu.title_h + menu.window.borderWidth() : 0) - 767 ((title_vis) ? menu.title_h + menu.window.borderWidth() : 0) -
699 ((item->submenu()->title_vis) ? 768 ((item->submenu()->title_vis) ?
700 item->submenu()->menu.title_h + menu.window.borderWidth() : 0)); 769 item->submenu()->menu.title_h + menu.window.borderWidth() : 0));
701 } 770 }
702 771
703 if (m_alignment == ALIGNBOTTOM && 772 if (m_alignment == ALIGNBOTTOM &&
@@ -752,50 +821,24 @@ bool Menu::hasSubmenu(unsigned int index) const {
752 821
753 822
754int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_trans, 823int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_trans,
755 int x, int y, unsigned int w, unsigned int h) { 824 int x, int y, unsigned int w, unsigned int h) {
756 if (index >= menuitems.size() || menuitems.size() == 0 || 825 if (index >= menuitems.size() || menuitems.size() == 0 ||
757 menu.persub == 0) 826 menu.persub == 0)
758 return 0; 827 return 0;
759 828
760 MenuItem *item = menuitems[index]; 829 MenuItem *item = menuitems[index];
761 if (! item) return 0; 830 if (! item) return 0;
762 831
763 bool dotext = true, dohilite = true, dosel = true;
764 const char *text = item->label().c_str();
765 int sbl = index / menu.persub, i = index - (sbl * menu.persub); 832 int sbl = index / menu.persub, i = index - (sbl * menu.persub);
766 int item_x = (sbl * menu.item_w), item_y = (i * menu.item_h); 833 int item_x = (sbl * menu.item_w), item_y = (i * menu.item_h);
767 int hilite_x = item_x, hilite_y = item_y, hoff_x = 0, hoff_y = 0; 834 int hilite_x = item_x, hilite_y = item_y, hoff_x = 0, hoff_y = 0;
768 int text_x = 0, text_y = 0, len = strlen(text), sel_x = 0, sel_y = 0; 835 int sel_x = 0, sel_y = 0;
769 unsigned int hilite_w = menu.item_w, hilite_h = menu.item_h, text_w = 0, text_h = 0; 836 unsigned int hilite_w = menu.item_w, hilite_h = menu.item_h;
770 unsigned int half_w = menu.item_h / 2, quarter_w = menu.item_h / 4; 837 unsigned int half_w = menu.item_h / 2, quarter_w = menu.item_h / 4;
771 const FbTk::Font &font = m_theme.frameFont();
772 if (text) {
773 text_w = font.textWidth(text, len);
774
775 text_y = item_y + menu.bevel_w/2 + font.ascent();
776
777 switch(m_theme.frameFontJustify()) {
778 case FbTk::LEFT:
779 text_x = item_x + menu.bevel_w + menu.item_h + 1;
780 break;
781
782 case FbTk::RIGHT:
783 text_x = item_x + menu.item_w - (menu.item_h + menu.bevel_w + text_w);
784 break;
785 default: //center
786 text_x = item_x + ((menu.item_w + 1 - text_w) / 2);
787 break;
788 }
789 838
790 text_h = menu.item_h - menu.bevel_w;
791 }
792
793 GC gc = 839 GC gc =
794 ((highlight || item->isSelected()) ? m_theme.hiliteTextGC().gc() : 840 ((highlight || item->isSelected()) ? m_theme.hiliteTextGC().gc() :
795 m_theme.frameTextGC().gc()); 841 m_theme.frameTextGC().gc());
796 const GContext &tgc =
797 (highlight ? m_theme.hiliteTextGC() :
798 (item->isEnabled() ? m_theme.frameTextGC() : m_theme.disableTextGC() ) );
799 842
800 sel_x = item_x; 843 sel_x = item_x;
801 844
@@ -806,7 +849,7 @@ int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_t
806 sel_y = item_y + quarter_w; 849 sel_y = item_y + quarter_w;
807 850
808 if (clear) { 851 if (clear) {
809 FbTk::GContext def_gc(menu.frame.window()); 852 GContext def_gc(menu.frame);
810 if (menu.frame_pixmap == 0) { 853 if (menu.frame_pixmap == 0) {
811 def_gc.setForeground(m_theme.frameTexture().color()); 854 def_gc.setForeground(m_theme.frameTexture().color());
812 m_frame_pm.fillRectangle(def_gc.gc(), item_x, item_y, menu.item_w, menu.item_h); 855 m_frame_pm.fillRectangle(def_gc.gc(), item_x, item_y, menu.item_w, menu.item_h);
@@ -820,10 +863,8 @@ int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_t
820 } 863 }
821 } else if (! (x == y && y == -1 && w == h && h == 0)) { 864 } else if (! (x == y && y == -1 && w == h && h == 0)) {
822 // calculate the which part of the hilite to redraw 865 // calculate the which part of the hilite to redraw
823 if (! (std::max(item_x, x) <= (signed) std::min(item_x + menu.item_w, x + w) && 866 if (!(std::max(item_x, x) <= (signed) std::min(item_x + menu.item_w, x + w) &&
824 std::max(item_y, y) <= (signed) std::min(item_y + menu.item_h, y + h))) { 867 std::max(item_y, y) <= (signed) std::min(item_y + menu.item_h, y + h))) {
825 dohilite = False;
826 } else {
827 hilite_x = std::max(item_x, x); 868 hilite_x = std::max(item_x, x);
828 hilite_y = std::max(item_y, y); 869 hilite_y = std::max(item_y, y);
829 hilite_w = std::min(item_x + menu.item_w, x + w) - hilite_x; 870 hilite_w = std::min(item_x + menu.item_w, x + w) - hilite_x;
@@ -832,20 +873,9 @@ int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_t
832 hoff_y = hilite_y % menu.item_h; 873 hoff_y = hilite_y % menu.item_h;
833 } 874 }
834 875
835 // check if we need to redraw the text
836 int text_ry = item_y + (menu.bevel_w / 2);
837 if (! (std::max(text_x, x) <= (signed) std::min(text_x + text_w, x + w) &&
838 std::max(text_ry, y) <= (signed) std::min(text_ry + text_h, y + h)))
839 dotext = false;
840
841 // check if we need to redraw the select pixmap/menu bullet
842 if (! (std::max(sel_x, x) <= (signed) std::min(sel_x + half_w, x + w) &&
843 std::max(sel_y, y) <= (signed) std::min(sel_y + half_w, y + h)))
844 dosel = false;
845
846 } 876 }
847 877
848 if (dohilite && highlight && (menu.hilite_pixmap != ParentRelative)) { 878 if (highlight && (menu.hilite_pixmap != ParentRelative)) {
849 if (menu.hilite_pixmap) { 879 if (menu.hilite_pixmap) {
850 m_frame_pm.copyArea(menu.hilite_pixmap, 880 m_frame_pm.copyArea(menu.hilite_pixmap,
851 m_theme.hiliteGC().gc(), hoff_x, hoff_y, 881 m_theme.hiliteGC().gc(), hoff_x, hoff_y,
@@ -859,8 +889,7 @@ int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_t
859 } 889 }
860 890
861 891
862 if (item->isToggleItem() && item->isSelected() && 892 if (item->isToggleItem() && item->isSelected()) {
863 menu.sel_pixmap != ParentRelative) {
864 if (m_theme.selectedPixmap().pixmap().drawable()) { 893 if (m_theme.selectedPixmap().pixmap().drawable()) {
865 // enable clip mask 894 // enable clip mask
866 XSetClipMask(FbTk::App::instance()->display(), 895 XSetClipMask(FbTk::App::instance()->display(),
@@ -892,119 +921,22 @@ int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_t
892 } 921 }
893 } 922 }
894 923
895 } else if (item->isToggleItem() && m_theme.unselectedPixmap().pixmap().drawable() != 0) {
896 // enable clip mask
897 XSetClipMask(FbTk::App::instance()->display(),
898 gc,
899 m_theme.unselectedPixmap().mask().drawable());
900 XSetClipOrigin(FbTk::App::instance()->display(),
901 gc, sel_x, item_y);
902 // copy bullet pixmap to frame
903 m_frame_pm.copyArea(m_theme.unselectedPixmap().pixmap().drawable(),
904 gc,
905 0, 0,
906 sel_x, item_y,
907 m_theme.unselectedPixmap().width(),
908 m_theme.unselectedPixmap().height());
909 // disable clip mask
910 XSetClipMask(FbTk::App::instance()->display(),
911 gc,
912 None);
913 }
914
915 if (dotext && text) {
916 //!! TODO: this is just temporarly and will be removed
917 // once we've cleaned up the menu code this will be somewhere else...
918 if (strcmp(text, "---") == 0){ // draw separator
919 m_frame_pm.drawRectangle(tgc.gc(),
920 item_x + menu.bevel_w + menu.item_h + 1, item_y + (menu.item_h / 2),
921 menu.item_w - ((menu.bevel_w + menu.item_h) * 2) - 1, 0);
922 } else { // draw normal text
923 m_theme.frameFont().drawText(m_frame_pm.drawable(), // drawable
924 screenNumber(),
925 tgc.gc(),
926 text, len, // text string and lenght
927 text_x, text_y); // position
928 }
929 } 924 }
930 925
931 if (dosel && item->submenu()) { 926 if (render_trans)
932 if (m_theme.bulletPixmap().pixmap().drawable() != 0) { 927 renderTransp(item_x, item_y,
933 // enable clip mask 928 width(), menu.item_h);
934 XSetClipMask(FbTk::App::instance()->display(), 929
935 gc, 930 item->draw(m_real_frame_pm, m_theme, highlight,
936 m_theme.bulletPixmap().mask().drawable()); 931 item_x, item_y,
937 XSetClipOrigin(FbTk::App::instance()->display(), 932 menu.item_w, menu.item_h);
938 gc, sel_x, item_y); 933
939 // copy bullet pixmap to frame 934
940 m_frame_pm.copyArea(m_theme.bulletPixmap().pixmap().drawable(), 935 if (clear)
941 gc, 936 menu.frame.clearArea(item_x, item_y,
942 0, 0, 937 menu.item_w, menu.item_h, False);
943 sel_x, item_y,
944 m_theme.bulletPixmap().width(),
945 m_theme.bulletPixmap().height());
946 // disable clip mask
947 XSetClipMask(FbTk::App::instance()->display(),
948 gc,
949 None);
950 } else {
951 switch (m_theme.bullet()) {
952 case MenuTheme::SQUARE:
953 m_frame_pm.drawRectangle(gc, sel_x, sel_y, half_w, half_w);
954 break;
955
956 case MenuTheme::TRIANGLE:
957 XPoint tri[3];
958
959 if (m_theme.bulletPos() == FbTk::RIGHT) {
960 tri[0].x = sel_x + quarter_w - 2;
961 tri[0].y = sel_y + quarter_w - 2;
962 tri[1].x = 4;
963 tri[1].y = 2;
964 tri[2].x = -4;
965 tri[2].y = 2;
966 } else {
967 tri[0].x = sel_x + quarter_w - 2;
968 tri[0].y = item_y + half_w;
969 tri[1].x = 4;
970 tri[1].y = 2;
971 tri[2].x = 0;
972 tri[2].y = -4;
973 }
974
975 m_frame_pm.fillPolygon(gc, tri, 3, Convex,
976 CoordModePrevious);
977 break;
978
979 case MenuTheme::DIAMOND:
980 XPoint dia[4];
981
982 dia[0].x = sel_x + quarter_w - 3;
983 dia[0].y = item_y + half_w;
984 dia[1].x = 3;
985 dia[1].y = -3;
986 dia[2].x = 3;
987 dia[2].y = 3;
988 dia[3].x = -3;
989 dia[3].y = 3;
990
991 m_frame_pm.fillPolygon(gc, dia, 4, Convex,
992 CoordModePrevious);
993 break;
994 default:
995 break;
996 }
997 }
998 }
999 938
1000 menu.frame.clearArea(item_x, item_y,
1001 menu.item_w, menu.item_h, False);
1002 939
1003 if (render_trans) {
1004 menu.frame.updateTransparent(item_x, item_y,
1005 menu.item_w, menu.item_h);
1006 }
1007
1008 return item_y; 940 return item_y;
1009} 941}
1010 942
@@ -1088,6 +1020,7 @@ void Menu::buttonPressEvent(XButtonEvent &be) {
1088 drawSubmenu(w); 1020 drawSubmenu(w);
1089 } else 1021 } else
1090 drawItem(w, item->isEnabled(), true, true); 1022 drawItem(w, item->isEnabled(), true, true);
1023
1091 } 1024 }
1092 } else { 1025 } else {
1093 menu.x_move = be.x_root - x(); 1026 menu.x_move = be.x_root - x();
@@ -1103,7 +1036,18 @@ void Menu::buttonReleaseEvent(XButtonEvent &re) {
1103 1036
1104 if (which_sub >= 0) 1037 if (which_sub >= 0)
1105 drawSubmenu(which_sub); 1038 drawSubmenu(which_sub);
1106 update(); 1039 if (alpha() < 255) {
1040 //m_need_update = true;
1041 // update();
1042 renderTransp(0, 0,
1043 m_real_frame_pm.width(), m_real_frame_pm.height());
1044 for (size_t i=0; i < menuitems.size(); ++i) {
1045 drawItem(i, false, // highlight
1046 true, // clear
1047 false); // transparent
1048
1049 }
1050 }
1107 } 1051 }
1108 1052
1109 if (re.x >= 0 && re.x <= (signed) width() && 1053 if (re.x >= 0 && re.x <= (signed) width() &&
@@ -1126,9 +1070,8 @@ void Menu::buttonReleaseEvent(XButtonEvent &re) {
1126 re.y > iy && re.y < (signed) (iy + menu.item_h)) { 1070 re.y > iy && re.y < (signed) (iy + menu.item_h)) {
1127 menuitems[w]->click(re.button, re.time); 1071 menuitems[w]->click(re.button, re.time);
1128 itemSelected(re.button, w); 1072 itemSelected(re.button, w);
1129 // redraw whole menu as enableds for any item 1073 // just redraw this item
1130 // may have changed 1074 drawItem(w, true, true, true);
1131 update(w);
1132 } 1075 }
1133 } else { 1076 } else {
1134 drawItem(p, isItemEnabled(p) && (p == which_sub), true, true); 1077 drawItem(p, isItemEnabled(p) && (p == which_sub), true, true);
@@ -1140,11 +1083,12 @@ void Menu::buttonReleaseEvent(XButtonEvent &re) {
1140 1083
1141 1084
1142void Menu::motionNotifyEvent(XMotionEvent &me) { 1085void Menu::motionNotifyEvent(XMotionEvent &me) {
1143 1086 // if draging the with the titlebar:
1144 if (me.window == menu.title && (me.state & Button1Mask)) { 1087 if (me.window == menu.title && (me.state & Button1Mask)) {
1145 stopHide(); 1088 stopHide();
1146 if (movable) { 1089 if (movable) {
1147 if (! moving) { 1090 if (! moving) {
1091 // if not moving: start moving operation
1148 if (m_parent && (! torn)) { 1092 if (m_parent && (! torn)) {
1149 m_parent->drawItem(m_parent->which_sub, false, true, true); 1093 m_parent->drawItem(m_parent->which_sub, false, true, true);
1150 m_parent->which_sub = -1; 1094 m_parent->which_sub = -1;
@@ -1178,7 +1122,9 @@ void Menu::motionNotifyEvent(XMotionEvent &me) {
1178 // don't redraw disabled items on enter/leave 1122 // don't redraw disabled items on enter/leave
1179 if (item != 0 && item->isEnabled()) { 1123 if (item != 0 && item->isEnabled()) {
1180 1124
1181 drawItem(p, false, true, true); 1125 drawItem(p, false, // highlight
1126 true, // clear
1127 true); // transparent
1182 1128
1183 if (item->submenu()) { 1129 if (item->submenu()) {
1184 1130
@@ -1200,7 +1146,7 @@ void Menu::motionNotifyEvent(XMotionEvent &me) {
1200 1146
1201 if (itmp->submenu()) { 1147 if (itmp->submenu()) {
1202 1148
1203 drawItem(w, true); 1149 drawItem(w, true, true);
1204 1150
1205 if (theme().menuMode() == MenuTheme::DELAY_OPEN) { 1151 if (theme().menuMode() == MenuTheme::DELAY_OPEN) {
1206 // setup show menu timer 1152 // setup show menu timer
@@ -1226,6 +1172,12 @@ void Menu::exposeEvent(XExposeEvent &ee) {
1226 if (ee.window == menu.title) { 1172 if (ee.window == menu.title) {
1227 redrawTitle(); 1173 redrawTitle();
1228 } else if (ee.window == menu.frame) { 1174 } else if (ee.window == menu.frame) {
1175
1176 if (moving) {
1177 menu.frame.clearArea(ee.x, ee.y, ee.width, ee.height);
1178 return;
1179 }
1180
1229 // this is a compilicated algorithm... lets do it step by step... 1181 // this is a compilicated algorithm... lets do it step by step...
1230 // first... we see in which sub level the expose starts... and how many 1182 // first... we see in which sub level the expose starts... and how many
1231 // items down in that sublevel 1183 // items down in that sublevel
@@ -1259,16 +1211,20 @@ void Menu::exposeEvent(XExposeEvent &ee) {
1259 unsigned int index = row + (col * menu.persub); 1211 unsigned int index = row + (col * menu.persub);
1260 max_y = max(drawItem(index, 1212 max_y = max(drawItem(index,
1261 (which_sub == static_cast<signed>(index)), // highlight 1213 (which_sub == static_cast<signed>(index)), // highlight
1262 true, // clear 1214 false, // clear
1263 false, // render trans 1215 true), max_y); // render trans
1264 ee.x, ee.y, ee.width, ee.height), max_y); 1216 // ee.x, ee.y, ee.width, ee.height), max_y);
1265 } 1217 }
1266 } 1218 }
1267 } 1219 }
1220
1221 menu.frame.clearArea(ee.x, ee.y, ee.width, ee.height);
1222 /*
1268 menu.frame.updateTransparent(start_column * menu.item_w, 1223 menu.frame.updateTransparent(start_column * menu.item_w,
1269 start_row * menu.item_h, 1224 start_row * menu.item_h,
1270 (end_column-start_column+1) * menu.item_w, 1225 (end_column-start_column+1) * menu.item_w,
1271 (end_row-start_row+1) * menu.item_h); 1226 (end_row-start_row+1) * menu.item_h);
1227 */
1272 } 1228 }
1273} 1229}
1274 1230
@@ -1373,10 +1329,24 @@ void Menu::keyPressEvent(XKeyEvent &event) {
1373} 1329}
1374 1330
1375void Menu::reconfigure() { 1331void Menu::reconfigure() {
1332
1333
1334 if (alpha() == 255 && m_transp.get() != 0) {
1335 m_transp.reset(0);
1336 } else if (alpha () < 255) {
1337
1338 if (m_transp.get() == 0) {
1339 m_transp.reset(new Transparent(getRootPixmap(screenNumber()),
1340 m_real_frame_pm.drawable(), alpha(),
1341 screenNumber()));
1342 } else
1343 m_transp->setAlpha(alpha());
1344 }
1345
1376 m_need_update = true; // redraw items 1346 m_need_update = true; // redraw items
1377 1347
1378 menu.bevel_w = m_theme.bevelWidth(); 1348 menu.bevel_w = theme().bevelWidth();
1379 m_border_width = m_theme.borderWidth(); 1349 m_border_width = theme().borderWidth();
1380 1350
1381 if (menu.bevel_w > 10) // clamp to "normal" size 1351 if (menu.bevel_w > 10) // clamp to "normal" size
1382 menu.bevel_w = 10; 1352 menu.bevel_w = 10;
@@ -1386,6 +1356,7 @@ void Menu::reconfigure() {
1386 if (m_border_width < 0) 1356 if (m_border_width < 0)
1387 m_border_width = 0; 1357 m_border_width = 0;
1388 1358
1359 menu.title.setAlpha(alpha());
1389 menu.window.setBackgroundColor(m_theme.borderColor()); 1360 menu.window.setBackgroundColor(m_theme.borderColor());
1390 menu.title.setBackgroundColor(m_theme.borderColor()); 1361 menu.title.setBackgroundColor(m_theme.borderColor());
1391 1362
@@ -1396,17 +1367,10 @@ void Menu::reconfigure() {
1396 menu.window.setBorderWidth(m_border_width); 1367 menu.window.setBorderWidth(m_border_width);
1397 menu.title.setBorderWidth(m_border_width); 1368 menu.title.setBorderWidth(m_border_width);
1398 1369
1399 menu.frame.setAlpha(alpha());
1400 menu.title.setAlpha(alpha());
1401 menu.window.setAlpha(alpha());
1402 1370
1403 update(); 1371 update();
1404} 1372}
1405 1373
1406void Menu::renderTransFrame() {
1407 menu.frame.clear();
1408 menu.frame.updateTransparent();
1409}
1410 1374
1411void Menu::openSubmenu() { 1375void Menu::openSubmenu() {
1412 if (!isVisible() || which_press < 0 || which_press >= static_cast<signed>(menuitems.size()) || 1376 if (!isVisible() || which_press < 0 || which_press >= static_cast<signed>(menuitems.size()) ||
@@ -1417,7 +1381,7 @@ void Menu::openSubmenu() {
1417 if (item < 0 || item >= static_cast<signed>(menuitems.size())) 1381 if (item < 0 || item >= static_cast<signed>(menuitems.size()))
1418 return; 1382 return;
1419 1383
1420 drawItem(item, true); 1384 drawItem(item, true, true);
1421 if (menuitems[item]->submenu() != 0 && !menuitems[item]->submenu()->isVisible()) 1385 if (menuitems[item]->submenu() != 0 && !menuitems[item]->submenu()->isVisible())
1422 drawSubmenu(item); 1386 drawSubmenu(item);
1423 1387
@@ -1440,4 +1404,64 @@ void Menu::stopHide() {
1440 m_hide_timer.stop(); 1404 m_hide_timer.stop();
1441} 1405}
1442 1406
1407void Menu::update(FbTk::Subject *subj) {
1408
1409 m_need_update = true;
1410
1411 Menuitems::iterator it = menuitems.begin();
1412 Menuitems::iterator it_end = menuitems.end();
1413 for (; it != it_end; ++it)
1414 (*it)->updateTheme(theme());
1415 reconfigure();
1416}
1417
1418void Menu::renderTransp(int x, int y,
1419 unsigned int width, unsigned int height) {
1420 GContext def_gc(menu.frame);
1421 m_real_frame_pm.copyArea(m_frame_pm.drawable(),
1422 def_gc.gc(),
1423 x, y,
1424 x, y,
1425 width, height);
1426 if (m_transp.get() == 0)
1427 return;
1428
1429#ifdef HAVE_XRENDER
1430
1431 Pixmap root = getRootPixmap(screenNumber());
1432 if (m_transp->source() != root)
1433 m_transp->setSource(root, screenNumber());
1434
1435
1436
1437 if (m_transp->dest() != m_real_frame_pm.drawable())
1438 m_transp->setDest(m_real_frame_pm.drawable(), screenNumber());
1439
1440 if (m_transp->alpha() != alpha())
1441 m_transp->setAlpha(alpha());
1442
1443 const FbWindow *root_parent = menu.frame.parent();
1444 // our position in parent ("root")
1445 int root_x = menu.frame.x() - menu.frame.borderWidth(),
1446 root_y = menu.frame.y() - menu.frame.borderWidth();
1447 if (root_parent != 0) {
1448 root_x += root_parent->x() + root_parent->borderWidth();
1449 root_y += root_parent->y() + root_parent->borderWidth();
1450 while (root_parent->parent() != 0) {
1451 root_parent = root_parent->parent();
1452 root_x += root_parent->x() + root_parent->borderWidth();
1453 root_y += root_parent->y() + root_parent->borderWidth();
1454 }
1455
1456 } // else toplevel window so we already have x, y set
1457
1458 // render background image from root pos to our window
1459 m_transp->render(root_x + x, root_y + y,
1460 x, y,
1461 width, height);
1462
1463#endif // HAVE_XRENDER
1464
1465}
1466
1443}; // end namespace FbTk 1467}; // end namespace FbTk