- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / gtk / tab_contents / render_view_context_menu_gtk.cc
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
20 using content::WebContents;
21
22 namespace {
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.
26 struct GtkWidgetAtParam {
27   int index;
28   GtkWidget* widget;
29 };
30
31 void 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.
46 GtkWidget* 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, &param);
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
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;
83 }
84
85 RenderViewContextMenuGtk::~RenderViewContextMenuGtk() {
86 }
87
88 void 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       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);
115       } else {
116         menu->AppendSeparator();
117         menu->AppendMenuItem(IDC_INPUT_METHODS_MENU, menuitem);
118       }
119     }
120   }
121 }
122
123 void RenderViewContextMenuGtk::PlatformCancel() {
124   menu_gtk_->Cancel();
125 }
126
127 bool RenderViewContextMenuGtk::GetAcceleratorForCommandId(
128     int command_id,
129     ui::Accelerator* accelerator) {
130   return false;
131 }
132
133 void RenderViewContextMenuGtk::Popup(const gfx::Point& point) {
134   menu_gtk_->PopupAsContext(point, triggering_event_time_);
135 }
136
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;
140 }
141
142 void RenderViewContextMenuGtk::UpdateMenuItem(int command_id,
143                                               bool enabled,
144                                               bool hidden,
145                                               const string16& title) {
146   GtkWidget* item = GetMenuItemByID(&menu_model_, menu_gtk_->widget(),
147                                     command_id);
148   if (!item || !GTK_IS_MENU_ITEM(item))
149     return;
150
151   // Enable (or disable) the menu item and updates its text.
152   gtk_widget_set_sensitive(item, enabled);
153   if (hidden)
154     gtk_widget_hide(item);
155   else
156     gtk_widget_show(item);
157   gtk_menu_item_set_label(GTK_MENU_ITEM(item), UTF16ToUTF8(title).c_str());
158 }