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

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

Issue 21187006: linux_aura: Implement the static part of the dbus menu for Unity. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: sadrul comments 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 (c) 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 EnsureMethodsLoaded();
sky 2013/08/05 20:19:42 member initialize root_item_ too.
233
234 if (server_new)
235 host_->AddObserver(this);
236 }
237
238 GlobalMenuBarX11::~GlobalMenuBarX11() {
239 if (server_) {
240 Disable();
241 g_object_unref(server_);
242 host_->RemoveObserver(this);
243 }
244 }
245
246 // static
247 std::string GlobalMenuBarX11::GetPathForWindow(unsigned long xid) {
248 return base::StringPrintf("/com/canonical/menu/%lX", xid);
249 }
250
251 void GlobalMenuBarX11::InitServer(unsigned long xid) {
252 std::string path = GetPathForWindow(xid);
253 server_ = server_new(path.c_str());
254
255 root_item_ = menuitem_new();
256 menuitem_property_set(root_item_, kPropertyLabel, "Root");
257 menuitem_property_set_bool(root_item_, kPropertyVisible, true);
258
259 BuildMenuFrom(root_item_, IDS_FILE_MENU_LINUX, &id_to_menu_item_, file_menu);
260 BuildMenuFrom(root_item_, IDS_EDIT_MENU_LINUX, &id_to_menu_item_, edit_menu);
261 BuildMenuFrom(root_item_, IDS_VIEW_MENU_LINUX, &id_to_menu_item_, view_menu);
262 // TODO(erg): History menu.
263 BuildMenuFrom(root_item_, IDS_TOOLS_MENU_LINUX, &id_to_menu_item_,
264 tools_menu);
265 BuildMenuFrom(root_item_, IDS_HELP_MENU_LINUX, &id_to_menu_item_, help_menu);
266
267 for (CommandIDMenuItemMap::const_iterator it = id_to_menu_item_.begin();
268 it != id_to_menu_item_.end(); ++it) {
269 menuitem_property_set_bool(it->second, kPropertyEnabled,
270 chrome::IsCommandEnabled(browser_, it->first));
271
272 ui::Accelerator accelerator;
273 if (browser_view_->GetAccelerator(it->first, &accelerator))
274 RegisterAccelerator(it->second, accelerator);
275
276 chrome::AddCommandObserver(browser_, it->first, this);
277 }
278
279 pref_change_registrar_.Init(browser_->profile()->GetPrefs());
280 pref_change_registrar_.Add(
281 prefs::kShowBookmarkBar,
282 base::Bind(&GlobalMenuBarX11::OnBookmarkBarVisibilityChanged,
283 base::Unretained(this)));
284 OnBookmarkBarVisibilityChanged();
285
286 server_set_root(server_, root_item_);
287 }
288
289 void GlobalMenuBarX11::Disable() {
290 for (CommandIDMenuItemMap::const_iterator it = id_to_menu_item_.begin();
291 it != id_to_menu_item_.end(); ++it) {
292 chrome::RemoveCommandObserver(browser_, it->first, this);
293 }
294 id_to_menu_item_.clear();
295
296 pref_change_registrar_.RemoveAll();
297 }
298
299 void GlobalMenuBarX11::BuildMenuFrom(
300 DbusmenuMenuitem* parent,
301 int menu_str_id,
302 std::map<int, DbusmenuMenuitem*>* id_to_menu_item,
303 GlobalMenuBarCommand* commands) {
304 DbusmenuMenuitem* top = menuitem_new();
305 menuitem_property_set(
306 top, kPropertyLabel,
307 ui::RemoveWindowsStyleAccelerators(
308 l10n_util::GetStringUTF8(menu_str_id)).c_str());
309 menuitem_property_set_bool(top, kPropertyVisible, true);
310
311 for (int i = 0; commands[i].str_id != MENU_END; ++i) {
312 DbusmenuMenuitem* menu_item = BuildMenuItem(
313 commands[i].str_id, commands[i].command, commands[i].tag,
314 id_to_menu_item);
315 menuitem_child_append(top, menu_item);
316 }
317
318 menuitem_child_append(parent, top);
319 }
320
321 DbusmenuMenuitem* GlobalMenuBarX11::BuildMenuItem(
322 int string_id,
323 int command_id,
324 int tag_id,
325 std::map<int, DbusmenuMenuitem*>* id_to_menu_item) {
326 DbusmenuMenuitem* item = menuitem_new();
327
328 if (string_id == MENU_SEPARATOR) {
329 menuitem_property_set(item, kPropertyType, kTypeSeparator);
330 } else {
331 std::string label = ui::ConvertAcceleratorsFromWindowsStyle(
332 l10n_util::GetStringUTF8(string_id));
333 menuitem_property_set(item, kPropertyLabel, label.c_str());
334
335 if (command_id == IDC_SHOW_BOOKMARK_BAR)
336 menuitem_property_set(item, kPropertyToggleType, kTypeCheckmark);
337
338 if (tag_id)
339 g_object_set_data(G_OBJECT(item), "type-tag", GINT_TO_POINTER(tag_id));
340
341 if (command_id == MENU_DISABLED_LABEL) {
342 menuitem_property_set_bool(item, kPropertyEnabled, false);
343 } else {
344 id_to_menu_item->insert(std::make_pair(command_id, item));
345 g_object_set_data(G_OBJECT(item), "command-id",
346 GINT_TO_POINTER(command_id));
347 g_signal_connect(item, "item-activated",
348 G_CALLBACK(OnItemActivatedThunk), this);
349 }
350 }
351
352 menuitem_property_set_bool(item, kPropertyVisible, true);
353 return item;
354 }
355
356 void GlobalMenuBarX11::RegisterAccelerator(DbusmenuMenuitem* item,
357 const ui::Accelerator& accelerator) {
358 // A translation of libdbusmenu-gtk's menuitem_property_set_shortcut()
359 // translated from GDK types to ui::Accelerator types.
360 GVariantBuilder builder;
361 g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
362
363 if (accelerator.IsCtrlDown())
364 g_variant_builder_add(&builder, "s", "Control");
365 if (accelerator.IsAltDown())
366 g_variant_builder_add(&builder, "s", "Alt");
367 if (accelerator.IsShiftDown())
368 g_variant_builder_add(&builder, "s", "Shift");
369
370 char* name = XKeysymToString(XKeysymForWindowsKeyCode(
371 accelerator.key_code(), false));
372 if (!name) {
373 NOTIMPLEMENTED();
374 return;
375 }
376 g_variant_builder_add(&builder, "s", name);
377
378 GVariant* inside_array = g_variant_builder_end(&builder);
379 g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
380 g_variant_builder_add_value(&builder, inside_array);
381 GVariant* outside_array = g_variant_builder_end(&builder);
382
383 menuitem_property_set_variant(item, kPropertyShortcut, outside_array);
384 }
385
386 void GlobalMenuBarX11::OnBookmarkBarVisibilityChanged() {
387 CommandIDMenuItemMap::iterator it =
388 id_to_menu_item_.find(IDC_SHOW_BOOKMARK_BAR);
389 if (it != id_to_menu_item_.end()) {
390 PrefService* prefs = browser_->profile()->GetPrefs();
391 // Note: Unlike the GTK version, we don't appear to need to do tricks where
392 // we block activation while setting the toggle.
393 menuitem_property_set_int(it->second, kPropertyToggleState,
394 prefs->GetBoolean(prefs::kShowBookmarkBar));
395 }
396 }
397
398 void GlobalMenuBarX11::EnabledStateChangedForCommand(int id, bool enabled) {
399 CommandIDMenuItemMap::iterator it = id_to_menu_item_.find(id);
400 if (it != id_to_menu_item_.end())
401 menuitem_property_set_bool(it->second, kPropertyEnabled, enabled);
402 }
403
404 void GlobalMenuBarX11::OnWindowMapped(unsigned long xid) {
405 if (!server_)
406 InitServer(xid);
407
408 GlobalMenuBarRegistrarX11::GetInstance()->OnWindowMapped(xid);
409 }
410
411 void GlobalMenuBarX11::OnWindowUnmapped(unsigned long xid) {
412 GlobalMenuBarRegistrarX11::GetInstance()->OnWindowUnmapped(xid);
413 }
414
415 void GlobalMenuBarX11::OnItemActivated(DbusmenuMenuitem* item,
416 unsigned int timestamp) {
417 int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(item), "command-id"));
418 chrome::ExecuteCommand(browser_, id);
419 }
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