Index: chrome/browser/gtk/menu_bar_helper.cc |
=================================================================== |
--- chrome/browser/gtk/menu_bar_helper.cc (revision 71352) |
+++ chrome/browser/gtk/menu_bar_helper.cc (working copy) |
@@ -1,183 +0,0 @@ |
-// Copyright (c) 2009 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome/browser/gtk/menu_bar_helper.h" |
- |
-#include <algorithm> |
- |
-#include "app/gtk_signal_registrar.h" |
-#include "base/logging.h" |
-#include "chrome/browser/gtk/gtk_util.h" |
- |
-namespace { |
- |
-// Recursively find all the GtkMenus that are attached to menu item |child| |
-// and add them to |data|, which is a vector of GtkWidgets. |
-void PopulateSubmenus(GtkWidget* child, gpointer data) { |
- std::vector<GtkWidget*>* submenus = |
- static_cast<std::vector<GtkWidget*>*>(data); |
- GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(child)); |
- if (submenu) { |
- submenus->push_back(submenu); |
- gtk_container_foreach(GTK_CONTAINER(submenu), PopulateSubmenus, submenus); |
- } |
-} |
- |
-// Is the cursor over |menu| or one of its parent menus? |
-bool MotionIsOverMenu(GtkWidget* menu, GdkEventMotion* motion) { |
- if (motion->x >= 0 && motion->y >= 0 && |
- motion->x < menu->allocation.width && |
- motion->y < menu->allocation.height) { |
- return true; |
- } |
- |
- while (menu) { |
- GtkWidget* menu_item = gtk_menu_get_attach_widget(GTK_MENU(menu)); |
- if (!menu_item) |
- return false; |
- GtkWidget* parent = gtk_widget_get_parent(menu_item); |
- |
- if (gtk_util::WidgetContainsCursor(parent)) |
- return true; |
- menu = parent; |
- } |
- |
- return false; |
-} |
- |
-} // namespace |
- |
-MenuBarHelper::MenuBarHelper(Delegate* delegate) |
- : button_showing_menu_(NULL), |
- showing_menu_(NULL), |
- delegate_(delegate) { |
- DCHECK(delegate_); |
-} |
- |
-MenuBarHelper::~MenuBarHelper() { |
-} |
- |
-void MenuBarHelper::Add(GtkWidget* button) { |
- buttons_.push_back(button); |
-} |
- |
-void MenuBarHelper::Remove(GtkWidget* button) { |
- std::vector<GtkWidget*>::iterator iter = |
- find(buttons_.begin(), buttons_.end(), button); |
- if (iter == buttons_.end()) { |
- NOTREACHED(); |
- return; |
- } |
- buttons_.erase(iter); |
-} |
- |
-void MenuBarHelper::Clear() { |
- buttons_.clear(); |
-} |
- |
-void MenuBarHelper::MenuStartedShowing(GtkWidget* button, GtkWidget* menu) { |
- DCHECK(GTK_IS_MENU(menu)); |
- button_showing_menu_ = button; |
- showing_menu_ = menu; |
- |
- signal_handlers_.reset(new GtkSignalRegistrar()); |
- signal_handlers_->Connect(menu, "destroy", |
- G_CALLBACK(OnMenuHiddenOrDestroyedThunk), this); |
- signal_handlers_->Connect(menu, "hide", |
- G_CALLBACK(OnMenuHiddenOrDestroyedThunk), this); |
- signal_handlers_->Connect(menu, "motion-notify-event", |
- G_CALLBACK(OnMenuMotionNotifyThunk), this); |
- signal_handlers_->Connect(menu, "move-current", |
- G_CALLBACK(OnMenuMoveCurrentThunk), this); |
- gtk_container_foreach(GTK_CONTAINER(menu), PopulateSubmenus, &submenus_); |
- |
- for (size_t i = 0; i < submenus_.size(); ++i) { |
- signal_handlers_->Connect(submenus_[i], "motion-notify-event", |
- G_CALLBACK(OnMenuMotionNotifyThunk), this); |
- } |
-} |
- |
-gboolean MenuBarHelper::OnMenuMotionNotify(GtkWidget* menu, |
- GdkEventMotion* motion) { |
- // Don't do anything if pointer is in the menu. |
- if (MotionIsOverMenu(menu, motion)) |
- return FALSE; |
- if (buttons_.empty()) |
- return FALSE; |
- |
- gint x = 0; |
- gint y = 0; |
- GtkWidget* last_button = NULL; |
- |
- for (size_t i = 0; i < buttons_.size(); ++i) { |
- GtkWidget* button = buttons_[i]; |
- // Figure out coordinates relative to this button. Avoid using |
- // gtk_widget_get_pointer() unnecessarily. |
- if (i == 0) { |
- // We have to make this call because the menu is a popup window, so it |
- // doesn't share a toplevel with the buttons and we can't just use |
- // gtk_widget_translate_coordinates(). |
- gtk_widget_get_pointer(buttons_[0], &x, &y); |
- } else { |
- gint last_x = x; |
- gint last_y = y; |
- if (!gtk_widget_translate_coordinates( |
- last_button, button, last_x, last_y, &x, &y)) { |
- // |button| may not be realized. |
- continue; |
- } |
- } |
- |
- last_button = button; |
- |
- if (x >= 0 && y >= 0 && x < button->allocation.width && |
- y < button->allocation.height) { |
- if (button != button_showing_menu_) |
- delegate_->PopupForButton(button); |
- return TRUE; |
- } |
- } |
- |
- return FALSE; |
-} |
- |
-void MenuBarHelper::OnMenuHiddenOrDestroyed(GtkWidget* menu) { |
- DCHECK_EQ(showing_menu_, menu); |
- |
- signal_handlers_.reset(); |
- showing_menu_ = NULL; |
- button_showing_menu_ = NULL; |
- submenus_.clear(); |
-} |
- |
-void MenuBarHelper::OnMenuMoveCurrent(GtkWidget* menu, |
- GtkMenuDirectionType dir) { |
- // The menu directions are triggered by the arrow keys as follows |
- // |
- // PARENT left |
- // CHILD right |
- // NEXT down |
- // PREV up |
- // |
- // We only care about left and right. Note that for RTL, they are swapped. |
- switch (dir) { |
- case GTK_MENU_DIR_CHILD: { |
- GtkWidget* active_item = GTK_MENU_SHELL(menu)->active_menu_item; |
- // The move is going to open a submenu; don't override default behavior. |
- if (active_item && gtk_menu_item_get_submenu(GTK_MENU_ITEM(active_item))) |
- return; |
- // Fall through. |
- } |
- case GTK_MENU_DIR_PARENT: { |
- delegate_->PopupForButtonNextTo(button_showing_menu_, dir); |
- break; |
- } |
- default: |
- return; |
- } |
- |
- // This signal doesn't have a return value; we have to manually stop its |
- // propagation. |
- g_signal_stop_emission_by_name(menu, "move-current"); |
-} |