diff options
author | dmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-31 15:33:01 +0000 |
---|---|---|
committer | dmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-31 15:33:01 +0000 |
commit | cc8243726aa110ed22194e7ebde5ea69430b6ab4 (patch) | |
tree | 455cce5da51deeb47c962ea7c2cb62331e896973 /views/controls/menu/native_menu_gtk.cc | |
parent | 3c5f059a2881b0d990e49cbc2b1e5a3dd4e9df7f (diff) | |
download | chromium_src-cc8243726aa110ed22194e7ebde5ea69430b6ab4.zip chromium_src-cc8243726aa110ed22194e7ebde5ea69430b6ab4.tar.gz chromium_src-cc8243726aa110ed22194e7ebde5ea69430b6ab4.tar.bz2 |
Keyboard accessibility for the page and app menus.
Works on Windows, and on Linux with toolkit_views.
The goal is to make Chrome behave more like a standard Windows
application, for users who rely on the keyboard and expect standard
keyboard accelerators to work.
Pressing F10, or pressing and releasing Alt, will set focus to the
Page menu, as if it was the first item in a menu bar.
Pressing enter, space, up arrow, or down arrow will open the focused menu.
Once a menu is opened, pressing left and right arrows will switch between
the two menus. Pressing escape will return focus to the title of the
previously open menu.
A new UI test attempts to select something from the menus using only the
keyboard. It works on Linux (with toolkit_views) and on Windows.
BUG=none
TEST=New keyboard accessibility interactive ui test.
Review URL: http://codereview.chromium.org/660323
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@43216 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views/controls/menu/native_menu_gtk.cc')
-rw-r--r-- | views/controls/menu/native_menu_gtk.cc | 58 |
1 files changed, 55 insertions, 3 deletions
diff --git a/views/controls/menu/native_menu_gtk.cc b/views/controls/menu/native_menu_gtk.cc index 71af5c8..2654e8c 100644 --- a/views/controls/menu/native_menu_gtk.cc +++ b/views/controls/menu/native_menu_gtk.cc @@ -76,7 +76,8 @@ NativeMenuGtk::NativeMenuGtk(Menu2* menu) activated_menu_(NULL), activated_index_(-1), activate_factory_(this), - host_menu_(menu) { + host_menu_(menu), + menu_action_(MENU_ACTION_NONE) { } NativeMenuGtk::~NativeMenuGtk() { @@ -93,6 +94,7 @@ NativeMenuGtk::~NativeMenuGtk() { void NativeMenuGtk::RunMenuAt(const gfx::Point& point, int alignment) { activated_menu_ = NULL; activated_index_ = -1; + menu_action_ = MENU_ACTION_NONE; UpdateStates(); Position position = { point, static_cast<Menu2::Alignment>(alignment) }; @@ -102,15 +104,25 @@ void NativeMenuGtk::RunMenuAt(const gfx::Point& point, int alignment) { DCHECK(!menu_shown_); menu_shown_ = true; + + for (unsigned int i = 0; i < listeners_.size(); ++i) { + listeners_[i]->OnMenuOpened(); + } + // Listen for "hide" signal so that we know when to return from the blocking // RunMenuAt call. - gint handle_id = + gint hide_handle_id = g_signal_connect(menu_, "hide", G_CALLBACK(OnMenuHiddenThunk), this); + gint move_handle_id = + g_signal_connect(menu_, "move-current", + G_CALLBACK(OnMenuMoveCurrentThunk), this); + // Block until menu is no longer shown by running a nested message loop. MessageLoopForUI::current()->Run(NULL); - g_signal_handler_disconnect(G_OBJECT(menu_), handle_id); + g_signal_handler_disconnect(G_OBJECT(menu_), hide_handle_id); + g_signal_handler_disconnect(G_OBJECT(menu_), move_handle_id); menu_shown_ = false; if (activated_menu_) { @@ -174,6 +186,25 @@ gfx::NativeMenu NativeMenuGtk::GetNativeMenu() const { return menu_; } +NativeMenuGtk::MenuAction NativeMenuGtk::GetMenuAction() const { + return menu_action_; +} + +void NativeMenuGtk::AddMenuListener(MenuListener* listener) { + listeners_.push_back(listener); +} + +void NativeMenuGtk::RemoveMenuListener(MenuListener* listener) { + for (std::vector<MenuListener*>::iterator iter = listeners_.begin(); + iter != listeners_.end(); + ++iter) { + if (*iter == listener) { + listeners_.erase(iter); + return; + } + } +} + //////////////////////////////////////////////////////////////////////////////// // NativeMenuGtk, private: @@ -187,6 +218,26 @@ void NativeMenuGtk::OnMenuHidden(GtkWidget* widget) { MessageLoop::current()->Quit(); } +// static +void NativeMenuGtk::OnMenuMoveCurrent(GtkWidget* menu_widget, + GtkMenuDirectionType focus_direction, + NativeMenuGtk* menu) { + GtkWidget* parent = GTK_MENU_SHELL(menu_widget)->parent_menu_shell; + GtkWidget* menu_item = GTK_MENU_SHELL(menu_widget)->active_menu_item; + GtkWidget* submenu = NULL; + if (menu_item) { + submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu_item)); + } + + if (focus_direction == GTK_MENU_DIR_CHILD && submenu == NULL) { + menu->GetAncestor()->menu_action_ = MENU_ACTION_NEXT; + gtk_menu_popdown(GTK_MENU(menu_widget)); + } else if (focus_direction == GTK_MENU_DIR_PARENT && parent == NULL) { + menu->GetAncestor()->menu_action_ = MENU_ACTION_PREVIOUS; + gtk_menu_popdown(GTK_MENU(menu_widget)); + } +} + void NativeMenuGtk::AddSeparatorAt(int index) { GtkWidget* separator = gtk_separator_menu_item_new(); gtk_widget_show(separator); @@ -374,6 +425,7 @@ void NativeMenuGtk::OnActivate(GtkMenuItem* menu_item) { NativeMenuGtk* ancestor = GetAncestor(); ancestor->activated_menu_ = this; activated_index_ = position; + ancestor->menu_action_ = MENU_ACTION_SELECTED; } } |