| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this |
| 2 // source code is governed by a BSD-style license that can be found in the | 2 // source code is governed by a BSD-style license that can be found in the |
| 3 // LICENSE file. | 3 // LICENSE file. |
| 4 | 4 |
| 5 #include "views/controls/menu/native_menu_gtk.h" | 5 #include "views/controls/menu/native_menu_gtk.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "app/gfx/gtk_util.h" | 10 #include "app/gfx/gtk_util.h" |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 | 59 |
| 60 namespace views { | 60 namespace views { |
| 61 | 61 |
| 62 //////////////////////////////////////////////////////////////////////////////// | 62 //////////////////////////////////////////////////////////////////////////////// |
| 63 // NativeMenuGtk, public: | 63 // NativeMenuGtk, public: |
| 64 | 64 |
| 65 NativeMenuGtk::NativeMenuGtk(menus::MenuModel* model) | 65 NativeMenuGtk::NativeMenuGtk(menus::MenuModel* model) |
| 66 : model_(model), | 66 : model_(model), |
| 67 menu_(NULL), | 67 menu_(NULL), |
| 68 menu_shown_(false), | 68 menu_shown_(false), |
| 69 suppress_activate_signal_(false) { | 69 suppress_activate_signal_(false), |
| 70 menu_activated_(false), |
| 71 activated_index_(-1) { |
| 70 } | 72 } |
| 71 | 73 |
| 72 NativeMenuGtk::~NativeMenuGtk() { | 74 NativeMenuGtk::~NativeMenuGtk() { |
| 73 gtk_widget_destroy(menu_); | 75 gtk_widget_destroy(menu_); |
| 74 } | 76 } |
| 75 | 77 |
| 76 //////////////////////////////////////////////////////////////////////////////// | 78 //////////////////////////////////////////////////////////////////////////////// |
| 77 // NativeMenuGtk, MenuWrapper implementation: | 79 // NativeMenuGtk, MenuWrapper implementation: |
| 78 | 80 |
| 79 void NativeMenuGtk::RunMenuAt(const gfx::Point& point, int alignment) { | 81 void NativeMenuGtk::RunMenuAt(const gfx::Point& point, int alignment) { |
| 82 menu_activated_ = false; |
| 83 |
| 80 UpdateStates(); | 84 UpdateStates(); |
| 81 Position position = { point, static_cast<Menu2::Alignment>(alignment) }; | 85 Position position = { point, static_cast<Menu2::Alignment>(alignment) }; |
| 82 // TODO(beng): value of '1' will not work for context menus! | 86 // TODO(beng): value of '1' will not work for context menus! |
| 83 gtk_menu_popup(GTK_MENU(menu_), NULL, NULL, MenuPositionFunc, &position, 1, | 87 gtk_menu_popup(GTK_MENU(menu_), NULL, NULL, MenuPositionFunc, &position, 1, |
| 84 gtk_get_current_event_time()); | 88 gtk_get_current_event_time()); |
| 85 | 89 |
| 86 DCHECK(!menu_shown_); | 90 DCHECK(!menu_shown_); |
| 87 menu_shown_ = true; | 91 menu_shown_ = true; |
| 88 // Listen for "hide" signal so that we know when to return from the blocking | 92 // Listen for "hide" signal so that we know when to return from the blocking |
| 89 // RunMenuAt call. | 93 // RunMenuAt call. |
| 90 gint handle_id = | 94 gint handle_id = |
| 91 g_signal_connect(G_OBJECT(menu_), "hide", G_CALLBACK(OnMenuHidden), this); | 95 g_signal_connect(G_OBJECT(menu_), "hide", G_CALLBACK(OnMenuHidden), this); |
| 92 | 96 |
| 93 // Block until menu is no longer shown by running a nested message loop. | 97 // Block until menu is no longer shown by running a nested message loop. |
| 94 MessageLoopForUI::current()->Run(NULL); | 98 MessageLoopForUI::current()->Run(NULL); |
| 95 | 99 |
| 96 g_signal_handler_disconnect(G_OBJECT(menu_), handle_id); | 100 g_signal_handler_disconnect(G_OBJECT(menu_), handle_id); |
| 97 menu_shown_ = false; | 101 menu_shown_ = false; |
| 102 |
| 103 // Call into the model after the nested message loop quits. This way if the |
| 104 // model ends up deleting us, or MessageLoop::Quit takes a while, there aren't |
| 105 // any problems. |
| 106 if (menu_activated_ && model_->IsEnabledAt(activated_index_) && |
| 107 MenuTypeCanExecute(model_->GetTypeAt(activated_index_))) { |
| 108 model_->ActivatedAt(activated_index_); |
| 109 } |
| 98 } | 110 } |
| 99 | 111 |
| 100 void NativeMenuGtk::CancelMenu() { | 112 void NativeMenuGtk::CancelMenu() { |
| 101 NOTIMPLEMENTED(); | 113 NOTIMPLEMENTED(); |
| 102 } | 114 } |
| 103 | 115 |
| 104 void NativeMenuGtk::Rebuild() { | 116 void NativeMenuGtk::Rebuild() { |
| 105 ResetMenu(); | 117 ResetMenu(); |
| 106 | 118 |
| 107 std::map<int, GtkRadioMenuItem*> radio_groups_; | 119 std::map<int, GtkRadioMenuItem*> radio_groups_; |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 // Ignore the signal if it's sent to an inactive checked radio item. | 298 // Ignore the signal if it's sent to an inactive checked radio item. |
| 287 // | 299 // |
| 288 // Suppose there are three radio items A, B, C, and A is now being | 300 // Suppose there are three radio items A, B, C, and A is now being |
| 289 // checked. If you click C, "activate" signal will be sent to A and C. | 301 // checked. If you click C, "activate" signal will be sent to A and C. |
| 290 // Here, we ignore the signal sent to A. | 302 // Here, we ignore the signal sent to A. |
| 291 if (GTK_IS_RADIO_MENU_ITEM(menu_item) && | 303 if (GTK_IS_RADIO_MENU_ITEM(menu_item) && |
| 292 !gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_item))) { | 304 !gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_item))) { |
| 293 return; | 305 return; |
| 294 } | 306 } |
| 295 | 307 |
| 296 if (model_->IsEnabledAt(position) && | 308 menu_activated_ = true; |
| 297 MenuTypeCanExecute(model_->GetTypeAt(position))) { | 309 activated_index_ = position; |
| 298 model_->ActivatedAt(position); | |
| 299 } | |
| 300 } | 310 } |
| 301 | 311 |
| 302 // static | 312 // static |
| 303 void NativeMenuGtk::CallActivate(GtkMenuItem* menu_item, | 313 void NativeMenuGtk::CallActivate(GtkMenuItem* menu_item, |
| 304 NativeMenuGtk* native_menu) { | 314 NativeMenuGtk* native_menu) { |
| 305 native_menu->OnActivate(menu_item); | 315 native_menu->OnActivate(menu_item); |
| 306 } | 316 } |
| 307 | 317 |
| 308 //////////////////////////////////////////////////////////////////////////////// | 318 //////////////////////////////////////////////////////////////////////////////// |
| 309 // MenuWrapper, public: | 319 // MenuWrapper, public: |
| 310 | 320 |
| 311 // static | 321 // static |
| 312 MenuWrapper* MenuWrapper::CreateWrapper(Menu2* menu) { | 322 MenuWrapper* MenuWrapper::CreateWrapper(Menu2* menu) { |
| 313 return new NativeMenuGtk(menu->model()); | 323 return new NativeMenuGtk(menu->model()); |
| 314 } | 324 } |
| 315 | 325 |
| 316 } // namespace views | 326 } // namespace views |
| OLD | NEW |