feat: allow macOS tray to maintain position (#48077)

This commit is contained in:
Shelley Vohr
2025-08-20 19:03:54 +02:00
committed by GitHub
parent aa022ce30e
commit 20a563c27d
13 changed files with 101 additions and 34 deletions

View File

@@ -16,6 +16,8 @@ gfx::Rect TrayIcon::GetBounds() {
return {};
}
void TrayIcon::SetAutoSaveName(const std::string& name) {}
void TrayIcon::NotifyClicked(const gfx::Rect& bounds,
const gfx::Point& location,
int modifiers) {

View File

@@ -18,7 +18,7 @@ namespace electron {
class TrayIcon {
public:
static TrayIcon* Create(std::optional<UUID> guid);
static TrayIcon* Create(std::optional<base::Uuid> guid);
#if BUILDFLAG(IS_WIN)
using ImageType = HICON;
@@ -99,6 +99,8 @@ class TrayIcon {
// Returns the bounds of tray icon.
virtual gfx::Rect GetBounds();
virtual void SetAutoSaveName(const std::string& name);
void AddObserver(TrayIconObserver* obs) { observers_.AddObserver(obs); }
void RemoveObserver(TrayIconObserver* obs) { observers_.RemoveObserver(obs); }

View File

@@ -35,6 +35,7 @@ class TrayIconCocoa : public TrayIcon {
void CloseContextMenu() override;
void SetContextMenu(raw_ptr<ElectronMenuModel> menu_model) override;
gfx::Rect GetBounds() override;
void SetAutoSaveName(const std::string& name) override;
base::WeakPtr<TrayIconCocoa> GetWeakPtr() {
return weak_factory_.GetWeakPtr();

View File

@@ -11,6 +11,7 @@
#include "base/message_loop/message_pump_apple.h"
#include "base/strings/sys_string_conversions.h"
#include "base/task/current_thread.h"
#include "base/uuid.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "shell/browser/ui/cocoa/NSString+ANSI.h"
@@ -68,6 +69,10 @@
[self setFrame:[statusItem_ button].frame];
}
- (void)setAutosaveName:(NSString*)name {
statusItem_.autosaveName = name;
}
- (void)updateTrackingAreas {
// Use NSTrackingArea for listening to mouseEnter, mouseExit, and mouseMove
// events.
@@ -420,8 +425,12 @@ gfx::Rect TrayIconCocoa::GetBounds() {
return gfx::ScreenRectFromNSRect([status_item_view_ window].frame);
}
void TrayIconCocoa::SetAutoSaveName(const std::string& name) {
[status_item_view_ setAutosaveName:base::SysUTF8ToNSString(name)];
}
// static
TrayIcon* TrayIcon::Create(std::optional<UUID> guid) {
TrayIcon* TrayIcon::Create(std::optional<base::Uuid> guid) {
return new TrayIconCocoa;
}

View File

@@ -112,7 +112,7 @@ ui::StatusIconLinux* TrayIconLinux::GetStatusIcon() {
}
// static
TrayIcon* TrayIcon::Create(std::optional<UUID> guid) {
TrayIcon* TrayIcon::Create(std::optional<base::Uuid> guid) {
return new TrayIconLinux;
}

View File

@@ -8,7 +8,7 @@
namespace electron {
// static
TrayIcon* TrayIcon::Create(std::optional<UUID> guid) {
TrayIcon* TrayIcon::Create(std::optional<base::Uuid> guid) {
static NotifyIconHost host;
return host.CreateNotifyIcon(guid);
}

View File

@@ -190,21 +190,32 @@ NotifyIconHost::~NotifyIconHost() {
delete ptr;
}
NotifyIcon* NotifyIconHost::CreateNotifyIcon(std::optional<UUID> guid) {
if (guid.has_value()) {
for (NotifyIcons::const_iterator i(notify_icons_.begin());
i != notify_icons_.end(); ++i) {
auto* current_win_icon = static_cast<NotifyIcon*>(*i);
if (current_win_icon->guid() == guid.value()) {
LOG(WARNING)
<< "Guid already in use. Existing tray entry will be replaced.";
NotifyIcon* NotifyIconHost::CreateNotifyIcon(std::optional<base::Uuid> guid) {
std::string guid_str =
guid.has_value() ? guid.value().AsLowercaseString() : "";
UUID uid = GUID_NULL;
if (!guid_str.empty()) {
if (guid_str[0] == '{' && guid_str[guid_str.length() - 1] == '}') {
guid_str = guid_str.substr(1, guid_str.length() - 2);
}
unsigned char* uid_cstr = (unsigned char*)guid_str.c_str();
RPC_STATUS result = UuidFromStringA(uid_cstr, &uid);
if (result != RPC_S_INVALID_STRING_UUID) {
for (NotifyIcons::const_iterator i(notify_icons_.begin());
i != notify_icons_.end(); ++i) {
auto* current_win_icon = static_cast<NotifyIcon*>(*i);
if (current_win_icon->guid() == uid) {
LOG(WARNING)
<< "Guid already in use. Existing tray entry will be replaced.";
}
}
}
}
auto* notify_icon =
new NotifyIcon(this, NextIconId(), window_, kNotifyIconMessage,
guid.has_value() ? guid.value() : GUID_DEFAULT);
uid == GUID_NULL ? GUID_DEFAULT : uid);
notify_icons_.push_back(notify_icon);
return notify_icon;

View File

@@ -27,7 +27,7 @@ class NotifyIconHost {
NotifyIconHost(const NotifyIconHost&) = delete;
NotifyIconHost& operator=(const NotifyIconHost&) = delete;
NotifyIcon* CreateNotifyIcon(std::optional<UUID> guid);
NotifyIcon* CreateNotifyIcon(std::optional<base::Uuid> guid);
void Remove(NotifyIcon* notify_icon);
private: