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

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

Issue 48065: Ensure that MenuGtks are destroyed before their accelerator group. (Closed)
Patch Set: reinterpretcast Created 11 years, 9 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
« no previous file with comments | « chrome/browser/gtk/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. 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 "base/gfx/gtk_util.h" 7 #include "base/gfx/gtk_util.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/string_util.h" 9 #include "base/string_util.h"
10 #include "chrome/common/l10n_util.h" 10 #include "chrome/common/l10n_util.h"
(...skipping 20 matching lines...) Expand all
31 31
32 return ret; 32 return ret;
33 } 33 }
34 34
35 } // namespace 35 } // namespace
36 36
37 MenuGtk::MenuGtk(MenuGtk::Delegate* delegate, 37 MenuGtk::MenuGtk(MenuGtk::Delegate* delegate,
38 const MenuCreateMaterial* menu_data, 38 const MenuCreateMaterial* menu_data,
39 GtkAccelGroup* accel_group) 39 GtkAccelGroup* accel_group)
40 : delegate_(delegate), 40 : delegate_(delegate),
41 accel_group_(accel_group),
42 menu_(gtk_menu_new()) { 41 menu_(gtk_menu_new()) {
43 BuildMenuIn(menu_.get(), menu_data); 42 BuildMenuIn(menu_.get(), menu_data, accel_group);
44 } 43 }
45 44
46 MenuGtk::MenuGtk(MenuGtk::Delegate* delegate) 45 MenuGtk::MenuGtk(MenuGtk::Delegate* delegate)
47 : delegate_(delegate), 46 : delegate_(delegate),
48 menu_(gtk_menu_new()) { 47 menu_(gtk_menu_new()) {
49 BuildMenuFromDelegate(); 48 BuildMenuFromDelegate();
50 } 49 }
51 50
52 MenuGtk::~MenuGtk() { 51 MenuGtk::~MenuGtk() {
53 menu_.Destroy(); 52 menu_.Destroy();
(...skipping 19 matching lines...) Expand all
73 void MenuGtk::PopupAsContext() { 72 void MenuGtk::PopupAsContext() {
74 gtk_container_foreach(GTK_CONTAINER(menu_.get()), SetMenuItemInfo, this); 73 gtk_container_foreach(GTK_CONTAINER(menu_.get()), SetMenuItemInfo, this);
75 74
76 // TODO(estade): |button| value of 0 (6th argument) is not strictly true, 75 // TODO(estade): |button| value of 0 (6th argument) is not strictly true,
77 // but does it matter? 76 // but does it matter?
78 gtk_menu_popup(GTK_MENU(menu_.get()), NULL, NULL, NULL, NULL, 0, 77 gtk_menu_popup(GTK_MENU(menu_.get()), NULL, NULL, NULL, NULL, 0,
79 gtk_get_current_event_time()); 78 gtk_get_current_event_time());
80 } 79 }
81 80
82 void MenuGtk::BuildMenuIn(GtkWidget* menu, 81 void MenuGtk::BuildMenuIn(GtkWidget* menu,
83 const MenuCreateMaterial* menu_data) { 82 const MenuCreateMaterial* menu_data,
83 GtkAccelGroup* accel_group) {
84 // We keep track of the last menu item in order to group radio items. 84 // We keep track of the last menu item in order to group radio items.
85 GtkWidget* last_menu_item = NULL; 85 GtkWidget* last_menu_item = NULL;
86 for (; menu_data->type != MENU_END; ++menu_data) { 86 for (; menu_data->type != MENU_END; ++menu_data) {
87 GtkWidget* menu_item = NULL; 87 GtkWidget* menu_item = NULL;
88 88
89 std::string label; 89 std::string label;
90 if (menu_data->label_argument) { 90 if (menu_data->label_argument) {
91 label = WideToUTF8(l10n_util::GetStringF( 91 label = WideToUTF8(l10n_util::GetStringF(
92 menu_data->label_id, 92 menu_data->label_id,
93 l10n_util::GetString(menu_data->label_argument))); 93 l10n_util::GetString(menu_data->label_argument)));
(...skipping 23 matching lines...) Expand all
117 menu_item = gtk_separator_menu_item_new(); 117 menu_item = gtk_separator_menu_item_new();
118 break; 118 break;
119 case MENU_NORMAL: 119 case MENU_NORMAL:
120 default: 120 default:
121 menu_item = gtk_menu_item_new_with_mnemonic(label.c_str()); 121 menu_item = gtk_menu_item_new_with_mnemonic(label.c_str());
122 break; 122 break;
123 } 123 }
124 124
125 if (menu_data->submenu) { 125 if (menu_data->submenu) {
126 GtkWidget* submenu = gtk_menu_new(); 126 GtkWidget* submenu = gtk_menu_new();
127 BuildMenuIn(submenu, menu_data->submenu); 127 BuildMenuIn(submenu, menu_data->submenu, accel_group);
128 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), submenu); 128 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), submenu);
129 } 129 }
130 130
131 if (accel_group_ && menu_data->accel_key) { 131 if (accel_group && menu_data->accel_key) {
132 // If we ever want to let the user do any key remaping, we'll need to 132 // If we ever want to let the user do any key remaping, we'll need to
133 // change the following so we make a gtk_accel_map which keeps the actual 133 // change the following so we make a gtk_accel_map which keeps the actual
134 // keys. 134 // keys.
135 gtk_widget_add_accelerator(menu_item, 135 gtk_widget_add_accelerator(menu_item,
136 "activate", 136 "activate",
137 accel_group_, 137 accel_group,
138 menu_data->accel_key, 138 menu_data->accel_key,
139 GdkModifierType(menu_data->accel_modifiers), 139 GdkModifierType(menu_data->accel_modifiers),
140 GTK_ACCEL_VISIBLE); 140 GTK_ACCEL_VISIBLE);
141 } 141 }
142 142
143 g_object_set_data(G_OBJECT(menu_item), "menu-data", 143 g_object_set_data(G_OBJECT(menu_item), "menu-data",
144 const_cast<MenuCreateMaterial*>(menu_data)); 144 const_cast<MenuCreateMaterial*>(menu_data));
145 145
146 g_signal_connect(G_OBJECT(menu_item), "activate", 146 g_signal_connect(G_OBJECT(menu_item), "activate",
147 G_CALLBACK(OnMenuItemActivated), this); 147 G_CALLBACK(OnMenuItemActivated), this);
(...skipping 23 matching lines...) Expand all
171 menu_item = gtk_menu_item_new_with_label(delegate_->GetLabel(i).c_str()); 171 menu_item = gtk_menu_item_new_with_label(delegate_->GetLabel(i).c_str());
172 } 172 }
173 173
174 g_object_set_data(G_OBJECT(menu_item), "menu-id", 174 g_object_set_data(G_OBJECT(menu_item), "menu-id",
175 reinterpret_cast<void*>(i)); 175 reinterpret_cast<void*>(i));
176 176
177 g_signal_connect(G_OBJECT(menu_item), "activate", 177 g_signal_connect(G_OBJECT(menu_item), "activate",
178 G_CALLBACK(OnMenuItemActivatedById), this); 178 G_CALLBACK(OnMenuItemActivatedById), this);
179 179
180 gtk_widget_show(menu_item); 180 gtk_widget_show(menu_item);
181 // TODO(estade): gtk_menu_append is deprecated. 181 gtk_menu_shell_append(GTK_MENU_SHELL(menu_.get()), menu_item);
182 gtk_menu_append(menu_.get(), menu_item);
183 } 182 }
184 } 183 }
185 184
186 // static 185 // static
187 void MenuGtk::OnMenuItemActivated(GtkMenuItem* menuitem, MenuGtk* menu) { 186 void MenuGtk::OnMenuItemActivated(GtkMenuItem* menuitem, MenuGtk* menu) {
188 // We receive activation messages when highlighting a menu that has a 187 // We receive activation messages when highlighting a menu that has a
189 // submenu. Ignore them. 188 // submenu. Ignore them.
190 if (!gtk_menu_item_get_submenu(menuitem)) { 189 if (!gtk_menu_item_get_submenu(menuitem)) {
191 const MenuCreateMaterial* data = 190 const MenuCreateMaterial* data =
192 reinterpret_cast<const MenuCreateMaterial*>( 191 reinterpret_cast<const MenuCreateMaterial*>(
(...skipping 14 matching lines...) Expand all
207 } 206 }
208 207
209 // static 208 // static
210 void MenuGtk::MenuPositionFunc(GtkMenu* menu, 209 void MenuGtk::MenuPositionFunc(GtkMenu* menu,
211 int* x, 210 int* x,
212 int* y, 211 int* y,
213 gboolean* push_in, 212 gboolean* push_in,
214 void* void_widget) { 213 void* void_widget) {
215 GtkWidget* widget = GTK_WIDGET(void_widget); 214 GtkWidget* widget = GTK_WIDGET(void_widget);
216 GtkRequisition menu_req; 215 GtkRequisition menu_req;
217 GdkRectangle monitor;
218 216
219 gtk_widget_size_request(GTK_WIDGET(menu), &menu_req); 217 gtk_widget_size_request(GTK_WIDGET(menu), &menu_req);
220 218
221 GdkScreen* screen = gtk_widget_get_screen(GTK_WIDGET(menu));
222 gint monitor_num = gdk_screen_get_monitor_at_window(screen, widget->window);
223 if (monitor_num < 0)
224 monitor_num = 0;
225 gdk_screen_get_monitor_geometry(screen, monitor_num, &monitor);
226
227 gdk_window_get_origin(widget->window, x, y); 219 gdk_window_get_origin(widget->window, x, y);
228 *x += widget->allocation.x; 220 *x += widget->allocation.x;
229 *y += widget->allocation.y + widget->allocation.height; 221 *y += widget->allocation.y + widget->allocation.height;
230 222
231 // g_object_get_data() returns NULL if no such object is found. |left_align| 223 // g_object_get_data() returns NULL if no such object is found. |left_align|
232 // acts as a boolean, but we can't actually cast it to bool because gcc 224 // acts as a boolean, but we can't actually cast it to bool because gcc
233 // complains about losing precision. 225 // complains about losing precision.
234 void* left_align = 226 if (!g_object_get_data(G_OBJECT(widget), "left-align-popup"))
235 g_object_get_data(G_OBJECT(widget), "left-align-popup");
236
237 if (!left_align)
238 *x += widget->allocation.width - menu_req.width; 227 *x += widget->allocation.width - menu_req.width;
239 228
240 // TODO(erg): Deal with this scrolling off the bottom of the screen. 229 // TODO(erg): Deal with this scrolling off the bottom of the screen.
241 230
242 // Regretfully, we can't rely on push_in to alter the coordinates above to 231 // Regretfully, we can't rely on push_in to alter the coordinates above to
243 // always make the menu fit on screen. It'd make the above calculations just 232 // always make the menu fit on screen. It'd make the above calculations just
244 // work though... 233 // work though...
245 *push_in = FALSE; 234 *push_in = FALSE;
246 } 235 }
247 236
248 // static 237 // static
249 void MenuGtk::SetMenuItemInfo(GtkWidget* widget, void* raw_menu) { 238 void MenuGtk::SetMenuItemInfo(GtkWidget* widget, gpointer userdata) {
250 MenuGtk* menu = static_cast<MenuGtk*>(raw_menu); 239 MenuGtk* menu = reinterpret_cast<MenuGtk*>(userdata);
251 const MenuCreateMaterial* data = 240 const MenuCreateMaterial* data =
252 reinterpret_cast<const MenuCreateMaterial*>( 241 reinterpret_cast<const MenuCreateMaterial*>(
253 g_object_get_data(G_OBJECT(widget), "menu-data")); 242 g_object_get_data(G_OBJECT(widget), "menu-data"));
254 243
255 if (data) { 244 if (data) {
256 if (GTK_IS_CHECK_MENU_ITEM(widget)) { 245 if (GTK_IS_CHECK_MENU_ITEM(widget)) {
257 GtkCheckMenuItem* item = GTK_CHECK_MENU_ITEM(widget); 246 GtkCheckMenuItem* item = GTK_CHECK_MENU_ITEM(widget);
258 gtk_check_menu_item_set_active( 247 gtk_check_menu_item_set_active(
259 item, menu->delegate_->IsItemChecked(data->id)); 248 item, menu->delegate_->IsItemChecked(data->id));
260 } 249 }
261 250
262 if (GTK_IS_MENU_ITEM(widget)) { 251 if (GTK_IS_MENU_ITEM(widget)) {
263 gtk_widget_set_sensitive( 252 gtk_widget_set_sensitive(
264 widget, menu->delegate_->IsCommandEnabled(data->id)); 253 widget, menu->delegate_->IsCommandEnabled(data->id));
265 254
266 GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget)); 255 GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget));
267 if (submenu) { 256 if (submenu) {
268 gtk_container_foreach(GTK_CONTAINER(submenu), &MenuGtk::SetMenuItemInfo, 257 gtk_container_foreach(GTK_CONTAINER(submenu), &SetMenuItemInfo,
269 raw_menu); 258 userdata);
270 } 259 }
271 } 260 }
272 } 261 }
273 } 262 }
OLDNEW
« no previous file with comments | « chrome/browser/gtk/menu_gtk.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698