diff --git a/modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp b/modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp index 59f67554d5..edc383f5ff 100644 --- a/modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp +++ b/modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp @@ -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 @@ -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 lastValidSize; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ContentWrapperComponent) diff --git a/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm b/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm index c35d55a07a..23d9bd5c51 100644 --- a/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm +++ b/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm @@ -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 @@ -1482,7 +1481,6 @@ public: setWantsKeyboardFocus (true); #endif - ignoreUnused (fakeMouseGenerator); setBounds (getSizeToContainChild()); lastBounds = getBounds(); @@ -1594,7 +1592,6 @@ public: } private: - FakeMouseMoveGenerator fakeMouseGenerator; Rectangle lastBounds; JUCE_DECLARE_NON_COPYABLE (EditorCompHolder) @@ -2432,7 +2429,6 @@ private: //============================================================================== AudioProcessor* juceFilter; std::unique_ptr windowComp; - FakeMouseMoveGenerator fakeMouseGenerator; void deleteUI() { diff --git a/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterApp.cpp b/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterApp.cpp index 04b416b621..8d65094b56 100644 --- a/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterApp.cpp +++ b/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterApp.cpp @@ -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 diff --git a/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp b/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp index d0b42aed28..82bae5249d 100644 --- a/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp +++ b/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp @@ -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; diff --git a/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.mm b/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.mm index 92944250a3..d943e8be42 100644 --- a/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.mm +++ b/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.mm @@ -35,7 +35,6 @@ #include "../utility/juce_IncludeSystemHeaders.h" #include "../utility/juce_IncludeModuleHeaders.h" -#include "../utility/juce_FakeMouseMoveGenerator.h" #include "../utility/juce_CarbonVisibility.h" //============================================================================== diff --git a/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp b/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp index 89ccf074f1..8853bdd14f 100644 --- a/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp +++ b/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp @@ -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 #include @@ -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; - FakeMouseMoveGenerator fakeMouseGenerator; Rectangle lastBounds; bool resizingChild = false, resizingParent = false; diff --git a/modules/juce_audio_plugin_client/utility/juce_FakeMouseMoveGenerator.h b/modules/juce_audio_plugin_client/utility/juce_FakeMouseMoveGenerator.h deleted file mode 100644 index 789cff55ae..0000000000 --- a/modules/juce_audio_plugin_client/utility/juce_FakeMouseMoveGenerator.h +++ /dev/null @@ -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 (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 lastScreenPos; - WeakReference safeOldComponent; -}; - -#else -struct FakeMouseMoveGenerator {}; -#endif - -#endif - -} // namespace juce diff --git a/modules/juce_gui_basics/components/juce_Component.cpp b/modules/juce_gui_basics/components/juce_Component.cpp index 7136d49e8f..adf76bd077 100644 --- a/modules/juce_gui_basics/components/juce_Component.cpp +++ b/modules/juce_gui_basics/components/juce_Component.cpp @@ -301,11 +301,11 @@ struct Component::ComponentHelpers } //============================================================================== - static bool hitTest (Component& comp, Point localPoint) + static bool hitTest (Component& comp, Point 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 { 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 (x, y)))) + && ComponentHelpers::hitTest (child, ComponentHelpers::convertFromParentSpace (child, Point (x, y).toFloat()))) return true; } } @@ -1405,7 +1405,7 @@ bool Component::contains (Point point) bool Component::containsInternal (Point 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 position) Component* Component::getComponentAtInternal (Point position) { - if (flags.visibleFlag && ComponentHelpers::hitTest (*this, position.roundToInt())) + if (flags.visibleFlag && ComponentHelpers::hitTest (*this, position)) { for (int i = childComponentList.size(); --i >= 0;) { diff --git a/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm b/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm index 654d4f6b18..ca591f0352 100644 --- a/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm +++ b/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm @@ -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 sender) { - if (auto* owner = getOwner (self)) - owner->sendDragCallback (1, sender); + callOnOwner (self, &NSViewComponentPeer::sendDragCallback, 1, sender); } static BOOL prepareForDragOperation (id, SEL, id) @@ -2201,6 +2198,13 @@ private: return sendSuperclassMessage (self, s, event); } + + template + static void callOnOwner (id self, Func&& func, Args&&... args) + { + if (auto* owner = getOwner (self)) + (owner->*func) (std::forward (args)...); + } }; //==============================================================================