diff options
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 a910a76..012d2a8 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(OnMenuHidden), this); + gint move_handle_id = + g_signal_connect(menu_, "move-current", G_CALLBACK(OnMenuMoveCurrent), + 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: @@ -188,6 +219,26 @@ void NativeMenuGtk::OnMenuHidden(GtkWidget* widget, NativeMenuGtk* menu) { MessageLoop::current()->Quit(); } +// static +void NativeMenuGtk::OnMenuMoveCurrent(GtkMenu* 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(menu_widget); + } else if (focus_direction == GTK_MENU_DIR_PARENT && parent == NULL) { + menu->GetAncestor()->menu_action_ = MENU_ACTION_PREVIOUS; + gtk_menu_popdown(menu_widget); + } +} + void NativeMenuGtk::AddSeparatorAt(int index) { GtkWidget* separator = gtk_separator_menu_item_new(); gtk_widget_show(separator); @@ -375,6 +426,7 @@ void NativeMenuGtk::OnActivate(GtkMenuItem* menu_item) { NativeMenuGtk* ancestor = GetAncestor(); ancestor->activated_menu_ = this; activated_index_ = position; + ancestor->menu_action_ = MENU_ACTION_SELECTED; } } |