Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "app/l10n_util.h" | 7 #include "app/l10n_util.h" |
| 8 #include "base/gfx/gtk_util.h" | 8 #include "base/gfx/gtk_util.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/stl_util-inl.h" | 10 #include "base/stl_util-inl.h" |
| 11 #include "base/string_util.h" | 11 #include "base/string_util.h" |
| 12 #include "chrome/browser/gtk/standard_menus.h" | 12 #include "chrome/browser/gtk/standard_menus.h" |
| 13 #include "chrome/common/gtk_util.h" | 13 #include "chrome/common/gtk_util.h" |
| 14 #include "third_party/skia/include/core/SkBitmap.h" | 14 #include "third_party/skia/include/core/SkBitmap.h" |
| 15 | 15 |
| 16 using gtk_util::ConvertAcceleratorsFromWindowsStyle; | 16 using gtk_util::ConvertAcceleratorsFromWindowsStyle; |
| 17 | 17 |
| 18 bool MenuGtk::block_activation_ = false; | |
| 19 | |
| 18 MenuGtk::MenuGtk(MenuGtk::Delegate* delegate, | 20 MenuGtk::MenuGtk(MenuGtk::Delegate* delegate, |
| 19 const MenuCreateMaterial* menu_data, | 21 const MenuCreateMaterial* menu_data, |
| 20 GtkAccelGroup* accel_group) | 22 GtkAccelGroup* accel_group) |
| 21 : delegate_(delegate), | 23 : delegate_(delegate), |
| 22 dummy_accel_group_(gtk_accel_group_new()), | 24 dummy_accel_group_(gtk_accel_group_new()), |
| 23 menu_(gtk_menu_new()) { | 25 menu_(gtk_menu_new()) { |
| 24 ConnectSignalHandlers(); | 26 ConnectSignalHandlers(); |
| 25 BuildMenuIn(menu_.get(), menu_data, accel_group); | 27 BuildMenuIn(menu_.get(), menu_data, accel_group); |
| 26 } | 28 } |
| 27 | 29 |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 220 } else { | 222 } else { |
| 221 menu_item = gtk_menu_item_new_with_label(delegate_->GetLabel(i).c_str()); | 223 menu_item = gtk_menu_item_new_with_label(delegate_->GetLabel(i).c_str()); |
| 222 } | 224 } |
| 223 | 225 |
| 224 AppendMenuItem(i, menu_item); | 226 AppendMenuItem(i, menu_item); |
| 225 } | 227 } |
| 226 } | 228 } |
| 227 | 229 |
| 228 // static | 230 // static |
| 229 void MenuGtk::OnMenuItemActivated(GtkMenuItem* menuitem, MenuGtk* menu) { | 231 void MenuGtk::OnMenuItemActivated(GtkMenuItem* menuitem, MenuGtk* menu) { |
| 232 if (block_activation_) | |
| 233 return; | |
| 234 | |
| 230 // We receive activation messages when highlighting a menu that has a | 235 // We receive activation messages when highlighting a menu that has a |
| 231 // submenu. Ignore them. | 236 // submenu. Ignore them. |
| 232 if (!gtk_menu_item_get_submenu(menuitem)) { | 237 if (gtk_menu_item_get_submenu(menuitem)) |
| 233 const MenuCreateMaterial* data = | 238 return; |
|
Elliot Glaysher
2009/08/03 22:46:34
You may be able to pull this check out; I think th
Evan Martin
2009/08/03 22:58:41
Nope, you get it when mousing through the menu. :
| |
| 234 reinterpret_cast<const MenuCreateMaterial*>( | |
| 235 g_object_get_data(G_OBJECT(menuitem), "menu-data")); | |
| 236 | 239 |
| 237 int id; | 240 const MenuCreateMaterial* data = |
| 238 if (data) { | 241 reinterpret_cast<const MenuCreateMaterial*>( |
| 239 id = data->id; | 242 g_object_get_data(G_OBJECT(menuitem), "menu-data")); |
| 240 } else { | |
| 241 id = reinterpret_cast<intptr_t>(g_object_get_data(G_OBJECT(menuitem), | |
| 242 "menu-id")); | |
| 243 } | |
| 244 | 243 |
| 245 // The menu item can still be activated by hotkeys even if it is disabled. | 244 int id; |
| 246 if (menu->delegate_->IsCommandEnabled(id)) | 245 if (data) { |
| 247 menu->delegate_->ExecuteCommand(id); | 246 id = data->id; |
| 247 } else { | |
| 248 id = reinterpret_cast<intptr_t>(g_object_get_data(G_OBJECT(menuitem), | |
| 249 "menu-id")); | |
| 248 } | 250 } |
| 251 | |
| 252 // The menu item can still be activated by hotkeys even if it is disabled. | |
| 253 if (menu->delegate_->IsCommandEnabled(id)) | |
| 254 menu->delegate_->ExecuteCommand(id); | |
| 249 } | 255 } |
| 250 | 256 |
| 251 // static | 257 // static |
| 252 void MenuGtk::MenuPositionFunc(GtkMenu* menu, | 258 void MenuGtk::MenuPositionFunc(GtkMenu* menu, |
| 253 int* x, | 259 int* x, |
| 254 int* y, | 260 int* y, |
| 255 gboolean* push_in, | 261 gboolean* push_in, |
| 256 void* void_widget) { | 262 void* void_widget) { |
| 257 GtkWidget* widget = GTK_WIDGET(void_widget); | 263 GtkWidget* widget = GTK_WIDGET(void_widget); |
| 258 GtkRequisition menu_req; | 264 GtkRequisition menu_req; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 318 "menu-id")); | 324 "menu-id")); |
| 319 } | 325 } |
| 320 | 326 |
| 321 if (GTK_IS_CHECK_MENU_ITEM(widget)) { | 327 if (GTK_IS_CHECK_MENU_ITEM(widget)) { |
| 322 GtkCheckMenuItem* item = GTK_CHECK_MENU_ITEM(widget); | 328 GtkCheckMenuItem* item = GTK_CHECK_MENU_ITEM(widget); |
| 323 | 329 |
| 324 // gtk_check_menu_item_set_active() will send the activate signal. Touching | 330 // gtk_check_menu_item_set_active() will send the activate signal. Touching |
| 325 // the underlying "active" property will also call the "activate" handler | 331 // the underlying "active" property will also call the "activate" handler |
| 326 // for this menu item. So we prevent the "activate" handler from | 332 // for this menu item. So we prevent the "activate" handler from |
| 327 // being called while we set the checkbox. | 333 // being called while we set the checkbox. |
| 328 g_signal_handlers_block_matched( | 334 // Why not use one of the glib signal-blocking functions? Because when we |
| 329 item, G_SIGNAL_MATCH_FUNC, | 335 // toggle a radio button, it will deactivate one of the other radio buttons, |
| 330 0, 0, NULL, | 336 // which we don't have a pointer to. |
| 331 reinterpret_cast<void*>(OnMenuItemActivated), | 337 // Wny not make this a member variable? Because "menu" is a pointer to the |
| 332 NULL); | 338 // root of the MenuGtk and we want to disable *all* MenuGtks, including |
| 333 | 339 // submenus. |
| 334 gtk_check_menu_item_set_active( | 340 block_activation_ = true; |
| 335 item, menu->delegate_->IsItemChecked(id)); | 341 gtk_check_menu_item_set_active(item, menu->delegate_->IsItemChecked(id)); |
| 336 | 342 block_activation_ = false; |
| 337 g_signal_handlers_unblock_matched( | |
| 338 item, G_SIGNAL_MATCH_FUNC, | |
| 339 0, 0, NULL, | |
| 340 reinterpret_cast<void*>(OnMenuItemActivated), | |
| 341 NULL); | |
| 342 } | 343 } |
| 343 | 344 |
| 344 if (GTK_IS_MENU_ITEM(widget)) { | 345 if (GTK_IS_MENU_ITEM(widget)) { |
| 345 gtk_widget_set_sensitive( | 346 gtk_widget_set_sensitive( |
| 346 widget, menu->delegate_->IsCommandEnabled(id)); | 347 widget, menu->delegate_->IsCommandEnabled(id)); |
| 347 | 348 |
| 348 GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget)); | 349 GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget)); |
| 349 if (submenu) { | 350 if (submenu) { |
| 350 gtk_container_foreach(GTK_CONTAINER(submenu), &SetMenuItemInfo, | 351 gtk_container_foreach(GTK_CONTAINER(submenu), &SetMenuItemInfo, |
| 351 userdata); | 352 userdata); |
| 352 } | 353 } |
| 353 } | 354 } |
| 354 } | 355 } |
| OLD | NEW |