Commit bd780414 authored by pkotwicz@chromium.org's avatar pkotwicz@chromium.org

Reland: Fall back to X11 system tray icons if libappindicator is not available.

This CL also splits out the code wrt to handling the GTK menu for the app indicator icon out of app_indicator_icon.cc in order to share code with gtk2_status_icon.cc

BUG=267195
TEST=Manual, see steps below.
1) Run chrome in a system which does not have libappindicator
2) Generate HTML 5 notifications via https://developer.cdn.mozilla.net/media/uploads/demos/e/l/elfoxero/c17223c414d8ddafb7808972b5617d9e/html5-notifications_1400214081_demo_package/index.html
3) Ensure that the bell icon shows up in the system tray and that clicking on the bell icon brings up the message center

Review URL: https://codereview.chromium.org/306063003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@273999 0039d316-1c4b-4281-b951-d872f2087c98
parent 092f9df5
...@@ -13,9 +13,10 @@ ...@@ -13,9 +13,10 @@
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/threading/sequenced_worker_pool.h" #include "base/threading/sequenced_worker_pool.h"
#include "chrome/browser/ui/libgtk2ui/menu_util.h" #include "chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "ui/base/models/menu_model.h" #include "ui/base/models/menu_model.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia.h"
namespace { namespace {
...@@ -167,10 +168,8 @@ AppIndicatorIcon::AppIndicatorIcon(std::string id, ...@@ -167,10 +168,8 @@ AppIndicatorIcon::AppIndicatorIcon(std::string id,
const base::string16& tool_tip) const base::string16& tool_tip)
: id_(id), : id_(id),
icon_(NULL), icon_(NULL),
gtk_menu_(NULL),
menu_model_(NULL), menu_model_(NULL),
icon_change_count_(0), icon_change_count_(0),
block_activation_(false),
weak_factory_(this) { weak_factory_(this) {
EnsureMethodsLoaded(); EnsureMethodsLoaded();
tool_tip_ = base::UTF16ToUTF8(tool_tip); tool_tip_ = base::UTF16ToUTF8(tool_tip);
...@@ -179,8 +178,6 @@ AppIndicatorIcon::AppIndicatorIcon(std::string id, ...@@ -179,8 +178,6 @@ AppIndicatorIcon::AppIndicatorIcon(std::string id,
AppIndicatorIcon::~AppIndicatorIcon() { AppIndicatorIcon::~AppIndicatorIcon() {
if (icon_) { if (icon_) {
app_indicator_set_status(icon_, APP_INDICATOR_STATUS_PASSIVE); app_indicator_set_status(icon_, APP_INDICATOR_STATUS_PASSIVE);
if (gtk_menu_)
DestroyMenu();
g_object_unref(icon_); g_object_unref(icon_);
content::BrowserThread::GetBlockingPool()->PostTask( content::BrowserThread::GetBlockingPool()->PostTask(
FROM_HERE, FROM_HERE,
...@@ -224,30 +221,13 @@ void AppIndicatorIcon::SetPressedImage(const gfx::ImageSkia& image) { ...@@ -224,30 +221,13 @@ void AppIndicatorIcon::SetPressedImage(const gfx::ImageSkia& image) {
void AppIndicatorIcon::SetToolTip(const base::string16& tool_tip) { void AppIndicatorIcon::SetToolTip(const base::string16& tool_tip) {
DCHECK(!tool_tip_.empty()); DCHECK(!tool_tip_.empty());
tool_tip_ = base::UTF16ToUTF8(tool_tip); tool_tip_ = base::UTF16ToUTF8(tool_tip);
UpdateClickActionReplacementMenuItem();
// We can set the click action label only if the icon exists. Also we only
// need to update the label if it is shown and it's only shown if we are sure
// that there is a click action or if there is no menu.
if (icon_ && (delegate()->HasClickAction() || menu_model_ == NULL)) {
GList* children = gtk_container_get_children(GTK_CONTAINER(gtk_menu_));
for (GList* child = children; child; child = g_list_next(child))
if (g_object_get_data(G_OBJECT(child->data), "click-action-item") !=
NULL) {
gtk_menu_item_set_label(GTK_MENU_ITEM(child->data),
tool_tip_.c_str());
break;
}
g_list_free(children);
}
} }
void AppIndicatorIcon::UpdatePlatformContextMenu(ui::MenuModel* model) { void AppIndicatorIcon::UpdatePlatformContextMenu(ui::MenuModel* model) {
if (!g_opened) if (!g_opened)
return; return;
if (gtk_menu_) {
DestroyMenu();
}
menu_model_ = model; menu_model_ = model;
// The icon is created asynchronously so it might not exist when the menu is // The icon is created asynchronously so it might not exist when the menu is
...@@ -257,8 +237,7 @@ void AppIndicatorIcon::UpdatePlatformContextMenu(ui::MenuModel* model) { ...@@ -257,8 +237,7 @@ void AppIndicatorIcon::UpdatePlatformContextMenu(ui::MenuModel* model) {
} }
void AppIndicatorIcon::RefreshPlatformContextMenu() { void AppIndicatorIcon::RefreshPlatformContextMenu() {
gtk_container_foreach( menu_->Refresh();
GTK_CONTAINER(gtk_menu_), SetMenuItemInfo, &block_activation_);
} }
void AppIndicatorIcon::SetImageFromFile(const base::FilePath& icon_file_path) { void AppIndicatorIcon::SetImageFromFile(const base::FilePath& icon_file_path) {
...@@ -294,78 +273,29 @@ void AppIndicatorIcon::SetImageFromFile(const base::FilePath& icon_file_path) { ...@@ -294,78 +273,29 @@ void AppIndicatorIcon::SetImageFromFile(const base::FilePath& icon_file_path) {
} }
void AppIndicatorIcon::SetMenu() { void AppIndicatorIcon::SetMenu() {
gtk_menu_ = gtk_menu_new(); menu_.reset(new AppIndicatorIconMenu(menu_model_));
UpdateClickActionReplacementMenuItem();
if (delegate()->HasClickAction() || menu_model_ == NULL) { app_indicator_set_menu(icon_, menu_->GetGtkMenu());
CreateClickActionReplacement();
if (menu_model_) {
// Add separator before the other menu items.
GtkWidget* menu_item = gtk_separator_menu_item_new();
gtk_widget_show(menu_item);
gtk_menu_shell_append(GTK_MENU_SHELL(gtk_menu_), menu_item);
}
}
if (menu_model_) {
BuildSubmenuFromModel(menu_model_,
gtk_menu_,
G_CALLBACK(OnMenuItemActivatedThunk),
&block_activation_,
this);
RefreshPlatformContextMenu();
}
app_indicator_set_menu(icon_, GTK_MENU(gtk_menu_));
} }
void AppIndicatorIcon::CreateClickActionReplacement() { void AppIndicatorIcon::UpdateClickActionReplacementMenuItem() {
DCHECK(!tool_tip_.empty()); // The menu may not have been created yet.
if (!menu_.get())
return;
// Add "click replacement menu item". if (!delegate()->HasClickAction() && menu_model_)
GtkWidget* menu_item = gtk_menu_item_new_with_mnemonic(tool_tip_.c_str()); return;
g_object_set_data(
G_OBJECT(menu_item), "click-action-item", GINT_TO_POINTER(1));
g_signal_connect(menu_item, "activate", G_CALLBACK(OnClickThunk), this);
gtk_widget_show(menu_item);
gtk_menu_shell_prepend(GTK_MENU_SHELL(gtk_menu_), menu_item);
}
void AppIndicatorIcon::DestroyMenu() { DCHECK(!tool_tip_.empty());
gtk_widget_destroy(gtk_menu_); menu_->UpdateClickActionReplacementMenuItem(
gtk_menu_ = NULL; tool_tip_.c_str(),
menu_model_ = NULL; base::Bind(&AppIndicatorIcon::OnClickActionReplacementMenuItemActivated,
base::Unretained(this)));
} }
void AppIndicatorIcon::OnClick(GtkWidget* menu_item) { void AppIndicatorIcon::OnClickActionReplacementMenuItemActivated() {
if (delegate()) if (delegate())
delegate()->OnClick(); delegate()->OnClick();
} }
void AppIndicatorIcon::OnMenuItemActivated(GtkWidget* menu_item) {
if (block_activation_)
return;
ui::MenuModel* model = ModelForMenuItem(GTK_MENU_ITEM(menu_item));
if (!model) {
// There won't be a model for "native" submenus like the "Input Methods"
// context menu. We don't need to handle activation messages for submenus
// anyway, so we can just return here.
DCHECK(gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu_item)));
return;
}
// The activate signal is sent to radio items as they get deselected;
// ignore it in this case.
if (GTK_IS_RADIO_MENU_ITEM(menu_item) &&
!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_item))) {
return;
}
int id;
if (!GetMenuItemID(menu_item, &id))
return;
// The menu item can still be activated by hotkeys even if it is disabled.
if (menu_model_->IsEnabledAt(id))
ExecuteCommand(model, id);
}
} // namespace libgtk2ui } // namespace libgtk2ui
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define CHROME_BROWSER_UI_LIBGTK2UI_APP_INDICATOR_ICON_H_ #define CHROME_BROWSER_UI_LIBGTK2UI_APP_INDICATOR_ICON_H_
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "chrome/browser/ui/libgtk2ui/gtk2_signal.h" #include "chrome/browser/ui/libgtk2ui/gtk2_signal.h"
#include "ui/views/linux_ui/status_icon_linux.h" #include "ui/views/linux_ui/status_icon_linux.h"
...@@ -22,7 +23,9 @@ class MenuModel; ...@@ -22,7 +23,9 @@ class MenuModel;
} }
namespace libgtk2ui { namespace libgtk2ui {
class AppIndicatorIconMenu;
// Status icon implementation which uses libappindicator.
class AppIndicatorIcon : public views::StatusIconLinux { class AppIndicatorIcon : public views::StatusIconLinux {
public: public:
// The id uniquely identifies the new status icon from other chrome status // The id uniquely identifies the new status icon from other chrome status
...@@ -46,18 +49,13 @@ class AppIndicatorIcon : public views::StatusIconLinux { ...@@ -46,18 +49,13 @@ class AppIndicatorIcon : public views::StatusIconLinux {
void SetImageFromFile(const base::FilePath& icon_file_path); void SetImageFromFile(const base::FilePath& icon_file_path);
void SetMenu(); void SetMenu();
// Adds a menu item to the top of the existing gtk_menu as a replacement for // Sets a menu item at the top of the menu as a replacement for the status
// the status icon click action or creates a new gtk menu with the menu item // icon click action. Clicking on this menu item should simulate a status icon
// if a menu doesn't exist. Clicking on this menu item should simulate a // click by despatching a click event.
// status icon click by despatching a click event. void UpdateClickActionReplacementMenuItem();
void CreateClickActionReplacement();
void DestroyMenu();
// Callback for when the status icon click replacement menu item is clicked. // Callback for when the status icon click replacement menu item is activated.
CHROMEGTK_CALLBACK_0(AppIndicatorIcon, void, OnClick); void OnClickActionReplacementMenuItemActivated();
// Callback for when a menu item is clicked.
CHROMEGTK_CALLBACK_0(AppIndicatorIcon, void, OnMenuItemActivated);
std::string id_; std::string id_;
std::string tool_tip_; std::string tool_tip_;
...@@ -65,12 +63,11 @@ class AppIndicatorIcon : public views::StatusIconLinux { ...@@ -65,12 +63,11 @@ class AppIndicatorIcon : public views::StatusIconLinux {
// Gtk status icon wrapper // Gtk status icon wrapper
AppIndicator* icon_; AppIndicator* icon_;
GtkWidget* gtk_menu_; scoped_ptr<AppIndicatorIconMenu> menu_;
ui::MenuModel* menu_model_; ui::MenuModel* menu_model_;
base::FilePath icon_file_path_; base::FilePath icon_file_path_;
int icon_change_count_; int icon_change_count_;
bool block_activation_;
base::WeakPtrFactory<AppIndicatorIcon> weak_factory_; base::WeakPtrFactory<AppIndicatorIcon> weak_factory_;
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.h"
#include <gtk/gtk.h>
#include "base/bind.h"
#include "base/debug/leak_annotations.h"
#include "chrome/browser/ui/libgtk2ui/menu_util.h"
#include "ui/base/models/menu_model.h"
namespace libgtk2ui {
AppIndicatorIconMenu::AppIndicatorIconMenu(ui::MenuModel* model)
: menu_model_(model),
click_action_replacement_menu_item_added_(false),
gtk_menu_(NULL),
block_activation_(false) {
{
ANNOTATE_SCOPED_MEMORY_LEAK; // http://crbug.com/378770
gtk_menu_ = gtk_menu_new();
}
g_object_ref_sink(gtk_menu_);
if (menu_model_) {
BuildSubmenuFromModel(menu_model_,
gtk_menu_,
G_CALLBACK(OnMenuItemActivatedThunk),
&block_activation_,
this);
Refresh();
}
}
AppIndicatorIconMenu::~AppIndicatorIconMenu() {
gtk_widget_destroy(gtk_menu_);
g_object_unref(gtk_menu_);
}
void AppIndicatorIconMenu::UpdateClickActionReplacementMenuItem(
const char* label,
const base::Closure& callback) {
click_action_replacement_callback_ = callback;
if (click_action_replacement_menu_item_added_) {
GList* children = gtk_container_get_children(GTK_CONTAINER(gtk_menu_));
for (GList* child = children; child; child = g_list_next(child)) {
if (g_object_get_data(G_OBJECT(child->data), "click-action-item") !=
NULL) {
gtk_menu_item_set_label(GTK_MENU_ITEM(child->data), label);
break;
}
}
g_list_free(children);
} else {
click_action_replacement_menu_item_added_ = true;
// If |menu_model_| is non empty, add a separator to separate the
// "click action replacement menu item" from the other menu items.
if (menu_model_ && menu_model_->GetItemCount() > 0) {
GtkWidget* menu_item = gtk_separator_menu_item_new();
gtk_widget_show(menu_item);
gtk_menu_shell_prepend(GTK_MENU_SHELL(gtk_menu_), menu_item);
}
GtkWidget* menu_item = gtk_menu_item_new_with_mnemonic(label);
g_object_set_data(
G_OBJECT(menu_item), "click-action-item", GINT_TO_POINTER(1));
g_signal_connect(menu_item,
"activate",
G_CALLBACK(OnClickActionReplacementMenuItemActivatedThunk),
this);
gtk_widget_show(menu_item);
gtk_menu_shell_prepend(GTK_MENU_SHELL(gtk_menu_), menu_item);
}
}
void AppIndicatorIconMenu::Refresh() {
gtk_container_foreach(
GTK_CONTAINER(gtk_menu_), SetMenuItemInfo, &block_activation_);
}
GtkMenu* AppIndicatorIconMenu::GetGtkMenu() {
return GTK_MENU(gtk_menu_);
}
void AppIndicatorIconMenu::OnClickActionReplacementMenuItemActivated(
GtkWidget* menu_item) {
click_action_replacement_callback_.Run();
}
void AppIndicatorIconMenu::OnMenuItemActivated(GtkWidget* menu_item) {
if (block_activation_)
return;
ui::MenuModel* model = ModelForMenuItem(GTK_MENU_ITEM(menu_item));
if (!model) {
// There won't be a model for "native" submenus like the "Input Methods"
// context menu. We don't need to handle activation messages for submenus
// anyway, so we can just return here.
DCHECK(gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu_item)));
return;
}
// The activate signal is sent to radio items as they get deselected;
// ignore it in this case.
if (GTK_IS_RADIO_MENU_ITEM(menu_item) &&
!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_item))) {
return;
}
int id;
if (!GetMenuItemID(menu_item, &id))
return;
// The menu item can still be activated by hotkeys even if it is disabled.
if (menu_model_->IsEnabledAt(id))
ExecuteCommand(model, id);
}
} // namespace libgtk2ui
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_LIBGTK2UI_APP_INDICATOR_ICON_MENU_H_
#define CHROME_BROWSER_UI_LIBGTK2UI_APP_INDICATOR_ICON_MENU_H_
#include "base/callback.h"
#include "chrome/browser/ui/libgtk2ui/gtk2_signal.h"
typedef struct _GtkMenu GtkMenu;
typedef struct _GtkWidget GtkWidget;
namespace ui {
class MenuModel;
}
namespace libgtk2ui {
// The app indicator icon's menu.
class AppIndicatorIconMenu {
public:
explicit AppIndicatorIconMenu(ui::MenuModel* model);
virtual ~AppIndicatorIconMenu();
// Sets a menu item at the top of |gtk_menu_| as a replacement for the app
// indicator icon's click action. |callback| is called when the menu item
// is activated.
void UpdateClickActionReplacementMenuItem(const char* label,
const base::Closure& callback);
// Refreshes all the menu item labels and menu item checked/enabled states.
void Refresh();
GtkMenu* GetGtkMenu();
private:
// Callback for when the "click action replacement" menu item is activated.
CHROMEGTK_CALLBACK_0(AppIndicatorIconMenu,
void,
OnClickActionReplacementMenuItemActivated);
// Callback for when a menu item is activated.
CHROMEGTK_CALLBACK_0(AppIndicatorIconMenu, void, OnMenuItemActivated);
// Not owned.
ui::MenuModel* menu_model_;
// Whether a "click action replacement" menu item has been added to the menu.
bool click_action_replacement_menu_item_added_;
// Called when the click action replacement menu item is activated. When a
// menu item from |menu_model_| is activated, MenuModel::ActivatedAt() is
// invoked and is assumed to do any necessary processing.
base::Closure click_action_replacement_callback_;
GtkWidget* gtk_menu_;
bool block_activation_;
DISALLOW_COPY_AND_ASSIGN(AppIndicatorIconMenu);
};
} // namespace libgtk2ui
#endif // CHROME_BROWSER_UI_LIBGTK2UI_APP_INDICATOR_ICON_MENU_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/libgtk2ui/gtk2_status_icon.h"
#include <gtk/gtk.h>
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.h"
#include "chrome/browser/ui/libgtk2ui/skia_utils_gtk2.h"
#include "ui/base/models/menu_model.h"
#include "ui/gfx/image/image_skia.h"
namespace libgtk2ui {
Gtk2StatusIcon::Gtk2StatusIcon(const gfx::ImageSkia& image,
const base::string16& tool_tip) {
GdkPixbuf* pixbuf = GdkPixbufFromSkBitmap(*image.bitmap());
gtk_status_icon_ = gtk_status_icon_new_from_pixbuf(pixbuf);
g_object_unref(pixbuf);
g_signal_connect(gtk_status_icon_, "activate", G_CALLBACK(OnClickThunk),
this);
g_signal_connect(gtk_status_icon_, "popup_menu",
G_CALLBACK(OnContextMenuRequestedThunk), this);
SetToolTip(tool_tip);
}
Gtk2StatusIcon::~Gtk2StatusIcon() {
g_object_unref(gtk_status_icon_);
}
void Gtk2StatusIcon::SetImage(const gfx::ImageSkia& image) {
GdkPixbuf* pixbuf = GdkPixbufFromSkBitmap(*image.bitmap());
gtk_status_icon_set_from_pixbuf(gtk_status_icon_, pixbuf);
g_object_unref(pixbuf);
}
void Gtk2StatusIcon::SetPressedImage(const gfx::ImageSkia& image) {
// Ignore pressed images, since the standard on Linux is to not highlight
// pressed status icons.
}
void Gtk2StatusIcon::SetToolTip(const base::string16& tool_tip) {
gtk_status_icon_set_tooltip_text(gtk_status_icon_,
base::UTF16ToUTF8(tool_tip).c_str());
}
void Gtk2StatusIcon::UpdatePlatformContextMenu(ui::MenuModel* model) {
menu_.reset();
if (model)
menu_.reset(new AppIndicatorIconMenu(model));
}
void Gtk2StatusIcon::RefreshPlatformContextMenu() {
if (menu_.get())
menu_->Refresh();
}
void Gtk2StatusIcon::OnClick(GtkStatusIcon* status_icon) {
if (delegate())
delegate()->OnClick();
}
void Gtk2StatusIcon::OnContextMenuRequested(GtkStatusIcon* status_icon,
guint button,
guint32 activate_time) {
if (menu_.get()) {
gtk_menu_popup(menu_->GetGtkMenu(),
NULL,
NULL,
gtk_status_icon_position_menu,
gtk_status_icon_,
button,
activate_time);
}
}
} // namespace libgtk2ui
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_LIBGTK2UI_GTK2_STATUS_ICON_H_
#define CHROME_BROWSER_UI_LIBGTK2UI_GTK2_STATUS_ICON_H_
#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
#include "chrome/browser/ui/libgtk2ui/gtk2_signal.h"
#include "ui/base/glib/glib_integers.h"
#include "ui/base/glib/glib_signal.h"
#include "ui/views/linux_ui/status_icon_linux.h"
typedef struct _GtkStatusIcon GtkStatusIcon;
namespace gfx {
class ImageSkia;
}
namespace ui {
class MenuModel;
}
namespace libgtk2ui {
class AppIndicatorIconMenu;
// Status icon implementation which uses the system tray X11 spec (via
// GtkStatusIcon).
class Gtk2StatusIcon : public views::StatusIconLinux {
public:
Gtk2StatusIcon(const gfx::ImageSkia& image, const base::string16& tool_tip);
virtual ~Gtk2StatusIcon();
// Overridden from views::StatusIconLinux:
virtual void SetImage(const gfx::ImageSkia& image) OVERRIDE;
virtual void SetPressedImage(const gfx::ImageSkia& image) OVERRIDE;
virtual void SetToolTip(const base::string16& tool_tip) OVERRIDE;
virtual void UpdatePlatformContextMenu(ui::MenuModel* menu) OVERRIDE;
virtual void RefreshPlatformContextMenu() OVERRIDE;
private:
CHROMEG_CALLBACK_0(Gtk2StatusIcon, void, OnClick, GtkStatusIcon*);
CHROMEG_CALLBACK_2(Gtk2StatusIcon,
void,
OnContextMenuRequested,
GtkStatusIcon*,
guint,
guint);
GtkStatusIcon* gtk_status_icon_;
scoped_ptr<AppIndicatorIconMenu> menu_;
DISALLOW_COPY_AND_ASSIGN(Gtk2StatusIcon);
};
} // namespace libgtk2ui
#endif // CHROME_BROWSER_UI_LIBGTK2UI_GTK2_STATUS_ICON_H_
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "chrome/browser/ui/libgtk2ui/gtk2_event_loop.h" #include "chrome/browser/ui/libgtk2ui/gtk2_event_loop.h"
#include "chrome/browser/ui/libgtk2ui/gtk2_key_bindings_handler.h" #include "chrome/browser/ui/libgtk2ui/gtk2_key_bindings_handler.h"
#include "chrome/browser/ui/libgtk2ui/gtk2_signal_registrar.h" #include "chrome/browser/ui/libgtk2ui/gtk2_signal_registrar.h"
#include "chrome/browser/ui/libgtk2ui/gtk2_status_icon.h"
#include "chrome/browser/ui/libgtk2ui/gtk2_util.h" #include "chrome/browser/ui/libgtk2ui/gtk2_util.h"
#include "chrome/browser/ui/libgtk2ui/native_theme_gtk2.h" #include "chrome/browser/ui/libgtk2ui/native_theme_gtk2.h"
#include "chrome/browser/ui/libgtk2ui/print_dialog_gtk2.h" #include "chrome/browser/ui/libgtk2ui/print_dialog_gtk2.h"
...@@ -504,7 +505,7 @@ void Gtk2UI::SetProgressFraction(float percentage) const { ...@@ -504,7 +505,7 @@ void Gtk2UI::SetProgressFraction(float percentage) const {
} }
bool Gtk2UI::IsStatusIconSupported() const { bool Gtk2UI::IsStatusIconSupported() const {
return AppIndicatorIcon::CouldOpen(); return true;
} }
scoped_ptr<views::StatusIconLinux> Gtk2UI::CreateLinuxStatusIcon( scoped_ptr<views::StatusIconLinux> Gtk2UI::CreateLinuxStatusIcon(
...@@ -517,7 +518,8 @@ scoped_ptr<views::StatusIconLinux> Gtk2UI::CreateLinuxStatusIcon( ...@@ -517,7 +518,8 @@ scoped_ptr<views::StatusIconLinux> Gtk2UI::CreateLinuxStatusIcon(
image, image,
tool_tip)); tool_tip));
} else { } else {
return scoped_ptr<views::StatusIconLinux>(); return scoped_ptr<views::StatusIconLinux>(new Gtk2StatusIcon(
image, tool_tip));
} }
} }
......
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
'sources': [ 'sources': [
'app_indicator_icon.cc', 'app_indicator_icon.cc',
'app_indicator_icon.h', 'app_indicator_icon.h',
'app_indicator_icon_menu.cc',
'app_indicator_icon_menu.h',
'chrome_gtk_frame.cc', 'chrome_gtk_frame.cc',
'chrome_gtk_frame.h', 'chrome_gtk_frame.h',
'chrome_gtk_menu_subclasses.cc', 'chrome_gtk_menu_subclasses.cc',
...@@ -55,6 +57,8 @@ ...@@ -55,6 +57,8 @@
'gtk2_key_bindings_handler.h', 'gtk2_key_bindings_handler.h',
'gtk2_signal_registrar.cc', 'gtk2_signal_registrar.cc',
'gtk2_signal_registrar.h', 'gtk2_signal_registrar.h',
'gtk2_status_icon.cc',
'gtk2_status_icon.h',
'gtk2_ui.cc', 'gtk2_ui.cc',
'gtk2_ui.h', 'gtk2_ui.h',
'gtk2_util.cc', 'gtk2_util.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment