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:
parent
fd74f1a39d
commit
9b79610cb0
7 changed files with 28 additions and 42 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -2209,6 +2209,7 @@ public:
|
|||
wheel.deltaY = amount;
|
||||
wheel.isReversed = false;
|
||||
wheel.isSmooth = false;
|
||||
wheel.isInertial = false;
|
||||
|
||||
handleMouseWheel (0, getMousePos (buttonPressEvent), getEventTime (buttonPressEvent), wheel);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue