1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/gtk/tab_contents/render_view_context_menu_gtk.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/app/chrome_command_ids.h"
12 #include "chrome/browser/ui/gtk/gtk_util.h"
13 #include "content/public/browser/render_widget_host_view.h"
14 #include "content/public/browser/web_contents.h"
15 #include "content/public/common/context_menu_params.h"
16 #include "grit/generated_resources.h"
17 #include "ui/base/accelerators/menu_label_accelerator_util_linux.h"
18 #include "ui/base/l10n/l10n_util.h"
20 using content::WebContents;
24 // A callback function for gtk_container_foreach(). This callback just checks
25 // the menu ID and set the given user data if it is same as the specified ID.
26 struct GtkWidgetAtParam {
31 void GtkWidgetAt(GtkWidget* widget, gpointer user_data) {
32 GtkWidgetAtParam* param = reinterpret_cast<GtkWidgetAtParam*>(user_data);
34 gpointer data = g_object_get_data(G_OBJECT(widget), "menu-id");
35 if (data && (GPOINTER_TO_INT(data) - 1) == param->index &&
36 GTK_IS_MENU_ITEM(widget)) {
37 param->widget = widget;
41 // Retrieves a GtkWidget which has the specified command_id. This function
42 // traverses the given |model| in the depth-first order. When this function
43 // finds an item whose command_id is the same as the given |command_id|, it
44 // returns the GtkWidget associated with the item. This function emulates
45 // views::MenuItemViews::GetMenuItemByID() for GTK.
46 GtkWidget* GetMenuItemByID(ui::MenuModel* model,
52 for (int i = 0; i < model->GetItemCount(); ++i) {
53 if (model->GetCommandIdAt(i) == command_id) {
54 GtkWidgetAtParam param;
57 gtk_container_foreach(GTK_CONTAINER(menu), &GtkWidgetAt, ¶m);
61 ui::MenuModel* submenu = model->GetSubmenuModelAt(i);
63 GtkWidget* subitem = GetMenuItemByID(
65 gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu)),
76 RenderViewContextMenuGtk::RenderViewContextMenuGtk(
77 WebContents* web_contents,
78 const content::ContextMenuParams& params,
79 content::RenderWidgetHostView* view)
80 : RenderViewContextMenu(web_contents, params) {
81 GdkEventButton* event = view->GetLastMouseDown();
82 triggering_event_time_ = event ? event->time : GDK_CURRENT_TIME;
85 RenderViewContextMenuGtk::~RenderViewContextMenuGtk() {
88 void RenderViewContextMenuGtk::PlatformInit() {
89 menu_gtk_.reset(new MenuGtk(this, &menu_model_));
91 if (params_.is_editable) {
92 content::RenderWidgetHostView* rwhv =
93 source_web_contents_->GetRenderWidgetHostView();
95 MenuGtk* menu = menu_gtk_.get();
96 gboolean show_input_method_menu = TRUE;
99 gtk_widget_get_settings(GTK_WIDGET(rwhv->GetNativeView())),
100 "gtk-show-input-method-menu", &show_input_method_menu, NULL);
101 if (!show_input_method_menu)
104 std::string label = ui::ConvertAcceleratorsFromWindowsStyle(
105 l10n_util::GetStringUTF8(IDS_CONTENT_CONTEXT_INPUT_METHODS_MENU));
106 GtkWidget* menuitem = gtk_menu_item_new_with_mnemonic(label.c_str());
107 GtkWidget* submenu = rwhv->BuildInputMethodsGtkMenu();
108 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);
109 int inspect_element_index =
110 menu_model_.GetIndexOfCommandId(IDC_CONTENT_CONTEXT_INSPECTELEMENT);
111 if (inspect_element_index != -1) {
112 menu->InsertSeparator(inspect_element_index - 1);
113 menu->InsertMenuItem(IDC_INPUT_METHODS_MENU, menuitem,
114 inspect_element_index);
116 menu->AppendSeparator();
117 menu->AppendMenuItem(IDC_INPUT_METHODS_MENU, menuitem);
123 void RenderViewContextMenuGtk::PlatformCancel() {
127 bool RenderViewContextMenuGtk::GetAcceleratorForCommandId(
129 ui::Accelerator* accelerator) {
133 void RenderViewContextMenuGtk::Popup(const gfx::Point& point) {
134 menu_gtk_->PopupAsContext(point, triggering_event_time_);
137 bool RenderViewContextMenuGtk::AlwaysShowIconForCmd(int command_id) const {
138 return command_id >= IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST &&
139 command_id <= IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST;
142 void RenderViewContextMenuGtk::UpdateMenuItem(int command_id,
145 const string16& title) {
146 GtkWidget* item = GetMenuItemByID(&menu_model_, menu_gtk_->widget(),
148 if (!item || !GTK_IS_MENU_ITEM(item))
151 // Enable (or disable) the menu item and updates its text.
152 gtk_widget_set_sensitive(item, enabled);
154 gtk_widget_hide(item);
156 gtk_widget_show(item);
157 gtk_menu_item_set_label(GTK_MENU_ITEM(item), UTF16ToUTF8(title).c_str());