| // Copyright (c) 2012 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/ui/gtk/tab_contents/render_view_context_menu_gtk.h" |
| |
| #include <gtk/gtk.h> |
| |
| #include "base/strings/string_util.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "chrome/app/chrome_command_ids.h" |
| #include "chrome/browser/ui/gtk/gtk_util.h" |
| #include "content/public/browser/render_widget_host_view.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/common/context_menu_params.h" |
| #include "grit/generated_resources.h" |
| #include "ui/base/accelerators/menu_label_accelerator_util_linux.h" |
| #include "ui/base/l10n/l10n_util.h" |
| |
| using content::WebContents; |
| |
| namespace { |
| |
| // A callback function for gtk_container_foreach(). This callback just checks |
| // the menu ID and set the given user data if it is same as the specified ID. |
| struct GtkWidgetAtParam { |
| int index; |
| GtkWidget* widget; |
| }; |
| |
| void GtkWidgetAt(GtkWidget* widget, gpointer user_data) { |
| GtkWidgetAtParam* param = reinterpret_cast<GtkWidgetAtParam*>(user_data); |
| |
| gpointer data = g_object_get_data(G_OBJECT(widget), "menu-id"); |
| if (data && (GPOINTER_TO_INT(data) - 1) == param->index && |
| GTK_IS_MENU_ITEM(widget)) { |
| param->widget = widget; |
| } |
| } |
| |
| // Retrieves a GtkWidget which has the specified command_id. This function |
| // traverses the given |model| in the depth-first order. When this function |
| // finds an item whose command_id is the same as the given |command_id|, it |
| // returns the GtkWidget associated with the item. This function emulates |
| // views::MenuItemViews::GetMenuItemByID() for GTK. |
| GtkWidget* GetMenuItemByID(ui::MenuModel* model, |
| GtkWidget* menu, |
| int command_id) { |
| if (!menu) |
| return NULL; |
| |
| for (int i = 0; i < model->GetItemCount(); ++i) { |
| if (model->GetCommandIdAt(i) == command_id) { |
| GtkWidgetAtParam param; |
| param.index = i; |
| param.widget = NULL; |
| gtk_container_foreach(GTK_CONTAINER(menu), &GtkWidgetAt, ¶m); |
| return param.widget; |
| } |
| |
| ui::MenuModel* submenu = model->GetSubmenuModelAt(i); |
| if (submenu) { |
| GtkWidget* subitem = GetMenuItemByID( |
| submenu, |
| gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu)), |
| command_id); |
| if (subitem) |
| return subitem; |
| } |
| } |
| return NULL; |
| } |
| |
| } // namespace |
| |
| RenderViewContextMenuGtk::RenderViewContextMenuGtk( |
| WebContents* web_contents, |
| const content::ContextMenuParams& params, |
| content::RenderWidgetHostView* view) |
| : RenderViewContextMenu(web_contents, params) { |
| GdkEventButton* event = view->GetLastMouseDown(); |
| triggering_event_time_ = event ? event->time : GDK_CURRENT_TIME; |
| } |
| |
| RenderViewContextMenuGtk::~RenderViewContextMenuGtk() { |
| } |
| |
| void RenderViewContextMenuGtk::PlatformInit() { |
| menu_gtk_.reset(new MenuGtk(this, &menu_model_)); |
| |
| if (params_.is_editable) { |
| content::RenderWidgetHostView* rwhv = |
| source_web_contents_->GetRenderWidgetHostView(); |
| if (rwhv) { |
| MenuGtk* menu = menu_gtk_.get(); |
| gboolean show_input_method_menu = TRUE; |
| |
| g_object_get( |
| gtk_widget_get_settings(GTK_WIDGET(rwhv->GetNativeView())), |
| "gtk-show-input-method-menu", &show_input_method_menu, NULL); |
| if (!show_input_method_menu) |
| return; |
| |
| std::string label = ui::ConvertAcceleratorsFromWindowsStyle( |
| l10n_util::GetStringUTF8(IDS_CONTENT_CONTEXT_INPUT_METHODS_MENU)); |
| GtkWidget* menuitem = gtk_menu_item_new_with_mnemonic(label.c_str()); |
| GtkWidget* submenu = rwhv->BuildInputMethodsGtkMenu(); |
| gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); |
| int inspect_element_index = |
| menu_model_.GetIndexOfCommandId(IDC_CONTENT_CONTEXT_INSPECTELEMENT); |
| if (inspect_element_index != -1) { |
| menu->InsertSeparator(inspect_element_index - 1); |
| menu->InsertMenuItem(IDC_INPUT_METHODS_MENU, menuitem, |
| inspect_element_index); |
| } else { |
| menu->AppendSeparator(); |
| menu->AppendMenuItem(IDC_INPUT_METHODS_MENU, menuitem); |
| } |
| } |
| } |
| } |
| |
| void RenderViewContextMenuGtk::PlatformCancel() { |
| menu_gtk_->Cancel(); |
| } |
| |
| bool RenderViewContextMenuGtk::GetAcceleratorForCommandId( |
| int command_id, |
| ui::Accelerator* accelerator) { |
| return false; |
| } |
| |
| void RenderViewContextMenuGtk::Popup(const gfx::Point& point) { |
| menu_gtk_->PopupAsContext(point, triggering_event_time_); |
| } |
| |
| bool RenderViewContextMenuGtk::AlwaysShowIconForCmd(int command_id) const { |
| return command_id >= IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST && |
| command_id <= IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST; |
| } |
| |
| void RenderViewContextMenuGtk::UpdateMenuItem(int command_id, |
| bool enabled, |
| bool hidden, |
| const string16& title) { |
| GtkWidget* item = GetMenuItemByID(&menu_model_, menu_gtk_->widget(), |
| command_id); |
| if (!item || !GTK_IS_MENU_ITEM(item)) |
| return; |
| |
| // Enable (or disable) the menu item and updates its text. |
| gtk_widget_set_sensitive(item, enabled); |
| if (hidden) |
| gtk_widget_hide(item); |
| else |
| gtk_widget_show(item); |
| gtk_menu_item_set_label(GTK_MENU_ITEM(item), UTF16ToUTF8(title).c_str()); |
| } |