From 269ebbb52568e8cab700d0f3a16a479721dfb3bb Mon Sep 17 00:00:00 2001 From: reuk Date: Thu, 21 Nov 2024 21:26:55 +0000 Subject: [PATCH] Accessibility: Add AccessibilityHandler::postSystemNotification() function for posting an OS-specific accessible notification --- .../juce_AccessibilityHandler.cpp | 16 +- .../accessibility/juce_AccessibilityHandler.h | 27 ++- .../juce_Accessibility_android.cpp | 5 + .../accessibility/juce_Accessibility_ios.mm | 5 + .../accessibility/juce_Accessibility_mac.mm | 5 + .../juce_Accessibility_windows.cpp | 144 +++++++------ .../misc/juce_PushNotifications.cpp | 200 +++++++++++++----- .../misc/juce_PushNotifications.h | 12 +- .../native/juce_PushNotifications_android.cpp | 25 ++- .../native/juce_PushNotifications_ios.cpp | 12 +- .../native/juce_PushNotifications_mac.cpp | 6 +- 11 files changed, 308 insertions(+), 149 deletions(-) diff --git a/modules/juce_gui_basics/accessibility/juce_AccessibilityHandler.cpp b/modules/juce_gui_basics/accessibility/juce_AccessibilityHandler.cpp index a6ddb49633..3e6b1af91b 100644 --- a/modules/juce_gui_basics/accessibility/juce_AccessibilityHandler.cpp +++ b/modules/juce_gui_basics/accessibility/juce_AccessibilityHandler.cpp @@ -35,8 +35,6 @@ namespace juce { -AccessibilityHandler* AccessibilityHandler::currentlyFocusedHandler = nullptr; - class NativeChildHandler { public: @@ -403,10 +401,24 @@ void AccessibilityHandler::setNativeChildForComponent (Component& component, voi NativeChildHandler::getInstance().setNativeChild (component, nativeChild); } +#if JUCE_MODULE_AVAILABLE_juce_gui_extra +void privatePostSystemNotification (const String&, const String&); +#endif + +void AccessibilityHandler::postSystemNotification ([[maybe_unused]] const String& notificationTitle, + [[maybe_unused]] const String& notificationBody) +{ + #if JUCE_MODULE_AVAILABLE_juce_gui_extra + if (areAnyAccessibilityClientsActive()) + privatePostSystemNotification (notificationTitle, notificationBody); + #endif +} + #if ! JUCE_NATIVE_ACCESSIBILITY_INCLUDED void AccessibilityHandler::notifyAccessibilityEvent (AccessibilityEvent) const {} void AccessibilityHandler::postAnnouncement (const String&, AnnouncementPriority) {} AccessibilityNativeHandle* AccessibilityHandler::getNativeImplementation() const { return nullptr; } + bool AccessibilityHandler::areAnyAccessibilityClientsActive() { return false; } #endif } // namespace juce diff --git a/modules/juce_gui_basics/accessibility/juce_AccessibilityHandler.h b/modules/juce_gui_basics/accessibility/juce_AccessibilityHandler.h index da8b3f3af4..540799839b 100644 --- a/modules/juce_gui_basics/accessibility/juce_AccessibilityHandler.h +++ b/modules/juce_gui_basics/accessibility/juce_AccessibilityHandler.h @@ -295,6 +295,30 @@ public: */ static void postAnnouncement (const String& announcementString, AnnouncementPriority priority); + /** Posts a local system notification. + + In order for this to do anything, the following conditions must be met. + - At build time: + - The juce_gui_extra module must be included in the project. + - Push notifications must be enabled by setting the preprocessor definition + JUCE_PUSH_NOTIFICATIONS=1 + - At run time: + - An accessibility client (narrator, voiceover etc.) must be active. + + Additionally, on Android, an icon is required for notifications. + This must be specified by adding the path to the icon file called + "accessibilitynotificationicon" in the "Extra Android Raw Resources" setting + in the Projucer. + + This will use the push notification client on macOS, iOS and Android. + On Windows this will create a system tray icon to post the notification. + + @param notificationTitle the title of the notification + @param notificationBody the main body text of the notification + */ + static void postSystemNotification (const String& notificationTitle, + const String& notificationBody); + //============================================================================== /** @internal */ AccessibilityNativeHandle* getNativeImplementation() const; @@ -329,8 +353,9 @@ private: void grabFocusInternal (bool); void giveAwayFocusInternal() const; void takeFocus(); + static bool areAnyAccessibilityClientsActive(); - static AccessibilityHandler* currentlyFocusedHandler; + static inline AccessibilityHandler* currentlyFocusedHandler = nullptr; //============================================================================== Component& component; diff --git a/modules/juce_gui_basics/native/accessibility/juce_Accessibility_android.cpp b/modules/juce_gui_basics/native/accessibility/juce_Accessibility_android.cpp index 4ab7bd9db8..418eba3108 100644 --- a/modules/juce_gui_basics/native/accessibility/juce_Accessibility_android.cpp +++ b/modules/juce_gui_basics/native/accessibility/juce_Accessibility_android.cpp @@ -1055,4 +1055,9 @@ void AccessibilityHandler::postAnnouncement (const String& announcementString, javaString (announcementString).get()); } +bool AccessibilityHandler::areAnyAccessibilityClientsActive() +{ + return AccessibilityNativeHandle::areAnyAccessibilityClientsActive(); +} + } // namespace juce diff --git a/modules/juce_gui_basics/native/accessibility/juce_Accessibility_ios.mm b/modules/juce_gui_basics/native/accessibility/juce_Accessibility_ios.mm index 21538ae777..5c4643b499 100644 --- a/modules/juce_gui_basics/native/accessibility/juce_Accessibility_ios.mm +++ b/modules/juce_gui_basics/native/accessibility/juce_Accessibility_ios.mm @@ -666,4 +666,9 @@ void AccessibilityHandler::postAnnouncement (const String& announcementString, A sendAccessibilityEvent (UIAccessibilityAnnouncementNotification, juceStringToNS (announcementString)); } +bool AccessibilityHandler::areAnyAccessibilityClientsActive() +{ + return juce::areAnyAccessibilityClientsActive(); +} + } // namespace juce diff --git a/modules/juce_gui_basics/native/accessibility/juce_Accessibility_mac.mm b/modules/juce_gui_basics/native/accessibility/juce_Accessibility_mac.mm index 48647846ad..a6001b00e7 100644 --- a/modules/juce_gui_basics/native/accessibility/juce_Accessibility_mac.mm +++ b/modules/juce_gui_basics/native/accessibility/juce_Accessibility_mac.mm @@ -939,4 +939,9 @@ void AccessibilityHandler::postAnnouncement (const String& announcementString, A NSAccessibilityPriorityKey: @(nsPriority) }); } +bool AccessibilityHandler::areAnyAccessibilityClientsActive() +{ + return juce::areAnyAccessibilityClientsActive(); +} + } // namespace juce diff --git a/modules/juce_gui_basics/native/accessibility/juce_Accessibility_windows.cpp b/modules/juce_gui_basics/native/accessibility/juce_Accessibility_windows.cpp index 0c98af66dd..9fa451fb4e 100644 --- a/modules/juce_gui_basics/native/accessibility/juce_Accessibility_windows.cpp +++ b/modules/juce_gui_basics/native/accessibility/juce_Accessibility_windows.cpp @@ -39,26 +39,83 @@ namespace juce JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wlanguage-extension-token") -static bool isStartingUpOrShuttingDown() +//============================================================================== +struct WindowsAccessibility { - if (auto* app = JUCEApplicationBase::getInstance()) - if (app->isInitialising()) + WindowsAccessibility() = delete; + + static long getUiaRootObjectId() + { + return static_cast (UiaRootObjectId); + } + + static bool handleWmGetObject (AccessibilityHandler* handler, WPARAM wParam, LPARAM lParam, LRESULT* res) + { + if (isStartingUpOrShuttingDown() || (handler == nullptr || ! isHandlerValid (*handler))) + return false; + + if (auto* uiaWrapper = WindowsUIAWrapper::getInstance()) + { + ComSmartPtr provider; + handler->getNativeImplementation()->QueryInterface (IID_PPV_ARGS (provider.resetAndGetPointerAddress())); + + if (! uiaWrapper->isProviderDisconnecting (provider)) + *res = uiaWrapper->returnRawElementProvider ((HWND) handler->getComponent().getWindowHandle(), wParam, lParam, provider); + return true; + } - if (auto* mm = MessageManager::getInstanceWithoutCreating()) - if (mm->hasStopMessageBeenSent()) - return true; + return false; + } - return false; -} + static void revokeUIAMapEntriesForWindow (HWND hwnd) + { + if (auto* uiaWrapper = WindowsUIAWrapper::getInstanceWithoutCreating()) + uiaWrapper->returnRawElementProvider (hwnd, 0, 0, nullptr); + } -static bool isHandlerValid (const AccessibilityHandler& handler) -{ - if (auto* provider = handler.getNativeImplementation()) - return provider->isElementValid(); + static bool isStartingUpOrShuttingDown() + { + if (auto* app = JUCEApplicationBase::getInstance()) + if (app->isInitialising()) + return true; - return false; -} + if (auto* mm = MessageManager::getInstanceWithoutCreating()) + if (mm->hasStopMessageBeenSent()) + return true; + + return false; + } + + static bool isHandlerValid (const AccessibilityHandler& handler) + { + if (auto* provider = handler.getNativeImplementation()) + return provider->isElementValid(); + + return false; + } + + static bool areAnyAccessibilityClientsActive() + { + const auto areClientsListening = [] + { + if (auto* uiaWrapper = WindowsUIAWrapper::getInstanceWithoutCreating()) + return uiaWrapper->clientsAreListening() != 0; + + return false; + }; + + const auto isScreenReaderRunning = [] + { + BOOL isRunning = FALSE; + SystemParametersInfo (SPI_GETSCREENREADER, 0, (PVOID) &isRunning, 0); + + return isRunning != 0; + }; + + return areClientsListening() || isScreenReaderRunning(); + } +}; //============================================================================== class AccessibilityHandler::AccessibilityNativeImpl @@ -103,31 +160,12 @@ AccessibilityNativeHandle* AccessibilityHandler::getNativeImplementation() const return nativeImpl->accessibilityElement; } -static bool areAnyAccessibilityClientsActive() -{ - const auto areClientsListening = [] - { - if (auto* uiaWrapper = WindowsUIAWrapper::getInstanceWithoutCreating()) - return uiaWrapper->clientsAreListening() != 0; - - return false; - }; - - const auto isScreenReaderRunning = [] - { - BOOL isRunning = FALSE; - SystemParametersInfo (SPI_GETSCREENREADER, 0, (PVOID) &isRunning, 0); - - return isRunning != 0; - }; - - return areClientsListening() || isScreenReaderRunning(); -} - template void getProviderWithCheckedWrapper (const AccessibilityHandler& handler, Callback&& callback) { - if (! areAnyAccessibilityClientsActive() || isStartingUpOrShuttingDown() || ! isHandlerValid (handler)) + if (! WindowsAccessibility::areAnyAccessibilityClientsActive() + || WindowsAccessibility::isStartingUpOrShuttingDown() + || ! WindowsAccessibility::isHandlerValid (handler)) return; if (auto* uiaWrapper = WindowsUIAWrapper::getInstanceWithoutCreating()) @@ -292,41 +330,11 @@ void AccessibilityHandler::postAnnouncement (const String& announcementString, A } } -//============================================================================== -namespace WindowsAccessibility +bool AccessibilityHandler::areAnyAccessibilityClientsActive() { - static long getUiaRootObjectId() - { - return static_cast (UiaRootObjectId); - } - - static bool handleWmGetObject (AccessibilityHandler* handler, WPARAM wParam, LPARAM lParam, LRESULT* res) - { - if (isStartingUpOrShuttingDown() || (handler == nullptr || ! isHandlerValid (*handler))) - return false; - - if (auto* uiaWrapper = WindowsUIAWrapper::getInstance()) - { - ComSmartPtr provider; - handler->getNativeImplementation()->QueryInterface (IID_PPV_ARGS (provider.resetAndGetPointerAddress())); - - if (! uiaWrapper->isProviderDisconnecting (provider)) - *res = uiaWrapper->returnRawElementProvider ((HWND) handler->getComponent().getWindowHandle(), wParam, lParam, provider); - - return true; - } - - return false; - } - - static void revokeUIAMapEntriesForWindow (HWND hwnd) - { - if (auto* uiaWrapper = WindowsUIAWrapper::getInstanceWithoutCreating()) - uiaWrapper->returnRawElementProvider (hwnd, 0, 0, nullptr); - } + return WindowsAccessibility::areAnyAccessibilityClientsActive(); } - JUCE_END_IGNORE_WARNINGS_GCC_LIKE } // namespace juce diff --git a/modules/juce_gui_extra/misc/juce_PushNotifications.cpp b/modules/juce_gui_extra/misc/juce_PushNotifications.cpp index 4b6bca78be..c6d4ee426e 100644 --- a/modules/juce_gui_extra/misc/juce_PushNotifications.cpp +++ b/modules/juce_gui_extra/misc/juce_PushNotifications.cpp @@ -36,10 +36,50 @@ namespace juce { //============================================================================== -#if ! JUCE_ANDROID && ! JUCE_IOS && ! JUCE_MAC +#if ! JUCE_PUSH_NOTIFICATIONS_IMPL + +struct PushNotifications::Impl +{ + explicit Impl (PushNotifications& o) : owner (o) {} + + void requestPermissionsWithSettings (const Settings&) const + { + owner.listeners.call ([] (Listener& l) { l.notificationSettingsReceived ({}); }); + } + + void requestSettingsUsed() const + { + owner.listeners.call ([] (Listener& l) { l.notificationSettingsReceived ({}); }); + } + + bool areNotificationsEnabled() const { return false; } + void getDeliveredNotifications() const {} + void removeAllDeliveredNotifications() const {} + String getDeviceToken() const { return {}; } + void setupChannels (const Array&, const Array&) const {} + void getPendingLocalNotifications() const {} + void removeAllPendingLocalNotifications() const {} + void subscribeToTopic (const String&) const {} + void unsubscribeFromTopic (const String&) const {} + void sendLocalNotification (const Notification&) const {} + void removeDeliveredNotification (const String&) const {} + void removePendingLocalNotification (const String&) const {} + void sendUpstreamMessage (const String&, + const String&, + const String&, + const String&, + int, + const StringPairArray&) const {} + +private: + PushNotifications& owner; +}; + bool PushNotifications::Notification::isValid() const noexcept { return true; } + #endif +//============================================================================== PushNotifications::Notification::Notification (const Notification& other) : identifier (other.identifier), title (other.title), @@ -82,9 +122,7 @@ PushNotifications::Notification::Notification (const Notification& other) //============================================================================== PushNotifications::PushNotifications() - #if JUCE_PUSH_NOTIFICATIONS - : pimpl (new Pimpl (*this)) - #endif + : pimpl (new Impl (*this)) { } @@ -93,128 +131,90 @@ PushNotifications::~PushNotifications() { clearSingletonInstance(); } void PushNotifications::addListener (Listener* l) { listeners.add (l); } void PushNotifications::removeListener (Listener* l) { listeners.remove (l); } -void PushNotifications::requestPermissionsWithSettings ([[maybe_unused]] const PushNotifications::Settings& settings) +void PushNotifications::requestPermissionsWithSettings (const Settings& settings) { - #if JUCE_PUSH_NOTIFICATIONS && (JUCE_IOS || JUCE_MAC) pimpl->requestPermissionsWithSettings (settings); - #else - listeners.call ([] (Listener& l) { l.notificationSettingsReceived ({}); }); - #endif } void PushNotifications::requestSettingsUsed() { - #if JUCE_PUSH_NOTIFICATIONS && (JUCE_IOS || JUCE_MAC) pimpl->requestSettingsUsed(); - #else - listeners.call ([] (Listener& l) { l.notificationSettingsReceived ({}); }); - #endif } bool PushNotifications::areNotificationsEnabled() const { - #if JUCE_PUSH_NOTIFICATIONS return pimpl->areNotificationsEnabled(); - #else - return false; - #endif } void PushNotifications::getDeliveredNotifications() const { - #if JUCE_PUSH_NOTIFICATIONS pimpl->getDeliveredNotifications(); - #endif } void PushNotifications::removeAllDeliveredNotifications() { - #if JUCE_PUSH_NOTIFICATIONS pimpl->removeAllDeliveredNotifications(); - #endif } String PushNotifications::getDeviceToken() const { - #if JUCE_PUSH_NOTIFICATIONS return pimpl->getDeviceToken(); - #else - return {}; - #endif } -void PushNotifications::setupChannels ([[maybe_unused]] const Array& groups, [[maybe_unused]] const Array& channels) +void PushNotifications::setupChannels (const Array& groups, + const Array& channels) { - #if JUCE_PUSH_NOTIFICATIONS pimpl->setupChannels (groups, channels); - #endif } void PushNotifications::getPendingLocalNotifications() const { - #if JUCE_PUSH_NOTIFICATIONS pimpl->getPendingLocalNotifications(); - #endif } void PushNotifications::removeAllPendingLocalNotifications() { - #if JUCE_PUSH_NOTIFICATIONS pimpl->removeAllPendingLocalNotifications(); - #endif } -void PushNotifications::subscribeToTopic ([[maybe_unused]] const String& topic) +void PushNotifications::subscribeToTopic (const String& topic) { - #if JUCE_PUSH_NOTIFICATIONS pimpl->subscribeToTopic (topic); - #endif } -void PushNotifications::unsubscribeFromTopic ([[maybe_unused]] const String& topic) +void PushNotifications::unsubscribeFromTopic (const String& topic) { - #if JUCE_PUSH_NOTIFICATIONS pimpl->unsubscribeFromTopic (topic); - #endif } - -void PushNotifications::sendLocalNotification ([[maybe_unused]] const Notification& n) +void PushNotifications::sendLocalNotification (const Notification& n) { - #if JUCE_PUSH_NOTIFICATIONS pimpl->sendLocalNotification (n); - #endif } -void PushNotifications::removeDeliveredNotification ([[maybe_unused]] const String& identifier) +void PushNotifications::removeDeliveredNotification (const String& identifier) { - #if JUCE_PUSH_NOTIFICATIONS pimpl->removeDeliveredNotification (identifier); - #endif } -void PushNotifications::removePendingLocalNotification ([[maybe_unused]] const String& identifier) +void PushNotifications::removePendingLocalNotification (const String& identifier) { - #if JUCE_PUSH_NOTIFICATIONS pimpl->removePendingLocalNotification (identifier); - #endif } -void PushNotifications::sendUpstreamMessage ([[maybe_unused]] const String& serverSenderId, - [[maybe_unused]] const String& collapseKey, - [[maybe_unused]] const String& messageId, - [[maybe_unused]] const String& messageType, - [[maybe_unused]] int timeToLive, - [[maybe_unused]] const StringPairArray& additionalData) +void PushNotifications::sendUpstreamMessage (const String& serverSenderId, + const String& collapseKey, + const String& messageId, + const String& messageType, + int timeToLive, + const StringPairArray& additionalData) { - #if JUCE_PUSH_NOTIFICATIONS pimpl->sendUpstreamMessage (serverSenderId, collapseKey, messageId, messageType, timeToLive, additionalData); - #endif } //============================================================================== @@ -234,4 +234,92 @@ void PushNotifications::Listener::upstreamMessageSent ([[maybe_unused]] const St void PushNotifications::Listener::upstreamMessageSendingError ([[maybe_unused]] const String& messageId, [[maybe_unused]] const String& error) {} +//============================================================================== +void privatePostSystemNotification (const String& notificationTitle, const String& notificationBody); +void privatePostSystemNotification ([[maybe_unused]] const String& notificationTitle, + [[maybe_unused]] const String& notificationBody) +{ + #if JUCE_PUSH_NOTIFICATIONS + #if JUCE_ANDROID || JUCE_IOS || JUCE_MAC + auto* notificationsInstance = PushNotifications::getInstance(); + + if (notificationsInstance == nullptr) + return; + + #if JUCE_ANDROID + notificationsInstance->requestPermissionsWithSettings ({}); + + static auto channels = std::invoke ([]() -> Array + { + PushNotifications::Channel chan; + + chan.identifier = "1"; + chan.name = "Notifications"; + chan.description = "Accessibility notifications"; + chan.groupId = "accessibility"; + chan.ledColour = Colours::yellow; + chan.canShowBadge = true; + chan.enableLights = true; + chan.enableVibration = true; + chan.soundToPlay = URL ("default_os_sound"); + chan.vibrationPattern = { 1000, 1000 }; + + return { chan }; + }); + + notificationsInstance->setupChannels ({ PushNotifications::ChannelGroup { "accessibility", "accessibility" } }, + channels); + #else + static auto settings = std::invoke ([] + { + PushNotifications::Settings s; + s.allowAlert = true; + s.allowBadge = true; + s.allowSound = true; + + #if JUCE_IOS + PushNotifications::Settings::Category c; + c.identifier = "Accessibility"; + + s.categories = { c }; + #endif + + return s; + }); + + notificationsInstance->requestPermissionsWithSettings (settings); + #endif + + const auto notification = std::invoke ([¬ificationTitle, ¬ificationBody] + { + PushNotifications::Notification n; + + n.identifier = String (Random::getSystemRandom().nextInt()); + n.title = notificationTitle; + n.body = notificationBody; + + #if JUCE_IOS + n.category = "Accessibility"; + #elif JUCE_ANDROID + n.channelId = "1"; + n.icon = "accessibilitynotificationicon"; + #endif + + return n; + }); + + if (notification.isValid()) + notificationsInstance->sendLocalNotification (notification); + + #else + SystemTrayIconComponent systemTrayIcon; + + Image im (Image::ARGB, 128, 128, true); + systemTrayIcon.setIconImage (im, im); + + systemTrayIcon.showInfoBubble (notificationTitle, notificationBody); + #endif + #endif +} + } // namespace juce diff --git a/modules/juce_gui_extra/misc/juce_PushNotifications.h b/modules/juce_gui_extra/misc/juce_PushNotifications.h index b3d7b550b1..b5bafe2511 100644 --- a/modules/juce_gui_extra/misc/juce_PushNotifications.h +++ b/modules/juce_gui_extra/misc/juce_PushNotifications.h @@ -403,8 +403,8 @@ public: */ struct Category { - juce::String identifier; /**< unique identifier */ - juce::Array actions; /**< optional list of actions within this category */ + String identifier; /**< unique identifier */ + Array actions; /**< optional list of actions within this category */ bool sendDismissAction = false; /**< whether dismiss action will be sent to the app */ }; @@ -703,12 +703,8 @@ private: friend struct JuceFirebaseMessagingService; #endif - #if JUCE_PUSH_NOTIFICATIONS - struct Pimpl; - friend struct Pimpl; - - std::unique_ptr pimpl; - #endif + struct Impl; + std::unique_ptr pimpl; }; } // namespace juce diff --git a/modules/juce_gui_extra/native/juce_PushNotifications_android.cpp b/modules/juce_gui_extra/native/juce_PushNotifications_android.cpp index 46c50123c8..25dd16027f 100644 --- a/modules/juce_gui_extra/native/juce_PushNotifications_android.cpp +++ b/modules/juce_gui_extra/native/juce_PushNotifications_android.cpp @@ -35,6 +35,8 @@ namespace juce { +#define JUCE_PUSH_NOTIFICATIONS_IMPL 1 + #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (constructor, "", "(Ljava/lang/String;Ljava/lang/CharSequence;I)V") \ METHOD (enableLights, "enableLights", "(Z)V") \ @@ -274,9 +276,9 @@ bool PushNotifications::Notification::isValid() const noexcept } //============================================================================== -struct PushNotifications::Pimpl +struct PushNotifications::Impl { - explicit Pimpl (PushNotifications& p) + explicit Impl (PushNotifications& p) : owner (p) {} @@ -306,7 +308,7 @@ struct PushNotifications::Pimpl const auto notifyListeners = [] { if (auto* instance = PushNotifications::getInstance()) - instance->listeners.call ([] (Listener& l) { l.notificationSettingsReceived ({}); }); + instance->listeners.call ([] (Listener& l) { l.notificationSettingsReceived (makeDefaultSettings()); }); }; if (MessageManager::getInstance()->isThisTheMessageThread()) @@ -318,7 +320,7 @@ struct PushNotifications::Pimpl void requestSettingsUsed() { - owner.listeners.call ([] (Listener& l) { l.notificationSettingsReceived ({}); }); + owner.listeners.call ([] (Listener& l) { l.notificationSettingsReceived (makeDefaultSettings()); }); } void sendLocalNotification (const Notification& n) @@ -1573,6 +1575,15 @@ struct PushNotifications::Pimpl && env->CallBooleanMethod (extras, AndroidBundle.containsKey, javaString ("google.message_id").get()); } + static Settings makeDefaultSettings() + { + Settings settings; + settings.allowAlert = true; + settings.allowBadge = true; + settings.allowSound = true; + return settings; + } + PushNotifications& owner; }; @@ -1640,14 +1651,14 @@ bool juce_handleNotificationIntent (void* intent) { auto* instance = PushNotifications::getInstanceWithoutCreating(); - if (PushNotifications::Pimpl::isDeleteNotificationIntent ((jobject) intent)) + if (PushNotifications::Impl::isDeleteNotificationIntent ((jobject) intent)) { if (instance) instance->pimpl->notifyListenersAboutLocalNotificationDeleted (LocalRef ((jobject) intent)); return true; } - else if (PushNotifications::Pimpl::isLocalNotificationIntent ((jobject) intent)) + else if (PushNotifications::Impl::isLocalNotificationIntent ((jobject) intent)) { if (instance) instance->pimpl->notifyListenersAboutLocalNotification (LocalRef ((jobject) intent)); @@ -1655,7 +1666,7 @@ bool juce_handleNotificationIntent (void* intent) return true; } #if defined (JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME) - else if (PushNotifications::Pimpl::isRemoteNotificationIntent ((jobject) intent)) + else if (PushNotifications::Impl::isRemoteNotificationIntent ((jobject) intent)) { if (instance) instance->pimpl->notifyListenersAboutRemoteNotificationFromSystemTray (LocalRef ((jobject) intent)); diff --git a/modules/juce_gui_extra/native/juce_PushNotifications_ios.cpp b/modules/juce_gui_extra/native/juce_PushNotifications_ios.cpp index b093a76434..a2d44c7c7e 100644 --- a/modules/juce_gui_extra/native/juce_PushNotifications_ios.cpp +++ b/modules/juce_gui_extra/native/juce_PushNotifications_ios.cpp @@ -35,6 +35,8 @@ namespace juce { +#define JUCE_PUSH_NOTIFICATIONS_IMPL 1 + struct PushNotificationsDelegateDetails { //============================================================================== @@ -301,9 +303,9 @@ bool PushNotifications::Notification::isValid() const noexcept } //============================================================================== -struct PushNotifications::Pimpl +struct PushNotifications::Impl { - Pimpl (PushNotifications& p) + explicit Impl (PushNotifications& p) : owner (p) { Class::setThis (delegate.get(), this); @@ -555,7 +557,7 @@ private: Class() : ObjCClass ("JucePushNotificationsDelegate_") { - addIvar ("self"); + addIvar ("self"); addMethod (@selector (application:didRegisterForRemoteNotificationsWithDeviceToken:), [] (id self, SEL, UIApplication*, NSData* data) { @@ -596,8 +598,8 @@ private: } //============================================================================== - static Pimpl& getThis (id self) { return *getIvar (self, "self"); } - static void setThis (id self, Pimpl* d) { object_setInstanceVariable (self, "self", d); } + static Impl& getThis (id self) { return *getIvar (self, "self"); } + static void setThis (id self, Impl* d) { object_setInstanceVariable (self, "self", d); } }; //============================================================================== diff --git a/modules/juce_gui_extra/native/juce_PushNotifications_mac.cpp b/modules/juce_gui_extra/native/juce_PushNotifications_mac.cpp index c994beb3bd..a06dd82dc9 100644 --- a/modules/juce_gui_extra/native/juce_PushNotifications_mac.cpp +++ b/modules/juce_gui_extra/native/juce_PushNotifications_mac.cpp @@ -35,6 +35,8 @@ namespace juce { +#define JUCE_PUSH_NOTIFICATIONS_IMPL 1 + JUCE_BEGIN_IGNORE_DEPRECATION_WARNINGS namespace PushNotificationsDelegateDetailsOsx @@ -343,9 +345,9 @@ private: bool PushNotifications::Notification::isValid() const noexcept { return true; } //============================================================================== -struct PushNotifications::Pimpl : private PushNotificationsDelegate +struct PushNotifications::Impl : private PushNotificationsDelegate { - Pimpl (PushNotifications& p) + explicit Impl (PushNotifications& p) : owner (p) { }