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

Side by Side Diff: chrome/browser/ui/libgtk2ui/app_indicator_icon.cc

Issue 304933002: Revert of Fall back to X11 system tray icons if libappindicator is not available (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 6 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/ui/libgtk2ui/app_indicator_icon.h" 5 #include "chrome/browser/ui/libgtk2ui/app_indicator_icon.h"
6 6
7 #include <gtk/gtk.h> 7 #include <gtk/gtk.h>
8 #include <dlfcn.h> 8 #include <dlfcn.h>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/file_util.h" 11 #include "base/file_util.h"
12 #include "base/memory/ref_counted_memory.h" 12 #include "base/memory/ref_counted_memory.h"
13 #include "base/strings/stringprintf.h" 13 #include "base/strings/stringprintf.h"
14 #include "base/strings/utf_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h"
15 #include "base/threading/sequenced_worker_pool.h" 15 #include "base/threading/sequenced_worker_pool.h"
16 #include "chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.h" 16 #include "chrome/browser/ui/libgtk2ui/menu_util.h"
17 #include "content/public/browser/browser_thread.h" 17 #include "content/public/browser/browser_thread.h"
18 #include "ui/base/models/menu_model.h" 18 #include "ui/base/models/menu_model.h"
19 #include "ui/gfx/image/image.h"
20 #include "ui/gfx/image/image_skia.h" 19 #include "ui/gfx/image/image_skia.h"
21 20
22 namespace { 21 namespace {
23 22
24 typedef enum { 23 typedef enum {
25 APP_INDICATOR_CATEGORY_APPLICATION_STATUS, 24 APP_INDICATOR_CATEGORY_APPLICATION_STATUS,
26 APP_INDICATOR_CATEGORY_COMMUNICATIONS, 25 APP_INDICATOR_CATEGORY_COMMUNICATIONS,
27 APP_INDICATOR_CATEGORY_SYSTEM_SERVICES, 26 APP_INDICATOR_CATEGORY_SYSTEM_SERVICES,
28 APP_INDICATOR_CATEGORY_HARDWARE, 27 APP_INDICATOR_CATEGORY_HARDWARE,
29 APP_INDICATOR_CATEGORY_OTHER 28 APP_INDICATOR_CATEGORY_OTHER
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 160
162 } // namespace 161 } // namespace
163 162
164 namespace libgtk2ui { 163 namespace libgtk2ui {
165 164
166 AppIndicatorIcon::AppIndicatorIcon(std::string id, 165 AppIndicatorIcon::AppIndicatorIcon(std::string id,
167 const gfx::ImageSkia& image, 166 const gfx::ImageSkia& image,
168 const base::string16& tool_tip) 167 const base::string16& tool_tip)
169 : id_(id), 168 : id_(id),
170 icon_(NULL), 169 icon_(NULL),
170 gtk_menu_(NULL),
171 menu_model_(NULL), 171 menu_model_(NULL),
172 icon_change_count_(0), 172 icon_change_count_(0),
173 block_activation_(false),
173 weak_factory_(this) { 174 weak_factory_(this) {
174 EnsureMethodsLoaded(); 175 EnsureMethodsLoaded();
175 tool_tip_ = base::UTF16ToUTF8(tool_tip); 176 tool_tip_ = base::UTF16ToUTF8(tool_tip);
176 SetImage(image); 177 SetImage(image);
177 } 178 }
178 AppIndicatorIcon::~AppIndicatorIcon() { 179 AppIndicatorIcon::~AppIndicatorIcon() {
179 if (icon_) { 180 if (icon_) {
180 app_indicator_set_status(icon_, APP_INDICATOR_STATUS_PASSIVE); 181 app_indicator_set_status(icon_, APP_INDICATOR_STATUS_PASSIVE);
182 if (gtk_menu_)
183 DestroyMenu();
181 g_object_unref(icon_); 184 g_object_unref(icon_);
182 content::BrowserThread::GetBlockingPool()->PostTask( 185 content::BrowserThread::GetBlockingPool()->PostTask(
183 FROM_HERE, 186 FROM_HERE,
184 base::Bind(&DeleteTempImagePath, icon_file_path_.DirName())); 187 base::Bind(&DeleteTempImagePath, icon_file_path_.DirName()));
185 } 188 }
186 } 189 }
187 190
188 // static 191 // static
189 bool AppIndicatorIcon::CouldOpen() { 192 bool AppIndicatorIcon::CouldOpen() {
190 EnsureMethodsLoaded(); 193 EnsureMethodsLoaded();
(...skipping 23 matching lines...) Expand all
214 } 217 }
215 218
216 void AppIndicatorIcon::SetPressedImage(const gfx::ImageSkia& image) { 219 void AppIndicatorIcon::SetPressedImage(const gfx::ImageSkia& image) {
217 // Ignore pressed images, since the standard on Linux is to not highlight 220 // Ignore pressed images, since the standard on Linux is to not highlight
218 // pressed status icons. 221 // pressed status icons.
219 } 222 }
220 223
221 void AppIndicatorIcon::SetToolTip(const base::string16& tool_tip) { 224 void AppIndicatorIcon::SetToolTip(const base::string16& tool_tip) {
222 DCHECK(!tool_tip_.empty()); 225 DCHECK(!tool_tip_.empty());
223 tool_tip_ = base::UTF16ToUTF8(tool_tip); 226 tool_tip_ = base::UTF16ToUTF8(tool_tip);
224 UpdateClickActionReplacementMenuItem(); 227
228 // We can set the click action label only if the icon exists. Also we only
229 // need to update the label if it is shown and it's only shown if we are sure
230 // that there is a click action or if there is no menu.
231 if (icon_ && (delegate()->HasClickAction() || menu_model_ == NULL)) {
232 GList* children = gtk_container_get_children(GTK_CONTAINER(gtk_menu_));
233 for (GList* child = children; child; child = g_list_next(child))
234 if (g_object_get_data(G_OBJECT(child->data), "click-action-item") !=
235 NULL) {
236 gtk_menu_item_set_label(GTK_MENU_ITEM(child->data),
237 tool_tip_.c_str());
238 break;
239 }
240 g_list_free(children);
241 }
225 } 242 }
226 243
227 void AppIndicatorIcon::UpdatePlatformContextMenu(ui::MenuModel* model) { 244 void AppIndicatorIcon::UpdatePlatformContextMenu(ui::MenuModel* model) {
228 if (!g_opened) 245 if (!g_opened)
229 return; 246 return;
230 247
248 if (gtk_menu_) {
249 DestroyMenu();
250 }
231 menu_model_ = model; 251 menu_model_ = model;
232 252
233 // The icon is created asynchronously so it might not exist when the menu is 253 // The icon is created asynchronously so it might not exist when the menu is
234 // set. 254 // set.
235 if (icon_) 255 if (icon_)
236 SetMenu(); 256 SetMenu();
237 } 257 }
238 258
239 void AppIndicatorIcon::RefreshPlatformContextMenu() { 259 void AppIndicatorIcon::RefreshPlatformContextMenu() {
240 menu_->Refresh(); 260 gtk_container_foreach(
261 GTK_CONTAINER(gtk_menu_), SetMenuItemInfo, &block_activation_);
241 } 262 }
242 263
243 void AppIndicatorIcon::SetImageFromFile(const base::FilePath& icon_file_path) { 264 void AppIndicatorIcon::SetImageFromFile(const base::FilePath& icon_file_path) {
244 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 265 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
245 if (icon_file_path.empty()) 266 if (icon_file_path.empty())
246 return; 267 return;
247 268
248 base::FilePath old_path = icon_file_path_; 269 base::FilePath old_path = icon_file_path_;
249 icon_file_path_ = icon_file_path; 270 icon_file_path_ = icon_file_path;
250 271
(...skipping 15 matching lines...) Expand all
266 app_indicator_set_icon_full(icon_, icon_name.c_str(), "icon"); 287 app_indicator_set_icon_full(icon_, icon_name.c_str(), "icon");
267 288
268 // Delete previous icon directory. 289 // Delete previous icon directory.
269 content::BrowserThread::GetBlockingPool()->PostTask( 290 content::BrowserThread::GetBlockingPool()->PostTask(
270 FROM_HERE, 291 FROM_HERE,
271 base::Bind(&DeleteTempImagePath, old_path.DirName())); 292 base::Bind(&DeleteTempImagePath, old_path.DirName()));
272 } 293 }
273 } 294 }
274 295
275 void AppIndicatorIcon::SetMenu() { 296 void AppIndicatorIcon::SetMenu() {
276 menu_.reset(new AppIndicatorIconMenu(menu_model_)); 297 gtk_menu_ = gtk_menu_new();
277 UpdateClickActionReplacementMenuItem(); 298
278 app_indicator_set_menu(icon_, menu_->GetGtkMenu()); 299 if (delegate()->HasClickAction() || menu_model_ == NULL) {
300 CreateClickActionReplacement();
301 if (menu_model_) {
302 // Add separator before the other menu items.
303 GtkWidget* menu_item = gtk_separator_menu_item_new();
304 gtk_widget_show(menu_item);
305 gtk_menu_shell_append(GTK_MENU_SHELL(gtk_menu_), menu_item);
306 }
307 }
308 if (menu_model_) {
309 BuildSubmenuFromModel(menu_model_,
310 gtk_menu_,
311 G_CALLBACK(OnMenuItemActivatedThunk),
312 &block_activation_,
313 this);
314 RefreshPlatformContextMenu();
315 }
316 app_indicator_set_menu(icon_, GTK_MENU(gtk_menu_));
279 } 317 }
280 318
281 void AppIndicatorIcon::UpdateClickActionReplacementMenuItem() { 319 void AppIndicatorIcon::CreateClickActionReplacement() {
282 // The menu may not have been created yet. 320 DCHECK(!tool_tip_.empty());
283 if (!menu_.get())
284 return;
285 321
286 if (!delegate()->HasClickAction() && menu_model_) 322 // Add "click replacement menu item".
287 return; 323 GtkWidget* menu_item = gtk_menu_item_new_with_mnemonic(tool_tip_.c_str());
288 324 g_object_set_data(
289 DCHECK(!tool_tip_.empty()); 325 G_OBJECT(menu_item), "click-action-item", GINT_TO_POINTER(1));
290 menu_->UpdateClickActionReplacementMenuItem( 326 g_signal_connect(menu_item, "activate", G_CALLBACK(OnClickThunk), this);
291 tool_tip_.c_str(), 327 gtk_widget_show(menu_item);
292 base::Bind(&AppIndicatorIcon::OnClickActionReplacementMenuItemActivated, 328 gtk_menu_shell_prepend(GTK_MENU_SHELL(gtk_menu_), menu_item);
293 base::Unretained(this)));
294 } 329 }
295 330
296 void AppIndicatorIcon::OnClickActionReplacementMenuItemActivated() { 331 void AppIndicatorIcon::DestroyMenu() {
332 gtk_widget_destroy(gtk_menu_);
333 gtk_menu_ = NULL;
334 menu_model_ = NULL;
335 }
336
337 void AppIndicatorIcon::OnClick(GtkWidget* menu_item) {
297 if (delegate()) 338 if (delegate())
298 delegate()->OnClick(); 339 delegate()->OnClick();
299 } 340 }
300 341
342 void AppIndicatorIcon::OnMenuItemActivated(GtkWidget* menu_item) {
343 if (block_activation_)
344 return;
345
346 ui::MenuModel* model = ModelForMenuItem(GTK_MENU_ITEM(menu_item));
347 if (!model) {
348 // There won't be a model for "native" submenus like the "Input Methods"
349 // context menu. We don't need to handle activation messages for submenus
350 // anyway, so we can just return here.
351 DCHECK(gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu_item)));
352 return;
353 }
354
355 // The activate signal is sent to radio items as they get deselected;
356 // ignore it in this case.
357 if (GTK_IS_RADIO_MENU_ITEM(menu_item) &&
358 !gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_item))) {
359 return;
360 }
361
362 int id;
363 if (!GetMenuItemID(menu_item, &id))
364 return;
365
366 // The menu item can still be activated by hotkeys even if it is disabled.
367 if (menu_model_->IsEnabledAt(id))
368 ExecuteCommand(model, id);
369 }
370
301 } // namespace libgtk2ui 371 } // namespace libgtk2ui
OLDNEW
« no previous file with comments | « chrome/browser/ui/libgtk2ui/app_indicator_icon.h ('k') | chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698