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

Added a flag MouseWheelEvent::isInertial (currently only implemented for OSX 10.7 or later), and used this to replace some clunky behaviour in the Viewport class that was there to avoid inertial wheel movements triggering nested scrollable components.

This commit is contained in:
jules 2015-06-22 20:28:15 +01:00
parent fd74f1a39d
commit 9b79610cb0
7 changed files with 28 additions and 42 deletions

View file

@ -24,13 +24,13 @@
Viewport::Viewport (const String& name)
: Component (name),
customScrollBarThickness(false),
scrollBarThickness (0),
singleStepX (16),
singleStepY (16),
showHScrollbar (true),
showVScrollbar (true),
deleteContent (true),
customScrollBarThickness (false),
allowScrollingWithoutScrollbarV (false),
allowScrollingWithoutScrollbarH (false),
verticalScrollBar (true),
@ -55,7 +55,6 @@ Viewport::Viewport (const String& name)
Viewport::~Viewport()
{
deleteContentComp();
mouseWheelTimer = nullptr;
}
//==============================================================================
@ -382,30 +381,6 @@ static int rescaleMouseWheelDistance (float distance, int singleStepSize) noexce
: jmax (distance, 1.0f));
}
// This puts a temporary component overlay over the content component, to prevent
// wheel events from reaching components inside it, so that while spinning a wheel
// with momentum, it won't accidentally scroll any subcomponents of the viewport.
struct Viewport::MouseWheelTimer : public Timer
{
MouseWheelTimer (Viewport& v) : viewport (v)
{
viewport.contentHolder.addAndMakeVisible (dummyOverlay);
dummyOverlay.setAlwaysOnTop (true);
dummyOverlay.setPaintingIsUnclipped (true);
dummyOverlay.setBounds (viewport.contentHolder.getLocalBounds());
}
void timerCallback() override
{
viewport.mouseWheelTimer = nullptr;
}
Component dummyOverlay;
Viewport& viewport;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MouseWheelTimer)
};
bool Viewport::useMouseWheelMoveIfNeeded (const MouseEvent& e, const MouseWheelDetails& wheel)
{
if (! (e.mods.isAltDown() || e.mods.isCtrlDown() || e.mods.isCommandDown()))
@ -436,11 +411,6 @@ bool Viewport::useMouseWheelMoveIfNeeded (const MouseEvent& e, const MouseWheelD
if (pos != getViewPosition())
{
if (mouseWheelTimer == nullptr)
mouseWheelTimer = new MouseWheelTimer (*this);
mouseWheelTimer->startTimer (300);
setViewPosition (pos);
return true;
}

View file

@ -263,15 +263,13 @@ private:
//==============================================================================
WeakReference<Component> contentComp;
Rectangle<int> lastVisibleArea;
bool customScrollBarThickness;
int scrollBarThickness;
int singleStepX, singleStepY;
bool showHScrollbar, showVScrollbar, deleteContent;
bool customScrollBarThickness;
bool allowScrollingWithoutScrollbarV, allowScrollingWithoutScrollbarH;
Component contentHolder;
ScrollBar verticalScrollBar, horizontalScrollBar;
struct MouseWheelTimer;
ScopedPointer<Timer> mouseWheelTimer;
Point<int> viewportPosToCompPos (Point<int>) const;

View file

@ -354,6 +354,10 @@ struct MouseWheelDetails
/** If true, then the wheel has continuous, un-stepped motion. */
bool isSmooth;
/** If true, then this event is part of the intertial momentum phase that follows
the wheel being released. */
bool isInertial;
};

View file

@ -331,10 +331,17 @@ public:
Time time, const MouseWheelDetails& wheel)
{
Desktop::getInstance().incrementMouseWheelCounter();
Point<float> screenPos;
if (Component* current = getTargetForGesture (peer, positionWithinPeer, time, screenPos))
sendMouseWheel (*current, screenPos, time, wheel);
// This will make sure that when the wheel spins in its inertial phase, any events
// continue to be sent to the last component that the mouse was over when it was being
// actively controlled by the user. This avoids confusion when scrolling through nested
// scrollable components.
if (lastNonInertialWheelTarget == nullptr || ! wheel.isInertial)
lastNonInertialWheelTarget = getTargetForGesture (peer, positionWithinPeer, time, screenPos);
if (Component* target = lastNonInertialWheelTarget)
sendMouseWheel (*target, screenPos, time, wheel);
}
void handleMagnifyGesture (ComponentPeer& peer, Point<float> positionWithinPeer,
@ -467,7 +474,7 @@ public:
bool isUnboundedMouseModeOn, isCursorVisibleUntilOffscreen;
private:
WeakReference<Component> componentUnderMouse;
WeakReference<Component> componentUnderMouse, lastNonInertialWheelTarget;
ComponentPeer* lastPeer;
void* currentCursorHandle;
@ -512,6 +519,7 @@ private:
mouseDowns[0].peerID = 0;
mouseMovedSignificantlySincePressed = false;
lastNonInertialWheelTarget = nullptr;
}
void registerMouseDrag (Point<float> screenPos) noexcept

View file

@ -2209,6 +2209,7 @@ public:
wheel.deltaY = amount;
wheel.isReversed = false;
wheel.isSmooth = false;
wheel.isInertial = false;
handleMouseWheel (0, getMousePos (buttonPressEvent), getEventTime (buttonPressEvent), wheel);
}

View file

@ -497,10 +497,7 @@ public:
void toBehind (ComponentPeer* other) override
{
NSViewComponentPeer* const otherPeer = dynamic_cast<NSViewComponentPeer*> (other);
jassert (otherPeer != nullptr); // wrong type of window?
if (otherPeer != nullptr)
if (NSViewComponentPeer* const otherPeer = dynamic_cast<NSViewComponentPeer*> (other))
{
if (isSharedWindow)
{
@ -514,6 +511,10 @@ public:
relativeTo: [otherPeer->window windowNumber]];
}
}
else
{
jassertfalse; // wrong type of window?
}
}
void setIcon (const Image&) override
@ -620,6 +621,7 @@ public:
wheel.deltaY = 0;
wheel.isReversed = false;
wheel.isSmooth = false;
wheel.isInertial = false;
#if ! JUCE_PPC
@try
@ -628,6 +630,8 @@ public:
if ([ev respondsToSelector: @selector (isDirectionInvertedFromDevice)])
wheel.isReversed = [ev isDirectionInvertedFromDevice];
wheel.isInertial = ([ev momentumPhase] != NSEventPhaseNone);
if ([ev respondsToSelector: @selector (hasPreciseScrollingDeltas)])
{
if ([ev hasPreciseScrollingDeltas])

View file

@ -1820,6 +1820,7 @@ private:
wheel.deltaY = isVertical ? amount / 256.0f : 0.0f;
wheel.isReversed = false;
wheel.isSmooth = false;
wheel.isInertial = false;
Point<float> localPos;
if (ComponentPeer* const peer = findPeerUnderMouse (localPos))