mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
NSViewComponentPeer: Allow mouse events to reach unfocused windows
This change allows mouse events (including enter and exit events) to reach unfocused views on macOS. This matches the behaviour of unfocused windows on Linux and Windows, where components paint in their "hovered" states even when the application window is in the background. As a byproduct of using tracking areas on macOS, we can remove the fake mouse move generator.
This commit is contained in:
parent
eeeeb117a1
commit
4ca923a34b
9 changed files with 58 additions and 190 deletions
|
|
@ -31,7 +31,6 @@
|
|||
#include "../utility/juce_IncludeSystemHeaders.h"
|
||||
#include "../utility/juce_IncludeModuleHeaders.h"
|
||||
#include "../utility/juce_WindowsHooks.h"
|
||||
#include "../utility/juce_FakeMouseMoveGenerator.h"
|
||||
|
||||
#include <juce_audio_processors/format_types/juce_LegacyAudioParameter.cpp>
|
||||
|
||||
|
|
@ -592,8 +591,6 @@ namespace AAXClasses
|
|||
setBounds (lastValidSize);
|
||||
pluginEditor->addMouseListener (this, true);
|
||||
}
|
||||
|
||||
ignoreUnused (fakeMouseGenerator);
|
||||
}
|
||||
|
||||
~ContentWrapperComponent() override
|
||||
|
|
@ -673,7 +670,6 @@ namespace AAXClasses
|
|||
#if JUCE_WINDOWS
|
||||
WindowsHooks hooks;
|
||||
#endif
|
||||
FakeMouseMoveGenerator fakeMouseGenerator;
|
||||
juce::Rectangle<int> lastValidSize;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ContentWrapperComponent)
|
||||
|
|
|
|||
|
|
@ -81,7 +81,6 @@ JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
|||
#define JUCE_CORE_INCLUDE_OBJC_HELPERS 1
|
||||
|
||||
#include "../utility/juce_IncludeModuleHeaders.h"
|
||||
#include "../utility/juce_FakeMouseMoveGenerator.h"
|
||||
#include "../utility/juce_CarbonVisibility.h"
|
||||
|
||||
#include <juce_audio_basics/native/juce_mac_CoreAudioLayouts.h>
|
||||
|
|
@ -1482,7 +1481,6 @@ public:
|
|||
setWantsKeyboardFocus (true);
|
||||
#endif
|
||||
|
||||
ignoreUnused (fakeMouseGenerator);
|
||||
setBounds (getSizeToContainChild());
|
||||
|
||||
lastBounds = getBounds();
|
||||
|
|
@ -1594,7 +1592,6 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
FakeMouseMoveGenerator fakeMouseGenerator;
|
||||
Rectangle<int> lastBounds;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (EditorCompHolder)
|
||||
|
|
@ -2432,7 +2429,6 @@ private:
|
|||
//==============================================================================
|
||||
AudioProcessor* juceFilter;
|
||||
std::unique_ptr<Component> windowComp;
|
||||
FakeMouseMoveGenerator fakeMouseGenerator;
|
||||
|
||||
void deleteUI()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
#include "../utility/juce_IncludeSystemHeaders.h"
|
||||
#include "../utility/juce_IncludeModuleHeaders.h"
|
||||
#include "../utility/juce_FakeMouseMoveGenerator.h"
|
||||
#include "../utility/juce_WindowsHooks.h"
|
||||
|
||||
#include <juce_audio_devices/juce_audio_devices.h>
|
||||
|
|
|
|||
|
|
@ -103,7 +103,6 @@ JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
|||
|
||||
using namespace juce;
|
||||
|
||||
#include "../utility/juce_FakeMouseMoveGenerator.h"
|
||||
#include "../utility/juce_WindowsHooks.h"
|
||||
#include "../utility/juce_LinuxMessageThread.h"
|
||||
|
||||
|
|
@ -984,7 +983,6 @@ public:
|
|||
#endif
|
||||
|
||||
setOpaque (true);
|
||||
ignoreUnused (fakeMouseGenerator);
|
||||
}
|
||||
|
||||
~EditorCompWrapper() override
|
||||
|
|
@ -1291,7 +1289,6 @@ public:
|
|||
|
||||
//==============================================================================
|
||||
JuceVSTWrapper& wrapper;
|
||||
FakeMouseMoveGenerator fakeMouseGenerator;
|
||||
bool resizingChild = false, resizingParent = false;
|
||||
|
||||
float editorScaleFactor = 1.0f;
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@
|
|||
|
||||
#include "../utility/juce_IncludeSystemHeaders.h"
|
||||
#include "../utility/juce_IncludeModuleHeaders.h"
|
||||
#include "../utility/juce_FakeMouseMoveGenerator.h"
|
||||
#include "../utility/juce_CarbonVisibility.h"
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ JUCE_BEGIN_NO_SANITIZE ("vptr")
|
|||
#include "../utility/juce_IncludeSystemHeaders.h"
|
||||
#include "../utility/juce_IncludeModuleHeaders.h"
|
||||
#include "../utility/juce_WindowsHooks.h"
|
||||
#include "../utility/juce_FakeMouseMoveGenerator.h"
|
||||
#include "../utility/juce_LinuxMessageThread.h"
|
||||
#include <juce_audio_processors/format_types/juce_LegacyAudioParameter.cpp>
|
||||
#include <juce_audio_processors/format_types/juce_VST3Common.h>
|
||||
|
|
@ -1929,8 +1928,6 @@ private:
|
|||
{
|
||||
setOpaque (true);
|
||||
setBroughtToFrontOnMouseClick (true);
|
||||
|
||||
ignoreUnused (fakeMouseGenerator);
|
||||
}
|
||||
|
||||
~ContentWrapperComponent() override
|
||||
|
|
@ -2100,7 +2097,6 @@ private:
|
|||
private:
|
||||
JuceVST3Editor& owner;
|
||||
std::unique_ptr<EditorHostContext> editorHostContext;
|
||||
FakeMouseMoveGenerator fakeMouseGenerator;
|
||||
Rectangle<int> lastBounds;
|
||||
bool resizingChild = false, resizingParent = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,119 +0,0 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN
|
||||
|
||||
#if JUCE_MAC
|
||||
|
||||
//==============================================================================
|
||||
// Helper class to workaround windows not getting mouse-moves...
|
||||
class FakeMouseMoveGenerator : private Timer
|
||||
{
|
||||
public:
|
||||
FakeMouseMoveGenerator()
|
||||
{
|
||||
startTimer (1000 / 30);
|
||||
}
|
||||
|
||||
static bool componentContainsAudioProcessorEditor (Component* comp) noexcept
|
||||
{
|
||||
if (dynamic_cast<AudioProcessorEditor*> (comp) != nullptr)
|
||||
return true;
|
||||
|
||||
for (auto* child : comp->getChildren())
|
||||
if (componentContainsAudioProcessorEditor (child))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void timerCallback() override
|
||||
{
|
||||
// Workaround for windows not getting mouse-moves...
|
||||
auto screenPos = Desktop::getInstance().getMainMouseSource().getScreenPosition();
|
||||
|
||||
if (screenPos != lastScreenPos)
|
||||
{
|
||||
lastScreenPos = screenPos;
|
||||
auto mods = ModifierKeys::currentModifiers;
|
||||
|
||||
if (! mods.isAnyMouseButtonDown())
|
||||
{
|
||||
if (auto* comp = Desktop::getInstance().findComponentAt (screenPos.roundToInt()))
|
||||
{
|
||||
if (componentContainsAudioProcessorEditor (comp->getTopLevelComponent()))
|
||||
{
|
||||
safeOldComponent = comp;
|
||||
|
||||
if (auto* peer = comp->getPeer())
|
||||
{
|
||||
if (! peer->isFocused())
|
||||
{
|
||||
peer->handleMouseEvent (MouseInputSource::InputSourceType::mouse,
|
||||
peer->globalToLocal (Desktop::getInstance().getMainMouseSource().getRawScreenPosition()),
|
||||
mods,
|
||||
MouseInputSource::invalidPressure,
|
||||
MouseInputSource::invalidOrientation,
|
||||
Time::currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (safeOldComponent != nullptr)
|
||||
{
|
||||
if (auto* peer = safeOldComponent->getPeer())
|
||||
{
|
||||
peer->handleMouseEvent (MouseInputSource::InputSourceType::mouse,
|
||||
MouseInputSource::offscreenMousePos,
|
||||
mods,
|
||||
MouseInputSource::invalidPressure,
|
||||
MouseInputSource::invalidOrientation,
|
||||
Time::currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
safeOldComponent = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Point<float> lastScreenPos;
|
||||
WeakReference<Component> safeOldComponent;
|
||||
};
|
||||
|
||||
#else
|
||||
struct FakeMouseMoveGenerator {};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
||||
|
|
@ -301,11 +301,11 @@ struct Component::ComponentHelpers
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
static bool hitTest (Component& comp, Point<int> localPoint)
|
||||
static bool hitTest (Component& comp, Point<float> localPoint)
|
||||
{
|
||||
return isPositiveAndBelow (localPoint.x, comp.getWidth())
|
||||
&& isPositiveAndBelow (localPoint.y, comp.getHeight())
|
||||
&& comp.hitTest (localPoint.x, localPoint.y);
|
||||
const auto intPoint = localPoint.roundToInt();
|
||||
return Rectangle<int> { comp.getWidth(), comp.getHeight() }.toFloat().contains (localPoint)
|
||||
&& comp.hitTest (intPoint.x, intPoint.y);
|
||||
}
|
||||
|
||||
// converts an unscaled position within a peer to the local position within that peer's component
|
||||
|
|
@ -1376,7 +1376,7 @@ bool Component::hitTest (int x, int y)
|
|||
auto& child = *childComponentList.getUnchecked (i);
|
||||
|
||||
if (child.isVisible()
|
||||
&& ComponentHelpers::hitTest (child, ComponentHelpers::convertFromParentSpace (child, Point<int> (x, y))))
|
||||
&& ComponentHelpers::hitTest (child, ComponentHelpers::convertFromParentSpace (child, Point<int> (x, y).toFloat())))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1405,7 +1405,7 @@ bool Component::contains (Point<int> point)
|
|||
|
||||
bool Component::containsInternal (Point<float> point)
|
||||
{
|
||||
if (ComponentHelpers::hitTest (*this, point.roundToInt()))
|
||||
if (ComponentHelpers::hitTest (*this, point))
|
||||
{
|
||||
if (parentComponent != nullptr)
|
||||
return parentComponent->containsInternal (ComponentHelpers::convertToParentSpace (*this, point));
|
||||
|
|
@ -1441,7 +1441,7 @@ Component* Component::getComponentAt (Point<int> position)
|
|||
|
||||
Component* Component::getComponentAtInternal (Point<float> position)
|
||||
{
|
||||
if (flags.visibleFlag && ComponentHelpers::hitTest (*this, position.roundToInt()))
|
||||
if (flags.visibleFlag && ComponentHelpers::hitTest (*this, position))
|
||||
{
|
||||
for (int i = childComponentList.size(); --i >= 0;)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -61,6 +61,16 @@ public:
|
|||
|
||||
[view registerForDraggedTypes: getSupportedDragTypes()];
|
||||
|
||||
const auto options = NSTrackingMouseEnteredAndExited
|
||||
| NSTrackingMouseMoved
|
||||
| NSTrackingEnabledDuringMouseDrag
|
||||
| NSTrackingActiveAlways
|
||||
| NSTrackingInVisibleRect;
|
||||
[view addTrackingArea: [[NSTrackingArea alloc] initWithRect: r
|
||||
options: options
|
||||
owner: view
|
||||
userInfo: nil]];
|
||||
|
||||
notificationCenter = [NSNotificationCenter defaultCenter];
|
||||
|
||||
[notificationCenter addObserver: view
|
||||
|
|
@ -118,7 +128,6 @@ public:
|
|||
setAlwaysOnTop (true);
|
||||
|
||||
[window setContentView: view];
|
||||
[window setAcceptsMouseMovedEvents: YES];
|
||||
|
||||
// We'll both retain and also release this on closing because plugin hosts can unexpectedly
|
||||
// close the window for us, and also tend to get cause trouble if setReleasedWhenClosed is NO.
|
||||
|
|
@ -392,7 +401,7 @@ public:
|
|||
NSRect viewFrame = [view frame];
|
||||
|
||||
if (! (isPositiveAndBelow (localPos.getX(), viewFrame.size.width)
|
||||
&& isPositiveAndBelow (localPos.getY(), viewFrame.size.height)))
|
||||
&& isPositiveAndBelow (localPos.getY(), viewFrame.size.height)))
|
||||
return false;
|
||||
|
||||
if (! SystemStats::isRunningInAppExtensionSandbox())
|
||||
|
|
@ -630,21 +639,12 @@ public:
|
|||
|
||||
void redirectMouseEnter (NSEvent* ev)
|
||||
{
|
||||
if (shouldIgnoreMouseEnterExit (ev))
|
||||
return;
|
||||
|
||||
Desktop::getInstance().getMainMouseSource().forceMouseCursorUpdate();
|
||||
ModifierKeys::currentModifiers = ModifierKeys::currentModifiers.withoutMouseButtons();
|
||||
sendMouseEvent (ev);
|
||||
sendMouseEnterExit (ev);
|
||||
}
|
||||
|
||||
void redirectMouseExit (NSEvent* ev)
|
||||
{
|
||||
if (shouldIgnoreMouseEnterExit (ev))
|
||||
return;
|
||||
|
||||
ModifierKeys::currentModifiers = ModifierKeys::currentModifiers.withoutMouseButtons();
|
||||
sendMouseEvent (ev);
|
||||
sendMouseEnterExit (ev);
|
||||
}
|
||||
|
||||
static float checkDeviceDeltaReturnValue (float v) noexcept
|
||||
|
|
@ -906,11 +906,11 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
drawRect (cg, r, displayScale);
|
||||
drawRectWithContext (cg, r, displayScale);
|
||||
invalidateTransparentWindowShadow();
|
||||
}
|
||||
|
||||
void drawRect (CGContextRef cg, NSRect r, float displayScale)
|
||||
void drawRectWithContext (CGContextRef cg, NSRect r, float displayScale)
|
||||
{
|
||||
#if USE_COREGRAPHICS_RENDERING
|
||||
if (usingCoreGraphics)
|
||||
|
|
@ -1531,10 +1531,13 @@ private:
|
|||
static NSView* createViewInstance();
|
||||
static NSWindow* createWindowInstance();
|
||||
|
||||
bool shouldIgnoreMouseEnterExit (NSEvent* ev) const
|
||||
void sendMouseEnterExit (NSEvent* ev)
|
||||
{
|
||||
auto* eventTrackingArea = [ev trackingArea];
|
||||
return eventTrackingArea != nil && ! [[view trackingAreas] containsObject: eventTrackingArea];
|
||||
if (auto* area = [ev trackingArea])
|
||||
if (! [[view trackingAreas] containsObject: area])
|
||||
return;
|
||||
|
||||
sendMouseEvent (ev);
|
||||
}
|
||||
|
||||
static void setOwner (id viewOrWindow, NSViewComponentPeer* newOwner)
|
||||
|
|
@ -1851,30 +1854,30 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
static void asyncMouseDown (id self, SEL, NSEvent* ev) { if (auto* p = getOwner (self)) p->redirectMouseDown (ev); }
|
||||
static void asyncMouseUp (id self, SEL, NSEvent* ev) { if (auto* p = getOwner (self)) p->redirectMouseUp (ev); }
|
||||
static void mouseDragged (id self, SEL, NSEvent* ev) { if (auto* p = getOwner (self)) p->redirectMouseDrag (ev); }
|
||||
static void mouseMoved (id self, SEL, NSEvent* ev) { if (auto* p = getOwner (self)) p->redirectMouseMove (ev); }
|
||||
static void mouseEntered (id self, SEL, NSEvent* ev) { if (auto* p = getOwner (self)) p->redirectMouseEnter (ev); }
|
||||
static void mouseExited (id self, SEL, NSEvent* ev) { if (auto* p = getOwner (self)) p->redirectMouseExit (ev); }
|
||||
static void scrollWheel (id self, SEL, NSEvent* ev) { if (auto* p = getOwner (self)) p->redirectMouseWheel (ev); }
|
||||
static void magnify (id self, SEL, NSEvent* ev) { if (auto* p = getOwner (self)) p->redirectMagnify (ev); }
|
||||
static void copy (id self, SEL, NSObject* s) { if (auto* p = getOwner (self)) p->redirectCopy (s); }
|
||||
static void paste (id self, SEL, NSObject* s) { if (auto* p = getOwner (self)) p->redirectPaste (s); }
|
||||
static void cut (id self, SEL, NSObject* s) { if (auto* p = getOwner (self)) p->redirectCut (s); }
|
||||
static void selectAll (id self, SEL, NSObject* s) { if (auto* p = getOwner (self)) p->redirectSelectAll (s); }
|
||||
static void willMoveToWindow (id self, SEL, NSWindow* w) { if (auto* p = getOwner (self)) p->redirectWillMoveToWindow (w); }
|
||||
static void asyncMouseDown (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMouseDown, ev); }
|
||||
static void asyncMouseUp (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMouseUp, ev); }
|
||||
static void mouseDragged (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMouseDrag, ev); }
|
||||
static void mouseMoved (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMouseMove, ev); }
|
||||
static void mouseEntered (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMouseEnter, ev); }
|
||||
static void mouseExited (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMouseExit, ev); }
|
||||
static void scrollWheel (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMouseWheel, ev); }
|
||||
static void magnify (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMagnify, ev); }
|
||||
static void copy (id self, SEL, NSObject* s) { callOnOwner (self, &NSViewComponentPeer::redirectCopy, s); }
|
||||
static void paste (id self, SEL, NSObject* s) { callOnOwner (self, &NSViewComponentPeer::redirectPaste, s); }
|
||||
static void cut (id self, SEL, NSObject* s) { callOnOwner (self, &NSViewComponentPeer::redirectCut, s); }
|
||||
static void selectAll (id self, SEL, NSObject* s) { callOnOwner (self, &NSViewComponentPeer::redirectSelectAll, s); }
|
||||
static void willMoveToWindow (id self, SEL, NSWindow* w) { callOnOwner (self, &NSViewComponentPeer::redirectWillMoveToWindow, w); }
|
||||
|
||||
static BOOL acceptsFirstMouse (id, SEL, NSEvent*) { return YES; }
|
||||
static BOOL wantsDefaultClipping (id, SEL) { return YES; } // (this is the default, but may want to customise it in future)
|
||||
static BOOL worksWhenModal (id self, SEL) { if (auto* p = getOwner (self)) return p->worksWhenModal(); return NO; }
|
||||
|
||||
static void drawRect (id self, SEL, NSRect r) { if (auto* p = getOwner (self)) p->drawRect (r); }
|
||||
static void frameChanged (id self, SEL, NSNotification*) { if (auto* p = getOwner (self)) p->redirectMovedOrResized(); }
|
||||
static void viewDidMoveToWindow (id self, SEL) { if (auto* p = getOwner (self)) p->viewMovedToWindow(); }
|
||||
static void dismissModals (id self, SEL) { if (auto* p = getOwner (self)) p->dismissModals(); }
|
||||
static void becomeKey (id self, SEL) { if (auto* p = getOwner (self)) p->becomeKey(); }
|
||||
static void resignKey (id self, SEL) { if (auto* p = getOwner (self)) p->resignKey(); }
|
||||
static void drawRect (id self, SEL, NSRect r) { callOnOwner (self, &NSViewComponentPeer::drawRect, r); }
|
||||
static void frameChanged (id self, SEL, NSNotification*) { callOnOwner (self, &NSViewComponentPeer::redirectMovedOrResized); }
|
||||
static void viewDidMoveToWindow (id self, SEL) { callOnOwner (self, &NSViewComponentPeer::viewMovedToWindow); }
|
||||
static void dismissModals (id self, SEL) { callOnOwner (self, &NSViewComponentPeer::dismissModals); }
|
||||
static void becomeKey (id self, SEL) { callOnOwner (self, &NSViewComponentPeer::becomeKey); }
|
||||
static void resignKey (id self, SEL) { callOnOwner (self, &NSViewComponentPeer::resignKey); }
|
||||
|
||||
static BOOL isFlipped (id, SEL) { return true; }
|
||||
|
||||
|
|
@ -2075,23 +2078,18 @@ private:
|
|||
//==============================================================================
|
||||
static void flagsChanged (id self, SEL, NSEvent* ev)
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
owner->redirectModKeyChange (ev);
|
||||
callOnOwner (self, &NSViewComponentPeer::redirectModKeyChange, ev);
|
||||
}
|
||||
|
||||
static BOOL becomeFirstResponder (id self, SEL)
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
owner->viewFocusGain();
|
||||
|
||||
callOnOwner (self, &NSViewComponentPeer::viewFocusGain);
|
||||
return YES;
|
||||
}
|
||||
|
||||
static BOOL resignFirstResponder (id self, SEL)
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
owner->viewFocusLoss();
|
||||
|
||||
callOnOwner (self, &NSViewComponentPeer::viewFocusLoss);
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
|
@ -2123,8 +2121,7 @@ private:
|
|||
|
||||
static void draggingExited (id self, SEL, id<NSDraggingInfo> sender)
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
owner->sendDragCallback (1, sender);
|
||||
callOnOwner (self, &NSViewComponentPeer::sendDragCallback, 1, sender);
|
||||
}
|
||||
|
||||
static BOOL prepareForDragOperation (id, SEL, id<NSDraggingInfo>)
|
||||
|
|
@ -2201,6 +2198,13 @@ private:
|
|||
|
||||
return sendSuperclassMessage<BOOL> (self, s, event);
|
||||
}
|
||||
|
||||
template <typename Func, typename... Args>
|
||||
static void callOnOwner (id self, Func&& func, Args&&... args)
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
(owner->*func) (std::forward<Args> (args)...);
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue