1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.h"
10 #include "base/debug/leak_annotations.h"
11 #include "chrome/browser/ui/libgtk2ui/menu_util.h"
12 #include "ui/base/models/menu_model.h"
16 AppIndicatorIconMenu::AppIndicatorIconMenu(ui::MenuModel
* model
)
18 click_action_replacement_menu_item_added_(false),
20 block_activation_(false) {
22 ANNOTATE_SCOPED_MEMORY_LEAK
; // http://crbug.com/378770
23 gtk_menu_
= gtk_menu_new();
25 g_object_ref_sink(gtk_menu_
);
27 BuildSubmenuFromModel(menu_model_
,
29 G_CALLBACK(OnMenuItemActivatedThunk
),
36 AppIndicatorIconMenu::~AppIndicatorIconMenu() {
37 gtk_widget_destroy(gtk_menu_
);
38 g_object_unref(gtk_menu_
);
41 void AppIndicatorIconMenu::UpdateClickActionReplacementMenuItem(
43 const base::Closure
& callback
) {
44 click_action_replacement_callback_
= callback
;
46 if (click_action_replacement_menu_item_added_
) {
47 GList
* children
= gtk_container_get_children(GTK_CONTAINER(gtk_menu_
));
48 for (GList
* child
= children
; child
; child
= g_list_next(child
)) {
49 if (g_object_get_data(G_OBJECT(child
->data
), "click-action-item") !=
51 gtk_menu_item_set_label(GTK_MENU_ITEM(child
->data
), label
);
55 g_list_free(children
);
57 click_action_replacement_menu_item_added_
= true;
59 // If |menu_model_| is non empty, add a separator to separate the
60 // "click action replacement menu item" from the other menu items.
61 if (menu_model_
&& menu_model_
->GetItemCount() > 0) {
62 GtkWidget
* menu_item
= gtk_separator_menu_item_new();
63 gtk_widget_show(menu_item
);
64 gtk_menu_shell_prepend(GTK_MENU_SHELL(gtk_menu_
), menu_item
);
67 GtkWidget
* menu_item
= gtk_menu_item_new_with_mnemonic(label
);
69 G_OBJECT(menu_item
), "click-action-item", GINT_TO_POINTER(1));
70 g_signal_connect(menu_item
,
72 G_CALLBACK(OnClickActionReplacementMenuItemActivatedThunk
),
74 gtk_widget_show(menu_item
);
75 gtk_menu_shell_prepend(GTK_MENU_SHELL(gtk_menu_
), menu_item
);
79 void AppIndicatorIconMenu::Refresh() {
80 gtk_container_foreach(
81 GTK_CONTAINER(gtk_menu_
), SetMenuItemInfo
, &block_activation_
);
84 GtkMenu
* AppIndicatorIconMenu::GetGtkMenu() {
85 return GTK_MENU(gtk_menu_
);
89 void AppIndicatorIconMenu::OnClickActionReplacementMenuItemActivated(
90 GtkWidget
* menu_item
) {
91 click_action_replacement_callback_
.Run();
94 void AppIndicatorIconMenu::OnMenuItemActivated(GtkWidget
* menu_item
) {
95 if (block_activation_
)
98 ui::MenuModel
* model
= ModelForMenuItem(GTK_MENU_ITEM(menu_item
));
100 // There won't be a model for "native" submenus like the "Input Methods"
101 // context menu. We don't need to handle activation messages for submenus
102 // anyway, so we can just return here.
103 DCHECK(gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu_item
)));
107 // The activate signal is sent to radio items as they get deselected;
108 // ignore it in this case.
109 if (GTK_IS_RADIO_MENU_ITEM(menu_item
) &&
110 !gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_item
))) {
115 if (!GetMenuItemID(menu_item
, &id
))
118 // The menu item can still be activated by hotkeys even if it is disabled.
119 if (menu_model_
->IsEnabledAt(id
))
120 ExecuteCommand(model
, id
);
123 } // namespace libgtk2ui