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

Side by Side Diff: chrome/browser/gtk/menu_gtk.cc

Issue 2879002: Reapply r50859 with chromeos fixes. (Closed) Base URL: http://src.chromium.org/git/chromium.git
Patch Set: add explicit menus:: to chromeos Created 10 years, 6 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
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/gtk/menu_gtk.h" 5 #include "chrome/browser/gtk/menu_gtk.h"
6 6
7 #include <map> 7 #include <map>
8 8
9 #include "app/l10n_util.h" 9 #include "app/l10n_util.h"
10 #include "app/menus/accelerator_gtk.h" 10 #include "app/menus/accelerator_gtk.h"
11 #include "app/menus/button_menu_item_model.h"
11 #include "app/menus/menu_model.h" 12 #include "app/menus/menu_model.h"
13 #include "app/resource_bundle.h"
12 #include "base/i18n/rtl.h" 14 #include "base/i18n/rtl.h"
13 #include "base/logging.h" 15 #include "base/logging.h"
14 #include "base/message_loop.h" 16 #include "base/message_loop.h"
15 #include "base/stl_util-inl.h" 17 #include "base/stl_util-inl.h"
16 #include "base/utf_string_conversions.h" 18 #include "base/utf_string_conversions.h"
19 #include "chrome/browser/gtk/gtk_custom_menu.h"
20 #include "chrome/browser/gtk/gtk_custom_menu_item.h"
17 #include "chrome/browser/gtk/gtk_util.h" 21 #include "chrome/browser/gtk/gtk_util.h"
18 #include "gfx/gtk_util.h" 22 #include "gfx/gtk_util.h"
19 #include "third_party/skia/include/core/SkBitmap.h" 23 #include "third_party/skia/include/core/SkBitmap.h"
20 24
21 using gtk_util::ConvertAcceleratorsFromWindowsStyle; 25 using gtk_util::ConvertAcceleratorsFromWindowsStyle;
26 using gtk_util::RemoveWindowsStyleAccelerators;
22 27
23 bool MenuGtk::block_activation_ = false; 28 bool MenuGtk::block_activation_ = false;
24 29
25 namespace { 30 namespace {
26 31
27 // Sets the ID of a menu item. 32 // Sets the ID of a menu item.
28 void SetMenuItemID(GtkWidget* menu_item, int menu_id) { 33 void SetMenuItemID(GtkWidget* menu_item, int menu_id) {
29 DCHECK_GE(menu_id, 0); 34 DCHECK_GE(menu_id, 0);
30 35
31 // Add 1 to the menu_id to avoid setting zero (null) to "menu-id". 36 // Add 1 to the menu_id to avoid setting zero (null) to "menu-id".
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 return y; 97 return y;
93 } 98 }
94 99
95 } // namespace 100 } // namespace
96 101
97 MenuGtk::MenuGtk(MenuGtk::Delegate* delegate, 102 MenuGtk::MenuGtk(MenuGtk::Delegate* delegate,
98 menus::MenuModel* model) 103 menus::MenuModel* model)
99 : delegate_(delegate), 104 : delegate_(delegate),
100 model_(model), 105 model_(model),
101 dummy_accel_group_(gtk_accel_group_new()), 106 dummy_accel_group_(gtk_accel_group_new()),
102 menu_(gtk_menu_new()), 107 menu_(gtk_custom_menu_new()),
103 factory_(this) { 108 factory_(this) {
104 DCHECK(model); 109 DCHECK(model);
105 g_object_ref_sink(menu_); 110 g_object_ref_sink(menu_);
106 ConnectSignalHandlers(); 111 ConnectSignalHandlers();
107 BuildMenuFromModel(); 112 BuildMenuFromModel();
108 } 113 }
109 114
110 MenuGtk::~MenuGtk() { 115 MenuGtk::~MenuGtk() {
111 Cancel(); 116 Cancel();
112 117
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 } 154 }
150 155
151 GtkWidget* MenuGtk::AppendSeparator() { 156 GtkWidget* MenuGtk::AppendSeparator() {
152 GtkWidget* menu_item = gtk_separator_menu_item_new(); 157 GtkWidget* menu_item = gtk_separator_menu_item_new();
153 gtk_widget_show(menu_item); 158 gtk_widget_show(menu_item);
154 gtk_menu_shell_append(GTK_MENU_SHELL(menu_), menu_item); 159 gtk_menu_shell_append(GTK_MENU_SHELL(menu_), menu_item);
155 return menu_item; 160 return menu_item;
156 } 161 }
157 162
158 GtkWidget* MenuGtk::AppendMenuItem(int command_id, GtkWidget* menu_item) { 163 GtkWidget* MenuGtk::AppendMenuItem(int command_id, GtkWidget* menu_item) {
159 return AppendMenuItemToMenu(command_id, menu_item, menu_); 164 return AppendMenuItemToMenu(command_id, menu_item, menu_, true);
160 } 165 }
161 166
162 GtkWidget* MenuGtk::AppendMenuItemToMenu(int command_id, 167 GtkWidget* MenuGtk::AppendMenuItemToMenu(int command_id,
163 GtkWidget* menu_item, 168 GtkWidget* menu_item,
164 GtkWidget* menu) { 169 GtkWidget* menu,
165 SetMenuItemID(menu_item, command_id); 170 bool connect_to_activate) {
166 g_signal_connect(menu_item, "activate", 171 // Native menu items do their own thing, so only selectively listen for the
167 G_CALLBACK(OnMenuItemActivated), this); 172 // activate signal.
173 if (connect_to_activate) {
174 SetMenuItemID(menu_item, command_id);
175 g_signal_connect(menu_item, "activate",
176 G_CALLBACK(OnMenuItemActivated), this);
177 }
168 178
169 gtk_widget_show(menu_item); 179 gtk_widget_show(menu_item);
170 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); 180 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
171 return menu_item; 181 return menu_item;
172 } 182 }
173 183
174 void MenuGtk::Popup(GtkWidget* widget, GdkEvent* event) { 184 void MenuGtk::Popup(GtkWidget* widget, GdkEvent* event) {
175 DCHECK(event->type == GDK_BUTTON_PRESS) 185 DCHECK(event->type == GDK_BUTTON_PRESS)
176 << "Non-button press event sent to RunMenuAt"; 186 << "Non-button press event sent to RunMenuAt";
177 187
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 BuildSubmenuFromModel(model_, menu_); 234 BuildSubmenuFromModel(model_, menu_);
225 } 235 }
226 236
227 void MenuGtk::BuildSubmenuFromModel(menus::MenuModel* model, GtkWidget* menu) { 237 void MenuGtk::BuildSubmenuFromModel(menus::MenuModel* model, GtkWidget* menu) {
228 std::map<int, GtkWidget*> radio_groups; 238 std::map<int, GtkWidget*> radio_groups;
229 GtkWidget* menu_item = NULL; 239 GtkWidget* menu_item = NULL;
230 for (int i = 0; i < model->GetItemCount(); ++i) { 240 for (int i = 0; i < model->GetItemCount(); ++i) {
231 SkBitmap icon; 241 SkBitmap icon;
232 std::string label = 242 std::string label =
233 ConvertAcceleratorsFromWindowsStyle(UTF16ToUTF8(model->GetLabelAt(i))); 243 ConvertAcceleratorsFromWindowsStyle(UTF16ToUTF8(model->GetLabelAt(i)));
244 bool connect_to_activate = true;
234 245
235 switch (model->GetTypeAt(i)) { 246 switch (model->GetTypeAt(i)) {
236 case menus::MenuModel::TYPE_SEPARATOR: 247 case menus::MenuModel::TYPE_SEPARATOR:
237 menu_item = gtk_separator_menu_item_new(); 248 menu_item = gtk_separator_menu_item_new();
238 break; 249 break;
239 250
240 case menus::MenuModel::TYPE_CHECK: 251 case menus::MenuModel::TYPE_CHECK:
241 menu_item = gtk_check_menu_item_new_with_mnemonic(label.c_str()); 252 menu_item = gtk_check_menu_item_new_with_mnemonic(label.c_str());
242 break; 253 break;
243 254
244 case menus::MenuModel::TYPE_RADIO: { 255 case menus::MenuModel::TYPE_RADIO: {
245 std::map<int, GtkWidget*>::iterator iter = 256 std::map<int, GtkWidget*>::iterator iter =
246 radio_groups.find(model->GetGroupIdAt(i)); 257 radio_groups.find(model->GetGroupIdAt(i));
247 258
248 if (iter == radio_groups.end()) { 259 if (iter == radio_groups.end()) {
249 menu_item = gtk_radio_menu_item_new_with_mnemonic( 260 menu_item = gtk_radio_menu_item_new_with_mnemonic(
250 NULL, label.c_str()); 261 NULL, label.c_str());
251 radio_groups[model->GetGroupIdAt(i)] = menu_item; 262 radio_groups[model->GetGroupIdAt(i)] = menu_item;
252 } else { 263 } else {
253 menu_item = gtk_radio_menu_item_new_with_mnemonic_from_widget( 264 menu_item = gtk_radio_menu_item_new_with_mnemonic_from_widget(
254 GTK_RADIO_MENU_ITEM(iter->second), label.c_str()); 265 GTK_RADIO_MENU_ITEM(iter->second), label.c_str());
255 } 266 }
256 break; 267 break;
257 } 268 }
269 case menus::MenuModel::TYPE_BUTTON_ITEM: {
270 menus::ButtonMenuItemModel* button_menu_item_model =
271 model->GetButtonMenuItemAt(i);
272
273 menu_item = BuildButtomMenuItem(button_menu_item_model);
274
275 connect_to_activate = false;
276 break;
277 }
258 case menus::MenuModel::TYPE_SUBMENU: 278 case menus::MenuModel::TYPE_SUBMENU:
259 case menus::MenuModel::TYPE_COMMAND: 279 case menus::MenuModel::TYPE_COMMAND:
260 if (model->GetIconAt(i, &icon)) 280 if (model->GetIconAt(i, &icon))
261 menu_item = BuildMenuItemWithImage(label, icon); 281 menu_item = BuildMenuItemWithImage(label, icon);
262 else 282 else
263 menu_item = gtk_menu_item_new_with_mnemonic(label.c_str()); 283 menu_item = gtk_menu_item_new_with_mnemonic(label.c_str());
264 break; 284 break;
265 285
266 default: 286 default:
267 NOTREACHED(); 287 NOTREACHED();
(...skipping 10 matching lines...) Expand all
278 gtk_widget_add_accelerator(menu_item, 298 gtk_widget_add_accelerator(menu_item,
279 "activate", 299 "activate",
280 dummy_accel_group_, 300 dummy_accel_group_,
281 accelerator.GetGdkKeyCode(), 301 accelerator.GetGdkKeyCode(),
282 accelerator.gdk_modifier_type(), 302 accelerator.gdk_modifier_type(),
283 GTK_ACCEL_VISIBLE); 303 GTK_ACCEL_VISIBLE);
284 } 304 }
285 305
286 g_object_set_data(G_OBJECT(menu_item), "model", 306 g_object_set_data(G_OBJECT(menu_item), "model",
287 reinterpret_cast<void*>(model)); 307 reinterpret_cast<void*>(model));
288 AppendMenuItemToMenu(i, menu_item, menu); 308 AppendMenuItemToMenu(i, menu_item, menu, connect_to_activate);
289 309
290 if (model->IsLabelDynamicAt(i)) { 310 if (model->IsLabelDynamicAt(i)) {
291 g_signal_connect(menu, "show", G_CALLBACK(OnSubmenuShow), 311 g_signal_connect(menu, "show", G_CALLBACK(OnSubmenuShow),
292 GINT_TO_POINTER(i)); 312 GINT_TO_POINTER(i));
293 } 313 }
294 314
295 menu_item = NULL; 315 menu_item = NULL;
296 } 316 }
297 } 317 }
298 318
319 GtkWidget* MenuGtk::BuildButtomMenuItem(menus::ButtonMenuItemModel* model) {
320 GtkWidget* menu_item = gtk_custom_menu_item_new(
321 RemoveWindowsStyleAccelerators(UTF16ToUTF8(model->label())).c_str());
322 for (int i = 0; i < model->GetItemCount(); ++i) {
323 switch (model->GetTypeAt(i)) {
324 case menus::ButtonMenuItemModel::TYPE_SPACE: {
325 gtk_custom_menu_item_add_space(GTK_CUSTOM_MENU_ITEM(menu_item));
326 break;
327 }
328 case menus::ButtonMenuItemModel::TYPE_BUTTON: {
329 GtkWidget* button = gtk_custom_menu_item_add_button(
330 GTK_CUSTOM_MENU_ITEM(menu_item),
331 model->GetCommandIdAt(i));
332
333 int icon_idr;
334 if (model->GetIconAt(i, &icon_idr)) {
335 // TODO(erg): This should go through the GtkThemeProvider so we can
336 // get a version tinted to label color.
337 gtk_button_set_image(
338 GTK_BUTTON(button),
339 gtk_image_new_from_pixbuf(
340 ResourceBundle::GetSharedInstance().
341 GetPixbufNamed(icon_idr)));
342 } else {
343 gtk_button_set_label(
344 GTK_BUTTON(button),
345 RemoveWindowsStyleAccelerators(
346 UTF16ToUTF8(model->GetLabelAt(i))).c_str());
347 }
348
349 // TODO(erg): Set up dynamic labels here.
350 break;
351 }
352 }
353 }
354
355 // Set up the callback to the model for when it is clicked.
356 g_object_set_data(G_OBJECT(menu_item), "button-model",
357 reinterpret_cast<void*>(model));
358 g_signal_connect(menu_item, "button-pushed",
359 G_CALLBACK(OnMenuButtonPressed), this);
360 return menu_item;
361 }
362
299 // static 363 // static
300 void MenuGtk::OnMenuItemActivated(GtkMenuItem* menuitem, MenuGtk* menu) { 364 void MenuGtk::OnMenuItemActivated(GtkMenuItem* menuitem, MenuGtk* menu) {
301 if (block_activation_) 365 if (block_activation_)
302 return; 366 return;
303 367
304 // We receive activation messages when highlighting a menu that has a 368 // We receive activation messages when highlighting a menu that has a
305 // submenu. Ignore them. 369 // submenu. Ignore them.
306 if (gtk_menu_item_get_submenu(menuitem)) 370 if (gtk_menu_item_get_submenu(menuitem))
307 return; 371 return;
308 372
309 // The activate signal is sent to radio items as they get deselected; 373 // The activate signal is sent to radio items as they get deselected;
310 // ignore it in this case. 374 // ignore it in this case.
311 if (GTK_IS_RADIO_MENU_ITEM(menuitem) && 375 if (GTK_IS_RADIO_MENU_ITEM(menuitem) &&
312 !gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) { 376 !gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) {
313 return; 377 return;
314 } 378 }
315 379
316 int id; 380 int id;
317 if (!GetMenuItemID(GTK_WIDGET(menuitem), &id)) 381 if (!GetMenuItemID(GTK_WIDGET(menuitem), &id))
318 return; 382 return;
319 383
320 menus::MenuModel* model = ModelForMenuItem(menuitem); 384 menus::MenuModel* model = ModelForMenuItem(menuitem);
321 385
322 // The menu item can still be activated by hotkeys even if it is disabled. 386 // The menu item can still be activated by hotkeys even if it is disabled.
323 if (model->IsEnabledAt(id)) 387 if (model->IsEnabledAt(id))
324 menu->ExecuteCommand(model, id); 388 menu->ExecuteCommand(model, id);
325 } 389 }
326 390
391 void MenuGtk::OnMenuButtonPressed(GtkMenuItem* menu_item, int command_id,
392 MenuGtk* menu) {
393 menus::ButtonMenuItemModel* model =
394 reinterpret_cast<menus::ButtonMenuItemModel*>(
395 g_object_get_data(G_OBJECT(menu_item), "button-model"));
396 if (model) {
397 if (menu->delegate_)
398 menu->delegate_->CommandWillBeExecuted();
399
400 model->ActivatedCommand(command_id);
401 }
402 }
403
327 // static 404 // static
328 void MenuGtk::WidgetMenuPositionFunc(GtkMenu* menu, 405 void MenuGtk::WidgetMenuPositionFunc(GtkMenu* menu,
329 int* x, 406 int* x,
330 int* y, 407 int* y,
331 gboolean* push_in, 408 gboolean* push_in,
332 void* void_widget) { 409 void* void_widget) {
333 GtkWidget* widget = GTK_WIDGET(void_widget); 410 GtkWidget* widget = GTK_WIDGET(void_widget);
334 GtkRequisition menu_req; 411 GtkRequisition menu_req;
335 412
336 gtk_widget_size_request(GTK_WIDGET(menu), &menu_req); 413 gtk_widget_size_request(GTK_WIDGET(menu), &menu_req);
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 if (GTK_IS_MENU_ITEM(widget)) { 526 if (GTK_IS_MENU_ITEM(widget)) {
450 gtk_widget_set_sensitive(widget, model->IsEnabledAt(id)); 527 gtk_widget_set_sensitive(widget, model->IsEnabledAt(id));
451 528
452 GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget)); 529 GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget));
453 if (submenu) { 530 if (submenu) {
454 gtk_container_foreach(GTK_CONTAINER(submenu), &SetMenuItemInfo, 531 gtk_container_foreach(GTK_CONTAINER(submenu), &SetMenuItemInfo,
455 userdata); 532 userdata);
456 } 533 }
457 } 534 }
458 } 535 }
OLDNEW
« no previous file with comments | « chrome/browser/gtk/menu_gtk.h ('k') | chrome/browser/gtk/notifications/notification_options_menu_model.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698