From 31d2f240ccc8d042aabcbe0379e3f6e4fb488fa6 Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Thu, 26 Jan 2023 10:16:16 +0000 Subject: [PATCH 1/3] chore: get ready for multi backend tray Co-authored-by: Cheng Zhao --- filenames.gni | 4 +- .../{tray_icon_gtk.cc => tray_icon_linux.cc} | 53 +++++++++++-------- .../ui/{tray_icon_gtk.h => tray_icon_linux.h} | 18 +++---- 3 files changed, 42 insertions(+), 33 deletions(-) rename shell/browser/ui/{tray_icon_gtk.cc => tray_icon_linux.cc} (55%) rename shell/browser/ui/{tray_icon_gtk.h => tray_icon_linux.h} (68%) diff --git a/filenames.gni b/filenames.gni index 8518fc08214de..2a0061e86fee0 100644 --- a/filenames.gni +++ b/filenames.gni @@ -36,8 +36,8 @@ filenames = { "shell/browser/ui/electron_desktop_window_tree_host_linux.cc", "shell/browser/ui/file_dialog_gtk.cc", "shell/browser/ui/message_box_gtk.cc", - "shell/browser/ui/tray_icon_gtk.cc", - "shell/browser/ui/tray_icon_gtk.h", + "shell/browser/ui/tray_icon_linux.cc", + "shell/browser/ui/tray_icon_linux.h", "shell/browser/ui/views/client_frame_view_linux.cc", "shell/browser/ui/views/client_frame_view_linux.h", "shell/common/application_info_linux.cc", diff --git a/shell/browser/ui/tray_icon_gtk.cc b/shell/browser/ui/tray_icon_linux.cc similarity index 55% rename from shell/browser/ui/tray_icon_gtk.cc rename to shell/browser/ui/tray_icon_linux.cc index 56b6e1bf1e093..12e3b4328d3f7 100644 --- a/shell/browser/ui/tray_icon_gtk.cc +++ b/shell/browser/ui/tray_icon_linux.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. -#include "shell/browser/ui/tray_icon_gtk.h" +#include "shell/browser/ui/tray_icon_linux.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h" @@ -29,48 +29,48 @@ gfx::ImageSkia GetBestImageRep(const gfx::ImageSkia& image) { } // namespace -TrayIconGtk::TrayIconGtk() - : status_icon_(new StatusIconLinuxDbus), +TrayIconLinux::TrayIconLinux() + : status_icon_dbus_(new StatusIconLinuxDbus), status_icon_type_(StatusIconType::kDbus) { - status_icon_->SetDelegate(this); + status_icon_dbus_->SetDelegate(this); } -TrayIconGtk::~TrayIconGtk() = default; +TrayIconLinux::~TrayIconLinux() = default; -void TrayIconGtk::SetImage(const gfx::Image& image) { +void TrayIconLinux::SetImage(const gfx::Image& image) { image_ = GetBestImageRep(image.AsImageSkia()); - if (status_icon_) - status_icon_->SetIcon(image_); + if (auto* status_icon = GetStatusIcon()) + status_icon->SetIcon(image_); } -void TrayIconGtk::SetToolTip(const std::string& tool_tip) { +void TrayIconLinux::SetToolTip(const std::string& tool_tip) { tool_tip_ = base::UTF8ToUTF16(tool_tip); - if (status_icon_) - status_icon_->SetToolTip(tool_tip_); + if (auto* status_icon = GetStatusIcon()) + status_icon->SetToolTip(tool_tip_); } -void TrayIconGtk::SetContextMenu(ElectronMenuModel* menu_model) { +void TrayIconLinux::SetContextMenu(ElectronMenuModel* menu_model) { menu_model_ = menu_model; - if (status_icon_) - status_icon_->UpdatePlatformContextMenu(menu_model_); + if (auto* status_icon = GetStatusIcon()) + status_icon->UpdatePlatformContextMenu(menu_model_); } -const gfx::ImageSkia& TrayIconGtk::GetImage() const { +const gfx::ImageSkia& TrayIconLinux::GetImage() const { return image_; } -const std::u16string& TrayIconGtk::GetToolTip() const { +const std::u16string& TrayIconLinux::GetToolTip() const { return tool_tip_; } -ui::MenuModel* TrayIconGtk::GetMenuModel() const { +ui::MenuModel* TrayIconLinux::GetMenuModel() const { return menu_model_; } -void TrayIconGtk::OnImplInitializationFailed() { +void TrayIconLinux::OnImplInitializationFailed() { switch (status_icon_type_) { case StatusIconType::kDbus: - status_icon_ = nullptr; + status_icon_dbus_.reset(); status_icon_type_ = StatusIconType::kNone; return; case StatusIconType::kNone: @@ -78,19 +78,28 @@ void TrayIconGtk::OnImplInitializationFailed() { } } -void TrayIconGtk::OnClick() { +void TrayIconLinux::OnClick() { NotifyClicked(); } -bool TrayIconGtk::HasClickAction() { +bool TrayIconLinux::HasClickAction() { // Returning true will make the tooltip show as an additional context menu // item, which makes sense in Chrome but not in most Electron apps. return false; } +ui::StatusIconLinux* TrayIconLinux::GetStatusIcon() { + switch (status_icon_type_) { + case StatusIconType::kDbus: + return status_icon_dbus_.get(); + case StatusIconType::kNone: + return nullptr; + } +} + // static TrayIcon* TrayIcon::Create(absl::optional guid) { - return new TrayIconGtk; + return new TrayIconLinux; } } // namespace electron diff --git a/shell/browser/ui/tray_icon_gtk.h b/shell/browser/ui/tray_icon_linux.h similarity index 68% rename from shell/browser/ui/tray_icon_gtk.h rename to shell/browser/ui/tray_icon_linux.h index ccbcd99b29612..fd6c3627961df 100644 --- a/shell/browser/ui/tray_icon_gtk.h +++ b/shell/browser/ui/tray_icon_linux.h @@ -2,8 +2,8 @@ // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. -#ifndef ELECTRON_SHELL_BROWSER_UI_TRAY_ICON_GTK_H_ -#define ELECTRON_SHELL_BROWSER_UI_TRAY_ICON_GTK_H_ +#ifndef ELECTRON_SHELL_BROWSER_UI_TRAY_ICON_LINUX_H_ +#define ELECTRON_SHELL_BROWSER_UI_TRAY_ICON_LINUX_H_ #include #include @@ -15,10 +15,10 @@ class StatusIconLinuxDbus; namespace electron { -class TrayIconGtk : public TrayIcon, public ui::StatusIconLinux::Delegate { +class TrayIconLinux : public TrayIcon, public ui::StatusIconLinux::Delegate { public: - TrayIconGtk(); - ~TrayIconGtk() override; + TrayIconLinux(); + ~TrayIconLinux() override; // TrayIcon: void SetImage(const gfx::Image& image) override; @@ -28,8 +28,6 @@ class TrayIconGtk : public TrayIcon, public ui::StatusIconLinux::Delegate { // ui::StatusIconLinux::Delegate void OnClick() override; bool HasClickAction() override; - // The following four methods are only used by StatusIconLinuxDbus, which we - // aren't yet using, so they are given stub implementations. const gfx::ImageSkia& GetImage() const override; const std::u16string& GetToolTip() const override; ui::MenuModel* GetMenuModel() const override; @@ -41,7 +39,9 @@ class TrayIconGtk : public TrayIcon, public ui::StatusIconLinux::Delegate { kNone, }; - scoped_refptr status_icon_; + ui::StatusIconLinux* GetStatusIcon(); + + scoped_refptr status_icon_dbus_; StatusIconType status_icon_type_; gfx::ImageSkia image_; @@ -51,4 +51,4 @@ class TrayIconGtk : public TrayIcon, public ui::StatusIconLinux::Delegate { } // namespace electron -#endif // ELECTRON_SHELL_BROWSER_UI_TRAY_ICON_GTK_H_ +#endif // ELECTRON_SHELL_BROWSER_UI_TRAY_ICON_LINUX_H_ From 791f472126c362ba76f7fdf3b16ff0c74bc2972c Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Thu, 26 Jan 2023 10:16:21 +0000 Subject: [PATCH 2/3] fix: fallback to GtkStatusIcon when app indicator is not supported Co-authored-by: Cheng Zhao --- BUILD.gn | 2 - docs/api/tray.md | 5 +- filenames.gni | 6 +++ shell/browser/ui/gtk/menu_gtk.cc | 74 +++++++++++++++++++++++++++++ shell/browser/ui/gtk/menu_gtk.h | 48 +++++++++++++++++++ shell/browser/ui/status_icon_gtk.cc | 70 +++++++++++++++++++++++++++ shell/browser/ui/status_icon_gtk.h | 51 ++++++++++++++++++++ shell/browser/ui/tray_icon_linux.cc | 10 ++++ shell/browser/ui/tray_icon_linux.h | 4 ++ 9 files changed, 266 insertions(+), 4 deletions(-) create mode 100644 shell/browser/ui/gtk/menu_gtk.cc create mode 100644 shell/browser/ui/gtk/menu_gtk.h create mode 100644 shell/browser/ui/status_icon_gtk.cc create mode 100644 shell/browser/ui/status_icon_gtk.h diff --git a/BUILD.gn b/BUILD.gn index 3f1b3b2febfa1..4e824c5eaa822 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -632,8 +632,6 @@ source_set("electron_lib") { sources += [ "shell/browser/certificate_manager_model.cc", "shell/browser/certificate_manager_model.h", - "shell/browser/ui/gtk/menu_util.cc", - "shell/browser/ui/gtk/menu_util.h", "shell/browser/ui/gtk_util.cc", "shell/browser/ui/gtk_util.h", ] diff --git a/docs/api/tray.md b/docs/api/tray.md index f64d02debf93a..2514931dd0d10 100644 --- a/docs/api/tray.md +++ b/docs/api/tray.md @@ -29,8 +29,9 @@ __Platform Considerations__ __Linux__ -* Tray icon requires support of [StatusNotifierItem](https://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/) - in user's desktop environment. +* Tray icon uses [StatusNotifierItem](https://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/) + by default, when it is not available in user's desktop environment the + `GtkStatusIcon` will be used instead. * The `click` event is emitted when the tray icon receives activation from user, however the StatusNotifierItem spec does not specify which action would cause an activation, for some environments it is left mouse click, but for diff --git a/filenames.gni b/filenames.gni index 2a0061e86fee0..19dd6b9d54875 100644 --- a/filenames.gni +++ b/filenames.gni @@ -35,7 +35,13 @@ filenames = { "shell/browser/relauncher_linux.cc", "shell/browser/ui/electron_desktop_window_tree_host_linux.cc", "shell/browser/ui/file_dialog_gtk.cc", + "shell/browser/ui/gtk/menu_gtk.cc", + "shell/browser/ui/gtk/menu_gtk.h", + "shell/browser/ui/gtk/menu_util.cc", + "shell/browser/ui/gtk/menu_util.h", "shell/browser/ui/message_box_gtk.cc", + "shell/browser/ui/status_icon_gtk.cc", + "shell/browser/ui/status_icon_gtk.h", "shell/browser/ui/tray_icon_linux.cc", "shell/browser/ui/tray_icon_linux.h", "shell/browser/ui/views/client_frame_view_linux.cc", diff --git a/shell/browser/ui/gtk/menu_gtk.cc b/shell/browser/ui/gtk/menu_gtk.cc new file mode 100644 index 0000000000000..ae5117229b18a --- /dev/null +++ b/shell/browser/ui/gtk/menu_gtk.cc @@ -0,0 +1,74 @@ +// 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 "shell/browser/ui/gtk/menu_gtk.h" + +#include + +#include "base/bind.h" +#include "shell/browser/ui/gtk/menu_util.h" +#include "ui/base/models/menu_model.h" + +namespace electron { + +namespace gtkui { + +MenuGtk::MenuGtk(ui::MenuModel* model) + : menu_model_(model), gtk_menu_(nullptr), block_activation_(false) { + 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(); + } +} + +MenuGtk::~MenuGtk() { + gtk_widget_destroy(gtk_menu_); + g_object_unref(gtk_menu_); +} + +void MenuGtk::Refresh() { + gtk_container_foreach(GTK_CONTAINER(gtk_menu_), SetMenuItemInfo, + &block_activation_); +} + +GtkMenu* MenuGtk::GetGtkMenu() { + return GTK_MENU(gtk_menu_); +} + +void MenuGtk::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 (model->IsEnabledAt(id)) + ExecuteCommand(model, id); +} + +} // namespace gtkui + +} // namespace electron diff --git a/shell/browser/ui/gtk/menu_gtk.h b/shell/browser/ui/gtk/menu_gtk.h new file mode 100644 index 0000000000000..1304bedda0de7 --- /dev/null +++ b/shell/browser/ui/gtk/menu_gtk.h @@ -0,0 +1,48 @@ +// 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 ELECTRON_SHELL_BROWSER_UI_GTK_MENU_GTK_H_ +#define ELECTRON_SHELL_BROWSER_UI_GTK_MENU_GTK_H_ + +#include "base/callback.h" +#include "ui/base/glib/glib_signal.h" + +typedef struct _GtkMenu GtkMenu; +typedef struct _GtkWidget GtkWidget; + +namespace ui { +class MenuModel; +} + +namespace electron { + +namespace gtkui { + +class MenuGtk { + public: + explicit MenuGtk(ui::MenuModel* model); + virtual ~MenuGtk(); + + // Refreshes all the menu item labels and menu item checked/enabled states. + void Refresh(); + + GtkMenu* GetGtkMenu(); + + private: + // Callback for when a menu item is activated. + CHROMEG_CALLBACK_0(MenuGtk, void, OnMenuItemActivated, GtkWidget*); + + // Not owned. + ui::MenuModel* menu_model_; + + GtkWidget* gtk_menu_; + + bool block_activation_; +}; + +} // namespace gtkui + +} // namespace electron + +#endif // ELECTRON_SHELL_BROWSER_UI_GTK_MENU_GTK_H_ diff --git a/shell/browser/ui/status_icon_gtk.cc b/shell/browser/ui/status_icon_gtk.cc new file mode 100644 index 0000000000000..9e9a595da4bdc --- /dev/null +++ b/shell/browser/ui/status_icon_gtk.cc @@ -0,0 +1,70 @@ +// Copyright (c) 2023 Microsoft, Inc. +// Copyright (c) 2011 The Chromium Authors. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "shell/browser/ui/status_icon_gtk.h" + +#include + +#include "base/strings/utf_string_conversions.h" +#include "shell/browser/ui/gtk/menu_gtk.h" +#include "shell/browser/ui/gtk_util.h" +#include "ui/gfx/image/image_skia.h" + +namespace electron { + +StatusIconGtk::StatusIconGtk() : icon_(gtk_status_icon_new()) { + g_signal_connect(icon_, "activate", G_CALLBACK(OnClickThunk), this); + g_signal_connect(icon_, "popup_menu", G_CALLBACK(OnContextMenuRequestedThunk), + this); +} + +StatusIconGtk::~StatusIconGtk() { + g_object_unref(icon_); +} + +void StatusIconGtk::SetIcon(const gfx::ImageSkia& image) { + if (image.isNull()) + return; + + GdkPixbuf* pixbuf = gtk_util::GdkPixbufFromSkBitmap(*image.bitmap()); + gtk_status_icon_set_from_pixbuf(icon_, pixbuf); + g_object_unref(pixbuf); +} + +void StatusIconGtk::SetToolTip(const std::u16string& tool_tip) { + gtk_status_icon_set_tooltip_text(icon_, base::UTF16ToUTF8(tool_tip).c_str()); +} + +void StatusIconGtk::UpdatePlatformContextMenu(ui::MenuModel* model) { + if (model) + menu_ = std::make_unique(model); +} + +void StatusIconGtk::RefreshPlatformContextMenu() { + if (menu_) + menu_->Refresh(); +} + +void StatusIconGtk::OnSetDelegate() { + SetIcon(delegate_->GetImage()); + SetToolTip(delegate_->GetToolTip()); + UpdatePlatformContextMenu(delegate_->GetMenuModel()); + gtk_status_icon_set_visible(icon_, TRUE); +} + +void StatusIconGtk::OnClick(GtkStatusIcon* status_icon) { + delegate_->OnClick(); +} + +void StatusIconGtk::OnContextMenuRequested(GtkStatusIcon* status_icon, + guint button, + guint32 activate_time) { + if (menu_.get()) { + gtk_menu_popup(menu_->GetGtkMenu(), nullptr, nullptr, + gtk_status_icon_position_menu, icon_, button, activate_time); + } +} + +} // namespace electron diff --git a/shell/browser/ui/status_icon_gtk.h b/shell/browser/ui/status_icon_gtk.h new file mode 100644 index 0000000000000..29a3ad9f48b76 --- /dev/null +++ b/shell/browser/ui/status_icon_gtk.h @@ -0,0 +1,51 @@ +// Copyright (c) 2023 Microsoft, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ELECTRON_SHELL_BROWSER_UI_STATUS_ICON_GTK_H_ +#define ELECTRON_SHELL_BROWSER_UI_STATUS_ICON_GTK_H_ + +#include + +#include "ui/base/glib/glib_integers.h" +#include "ui/base/glib/glib_signal.h" +#include "ui/linux/status_icon_linux.h" + +typedef struct _GtkStatusIcon GtkStatusIcon; + +namespace electron { + +namespace gtkui { +class MenuGtk; +} + +class StatusIconGtk : public ui::StatusIconLinux { + public: + StatusIconGtk(); + StatusIconGtk(const StatusIconGtk&) = delete; + StatusIconGtk& operator=(const StatusIconGtk&) = delete; + ~StatusIconGtk() override; + + // ui::StatusIconLinux: + void SetIcon(const gfx::ImageSkia& image) override; + void SetToolTip(const std::u16string& tool_tip) override; + void UpdatePlatformContextMenu(ui::MenuModel* model) override; + void RefreshPlatformContextMenu() override; + void OnSetDelegate() override; + + private: + CHROMEG_CALLBACK_0(StatusIconGtk, void, OnClick, GtkStatusIcon*); + CHROMEG_CALLBACK_2(StatusIconGtk, + void, + OnContextMenuRequested, + GtkStatusIcon*, + guint, + guint); + + std::unique_ptr menu_; + GtkStatusIcon* icon_; +}; + +} // namespace electron + +#endif // ELECTRON_SHELL_BROWSER_UI_STATUS_ICON_GTK_H_ diff --git a/shell/browser/ui/tray_icon_linux.cc b/shell/browser/ui/tray_icon_linux.cc index 12e3b4328d3f7..6f0a9e1dc50ff 100644 --- a/shell/browser/ui/tray_icon_linux.cc +++ b/shell/browser/ui/tray_icon_linux.cc @@ -6,6 +6,7 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h" +#include "shell/browser/ui/status_icon_gtk.h" #include "ui/gfx/image/image_skia_rep.h" namespace electron { @@ -71,7 +72,14 @@ void TrayIconLinux::OnImplInitializationFailed() { switch (status_icon_type_) { case StatusIconType::kDbus: status_icon_dbus_.reset(); + status_icon_gtk_ = std::make_unique(); + status_icon_type_ = StatusIconType::kGtk; + status_icon_gtk_->SetDelegate(this); + return; + case StatusIconType::kGtk: + status_icon_gtk_.reset(); status_icon_type_ = StatusIconType::kNone; + menu_model_ = nullptr; return; case StatusIconType::kNone: NOTREACHED(); @@ -92,6 +100,8 @@ ui::StatusIconLinux* TrayIconLinux::GetStatusIcon() { switch (status_icon_type_) { case StatusIconType::kDbus: return status_icon_dbus_.get(); + case StatusIconType::kGtk: + return status_icon_gtk_.get(); case StatusIconType::kNone: return nullptr; } diff --git a/shell/browser/ui/tray_icon_linux.h b/shell/browser/ui/tray_icon_linux.h index fd6c3627961df..76b94433aa946 100644 --- a/shell/browser/ui/tray_icon_linux.h +++ b/shell/browser/ui/tray_icon_linux.h @@ -15,6 +15,8 @@ class StatusIconLinuxDbus; namespace electron { +class StatusIconGtk; + class TrayIconLinux : public TrayIcon, public ui::StatusIconLinux::Delegate { public: TrayIconLinux(); @@ -36,12 +38,14 @@ class TrayIconLinux : public TrayIcon, public ui::StatusIconLinux::Delegate { private: enum class StatusIconType { kDbus, + kGtk, kNone, }; ui::StatusIconLinux* GetStatusIcon(); scoped_refptr status_icon_dbus_; + std::unique_ptr status_icon_gtk_; StatusIconType status_icon_type_; gfx::ImageSkia image_; From 71d1facad820ea195e9ff42427af86ff1c324725 Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Thu, 26 Jan 2023 10:16:25 +0000 Subject: [PATCH 3/3] chore: use smart pointers Co-authored-by: Cheng Zhao --- shell/browser/ui/gtk/menu_gtk.cc | 10 +++------- shell/browser/ui/gtk/menu_gtk.h | 10 +++++----- shell/browser/ui/status_icon_gtk.cc | 6 ++---- shell/browser/ui/status_icon_gtk.h | 3 ++- 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/shell/browser/ui/gtk/menu_gtk.cc b/shell/browser/ui/gtk/menu_gtk.cc index ae5117229b18a..8e73a50569a56 100644 --- a/shell/browser/ui/gtk/menu_gtk.cc +++ b/shell/browser/ui/gtk/menu_gtk.cc @@ -6,7 +6,6 @@ #include -#include "base/bind.h" #include "shell/browser/ui/gtk/menu_util.h" #include "ui/base/models/menu_model.h" @@ -15,9 +14,7 @@ namespace electron { namespace gtkui { MenuGtk::MenuGtk(ui::MenuModel* model) - : menu_model_(model), gtk_menu_(nullptr), block_activation_(false) { - gtk_menu_ = gtk_menu_new(); - g_object_ref_sink(gtk_menu_); + : menu_model_(model), gtk_menu_(TakeGObject(gtk_menu_new())) { if (menu_model_) { BuildSubmenuFromModel(menu_model_, gtk_menu_, G_CALLBACK(OnMenuItemActivatedThunk), @@ -28,16 +25,15 @@ MenuGtk::MenuGtk(ui::MenuModel* model) MenuGtk::~MenuGtk() { gtk_widget_destroy(gtk_menu_); - g_object_unref(gtk_menu_); } void MenuGtk::Refresh() { - gtk_container_foreach(GTK_CONTAINER(gtk_menu_), SetMenuItemInfo, + gtk_container_foreach(GTK_CONTAINER(gtk_menu_.get()), SetMenuItemInfo, &block_activation_); } GtkMenu* MenuGtk::GetGtkMenu() { - return GTK_MENU(gtk_menu_); + return GTK_MENU(gtk_menu_.get()); } void MenuGtk::OnMenuItemActivated(GtkWidget* menu_item) { diff --git a/shell/browser/ui/gtk/menu_gtk.h b/shell/browser/ui/gtk/menu_gtk.h index 1304bedda0de7..86ad8083d9b32 100644 --- a/shell/browser/ui/gtk/menu_gtk.h +++ b/shell/browser/ui/gtk/menu_gtk.h @@ -6,7 +6,9 @@ #define ELECTRON_SHELL_BROWSER_UI_GTK_MENU_GTK_H_ #include "base/callback.h" +#include "base/memory/raw_ptr.h" #include "ui/base/glib/glib_signal.h" +#include "ui/base/glib/scoped_gobject.h" typedef struct _GtkMenu GtkMenu; typedef struct _GtkWidget GtkWidget; @@ -33,12 +35,10 @@ class MenuGtk { // Callback for when a menu item is activated. CHROMEG_CALLBACK_0(MenuGtk, void, OnMenuItemActivated, GtkWidget*); - // Not owned. - ui::MenuModel* menu_model_; + raw_ptr menu_model_; // not owned + ScopedGObject gtk_menu_; - GtkWidget* gtk_menu_; - - bool block_activation_; + bool block_activation_ = false; }; } // namespace gtkui diff --git a/shell/browser/ui/status_icon_gtk.cc b/shell/browser/ui/status_icon_gtk.cc index 9e9a595da4bdc..1c8d0024c92e5 100644 --- a/shell/browser/ui/status_icon_gtk.cc +++ b/shell/browser/ui/status_icon_gtk.cc @@ -14,15 +14,13 @@ namespace electron { -StatusIconGtk::StatusIconGtk() : icon_(gtk_status_icon_new()) { +StatusIconGtk::StatusIconGtk() : icon_(TakeGObject(gtk_status_icon_new())) { g_signal_connect(icon_, "activate", G_CALLBACK(OnClickThunk), this); g_signal_connect(icon_, "popup_menu", G_CALLBACK(OnContextMenuRequestedThunk), this); } -StatusIconGtk::~StatusIconGtk() { - g_object_unref(icon_); -} +StatusIconGtk::~StatusIconGtk() = default; void StatusIconGtk::SetIcon(const gfx::ImageSkia& image) { if (image.isNull()) diff --git a/shell/browser/ui/status_icon_gtk.h b/shell/browser/ui/status_icon_gtk.h index 29a3ad9f48b76..beeff7593043c 100644 --- a/shell/browser/ui/status_icon_gtk.h +++ b/shell/browser/ui/status_icon_gtk.h @@ -9,6 +9,7 @@ #include "ui/base/glib/glib_integers.h" #include "ui/base/glib/glib_signal.h" +#include "ui/base/glib/scoped_gobject.h" #include "ui/linux/status_icon_linux.h" typedef struct _GtkStatusIcon GtkStatusIcon; @@ -43,7 +44,7 @@ class StatusIconGtk : public ui::StatusIconLinux { guint); std::unique_ptr menu_; - GtkStatusIcon* icon_; + ScopedGObject icon_; }; } // namespace electron