1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

ObjC: Add scoped notification observer

This commit is contained in:
reuk 2022-07-05 13:56:08 +01:00
parent 921d86e586
commit 869760cb2a
No known key found for this signature in database
GPG key ID: FCB43929F012EE5C
3 changed files with 79 additions and 90 deletions

View file

@ -520,4 +520,57 @@ private:
BlockType block;
};
//==============================================================================
class ScopedNotificationCenterObserver
{
public:
ScopedNotificationCenterObserver() = default;
ScopedNotificationCenterObserver (id observerIn, SEL selector, NSNotificationName nameIn, id objectIn)
: observer (observerIn), name (nameIn), object (objectIn)
{
[[NSNotificationCenter defaultCenter] addObserver: observer
selector: selector
name: name
object: object];
}
~ScopedNotificationCenterObserver()
{
if (observer != nullptr && name != nullptr)
{
[[NSNotificationCenter defaultCenter] removeObserver: observer
name: name
object: object];
}
}
ScopedNotificationCenterObserver (ScopedNotificationCenterObserver&& other) noexcept
{
swap (other);
}
ScopedNotificationCenterObserver& operator= (ScopedNotificationCenterObserver&& other) noexcept
{
auto moved = std::move (other);
swap (moved);
return *this;
}
ScopedNotificationCenterObserver (const ScopedNotificationCenterObserver&) = delete;
ScopedNotificationCenterObserver& operator= (const ScopedNotificationCenterObserver&) = delete;
private:
void swap (ScopedNotificationCenterObserver& other) noexcept
{
std::swap (other.observer, observer);
std::swap (other.name, name);
std::swap (other.object, object);
}
id observer = nullptr;
NSNotificationName name = nullptr;
id object = nullptr;
};
} // namespace juce

View file

@ -710,24 +710,14 @@ public:
{
static DelegateClass delegateClass;
delegate = [delegateClass.createInstance() init];
object_setInstanceVariable (delegate, "owner", this);
delegate.reset ([delegateClass.createInstance() init]);
object_setInstanceVariable (delegate.get(), "owner", this);
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector")
[[NSNotificationCenter defaultCenter] addObserver: delegate
selector: @selector (darkModeChanged:)
name: UIViewComponentPeer::getDarkModeNotificationName()
object: nil];
observer.emplace (delegate.get(), @selector (darkModeChanged:), UIViewComponentPeer::getDarkModeNotificationName(), nil);
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
}
~NativeDarkModeChangeDetectorImpl()
{
object_setInstanceVariable (delegate, "owner", nullptr);
[[NSNotificationCenter defaultCenter] removeObserver: delegate];
[delegate release];
}
void darkModeChanged()
{
Desktop::getInstance().darkModeChanged();
@ -741,20 +731,19 @@ private:
addIvar<NativeDarkModeChangeDetectorImpl*> ("owner");
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector")
addMethod (@selector (darkModeChanged:), darkModeChanged);
addMethod (@selector (darkModeChanged:), [] (id self, SEL, NSNotification*)
{
if (auto* owner = getIvar<NativeDarkModeChangeDetectorImpl*> (self, "owner"))
owner->darkModeChanged();
});
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
registerClass();
}
static void darkModeChanged (id self, SEL, NSNotification*)
{
if (auto* owner = getIvar<NativeDarkModeChangeDetectorImpl*> (self, "owner"))
owner->darkModeChanged();
}
};
id delegate = nil;
NSUniquePtr<NSObject> delegate;
Optional<ScopedNotificationCenterObserver> observer;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeDarkModeChangeDetectorImpl)
};

View file

@ -144,12 +144,7 @@ public:
resetTrackingArea (view);
notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver: view
selector: frameChangedSelector
name: NSViewFrameDidChangeNotification
object: view];
scopedObservers.emplace_back (view, frameChangedSelector, NSViewFrameDidChangeNotification, view);
[view setPostsFrameChangedNotifications: YES];
@ -225,25 +220,10 @@ public:
[window setTabbingMode: NSWindowTabbingModeDisallowed];
#endif
[notificationCenter addObserver: view
selector: frameChangedSelector
name: NSWindowDidMoveNotification
object: window];
[notificationCenter addObserver: view
selector: frameChangedSelector
name: NSWindowDidMiniaturizeNotification
object: window];
[notificationCenter addObserver: view
selector: @selector (windowWillMiniaturize:)
name: NSWindowWillMiniaturizeNotification
object: window];
[notificationCenter addObserver: view
selector: @selector (windowDidDeminiaturize:)
name: NSWindowDidDeminiaturizeNotification
object: window];
scopedObservers.emplace_back (view, frameChangedSelector, NSWindowDidMoveNotification, window);
scopedObservers.emplace_back (view, frameChangedSelector, NSWindowDidMiniaturizeNotification, window);
scopedObservers.emplace_back (view, @selector (windowWillMiniaturize:), NSWindowWillMiniaturizeNotification, window);
scopedObservers.emplace_back (view, @selector (windowDidMiniaturize:), NSWindowDidMiniaturizeNotification, window);
}
auto alpha = component.getAlpha();
@ -267,7 +247,8 @@ public:
CVDisplayLinkStop (displayLink);
dispatch_source_cancel (displaySource);
[notificationCenter removeObserver: view];
scopedObservers.clear();
setOwner (view, nullptr);
if ([view superview] != nil)
@ -797,24 +778,7 @@ public:
void redirectWillMoveToWindow (NSWindow* newWindow)
{
if (auto* currentWindow = [view window])
{
[notificationCenter removeObserver: view
name: NSWindowDidMoveNotification
object: currentWindow];
[notificationCenter removeObserver: view
name: NSWindowWillMiniaturizeNotification
object: currentWindow];
[notificationCenter removeObserver: view
name: NSWindowDidBecomeKeyNotification
object: currentWindow];
[notificationCenter removeObserver: view
name: NSWindowDidChangeScreenNotification
object: currentWindow];
}
windowObservers.clear();
if (isSharedWindow && [view window] == window && newWindow == nullptr)
{
@ -1256,30 +1220,11 @@ public:
if (auto* currentWindow = [view window])
{
[notificationCenter addObserver: view
selector: dismissModalsSelector
name: NSWindowWillMoveNotification
object: currentWindow];
[notificationCenter addObserver: view
selector: dismissModalsSelector
name: NSWindowWillMiniaturizeNotification
object: currentWindow];
[notificationCenter addObserver: view
selector: becomeKeySelector
name: NSWindowDidBecomeKeyNotification
object: currentWindow];
[notificationCenter addObserver: view
selector: resignKeySelector
name: NSWindowDidResignKeyNotification
object: currentWindow];
[notificationCenter addObserver: view
selector: @selector (windowDidChangeScreen:)
name: NSWindowDidChangeScreenNotification
object: currentWindow];
windowObservers.emplace_back (view, dismissModalsSelector, NSWindowWillMoveNotification, currentWindow);
windowObservers.emplace_back (view, dismissModalsSelector, NSWindowWillMiniaturizeNotification, currentWindow);
windowObservers.emplace_back (view, becomeKeySelector, NSWindowDidBecomeKeyNotification, currentWindow);
windowObservers.emplace_back (view, resignKeySelector, NSWindowDidResignKeyNotification, currentWindow);
windowObservers.emplace_back (view, @selector (windowDidChangeScreen:), NSWindowDidChangeScreenNotification, currentWindow);
updateCVDisplayLinkScreen();
}
@ -1659,7 +1604,6 @@ public:
bool windowRepresentsFile = false;
bool isAlwaysOnTop = false, wasAlwaysOnTop = false;
String stringBeingComposed;
NSNotificationCenter* notificationCenter = nil;
Rectangle<float> lastSizeBeforeZoom;
RectangleList<float> deferredRepaints;
@ -1892,6 +1836,9 @@ private:
int numFramesToSkipMetalRenderer = 0;
std::unique_ptr<CoreGraphicsMetalLayerRenderer<NSView>> metalRenderer;
std::vector<ScopedNotificationCenterObserver> scopedObservers;
std::vector<ScopedNotificationCenterObserver> windowObservers;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NSViewComponentPeer)
};