all repos — fluxbox @ 10d70ecd54fc678499786ab84279223c5bd776e3

custom fork of the fluxbox windowmanager

added keyboard navigation
fluxgen fluxgen
commit

10d70ecd54fc678499786ab84279223c5bd776e3

parent

2737e94b242ffc38f4d6760512ba794755603bf7

2 files changed, 168 insertions(+), 6 deletions(-)

jump to
M src/FbTk/Menu.ccsrc/FbTk/Menu.cc

@@ -22,7 +22,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING

// 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 "EventManager.hh"

#include "Transparent.hh" #include <X11/Xatom.h> +#include <X11/keysym.h> + #include <cstdio> #include <cstdlib> #include <cstring>

@@ -76,10 +78,12 @@

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 @@ unsigned long attrib_mask = CWOverrideRedirect | CWEventMask;

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 @@ FbTk::EventManager &evm = *FbTk::EventManager::instance();

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<Command> &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__<<")"<<endl; + cerr<<"which_press = "<<which_press<<endl; +#endif // DEBUG + +} + +void Menu::prevItem() { + + int old_which_press = which_press; + + if (old_which_press >= 0 && old_which_press < menuitems.size()) { + 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 - 1 >= 0) + which_press--; + + if (menuitems[which_press] != 0) { + if (menuitems[which_press]->submenu()) + drawSubmenu(which_press); + else + drawItem(which_press, true, true, true); + } + +#ifdef DEBUG + cerr<<__FILE__<<"("<<__FUNCTION__<<")"<<endl; + cerr<<"which_press = "<<which_press<<endl; +#endif // DEBUG + +} + void Menu::disableTitle() { setTitleVisibility(false); }

@@ -486,7 +567,17 @@ p = p->m_parent;

p->internal_hide(); } else internal_hide(); + } + +void Menu::grabInputFocus() { + s_focused = this; + + // grab input focus + menu.window.setInputFocus(RevertToPointerRoot, CurrentTime); + +} + void Menu::clearWindow() { menu.window.clear();

@@ -925,9 +1016,22 @@

return item->isEnabled(); } +void Menu::handleEvent(XEvent &event) { + if (event.type == FocusOut) { + cerr<<"Focus out"<<endl; + if (s_focused == this) + s_focused = 0; + } else if (event.type == FocusIn) { + cerr<<"Focus in"<<endl; + if (s_focused != this) + s_focused = this; + } +} void Menu::buttonPressEvent(XButtonEvent &be) { + grabInputFocus(); if (be.window == menu.frame && menu.item_h != 0 && menu.item_w != 0) { + int sbl = (be.x / menu.item_w), i = (be.y / menu.item_h); int w = (sbl * menu.persub) + i;

@@ -1025,7 +1129,7 @@

if ((i != which_press || sbl != which_sbl) && (w < static_cast<int>(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 @@ drawSubmenu(which_sub);

} } +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
M src/FbTk/Menu.hhsrc/FbTk/Menu.hh

@@ -22,7 +22,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING

// 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 @@ /// raise this window

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 @@ /**

@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 @@ bool hasSubmenu(unsigned int index) const;

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 @@ typedef std::vector<MenuItem *> Menuitems;

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 @@ ThemeObserver m_themeobserver;

std::auto_ptr<Transparent> 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; };