From feb56381d704d61255ca5b0f0ae60e3f4f5f9986 Mon Sep 17 00:00:00 2001 From: markt <markt> Date: Sun, 21 Jan 2007 18:43:22 +0000 Subject: various changes to menu behavior --- ChangeLog | 6 ++++++ src/FbTk/Menu.cc | 32 ++++++++++++++++++++++++-------- src/FbTk/Menu.hh | 2 ++ src/FocusControl.cc | 22 ++++++++++++++-------- 4 files changed, 46 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1d51ace..e5f6d4b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ (Format: Year/Month/Day) Changes for 1.0rc3: +*07/01/21: + * Several fixes for menu behavior (Mark) + - always give focus to the menu with the highlighted item + - revert focus to menu when no other windows will take it + - don't reopen closed submenus when moving the menu + FocusControl.cc FbTk/Menu.cc/hh *07/01/20: * Make sure styles don't change the lastwallpaper in fbsetbg (Mark) RootTheme.cc diff --git a/src/FbTk/Menu.cc b/src/FbTk/Menu.cc index e7fc6d8..5ee329b 100644 --- a/src/FbTk/Menu.cc +++ b/src/FbTk/Menu.cc @@ -73,7 +73,7 @@ using std::endl; namespace FbTk { -static Menu *shown = 0; +Menu *Menu::shown = 0; Menu *Menu::s_focused = 0; @@ -365,12 +365,14 @@ void Menu::enterSubmenu() { } void Menu::enterParent() { - if (!validIndex(m_which_press) || parent() == 0) + if (parent() == 0) return; - Menu *submenu = menuitems[m_which_press]->submenu(); - if (submenu) - submenu->internal_hide(); + if (validIndex(m_which_press)) { + Menu *submenu = menuitems[m_which_press]->submenu(); + if (submenu) + submenu->internal_hide(); + } m_active_index = -1; //clearItem(m_which_press); @@ -570,6 +572,13 @@ void Menu::hide() { } void Menu::grabInputFocus() { + // if there's a submenu open, focus it instead + if (validIndex(m_which_sub) && + menuitems[m_which_sub]->submenu()->isVisible()) { + menuitems[m_which_sub]->submenu()->grabInputFocus(); + return; + } + s_focused = this; // grab input focus @@ -632,7 +641,8 @@ void Menu::move(int x, int y) { if (alpha() < 255) clearWindow(); - if (m_which_sub != -1) + if (validIndex(m_which_sub) && + menuitems[m_which_sub]->submenu()->isVisible()) drawSubmenu(m_which_sub); } @@ -846,6 +856,10 @@ void Menu::handleEvent(XEvent &event) { } else if (event.type == FocusIn) { if (s_focused != this) s_focused = this; + // if there's a submenu open, focus it instead + if (validIndex(m_which_sub) && + menuitems[m_which_sub]->submenu()->isVisible()) + menuitems[m_which_sub]->submenu()->grabInputFocus(); } } @@ -881,7 +895,8 @@ void Menu::buttonReleaseEvent(XButtonEvent &re) { if (m_moving) { m_moving = false; - if (m_which_sub != -1) + if (validIndex(m_which_sub) && + menuitems[m_which_sub]->submenu()->isVisible()) drawSubmenu(m_which_sub); if (alpha() < 255) { @@ -933,7 +948,8 @@ void Menu::motionNotifyEvent(XMotionEvent &me) { // clear current highlighted item clearItem(m_active_index); - if (m_which_sub >= 0) + if (validIndex(m_which_sub) && + menuitems[m_which_sub]->submenu()->isVisible()) drawSubmenu(m_which_sub); } else { // we dont call ::move here 'cause we dont want to update transparency diff --git a/src/FbTk/Menu.hh b/src/FbTk/Menu.hh index 28eb70a..94a1e6f 100644 --- a/src/FbTk/Menu.hh +++ b/src/FbTk/Menu.hh @@ -160,6 +160,7 @@ public: bool isItemSelectable(unsigned int index) const; inline const MenuTheme &theme() const { return m_theme; } inline unsigned char alpha() const { return theme().alpha(); } + inline static Menu *shownMenu() { return shown; } inline static Menu *focused() { return s_focused; } /// @return menuitem at index inline const MenuItem *find(unsigned int index) const { return menuitems[index]; } @@ -235,6 +236,7 @@ private: int m_active_index; ///< current highlighted index Drawable m_root_pm; + static Menu *shown; ///< used for determining if there's a menu open at all static Menu *s_focused; ///< holds current input focused menu, so one can determine if a menu is focused bool m_need_update; Timer m_submenu_timer; diff --git a/src/FocusControl.cc b/src/FocusControl.cc index 9c82e3e..61d6e87 100644 --- a/src/FocusControl.cc +++ b/src/FocusControl.cc @@ -405,14 +405,20 @@ void FocusControl::revertFocus(BScreen &screen) { // if setting focus fails, or isn't possible, fallback correctly if (!(next_focus && next_focus->focus())) { setFocusedWindow(0); // so we don't get dangling m_focused_window pointer - switch (screen.focusControl().focusModel()) { - case FocusControl::MOUSEFOCUS: - XSetInputFocus(screen.rootWindow().display(), - PointerRoot, None, CurrentTime); - break; - case FocusControl::CLICKFOCUS: - screen.rootWindow().setInputFocus(RevertToPointerRoot, CurrentTime); - break; + // if there's a menu open, focus it + if (FbTk::Menu::shownMenu()) + FbTk::Menu::shownMenu()->grabInputFocus(); + else { + switch (screen.focusControl().focusModel()) { + case FocusControl::MOUSEFOCUS: + XSetInputFocus(screen.rootWindow().display(), + PointerRoot, None, CurrentTime); + break; + case FocusControl::CLICKFOCUS: + screen.rootWindow().setInputFocus(RevertToPointerRoot, + CurrentTime); + break; + } } } -- cgit v0.11.2