From 10d70ecd54fc678499786ab84279223c5bd776e3 Mon Sep 17 00:00:00 2001 From: fluxgen Date: Wed, 2 Jul 2003 05:26:45 +0000 Subject: added keyboard navigation --- src/FbTk/Menu.cc | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/FbTk/Menu.hh | 14 ++++- 2 files changed, 168 insertions(+), 6 deletions(-) diff --git a/src/FbTk/Menu.cc b/src/FbTk/Menu.cc index 04bcc03..c953be9 100644 --- a/src/FbTk/Menu.cc +++ b/src/FbTk/Menu.cc @@ -22,7 +22,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: Menu.cc,v 1.24 2003/05/24 12:34:16 rathnor Exp $ +// $Id: Menu.cc,v 1.25 2003/07/02 05:26:14 fluxgen Exp $ //use GNU extensions #ifndef _GNU_SOURCE @@ -39,6 +39,8 @@ #include "Transparent.hh" #include +#include + #include #include #include @@ -76,10 +78,12 @@ namespace FbTk { static Menu *shown = 0; unsigned char Menu::s_alpha = 255; +Menu *Menu::s_focused = 0; Menu::Menu(MenuTheme &tm, int screen_num, ImageControl &imgctrl): m_theme(tm), m_screen_num(screen_num), + m_prev_focused_window(0), m_image_ctrl(imgctrl), m_display(FbTk::App::instance()->display()), m_parent(0), @@ -143,13 +147,15 @@ Menu::Menu(MenuTheme &tm, int screen_num, ImageControl &imgctrl): XSetWindowAttributes attrib; attrib.override_redirect = True; attrib.event_mask = ButtonPressMask | ButtonReleaseMask | - ButtonMotionMask | KeyPressMask | ExposureMask; + ButtonMotionMask | KeyPressMask | ExposureMask | FocusChangeMask; //create menu window menu.window = XCreateWindow(m_display, RootWindow(m_display, screen_num), menu.x, menu.y, menu.width, menu.height, 0, CopyFromParent, InputOutput, CopyFromParent, attrib_mask, &attrib); + // strip focus change mask from attrib, since we should only use it with main window + attrib.event_mask ^= FocusChangeMask; FbTk::EventManager &evm = *FbTk::EventManager::instance(); evm.add(*this, menu.window); @@ -199,7 +205,8 @@ Menu::~Menu() { evm.remove(menu.title); evm.remove(menu.frame); evm.remove(menu.window); - + if (s_focused == this) + s_focused = 0; } int Menu::insert(const char *label, RefCount &cmd, int pos) { @@ -280,6 +287,80 @@ void Menu::lower() { menu.window.lower(); } +void Menu::nextItem() { + if (which_press == menuitems.size() - 1) + return; + + int old_which_press = which_press; + + if (old_which_press >= 0 && + old_which_press < menuitems.size() && + menuitems[old_which_press] != 0) { + if (menuitems[old_which_press]->submenu()) { + // we need to do this explicitly on the menu.window + // since it might hide the parent if we use Menu::hide + menuitems[old_which_press]->submenu()->menu.window.hide(); + } + drawItem(old_which_press, false, true, true); + } + + // restore old in case we changed which_press + which_press = old_which_press; + if (which_press < 0 || which_press >= menuitems.size()) + which_press = 0; + else if (which_press < menuitems.size() - 1) + which_press++; + + + if (menuitems[which_press] == 0) + return; + + if (menuitems[which_press]->submenu()) + drawSubmenu(which_press); + else + drawItem(which_press, true, true, true); + +#ifdef DEBUG + cerr<<__FILE__<<"("<<__FUNCTION__<<")"<(menuitems.size()) && w >= 0)) { if (which_press != -1 && which_sbl != -1) { - int p = (which_sbl * menu.persub) + which_press; + int p = which_sbl * menu.persub + which_press; MenuItem *item = menuitems[p]; drawItem(p, false, true, true); @@ -1155,6 +1259,54 @@ void Menu::leaveNotifyEvent(XCrossingEvent &ce) { } } +void Menu::keyPressEvent(XKeyEvent &event) { + KeySym ks; + char keychar[1]; + XLookupString(&event, keychar, 1, &ks, 0); + // a modifier key by itself doesn't do anything + if (IsModifierKey(ks)) + return; + if (event.state) // dont handle modifier with normal key + return; + + switch (ks) { + case XK_Up: + prevItem(); + break; + case XK_Down: + nextItem(); + break; + case XK_Left: + if (which_press >= 0 && which_press < menuitems.size() && + m_parent != 0) { + if (menuitems[which_press]->submenu()) + menuitems[which_press]->submenu()->menu.window.hide(); + drawItem(which_press, false, true, true); + m_parent->grabInputFocus(); + } + break; + case XK_Right: + if (which_press >= 0 && which_press < menuitems.size() && + menuitems[which_press]->submenu()) { + menuitems[which_press]->submenu()->grabInputFocus(); + menuitems[which_press]->submenu()->which_press = -1; + menuitems[which_press]->submenu()->nextItem(); + } + break; + case XK_Escape: + hide(); + break; + case XK_Return: + if (which_press >= 0 && which_press < menuitems.size()) { + menuitems[which_press]->click(1, event.time); + itemSelected(1, which_press); + update(); + } + break; + default: + break; + } +} void Menu::reconfigure() { m_need_update = true; // redraw items diff --git a/src/FbTk/Menu.hh b/src/FbTk/Menu.hh index 5dd0eb8..1803241 100644 --- a/src/FbTk/Menu.hh +++ b/src/FbTk/Menu.hh @@ -22,7 +22,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: Menu.hh,v 1.15 2003/05/13 00:24:00 fluxgen Exp $ +// $Id: Menu.hh,v 1.16 2003/07/02 05:26:45 fluxgen Exp $ #ifndef FBTK_MENU_HH #define FBTK_MENU_HH @@ -85,6 +85,10 @@ public: virtual void raise(); /// lower this window virtual void lower(); + /// select next item + void nextItem(); + /// select previous item + void prevItem(); void disableTitle(); void enableTitle(); @@ -95,14 +99,17 @@ public: @name event handlers */ //@{ + void handleEvent(XEvent &event); void buttonPressEvent(XButtonEvent &bp); void buttonReleaseEvent(XButtonEvent &br); void motionNotifyEvent(XMotionEvent &mn); void enterNotifyEvent(XCrossingEvent &en); void leaveNotifyEvent(XCrossingEvent &ce); void exposeEvent(XExposeEvent &ee); + void keyPressEvent(XKeyEvent &ke); //@} - + /// get input focus + void grabInputFocus(); void reconfigure(); /// set label string void setLabel(const char *labelstr); @@ -142,6 +149,7 @@ public: bool isItemSelected(unsigned int index) const; bool isItemEnabled(unsigned int index) const; static unsigned char alpha() { return s_alpha; } + static Menu *focused() { return s_focused; } /// @return menuitem at index inline const MenuItem *find(unsigned int index) const { return menuitems[index]; } inline MenuItem *find(unsigned int index) { return menuitems[index]; } @@ -170,6 +178,7 @@ private: const MenuTheme &m_theme; Display *m_display; const int m_screen_num; + Window m_prev_focused_window; Menu *m_parent; ImageControl &m_image_ctrl; Menuitems menuitems; @@ -206,6 +215,7 @@ private: std::auto_ptr m_trans; Drawable m_root_pm; static unsigned char s_alpha; + static Menu *s_focused; ///< holds current input focused menu, so one can determine if a menu is focused FbPixmap m_frame_pm; bool m_need_update; }; -- cgit v0.11.2