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

Side by Side Diff: views/controls/menu/native_menu_gtk.cc

Issue 383012: Fix for issue 27210, show bookmarks bar menu is out of sync with the browser's status. (Closed)
Patch Set: Created 11 years, 1 month 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
« no previous file with comments | « views/controls/menu/native_menu_gtk.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <string> 7 #include <string>
8 8
9 #include "app/gfx/gtk_util.h" 9 #include "app/gfx/gtk_util.h"
10 #include "base/keyboard_codes.h" 10 #include "base/keyboard_codes.h"
11 #include "base/message_loop.h" 11 #include "base/message_loop.h"
12 #include "base/string_util.h" 12 #include "base/string_util.h"
13 #include "base/time.h" 13 #include "base/time.h"
14 #include "third_party/skia/include/core/SkBitmap.h" 14 #include "third_party/skia/include/core/SkBitmap.h"
15 #include "views/accelerator.h" 15 #include "views/accelerator.h"
16 #include "views/controls/menu/menu_2.h" 16 #include "views/controls/menu/menu_2.h"
17 17
18 namespace { 18 namespace {
19 // Data passed to the UpdateStateCallback from gtk_container_foreach. 19
20 struct UpdateStateData { 20 const char kPositionString[] = "position";
21 // The model to retrieve state from.
22 views::Menu2Model* model;
23 // The index within said model.
24 int index;
25 };
26 21
27 // Data passed to the MenuPositionFunc from gtk_menu_popup 22 // Data passed to the MenuPositionFunc from gtk_menu_popup
28 struct Position { 23 struct Position {
29 // The point to run the menu at. 24 // The point to run the menu at.
30 gfx::Point point; 25 gfx::Point point;
31 // The alignment of the menu at that point. 26 // The alignment of the menu at that point.
32 views::Menu2::Alignment alignment; 27 views::Menu2::Alignment alignment;
33 }; 28 };
34 29
35 std::string ConvertAcceleratorsFromWindowsStyle(const std::string& label) { 30 std::string ConvertAcceleratorsFromWindowsStyle(const std::string& label) {
(...skipping 25 matching lines...) Expand all
61 } // namespace 56 } // namespace
62 57
63 namespace views { 58 namespace views {
64 59
65 //////////////////////////////////////////////////////////////////////////////// 60 ////////////////////////////////////////////////////////////////////////////////
66 // NativeMenuGtk, public: 61 // NativeMenuGtk, public:
67 62
68 NativeMenuGtk::NativeMenuGtk(Menu2Model* model) 63 NativeMenuGtk::NativeMenuGtk(Menu2Model* model)
69 : model_(model), 64 : model_(model),
70 menu_(NULL), 65 menu_(NULL),
71 menu_shown_(false) { 66 menu_shown_(false),
67 suppress_activate_signal_(false) {
72 } 68 }
73 69
74 NativeMenuGtk::~NativeMenuGtk() { 70 NativeMenuGtk::~NativeMenuGtk() {
75 gtk_widget_destroy(menu_); 71 gtk_widget_destroy(menu_);
76 } 72 }
77 73
78 //////////////////////////////////////////////////////////////////////////////// 74 ////////////////////////////////////////////////////////////////////////////////
79 // NativeMenuGtk, MenuWrapper implementation: 75 // NativeMenuGtk, MenuWrapper implementation:
80 76
81 void NativeMenuGtk::RunMenuAt(const gfx::Point& point, int alignment) { 77 void NativeMenuGtk::RunMenuAt(const gfx::Point& point, int alignment) {
78 UpdateStates();
82 Position position = { point, static_cast<Menu2::Alignment>(alignment) }; 79 Position position = { point, static_cast<Menu2::Alignment>(alignment) };
83 // TODO(beng): value of '1' will not work for context menus! 80 // TODO(beng): value of '1' will not work for context menus!
84 gtk_menu_popup(GTK_MENU(menu_), NULL, NULL, MenuPositionFunc, &position, 1, 81 gtk_menu_popup(GTK_MENU(menu_), NULL, NULL, MenuPositionFunc, &position, 1,
85 gtk_get_current_event_time()); 82 gtk_get_current_event_time());
86 83
87 DCHECK(!menu_shown_); 84 DCHECK(!menu_shown_);
88 menu_shown_ = true; 85 menu_shown_ = true;
89 // Listen for "hide" signal so that we know when to return from the blocking 86 // Listen for "hide" signal so that we know when to return from the blocking
90 // RunMenuAt call. 87 // RunMenuAt call.
91 gint handle_id = 88 gint handle_id =
(...skipping 17 matching lines...) Expand all
109 for (int i = 0; i < model_->GetItemCount(); ++i) { 106 for (int i = 0; i < model_->GetItemCount(); ++i) {
110 Menu2Model::ItemType type = model_->GetTypeAt(i); 107 Menu2Model::ItemType type = model_->GetTypeAt(i);
111 if (type == Menu2Model::TYPE_SEPARATOR) 108 if (type == Menu2Model::TYPE_SEPARATOR)
112 AddSeparatorAt(i); 109 AddSeparatorAt(i);
113 else 110 else
114 AddMenuItemAt(i, &last_radio_item); 111 AddMenuItemAt(i, &last_radio_item);
115 } 112 }
116 } 113 }
117 114
118 void NativeMenuGtk::UpdateStates() { 115 void NativeMenuGtk::UpdateStates() {
119 UpdateStateData data = { model_, 0 }; 116 gtk_container_foreach(GTK_CONTAINER(menu_), &UpdateStateCallback, this);
120 gtk_container_foreach(GTK_CONTAINER(menu_), &UpdateStateCallback, &data);
121 } 117 }
122 118
123 gfx::NativeMenu NativeMenuGtk::GetNativeMenu() const { 119 gfx::NativeMenu NativeMenuGtk::GetNativeMenu() const {
124 return menu_; 120 return menu_;
125 } 121 }
126 122
127 //////////////////////////////////////////////////////////////////////////////// 123 ////////////////////////////////////////////////////////////////////////////////
128 // NativeMenuGtk, private: 124 // NativeMenuGtk, private:
129 125
130 // static 126 // static
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 Menu2* submenu = new Menu2(model_->GetSubmenuModelAt(index)); 184 Menu2* submenu = new Menu2(model_->GetSubmenuModelAt(index));
189 g_object_set_data(G_OBJECT(menu_item), "submenu", submenu); 185 g_object_set_data(G_OBJECT(menu_item), "submenu", submenu);
190 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), 186 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
191 submenu->GetNativeMenu()); 187 submenu->GetNativeMenu());
192 } 188 }
193 189
194 views::Accelerator accelerator(base::VKEY_UNKNOWN, false, false, false); 190 views::Accelerator accelerator(base::VKEY_UNKNOWN, false, false, false);
195 if (model_->GetAcceleratorAt(index, &accelerator)) { 191 if (model_->GetAcceleratorAt(index, &accelerator)) {
196 // TODO(beng): accelerators w/gtk_widget_add_accelerator. 192 // TODO(beng): accelerators w/gtk_widget_add_accelerator.
197 } 193 }
198 g_object_set_data(G_OBJECT(menu_item), "position", 194 g_object_set_data(G_OBJECT(menu_item), kPositionString,
199 reinterpret_cast<void*>(index)); 195 reinterpret_cast<void*>(index));
200 g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(CallActivate), 196 g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(CallActivate),
201 this); 197 this);
202 gtk_widget_show(menu_item); 198 gtk_widget_show(menu_item);
203 gtk_menu_append(menu_, menu_item); 199 gtk_menu_append(menu_, menu_item);
204 } 200 }
205 201
206 // static 202 void NativeMenuGtk::ResetMenu() {
207 void NativeMenuGtk::UpdateStateCallback(GtkWidget* menu_item, gpointer data) { 203 if (menu_)
208 UpdateStateData* usd = reinterpret_cast<UpdateStateData*>(data); 204 gtk_widget_destroy(menu_);
209 gtk_widget_set_sensitive(menu_item, usd->model->IsEnabledAt(usd->index)); 205 menu_ = gtk_menu_new();
206 }
207
208 void NativeMenuGtk::UpdateMenuItemState(GtkWidget* menu_item) {
209 int index = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu_item),
210 kPositionString));
211
212 gtk_widget_set_sensitive(menu_item, model_->IsEnabledAt(index));
210 if (GTK_IS_CHECK_MENU_ITEM(menu_item)) { 213 if (GTK_IS_CHECK_MENU_ITEM(menu_item)) {
214 suppress_activate_signal_ = true;
211 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_item), 215 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_item),
212 usd->model->IsItemCheckedAt(usd->index)); 216 model_->IsItemCheckedAt(index));
217 suppress_activate_signal_ = false;
213 } 218 }
214 // Recurse into submenus, too. 219 // Recurse into submenus, too.
215 if (GTK_IS_MENU_ITEM(menu_item)) { 220 if (GTK_IS_MENU_ITEM(menu_item)) {
216 if (gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu_item))) { 221 if (gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu_item))) {
217 Menu2* submenu = 222 Menu2* submenu =
218 reinterpret_cast<Menu2*>(g_object_get_data(G_OBJECT(menu_item), 223 reinterpret_cast<Menu2*>(g_object_get_data(G_OBJECT(menu_item),
219 "submenu")); 224 "submenu"));
220 if (submenu) 225 if (submenu)
221 submenu->UpdateStates(); 226 submenu->UpdateStates();
222 } 227 }
223 } 228 }
224 ++usd->index;
225 }
226
227 void NativeMenuGtk::ResetMenu() {
228 if (menu_)
229 gtk_widget_destroy(menu_);
230 menu_ = gtk_menu_new();
231 } 229 }
232 230
233 // static 231 // static
232 void NativeMenuGtk::UpdateStateCallback(GtkWidget* menu_item, gpointer data) {
233 NativeMenuGtk* menu = reinterpret_cast<NativeMenuGtk*>(data);
234 menu->UpdateMenuItemState(menu_item);
235 }
236
237 // static
234 void NativeMenuGtk::MenuPositionFunc(GtkMenu* menu, 238 void NativeMenuGtk::MenuPositionFunc(GtkMenu* menu,
235 int* x, 239 int* x,
236 int* y, 240 int* y,
237 gboolean* push_in, 241 gboolean* push_in,
238 void* data) { 242 void* data) {
239 Position* position = reinterpret_cast<Position*>(data); 243 Position* position = reinterpret_cast<Position*>(data);
240 // TODO(beng): RTL 244 // TODO(beng): RTL
241 *x = position->point.x(); 245 *x = position->point.x();
242 *y = position->point.y(); 246 *y = position->point.y();
243 if (position->alignment == Menu2::ALIGN_TOPRIGHT) { 247 if (position->alignment == Menu2::ALIGN_TOPRIGHT) {
244 GtkRequisition menu_req; 248 GtkRequisition menu_req;
245 gtk_widget_size_request(GTK_WIDGET(menu), &menu_req); 249 gtk_widget_size_request(GTK_WIDGET(menu), &menu_req);
246 *x -= menu_req.width; 250 *x -= menu_req.width;
247 } 251 }
248 *push_in = FALSE; 252 *push_in = FALSE;
249 } 253 }
250 254
251 void NativeMenuGtk::OnActivate(GtkMenuItem* menu_item) { 255 void NativeMenuGtk::OnActivate(GtkMenuItem* menu_item) {
256 if (suppress_activate_signal_)
257 return;
252 int position = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu_item), 258 int position = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu_item),
253 "position")); 259 kPositionString));
254 if (model_->IsEnabledAt(position) && 260 if (model_->IsEnabledAt(position) &&
255 MenuTypeCanExecute(model_->GetTypeAt(position))) { 261 MenuTypeCanExecute(model_->GetTypeAt(position))) {
256 model_->ActivatedAt(position); 262 model_->ActivatedAt(position);
257 } 263 }
258 } 264 }
259 265
260 // static 266 // static
261 void NativeMenuGtk::CallActivate(GtkMenuItem* menu_item, 267 void NativeMenuGtk::CallActivate(GtkMenuItem* menu_item,
262 NativeMenuGtk* native_menu) { 268 NativeMenuGtk* native_menu) {
263 native_menu->OnActivate(menu_item); 269 native_menu->OnActivate(menu_item);
264 } 270 }
265 271
266 //////////////////////////////////////////////////////////////////////////////// 272 ////////////////////////////////////////////////////////////////////////////////
267 // MenuWrapper, public: 273 // MenuWrapper, public:
268 274
269 // static 275 // static
270 MenuWrapper* MenuWrapper::CreateWrapper(Menu2* menu) { 276 MenuWrapper* MenuWrapper::CreateWrapper(Menu2* menu) {
271 return new NativeMenuGtk(menu->model()); 277 return new NativeMenuGtk(menu->model());
272 } 278 }
273 279
274 } // namespace views 280 } // namespace views
OLDNEW
« no previous file with comments | « views/controls/menu/native_menu_gtk.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698