linux: GTK+ status icon has come back
This commit is contained in:
parent
e58b3ddc86
commit
22c4911b58
9 changed files with 4 additions and 340 deletions
4
atom.gyp
4
atom.gyp
|
@ -309,10 +309,6 @@
|
|||
'chromium_src/chrome/browser/ui/cocoa/color_chooser_mac.mm',
|
||||
'chromium_src/chrome/browser/ui/views/color_chooser_aura.cc',
|
||||
'chromium_src/chrome/browser/ui/views/color_chooser_aura.h',
|
||||
'chromium_src/chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.cc',
|
||||
'chromium_src/chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.h',
|
||||
'chromium_src/chrome/browser/ui/libgtk2ui/gtk2_status_icon.cc',
|
||||
'chromium_src/chrome/browser/ui/libgtk2ui/gtk2_status_icon.h',
|
||||
'chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc',
|
||||
'chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h',
|
||||
'chromium_src/chrome/common/print_messages.cc',
|
||||
|
|
|
@ -12,6 +12,9 @@ TrayIcon::TrayIcon() {
|
|||
TrayIcon::~TrayIcon() {
|
||||
}
|
||||
|
||||
void TrayIcon::SetPressedImage(const gfx::ImageSkia& image) {
|
||||
}
|
||||
|
||||
void TrayIcon::SetTitle(const std::string& title) {
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ class TrayIcon {
|
|||
virtual void SetImage(const gfx::ImageSkia& image) = 0;
|
||||
|
||||
// Sets the image associated with this status icon when pressed.
|
||||
virtual void SetPressedImage(const gfx::ImageSkia& image) = 0;
|
||||
virtual void SetPressedImage(const gfx::ImageSkia& image);
|
||||
|
||||
// Sets the hover text for this status icon. This is also used as the label
|
||||
// for the menu item which is created as a replacement for the status icon
|
||||
|
|
|
@ -32,10 +32,6 @@ void TrayIconGtk::SetImage(const gfx::ImageSkia& image) {
|
|||
icon_->set_delegate(this);
|
||||
}
|
||||
|
||||
void TrayIconGtk::SetPressedImage(const gfx::ImageSkia& image) {
|
||||
icon_->SetPressedImage(image);
|
||||
}
|
||||
|
||||
void TrayIconGtk::SetToolTip(const std::string& tool_tip) {
|
||||
icon_->SetToolTip(base::UTF8ToUTF16(tool_tip));
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ class TrayIconGtk : public TrayIcon,
|
|||
|
||||
// TrayIcon:
|
||||
virtual void SetImage(const gfx::ImageSkia& image) OVERRIDE;
|
||||
virtual void SetPressedImage(const gfx::ImageSkia& image) OVERRIDE;
|
||||
virtual void SetToolTip(const std::string& tool_tip) OVERRIDE;
|
||||
virtual void SetContextMenu(ui::SimpleMenuModel* menu_model) OVERRIDE;
|
||||
|
||||
|
|
|
@ -1,123 +0,0 @@
|
|||
// 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
|
|
@ -1,66 +0,0 @@
|
|||
// 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_
|
|
@ -1,80 +0,0 @@
|
|||
// 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
|
|
@ -1,61 +0,0 @@
|
|||
// 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_
|
Loading…
Reference in a new issue