Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(284)

Side by Side Diff: chrome/browser/ui/views/frame/global_menu_bar_x11.cc

Issue 22455002: linux_aura: Implement the static part of the dbus menu for Unity. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: The gyp fix Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/ui/views/frame/global_menu_bar_x11.h ('k') | chrome/chrome_browser_ui.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2013 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/views/frame/global_menu_bar_x11.h"
6
7 #include <dlfcn.h>
8 #include <glib-object.h>
9
10 #include "base/logging.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/strings/stringprintf.h"
13 #include "chrome/app/chrome_command_ids.h"
14 #include "chrome/browser/ui/browser_commands.h"
15 #include "chrome/browser/ui/views/frame/browser_desktop_root_window_host_x11.h"
16 #include "chrome/browser/ui/views/frame/browser_view.h"
17 #include "chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h"
18 #include "chrome/common/pref_names.h"
19 #include "grit/generated_resources.h"
20 #include "ui/base/accelerators/menu_label_accelerator_util_linux.h"
21 #include "ui/base/keycodes/keyboard_code_conversion_x.h"
22 #include "ui/base/l10n/l10n_util.h"
23
24 // libdbusmenu-glib types
25 typedef struct _DbusmenuMenuitem DbusmenuMenuitem;
26 typedef DbusmenuMenuitem* (*dbusmenu_menuitem_new_func)();
27 typedef DbusmenuMenuitem* (*dbusmenu_menuitem_new_with_id_func)(int id);
28
29 typedef int (*dbusmenu_menuitem_get_id_func)(DbusmenuMenuitem* item);
30 typedef DbusmenuMenuitem* (*dbusmenu_menuitem_child_append_func)(
31 DbusmenuMenuitem* parent,
32 DbusmenuMenuitem* child);
33 typedef DbusmenuMenuitem* (*dbusmenu_menuitem_property_set_func)(
34 DbusmenuMenuitem* item,
35 const char* property,
36 const char* value);
37 typedef DbusmenuMenuitem* (*dbusmenu_menuitem_property_set_variant_func)(
38 DbusmenuMenuitem* item,
39 const char* property,
40 GVariant* value);
41 typedef DbusmenuMenuitem* (*dbusmenu_menuitem_property_set_bool_func)(
42 DbusmenuMenuitem* item,
43 const char* property,
44 bool value);
45 typedef DbusmenuMenuitem* (*dbusmenu_menuitem_property_set_int_func)(
46 DbusmenuMenuitem* item,
47 const char* property,
48 int value);
49
50 typedef struct _DbusmenuServer DbusmenuServer;
51 typedef DbusmenuServer* (*dbusmenu_server_new_func)(const char* object);
52 typedef void (*dbusmenu_server_set_root_func)(DbusmenuServer* self,
53 DbusmenuMenuitem* root);
54
55 // A line in the static menu definitions.
56 struct GlobalMenuBarCommand {
57 int str_id;
58 int command;
59 int tag;
60 };
61
62 namespace {
63
64 // Retrieved functions from libdbusmenu-glib.
65
66 // DbusmenuMenuItem methods:
67 dbusmenu_menuitem_new_func menuitem_new = NULL;
68 dbusmenu_menuitem_new_with_id_func menuitem_new_with_id = NULL;
69 dbusmenu_menuitem_get_id_func menuitem_get_id = NULL;
70 dbusmenu_menuitem_child_append_func menuitem_child_append = NULL;
71 dbusmenu_menuitem_property_set_func menuitem_property_set = NULL;
72 dbusmenu_menuitem_property_set_variant_func menuitem_property_set_variant =
73 NULL;
74 dbusmenu_menuitem_property_set_bool_func menuitem_property_set_bool = NULL;
75 dbusmenu_menuitem_property_set_int_func menuitem_property_set_int = NULL;
76
77 // DbusmenuServer methods:
78 dbusmenu_server_new_func server_new = NULL;
79 dbusmenu_server_set_root_func server_set_root = NULL;
80
81 // Properties that we set on menu items:
82 const char kPropertyEnabled[] = "enabled";
83 const char kPropertyLabel[] = "label";
84 const char kPropertyShortcut[] = "shortcut";
85 const char kPropertyType[] = "type";
86 const char kPropertyToggleType[] = "toggle-type";
87 const char kPropertyToggleState[] = "toggle-state";
88 const char kPropertyVisible[] = "visible";
89
90 const char kTypeCheckmark[] = "checkmark";
91 const char kTypeSeparator[] = "separator";
92
93 // Constants used in menu definitions
94 const int MENU_SEPARATOR =-1;
95 const int MENU_END = -2;
96 const int MENU_DISABLED_LABEL = -3;
97
98 GlobalMenuBarCommand file_menu[] = {
99 { IDS_NEW_TAB, IDC_NEW_TAB },
100 { IDS_NEW_WINDOW, IDC_NEW_WINDOW },
101 { IDS_NEW_INCOGNITO_WINDOW, IDC_NEW_INCOGNITO_WINDOW },
102 { IDS_REOPEN_CLOSED_TABS_LINUX, IDC_RESTORE_TAB },
103 { IDS_OPEN_FILE_LINUX, IDC_OPEN_FILE },
104 { IDS_OPEN_LOCATION_LINUX, IDC_FOCUS_LOCATION },
105
106 { MENU_SEPARATOR, MENU_SEPARATOR },
107
108 { IDS_CREATE_SHORTCUTS, IDC_CREATE_SHORTCUTS },
109
110 { MENU_SEPARATOR, MENU_SEPARATOR },
111
112 { IDS_CLOSE_WINDOW_LINUX, IDC_CLOSE_WINDOW },
113 { IDS_CLOSE_TAB_LINUX, IDC_CLOSE_TAB },
114 { IDS_SAVE_PAGE, IDC_SAVE_PAGE },
115
116 { MENU_SEPARATOR, MENU_SEPARATOR },
117
118 { IDS_PRINT, IDC_PRINT },
119
120 { MENU_END, MENU_END }
121 };
122
123 GlobalMenuBarCommand edit_menu[] = {
124 { IDS_CUT, IDC_CUT },
125 { IDS_COPY, IDC_COPY },
126 { IDS_PASTE, IDC_PASTE },
127
128 { MENU_SEPARATOR, MENU_SEPARATOR },
129
130 { IDS_FIND, IDC_FIND },
131
132 { MENU_SEPARATOR, MENU_SEPARATOR },
133
134 { IDS_PREFERENCES, IDC_OPTIONS },
135
136 { MENU_END, MENU_END }
137 };
138
139
140 GlobalMenuBarCommand view_menu[] = {
141 { IDS_SHOW_BOOKMARK_BAR, IDC_SHOW_BOOKMARK_BAR },
142
143 { MENU_SEPARATOR, MENU_SEPARATOR },
144
145 { IDS_STOP_MENU_LINUX, IDC_STOP },
146 { IDS_RELOAD_MENU_LINUX, IDC_RELOAD },
147
148 { MENU_SEPARATOR, MENU_SEPARATOR },
149
150 { IDS_FULLSCREEN, IDC_FULLSCREEN },
151 { IDS_TEXT_DEFAULT_LINUX, IDC_ZOOM_NORMAL },
152 { IDS_TEXT_BIGGER_LINUX, IDC_ZOOM_PLUS },
153 { IDS_TEXT_SMALLER_LINUX, IDC_ZOOM_MINUS },
154
155 { MENU_END, MENU_END }
156 };
157
158 // TODO(erg): History menu.
159
160 GlobalMenuBarCommand tools_menu[] = {
161 { IDS_SHOW_DOWNLOADS, IDC_SHOW_DOWNLOADS },
162 { IDS_SHOW_HISTORY, IDC_SHOW_HISTORY },
163 { IDS_SHOW_EXTENSIONS, IDC_MANAGE_EXTENSIONS },
164
165 { MENU_SEPARATOR, MENU_SEPARATOR },
166
167 { IDS_TASK_MANAGER, IDC_TASK_MANAGER },
168 { IDS_CLEAR_BROWSING_DATA, IDC_CLEAR_BROWSING_DATA },
169
170 { MENU_SEPARATOR, MENU_SEPARATOR },
171
172 { IDS_VIEW_SOURCE, IDC_VIEW_SOURCE },
173 { IDS_DEV_TOOLS, IDC_DEV_TOOLS },
174 { IDS_DEV_TOOLS_CONSOLE, IDC_DEV_TOOLS_CONSOLE },
175
176 { MENU_END, MENU_END }
177 };
178
179 GlobalMenuBarCommand help_menu[] = {
180 { IDS_FEEDBACK, IDC_FEEDBACK },
181 { IDS_HELP_PAGE , IDC_HELP_PAGE_VIA_MENU },
182 { MENU_END, MENU_END }
183 };
184
185
186 void EnsureMethodsLoaded() {
187 static bool attempted_load = false;
188 if (attempted_load)
189 return;
190 attempted_load = true;
191
192 void* dbusmenu_lib = dlopen("libdbusmenu-glib.so", RTLD_LAZY);
193 if (!dbusmenu_lib)
194 return;
195
196 // DbusmenuMenuItem methods.
197 menuitem_new = reinterpret_cast<dbusmenu_menuitem_new_func>(
198 dlsym(dbusmenu_lib, "dbusmenu_menuitem_new"));
199 menuitem_new_with_id = reinterpret_cast<dbusmenu_menuitem_new_with_id_func>(
200 dlsym(dbusmenu_lib, "dbusmenu_menuitem_new_with_id"));
201 menuitem_get_id = reinterpret_cast<dbusmenu_menuitem_get_id_func>(
202 dlsym(dbusmenu_lib, "dbusmenu_menuitem_get_id"));
203 menuitem_child_append = reinterpret_cast<dbusmenu_menuitem_child_append_func>(
204 dlsym(dbusmenu_lib, "dbusmenu_menuitem_child_append"));
205 menuitem_property_set = reinterpret_cast<dbusmenu_menuitem_property_set_func>(
206 dlsym(dbusmenu_lib, "dbusmenu_menuitem_property_set"));
207 menuitem_property_set_variant =
208 reinterpret_cast<dbusmenu_menuitem_property_set_variant_func>(
209 dlsym(dbusmenu_lib, "dbusmenu_menuitem_property_set_variant"));
210 menuitem_property_set_bool =
211 reinterpret_cast<dbusmenu_menuitem_property_set_bool_func>(
212 dlsym(dbusmenu_lib, "dbusmenu_menuitem_property_set_bool"));
213 menuitem_property_set_int =
214 reinterpret_cast<dbusmenu_menuitem_property_set_int_func>(
215 dlsym(dbusmenu_lib, "dbusmenu_menuitem_property_set_int"));
216
217 // DbusmenuServer methods.
218 server_new = reinterpret_cast<dbusmenu_server_new_func>(
219 dlsym(dbusmenu_lib, "dbusmenu_server_new"));
220 server_set_root = reinterpret_cast<dbusmenu_server_set_root_func>(
221 dlsym(dbusmenu_lib, "dbusmenu_server_set_root"));
222 }
223
224 } // namespace
225
226 GlobalMenuBarX11::GlobalMenuBarX11(BrowserView* browser_view,
227 BrowserDesktopRootWindowHostX11* host)
228 : browser_(browser_view->browser()),
229 browser_view_(browser_view),
230 host_(host),
231 server_(NULL),
232 root_item_(NULL) {
233 EnsureMethodsLoaded();
234
235 if (server_new)
236 host_->AddObserver(this);
237 }
238
239 GlobalMenuBarX11::~GlobalMenuBarX11() {
240 if (server_) {
241 Disable();
242 g_object_unref(server_);
243 host_->RemoveObserver(this);
244 }
245 }
246
247 // static
248 std::string GlobalMenuBarX11::GetPathForWindow(unsigned long xid) {
249 return base::StringPrintf("/com/canonical/menu/%lX", xid);
250 }
251
252 void GlobalMenuBarX11::InitServer(unsigned long xid) {
253 std::string path = GetPathForWindow(xid);
254 server_ = server_new(path.c_str());
255
256 root_item_ = menuitem_new();
257 menuitem_property_set(root_item_, kPropertyLabel, "Root");
258 menuitem_property_set_bool(root_item_, kPropertyVisible, true);
259
260 BuildMenuFrom(root_item_, IDS_FILE_MENU_LINUX, &id_to_menu_item_, file_menu);
261 BuildMenuFrom(root_item_, IDS_EDIT_MENU_LINUX, &id_to_menu_item_, edit_menu);
262 BuildMenuFrom(root_item_, IDS_VIEW_MENU_LINUX, &id_to_menu_item_, view_menu);
263 // TODO(erg): History menu.
264 BuildMenuFrom(root_item_, IDS_TOOLS_MENU_LINUX, &id_to_menu_item_,
265 tools_menu);
266 BuildMenuFrom(root_item_, IDS_HELP_MENU_LINUX, &id_to_menu_item_, help_menu);
267
268 for (CommandIDMenuItemMap::const_iterator it = id_to_menu_item_.begin();
269 it != id_to_menu_item_.end(); ++it) {
270 menuitem_property_set_bool(it->second, kPropertyEnabled,
271 chrome::IsCommandEnabled(browser_, it->first));
272
273 ui::Accelerator accelerator;
274 if (browser_view_->GetAccelerator(it->first, &accelerator))
275 RegisterAccelerator(it->second, accelerator);
276
277 chrome::AddCommandObserver(browser_, it->first, this);
278 }
279
280 pref_change_registrar_.Init(browser_->profile()->GetPrefs());
281 pref_change_registrar_.Add(
282 prefs::kShowBookmarkBar,
283 base::Bind(&GlobalMenuBarX11::OnBookmarkBarVisibilityChanged,
284 base::Unretained(this)));
285 OnBookmarkBarVisibilityChanged();
286
287 server_set_root(server_, root_item_);
288 }
289
290 void GlobalMenuBarX11::Disable() {
291 for (CommandIDMenuItemMap::const_iterator it = id_to_menu_item_.begin();
292 it != id_to_menu_item_.end(); ++it) {
293 chrome::RemoveCommandObserver(browser_, it->first, this);
294 }
295 id_to_menu_item_.clear();
296
297 pref_change_registrar_.RemoveAll();
298 }
299
300 void GlobalMenuBarX11::BuildMenuFrom(
301 DbusmenuMenuitem* parent,
302 int menu_str_id,
303 std::map<int, DbusmenuMenuitem*>* id_to_menu_item,
304 GlobalMenuBarCommand* commands) {
305 DbusmenuMenuitem* top = menuitem_new();
306 menuitem_property_set(
307 top, kPropertyLabel,
308 ui::RemoveWindowsStyleAccelerators(
309 l10n_util::GetStringUTF8(menu_str_id)).c_str());
310 menuitem_property_set_bool(top, kPropertyVisible, true);
311
312 for (int i = 0; commands[i].str_id != MENU_END; ++i) {
313 DbusmenuMenuitem* menu_item = BuildMenuItem(
314 commands[i].str_id, commands[i].command, commands[i].tag,
315 id_to_menu_item);
316 menuitem_child_append(top, menu_item);
317 }
318
319 menuitem_child_append(parent, top);
320 }
321
322 DbusmenuMenuitem* GlobalMenuBarX11::BuildMenuItem(
323 int string_id,
324 int command_id,
325 int tag_id,
326 std::map<int, DbusmenuMenuitem*>* id_to_menu_item) {
327 DbusmenuMenuitem* item = menuitem_new();
328
329 if (string_id == MENU_SEPARATOR) {
330 menuitem_property_set(item, kPropertyType, kTypeSeparator);
331 } else {
332 std::string label = ui::ConvertAcceleratorsFromWindowsStyle(
333 l10n_util::GetStringUTF8(string_id));
334 menuitem_property_set(item, kPropertyLabel, label.c_str());
335
336 if (command_id == IDC_SHOW_BOOKMARK_BAR)
337 menuitem_property_set(item, kPropertyToggleType, kTypeCheckmark);
338
339 if (tag_id)
340 g_object_set_data(G_OBJECT(item), "type-tag", GINT_TO_POINTER(tag_id));
341
342 if (command_id == MENU_DISABLED_LABEL) {
343 menuitem_property_set_bool(item, kPropertyEnabled, false);
344 } else {
345 id_to_menu_item->insert(std::make_pair(command_id, item));
346 g_object_set_data(G_OBJECT(item), "command-id",
347 GINT_TO_POINTER(command_id));
348 g_signal_connect(item, "item-activated",
349 G_CALLBACK(OnItemActivatedThunk), this);
350 }
351 }
352
353 menuitem_property_set_bool(item, kPropertyVisible, true);
354 return item;
355 }
356
357 void GlobalMenuBarX11::RegisterAccelerator(DbusmenuMenuitem* item,
358 const ui::Accelerator& accelerator) {
359 // A translation of libdbusmenu-gtk's menuitem_property_set_shortcut()
360 // translated from GDK types to ui::Accelerator types.
361 GVariantBuilder builder;
362 g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
363
364 if (accelerator.IsCtrlDown())
365 g_variant_builder_add(&builder, "s", "Control");
366 if (accelerator.IsAltDown())
367 g_variant_builder_add(&builder, "s", "Alt");
368 if (accelerator.IsShiftDown())
369 g_variant_builder_add(&builder, "s", "Shift");
370
371 char* name = XKeysymToString(XKeysymForWindowsKeyCode(
372 accelerator.key_code(), false));
373 if (!name) {
374 NOTIMPLEMENTED();
375 return;
376 }
377 g_variant_builder_add(&builder, "s", name);
378
379 GVariant* inside_array = g_variant_builder_end(&builder);
380 g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
381 g_variant_builder_add_value(&builder, inside_array);
382 GVariant* outside_array = g_variant_builder_end(&builder);
383
384 menuitem_property_set_variant(item, kPropertyShortcut, outside_array);
385 }
386
387 void GlobalMenuBarX11::OnBookmarkBarVisibilityChanged() {
388 CommandIDMenuItemMap::iterator it =
389 id_to_menu_item_.find(IDC_SHOW_BOOKMARK_BAR);
390 if (it != id_to_menu_item_.end()) {
391 PrefService* prefs = browser_->profile()->GetPrefs();
392 // Note: Unlike the GTK version, we don't appear to need to do tricks where
393 // we block activation while setting the toggle.
394 menuitem_property_set_int(it->second, kPropertyToggleState,
395 prefs->GetBoolean(prefs::kShowBookmarkBar));
396 }
397 }
398
399 void GlobalMenuBarX11::EnabledStateChangedForCommand(int id, bool enabled) {
400 CommandIDMenuItemMap::iterator it = id_to_menu_item_.find(id);
401 if (it != id_to_menu_item_.end())
402 menuitem_property_set_bool(it->second, kPropertyEnabled, enabled);
403 }
404
405 void GlobalMenuBarX11::OnWindowMapped(unsigned long xid) {
406 if (!server_)
407 InitServer(xid);
408
409 GlobalMenuBarRegistrarX11::GetInstance()->OnWindowMapped(xid);
410 }
411
412 void GlobalMenuBarX11::OnWindowUnmapped(unsigned long xid) {
413 GlobalMenuBarRegistrarX11::GetInstance()->OnWindowUnmapped(xid);
414 }
415
416 void GlobalMenuBarX11::OnItemActivated(DbusmenuMenuitem* item,
417 unsigned int timestamp) {
418 int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(item), "command-id"));
419 chrome::ExecuteCommand(browser_, id);
420 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/frame/global_menu_bar_x11.h ('k') | chrome/chrome_browser_ui.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698