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. 4 5#include "chrome/browser/ui/gtk/tab_contents/render_view_context_menu_gtk.h" 6 7#include <gtk/gtk.h> 8 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" 19 20using content::WebContents; 21 22namespace { 23 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. 26struct GtkWidgetAtParam { 27 int index; 28 GtkWidget* widget; 29}; 30 31void GtkWidgetAt(GtkWidget* widget, gpointer user_data) { 32 GtkWidgetAtParam* param = reinterpret_cast<GtkWidgetAtParam*>(user_data); 33 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; 38 } 39} 40 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. 46GtkWidget* GetMenuItemByID(ui::MenuModel* model, 47 GtkWidget* menu, 48 int command_id) { 49 if (!menu) 50 return NULL; 51 52 for (int i = 0; i < model->GetItemCount(); ++i) { 53 if (model->GetCommandIdAt(i) == command_id) { 54 GtkWidgetAtParam param; 55 param.index = i; 56 param.widget = NULL; 57 gtk_container_foreach(GTK_CONTAINER(menu), &GtkWidgetAt, ¶m); 58 return param.widget; 59 } 60 61 ui::MenuModel* submenu = model->GetSubmenuModelAt(i); 62 if (submenu) { 63 GtkWidget* subitem = GetMenuItemByID( 64 submenu, 65 gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu)), 66 command_id); 67 if (subitem) 68 return subitem; 69 } 70 } 71 return NULL; 72} 73 74} // namespace 75 76RenderViewContextMenuGtk::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; 83} 84 85RenderViewContextMenuGtk::~RenderViewContextMenuGtk() { 86} 87 88void RenderViewContextMenuGtk::PlatformInit() { 89 menu_gtk_.reset(new MenuGtk(this, &menu_model_)); 90 91 if (params_.is_editable) { 92 content::RenderWidgetHostView* rwhv = 93 source_web_contents_->GetRenderWidgetHostView(); 94 if (rwhv) { 95 MenuGtk* menu = menu_gtk_.get(); 96 gboolean show_input_method_menu = TRUE; 97 98 g_object_get( 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) 102 return; 103 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 menu->AppendSeparator(); 110 menu->AppendMenuItem(IDC_INPUT_METHODS_MENU, menuitem); 111 } 112 } 113} 114 115void RenderViewContextMenuGtk::PlatformCancel() { 116 menu_gtk_->Cancel(); 117} 118 119bool RenderViewContextMenuGtk::GetAcceleratorForCommandId( 120 int command_id, 121 ui::Accelerator* accelerator) { 122 return false; 123} 124 125void RenderViewContextMenuGtk::Popup(const gfx::Point& point) { 126 menu_gtk_->PopupAsContext(point, triggering_event_time_); 127} 128 129bool RenderViewContextMenuGtk::AlwaysShowIconForCmd(int command_id) const { 130 return command_id >= IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST && 131 command_id <= IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST; 132} 133 134void RenderViewContextMenuGtk::UpdateMenuItem(int command_id, 135 bool enabled, 136 bool hidden, 137 const string16& title) { 138 GtkWidget* item = GetMenuItemByID(&menu_model_, menu_gtk_->widget(), 139 command_id); 140 if (!item || !GTK_IS_MENU_ITEM(item)) 141 return; 142 143 // Enable (or disable) the menu item and updates its text. 144 gtk_widget_set_sensitive(item, enabled); 145 if (hidden) 146 gtk_widget_hide(item); 147 else 148 gtk_widget_show(item); 149 gtk_menu_item_set_label(GTK_MENU_ITEM(item), UTF16ToUTF8(title).c_str()); 150} 151