From 642f5a84d4a198a638c1e0aabe0eb4f4556aa657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Beffa?= Date: Thu, 22 Mar 2018 10:41:03 +0100 Subject: [PATCH] Workspace notifications support on macOS (#12093) --- .../api/atom_api_system_preferences.cc | 10 +- .../browser/api/atom_api_system_preferences.h | 23 +++- .../api/atom_api_system_preferences_mac.mm | 104 ++++++++++++------ docs/api/system-preferences.md | 36 +++++- 4 files changed, 127 insertions(+), 46 deletions(-) diff --git a/atom/browser/api/atom_api_system_preferences.cc b/atom/browser/api/atom_api_system_preferences.cc index 2b18d0f7974..3eeba8a7eed 100644 --- a/atom/browser/api/atom_api_system_preferences.cc +++ b/atom/browser/api/atom_api_system_preferences.cc @@ -55,16 +55,22 @@ void SystemPreferences::BuildPrototype( #elif defined(OS_MACOSX) .SetMethod("postNotification", &SystemPreferences::PostNotification) - .SetMethod("postLocalNotification", - &SystemPreferences::PostLocalNotification) .SetMethod("subscribeNotification", &SystemPreferences::SubscribeNotification) .SetMethod("unsubscribeNotification", &SystemPreferences::UnsubscribeNotification) + .SetMethod("postLocalNotification", + &SystemPreferences::PostLocalNotification) .SetMethod("subscribeLocalNotification", &SystemPreferences::SubscribeLocalNotification) .SetMethod("unsubscribeLocalNotification", &SystemPreferences::UnsubscribeLocalNotification) + .SetMethod("postWorkspaceNotification", + &SystemPreferences::PostWorkspaceNotification) + .SetMethod("subscribeWorkspaceNotification", + &SystemPreferences::SubscribeWorkspaceNotification) + .SetMethod("unsubscribeWorkspaceNotification", + &SystemPreferences::UnsubscribeWorkspaceNotification) .SetMethod("registerDefaults", &SystemPreferences::RegisterDefaults) .SetMethod("getUserDefault", &SystemPreferences::GetUserDefault) .SetMethod("setUserDefault", &SystemPreferences::SetUserDefault) diff --git a/atom/browser/api/atom_api_system_preferences.h b/atom/browser/api/atom_api_system_preferences.h index 4e432d7e51e..057543dadeb 100644 --- a/atom/browser/api/atom_api_system_preferences.h +++ b/atom/browser/api/atom_api_system_preferences.h @@ -26,6 +26,14 @@ namespace atom { namespace api { +#if defined(OS_MACOSX) +enum NotificationCenterKind { + kNSDistributedNotificationCenter = 0, + kNSNotificationCenter, + kNSWorkspaceNotificationCenter, +}; +#endif + class SystemPreferences : public mate::EventEmitter #if defined(OS_WIN) , public BrowserObserver @@ -63,14 +71,19 @@ class SystemPreferences : public mate::EventEmitter void PostNotification(const std::string& name, const base::DictionaryValue& user_info); - void PostLocalNotification(const std::string& name, - const base::DictionaryValue& user_info); int SubscribeNotification(const std::string& name, const NotificationCallback& callback); void UnsubscribeNotification(int id); + void PostLocalNotification(const std::string& name, + const base::DictionaryValue& user_info); int SubscribeLocalNotification(const std::string& name, const NotificationCallback& callback); void UnsubscribeLocalNotification(int request_id); + void PostWorkspaceNotification(const std::string& name, + const base::DictionaryValue& user_info); + int SubscribeWorkspaceNotification(const std::string& name, + const NotificationCallback& callback); + void UnsubscribeWorkspaceNotification(int request_id); v8::Local GetUserDefault(const std::string& name, const std::string& type); void RegisterDefaults(mate::Arguments* args); @@ -90,11 +103,11 @@ class SystemPreferences : public mate::EventEmitter #if defined(OS_MACOSX) void DoPostNotification(const std::string& name, const base::DictionaryValue& user_info, - bool is_local); + NotificationCenterKind kind); int DoSubscribeNotification(const std::string& name, const NotificationCallback& callback, - bool is_local); - void DoUnsubscribeNotification(int request_id, bool is_local); + NotificationCenterKind kind); + void DoUnsubscribeNotification(int request_id, NotificationCenterKind kind); #endif private: diff --git a/atom/browser/api/atom_api_system_preferences_mac.mm b/atom/browser/api/atom_api_system_preferences_mac.mm index 8f7ce7f144c..4e9af12b7a7 100644 --- a/atom/browser/api/atom_api_system_preferences_mac.mm +++ b/atom/browser/api/atom_api_system_preferences_mac.mm @@ -30,19 +30,59 @@ std::map g_id_map; void SystemPreferences::PostNotification(const std::string& name, const base::DictionaryValue& user_info) { - DoPostNotification(name, user_info, false); + DoPostNotification(name, user_info, kNSDistributedNotificationCenter); +} + +int SystemPreferences::SubscribeNotification( + const std::string& name, const NotificationCallback& callback) { + return DoSubscribeNotification(name, callback, kNSDistributedNotificationCenter); +} + +void SystemPreferences::UnsubscribeNotification(int request_id) { + DoUnsubscribeNotification(request_id, kNSDistributedNotificationCenter); } void SystemPreferences::PostLocalNotification(const std::string& name, const base::DictionaryValue& user_info) { - DoPostNotification(name, user_info, true); + DoPostNotification(name, user_info, kNSNotificationCenter); +} + +int SystemPreferences::SubscribeLocalNotification( + const std::string& name, const NotificationCallback& callback) { + return DoSubscribeNotification(name, callback, kNSNotificationCenter); +} + +void SystemPreferences::UnsubscribeLocalNotification(int request_id) { + DoUnsubscribeNotification(request_id, kNSNotificationCenter); +} + +void SystemPreferences::PostWorkspaceNotification(const std::string& name, + const base::DictionaryValue& user_info) { + DoPostNotification(name, user_info, kNSWorkspaceNotificationCenter); +} + +int SystemPreferences::SubscribeWorkspaceNotification( + const std::string& name, const NotificationCallback& callback) { + return DoSubscribeNotification(name, callback, kNSWorkspaceNotificationCenter); +} + +void SystemPreferences::UnsubscribeWorkspaceNotification(int request_id) { + DoUnsubscribeNotification(request_id, kNSWorkspaceNotificationCenter); } void SystemPreferences::DoPostNotification(const std::string& name, - const base::DictionaryValue& user_info, bool is_local) { - NSNotificationCenter* center = is_local ? - [NSNotificationCenter defaultCenter] : - [NSDistributedNotificationCenter defaultCenter]; + const base::DictionaryValue& user_info, NotificationCenterKind kind) { + NSNotificationCenter* center; + switch (kind) { + case kNSDistributedNotificationCenter: + center = [NSDistributedNotificationCenter defaultCenter]; break; + case kNSNotificationCenter: + center = [NSNotificationCenter defaultCenter]; break; + case kNSWorkspaceNotificationCenter: + center = [[NSWorkspace sharedWorkspace] notificationCenter]; break; + default: + break; + } [center postNotificationName:base::SysUTF8ToNSString(name) object:nil @@ -50,32 +90,22 @@ void SystemPreferences::DoPostNotification(const std::string& name, ]; } -int SystemPreferences::SubscribeNotification( - const std::string& name, const NotificationCallback& callback) { - return DoSubscribeNotification(name, callback, false); -} - -void SystemPreferences::UnsubscribeNotification(int request_id) { - DoUnsubscribeNotification(request_id, false); -} - -int SystemPreferences::SubscribeLocalNotification( - const std::string& name, const NotificationCallback& callback) { - return DoSubscribeNotification(name, callback, true); -} - -void SystemPreferences::UnsubscribeLocalNotification(int request_id) { - DoUnsubscribeNotification(request_id, true); -} - int SystemPreferences::DoSubscribeNotification(const std::string& name, - const NotificationCallback& callback, bool is_local) { + const NotificationCallback& callback, NotificationCenterKind kind) { int request_id = g_next_id++; __block NotificationCallback copied_callback = callback; - NSNotificationCenter* center = is_local ? - [NSNotificationCenter defaultCenter] : - [NSDistributedNotificationCenter defaultCenter]; - + NSNotificationCenter* center; + switch (kind) { + case kNSDistributedNotificationCenter: + center = [NSDistributedNotificationCenter defaultCenter]; break; + case kNSNotificationCenter: + center = [NSNotificationCenter defaultCenter]; break; + case kNSWorkspaceNotificationCenter: + center = [[NSWorkspace sharedWorkspace] notificationCenter]; break; + default: + break; + } + g_id_map[request_id] = [center addObserverForName:base::SysUTF8ToNSString(name) object:nil @@ -97,13 +127,21 @@ int SystemPreferences::DoSubscribeNotification(const std::string& name, return request_id; } -void SystemPreferences::DoUnsubscribeNotification(int request_id, bool is_local) { +void SystemPreferences::DoUnsubscribeNotification(int request_id, NotificationCenterKind kind) { auto iter = g_id_map.find(request_id); if (iter != g_id_map.end()) { id observer = iter->second; - NSNotificationCenter* center = is_local ? - [NSNotificationCenter defaultCenter] : - [NSDistributedNotificationCenter defaultCenter]; + NSNotificationCenter* center; + switch (kind) { + case kNSDistributedNotificationCenter: + center = [NSDistributedNotificationCenter defaultCenter]; break; + case kNSNotificationCenter: + center = [NSNotificationCenter defaultCenter]; break; + case kNSWorkspaceNotificationCenter: + center = [[NSWorkspace sharedWorkspace] notificationCenter]; break; + default: + break; + } [center removeObserver:observer]; g_id_map.erase(iter); } diff --git a/docs/api/system-preferences.md b/docs/api/system-preferences.md index f0031ffe2b8..88948789cf3 100644 --- a/docs/api/system-preferences.md +++ b/docs/api/system-preferences.md @@ -61,6 +61,14 @@ that contains the user information dictionary sent along with the notification. Posts `event` as native notifications of macOS. The `userInfo` is an Object that contains the user information dictionary sent along with the notification. +### `systemPreferences.postWorkspaceNotification(event, userInfo)` _macOS_ + +* `event` String +* `userInfo` Object + +Posts `event` as native notifications of macOS. The `userInfo` is an Object +that contains the user information dictionary sent along with the notification. + ### `systemPreferences.subscribeNotification(event, callback)` _macOS_ * `event` String @@ -84,12 +92,6 @@ example values of `event` are: * `AppleColorPreferencesChangedNotification` * `AppleShowScrollBarsSettingChanged` -### `systemPreferences.unsubscribeNotification(id)` _macOS_ - -* `id` Integer - -Removes the subscriber with `id`. - ### `systemPreferences.subscribeLocalNotification(event, callback)` _macOS_ * `event` String @@ -100,12 +102,34 @@ Removes the subscriber with `id`. Same as `subscribeNotification`, but uses `NSNotificationCenter` for local defaults. This is necessary for events such as `NSUserDefaultsDidChangeNotification`. +### `systemPreferences.subscribeWorkspaceNotification(event, callback)` _macOS_ + +* `event` String +* `callback` Function + * `event` String + * `userInfo` Object + +Same as `subscribeNotification`, but uses `NSWorkspace.sharedWorkspace.notificationCenter`. +This is necessary for events such as `NSWorkspaceDidActivateApplicationNotification`. + +### `systemPreferences.unsubscribeNotification(id)` _macOS_ + +* `id` Integer + +Removes the subscriber with `id`. + ### `systemPreferences.unsubscribeLocalNotification(id)` _macOS_ * `id` Integer Same as `unsubscribeNotification`, but removes the subscriber from `NSNotificationCenter`. +### `systemPreferences.unsubscribeWorkspaceNotification(id)` _macOS_ + +* `id` Integer + +Same as `unsubscribeNotification`, but removes the subscriber from `NSWorkspace.sharedWorkspace.notificationCenter`. + ### `systemPreferences.registerDefaults(defaults)` _macOS_ * `defaults` Object - a dictionary of (`key: value`) user defaults