Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / gtk / global_menu_bar.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/global_menu_bar.h"
6
7 #include <gtk/gtk.h>
8
9 #include "base/command_line.h"
10 #include "base/prefs/pref_service.h"
11 #include "chrome/app/chrome_command_ids.h"
12 #include "chrome/browser/chrome_notification_types.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_commands.h"
16 #include "chrome/browser/ui/gtk/accelerators_gtk.h"
17 #include "chrome/browser/ui/gtk/gtk_theme_service.h"
18 #include "chrome/browser/ui/gtk/gtk_util.h"
19 #include "chrome/common/chrome_switches.h"
20 #include "chrome/common/pref_names.h"
21 #include "content/public/browser/notification_details.h"
22 #include "content/public/browser/notification_source.h"
23 #include "grit/generated_resources.h"
24 #include "ui/base/accelerators/menu_label_accelerator_util_linux.h"
25 #include "ui/base/accelerators/platform_accelerator_gtk.h"
26 #include "ui/base/l10n/l10n_util.h"
27
28 struct GlobalMenuBarCommand {
29   int str_id;
30   int command;
31   int tag;
32 };
33
34 namespace {
35
36 const int MENU_SEPARATOR =-1;
37 const int MENU_END = -2;
38 const int MENU_DISABLED_LABEL = -3;
39
40 GlobalMenuBarCommand file_menu[] = {
41   { IDS_NEW_TAB, IDC_NEW_TAB },
42   { IDS_NEW_WINDOW, IDC_NEW_WINDOW },
43   { IDS_NEW_INCOGNITO_WINDOW, IDC_NEW_INCOGNITO_WINDOW },
44   { IDS_REOPEN_CLOSED_TABS_LINUX, IDC_RESTORE_TAB },
45   { IDS_OPEN_FILE_LINUX, IDC_OPEN_FILE },
46   { IDS_OPEN_LOCATION_LINUX, IDC_FOCUS_LOCATION },
47
48   { MENU_SEPARATOR, MENU_SEPARATOR },
49
50   { IDS_CREATE_SHORTCUTS, IDC_CREATE_SHORTCUTS },
51
52   { MENU_SEPARATOR, MENU_SEPARATOR },
53
54   { IDS_CLOSE_WINDOW_LINUX, IDC_CLOSE_WINDOW },
55   { IDS_CLOSE_TAB_LINUX, IDC_CLOSE_TAB },
56   { IDS_SAVE_PAGE, IDC_SAVE_PAGE },
57
58   { MENU_SEPARATOR, MENU_SEPARATOR },
59
60   { IDS_PRINT, IDC_PRINT },
61
62   { MENU_END, MENU_END }
63 };
64
65 GlobalMenuBarCommand edit_menu[] = {
66   { IDS_CUT, IDC_CUT },
67   { IDS_COPY, IDC_COPY },
68   { IDS_PASTE, IDC_PASTE },
69
70   { MENU_SEPARATOR, MENU_SEPARATOR },
71
72   { IDS_FIND, IDC_FIND },
73
74   { MENU_SEPARATOR, MENU_SEPARATOR },
75
76   { IDS_PREFERENCES, IDC_OPTIONS },
77
78   { MENU_END, MENU_END }
79 };
80
81 GlobalMenuBarCommand view_menu[] = {
82   { IDS_SHOW_BOOKMARK_BAR, IDC_SHOW_BOOKMARK_BAR },
83
84   { MENU_SEPARATOR, MENU_SEPARATOR },
85
86   { IDS_STOP_MENU_LINUX, IDC_STOP },
87   { IDS_RELOAD_MENU_LINUX, IDC_RELOAD },
88
89   { MENU_SEPARATOR, MENU_SEPARATOR },
90
91   { IDS_FULLSCREEN, IDC_FULLSCREEN },
92   { IDS_TEXT_DEFAULT_LINUX, IDC_ZOOM_NORMAL },
93   { IDS_TEXT_BIGGER_LINUX, IDC_ZOOM_PLUS },
94   { IDS_TEXT_SMALLER_LINUX, IDC_ZOOM_MINUS },
95
96   { MENU_END, MENU_END }
97 };
98
99 GlobalMenuBarCommand history_menu[] = {
100   { IDS_HISTORY_HOME_LINUX, IDC_HOME },
101   { IDS_HISTORY_BACK_LINUX, IDC_BACK },
102   { IDS_HISTORY_FORWARD_LINUX, IDC_FORWARD },
103
104   { MENU_SEPARATOR, MENU_SEPARATOR },
105
106   { IDS_HISTORY_VISITED_LINUX, MENU_DISABLED_LABEL,
107     GlobalMenuBar::TAG_MOST_VISITED_HEADER },
108
109   { MENU_SEPARATOR, MENU_SEPARATOR },
110
111   { IDS_HISTORY_CLOSED_LINUX, MENU_DISABLED_LABEL,
112     GlobalMenuBar::TAG_RECENTLY_CLOSED_HEADER },
113
114   { MENU_SEPARATOR, MENU_SEPARATOR },
115
116   { IDS_SHOWFULLHISTORY_LINK, IDC_SHOW_HISTORY },
117
118   { MENU_END, MENU_END }
119 };
120
121 GlobalMenuBarCommand tools_menu[] = {
122   { IDS_SHOW_DOWNLOADS, IDC_SHOW_DOWNLOADS },
123   { IDS_SHOW_HISTORY, IDC_SHOW_HISTORY },
124   { IDS_SHOW_EXTENSIONS, IDC_MANAGE_EXTENSIONS },
125
126   { MENU_SEPARATOR, MENU_SEPARATOR },
127
128   { IDS_TASK_MANAGER, IDC_TASK_MANAGER },
129   { IDS_CLEAR_BROWSING_DATA, IDC_CLEAR_BROWSING_DATA },
130
131   { MENU_SEPARATOR, MENU_SEPARATOR },
132
133   { IDS_VIEW_SOURCE, IDC_VIEW_SOURCE },
134   { IDS_DEV_TOOLS, IDC_DEV_TOOLS },
135   { IDS_DEV_TOOLS_CONSOLE, IDC_DEV_TOOLS_CONSOLE },
136   { IDS_DEV_TOOLS_DEVICES, IDC_DEV_TOOLS_DEVICES },
137
138   { MENU_END, MENU_END }
139 };
140
141 GlobalMenuBarCommand help_menu[] = {
142 #if defined(GOOGLE_CHROME_BUILD)
143   { IDS_FEEDBACK, IDC_FEEDBACK },
144 #endif
145   { IDS_HELP_PAGE , IDC_HELP_PAGE_VIA_MENU },
146   { MENU_END, MENU_END }
147 };
148
149 }  // namespace
150
151 GlobalMenuBar::GlobalMenuBar(Browser* browser)
152     : browser_(browser),
153       menu_bar_(gtk_menu_bar_new()),
154       history_menu_(browser_),
155       dummy_accel_group_(gtk_accel_group_new()),
156       block_activation_(false) {
157   // The global menu bar should never actually be shown in the app; it should
158   // instead remain in our widget hierarchy simply to be noticed by third party
159   // components.
160   g_object_ref_sink(menu_bar_);
161   gtk_widget_set_no_show_all(menu_bar_, TRUE);
162
163   // Set a nice name so it shows up in gtkparasite and others.
164   gtk_widget_set_name(menu_bar_, "chrome-hidden-global-menubar");
165
166   BuildGtkMenuFrom(IDS_FILE_MENU_LINUX, &id_to_menu_item_, file_menu, NULL);
167   BuildGtkMenuFrom(IDS_EDIT_MENU_LINUX, &id_to_menu_item_, edit_menu, NULL);
168   BuildGtkMenuFrom(IDS_VIEW_MENU_LINUX, &id_to_menu_item_, view_menu, NULL);
169   BuildGtkMenuFrom(IDS_HISTORY_MENU_LINUX, &id_to_menu_item_,
170                    history_menu, &history_menu_);
171
172   BuildGtkMenuFrom(IDS_TOOLS_MENU_LINUX, &id_to_menu_item_, tools_menu, NULL);
173   BuildGtkMenuFrom(IDS_HELP_MENU_LINUX, &id_to_menu_item_, help_menu, NULL);
174
175   for (CommandIDMenuItemMap::const_iterator it = id_to_menu_item_.begin();
176        it != id_to_menu_item_.end(); ++it) {
177     // Get the starting enabled state.
178     gtk_widget_set_sensitive(it->second,
179                              chrome::IsCommandEnabled(browser_, it->first));
180
181     // Set the accelerator for each menu item.
182     AcceleratorsGtk* accelerators = AcceleratorsGtk::GetInstance();
183     const ui::Accelerator* accelerator =
184         accelerators->GetPrimaryAcceleratorForCommand(it->first);
185     if (accelerator) {
186       gtk_widget_add_accelerator(it->second,
187                                  "activate",
188                                  dummy_accel_group_,
189                                  ui::GetGdkKeyCodeForAccelerator(*accelerator),
190                                  ui::GetGdkModifierForAccelerator(*accelerator),
191                                  GTK_ACCEL_VISIBLE);
192     }
193
194     chrome::AddCommandObserver(browser_, it->first, this);
195   }
196
197   pref_change_registrar_.Init(browser_->profile()->GetPrefs());
198   pref_change_registrar_.Add(
199       prefs::kShowBookmarkBar,
200       base::Bind(&GlobalMenuBar::OnBookmarkBarVisibilityChanged,
201                  base::Unretained(this)));
202   OnBookmarkBarVisibilityChanged();
203 }
204
205 GlobalMenuBar::~GlobalMenuBar() {
206   Disable();
207   g_object_unref(dummy_accel_group_);
208   gtk_widget_destroy(menu_bar_);
209   g_object_unref(menu_bar_);
210 }
211
212 void GlobalMenuBar::Disable() {
213   for (CommandIDMenuItemMap::const_iterator it = id_to_menu_item_.begin();
214        it != id_to_menu_item_.end(); ++it) {
215     chrome::RemoveCommandObserver(browser_, it->first, this);
216   }
217   id_to_menu_item_.clear();
218
219   pref_change_registrar_.RemoveAll();
220 }
221
222 void GlobalMenuBar::BuildGtkMenuFrom(
223     int menu_str_id,
224     std::map<int, GtkWidget*>* id_to_menu_item,
225     GlobalMenuBarCommand* commands,
226     GlobalMenuOwner* owner) {
227   GtkWidget* menu = gtk_menu_new();
228   for (int i = 0; commands[i].str_id != MENU_END; ++i) {
229     GtkWidget* menu_item = BuildMenuItem(
230         commands[i].str_id, commands[i].command, commands[i].tag,
231         id_to_menu_item, menu);
232     gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
233   }
234
235   gtk_widget_show(menu);
236
237   GtkWidget* menu_item = gtk_menu_item_new_with_mnemonic(
238       ui::RemoveWindowsStyleAccelerators(
239           l10n_util::GetStringUTF8(menu_str_id)).c_str());
240
241   // Give the owner a chance to sink the reference before we add it to the menu
242   // bar.
243   if (owner)
244     owner->Init(menu, menu_item);
245
246   gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), menu);
247   gtk_widget_show(menu_item);
248   gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar_), menu_item);
249 }
250
251 GtkWidget* GlobalMenuBar::BuildMenuItem(
252     int string_id,
253     int command_id,
254     int tag_id,
255     std::map<int, GtkWidget*>* id_to_menu_item,
256     GtkWidget* menu_to_add_to) {
257   GtkWidget* menu_item = NULL;
258   if (string_id == MENU_SEPARATOR) {
259     menu_item = gtk_separator_menu_item_new();
260   } else {
261     std::string label = ui::ConvertAcceleratorsFromWindowsStyle(
262         l10n_util::GetStringUTF8(string_id));
263
264     if (command_id == IDC_SHOW_BOOKMARK_BAR)
265       menu_item = gtk_check_menu_item_new_with_mnemonic(label.c_str());
266     else
267       menu_item = gtk_menu_item_new_with_mnemonic(label.c_str());
268
269     if (tag_id) {
270       g_object_set_data(G_OBJECT(menu_item), "type-tag",
271                         GINT_TO_POINTER(tag_id));
272     }
273
274     if (command_id == MENU_DISABLED_LABEL) {
275       gtk_widget_set_sensitive(menu_item, FALSE);
276     } else {
277       id_to_menu_item->insert(std::make_pair(command_id, menu_item));
278       g_object_set_data(G_OBJECT(menu_item), "command-id",
279                         GINT_TO_POINTER(command_id));
280       g_signal_connect(menu_item, "activate",
281                        G_CALLBACK(OnItemActivatedThunk), this);
282     }
283   }
284   gtk_widget_show(menu_item);
285   return menu_item;
286 }
287
288 void GlobalMenuBar::EnabledStateChangedForCommand(int id, bool enabled) {
289   CommandIDMenuItemMap::iterator it = id_to_menu_item_.find(id);
290   if (it != id_to_menu_item_.end())
291     gtk_widget_set_sensitive(it->second, enabled);
292 }
293
294 void GlobalMenuBar::OnBookmarkBarVisibilityChanged() {
295   CommandIDMenuItemMap::iterator it =
296       id_to_menu_item_.find(IDC_SHOW_BOOKMARK_BAR);
297   if (it != id_to_menu_item_.end()) {
298     PrefService* prefs = browser_->profile()->GetPrefs();
299     block_activation_ = true;
300     gtk_check_menu_item_set_active(
301         GTK_CHECK_MENU_ITEM(it->second),
302         prefs->GetBoolean(prefs::kShowBookmarkBar));
303     block_activation_ = false;
304   }
305 }
306
307 void GlobalMenuBar::OnItemActivated(GtkWidget* sender) {
308   if (block_activation_)
309     return;
310
311   int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(sender), "command-id"));
312   chrome::ExecuteCommand(browser_, id);
313 }