Browse Source

Added MouseInputSource::isUnboundedMouseMovementEnabled(). Tweaks to mouse cursor snap-back in Sliders.

tags/2021-05-28
jules 12 years ago
parent
commit
7bf1da5e17
7 changed files with 57 additions and 58 deletions
  1. +3
    -5
      modules/juce_core/native/juce_win32_Threads.cpp
  2. +4
    -7
      modules/juce_core/threads/juce_ReadWriteLock.h
  3. +1
    -1
      modules/juce_gui_basics/keyboard/juce_ModifierKeys.h
  4. +1
    -1
      modules/juce_gui_basics/mouse/juce_ComponentDragger.cpp
  5. +7
    -4
      modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp
  6. +3
    -0
      modules/juce_gui_basics/mouse/juce_MouseInputSource.h
  7. +38
    -40
      modules/juce_gui_basics/widgets/juce_Slider.cpp

+ 3
- 5
modules/juce_core/native/juce_win32_Threads.cpp View File

@@ -210,17 +210,15 @@ static SleepEvent sleepEvent;
void JUCE_CALLTYPE Thread::sleep (const int millisecs) void JUCE_CALLTYPE Thread::sleep (const int millisecs)
{ {
jassert (millisecs >= 0);
if (millisecs >= 10 || sleepEvent.handle == 0) if (millisecs >= 10 || sleepEvent.handle == 0)
{
Sleep ((DWORD) millisecs); Sleep ((DWORD) millisecs);
}
else else
{
// unlike Sleep() this is guaranteed to return to the current thread after // unlike Sleep() this is guaranteed to return to the current thread after
// the time expires, so we'll use this for short waits, which are more likely // the time expires, so we'll use this for short waits, which are more likely
// to need to be accurate // to need to be accurate
WaitForSingleObject (sleepEvent.handle, (DWORD) millisecs); WaitForSingleObject (sleepEvent.handle, (DWORD) millisecs);
}
} }
void Thread::yield() void Thread::yield()
@@ -231,7 +229,7 @@ void Thread::yield()
//============================================================================== //==============================================================================
static int lastProcessPriority = -1; static int lastProcessPriority = -1;
// called by WindowDriver because Windows does weird things to process priority
// called when the app gains focus because Windows does weird things to process priority
// when you swap apps, and this forces an update when the app is brought to the front. // when you swap apps, and this forces an update when the app is brought to the front.
void juce_repeatLastProcessPriority() void juce_repeatLastProcessPriority()
{ {


+ 4
- 7
modules/juce_core/threads/juce_ReadWriteLock.h View File

@@ -59,18 +59,15 @@ public:
ReadWriteLock() noexcept; ReadWriteLock() noexcept;
/** Destructor. /** Destructor.
If the object is deleted whilst locked, any subsequent behaviour
is unpredictable.
If the object is deleted whilst locked, any subsequent behaviour is undefined.
*/ */
~ReadWriteLock() noexcept; ~ReadWriteLock() noexcept;
//============================================================================== //==============================================================================
/** Locks this object for reading. /** Locks this object for reading.
Multiple threads can simulaneously lock the object for reading, but if another
thread has it locked for writing, then this will block until it releases the
lock.
Multiple threads can simultaneously lock the object for reading, but if another
thread has it locked for writing, then this will block until it releases the lock.
@see exitRead, ScopedReadLock @see exitRead, ScopedReadLock
*/ */
@@ -78,7 +75,7 @@ public:
/** Tries to lock this object for reading. /** Tries to lock this object for reading.
Multiple threads can simulaneously lock the object for reading, but if another
Multiple threads can simultaneously lock the object for reading, but if another
thread has it locked for writing, then this will fail and return false. thread has it locked for writing, then this will fail and return false.
@returns true if the lock is successfully gained. @returns true if the lock is successfully gained.


+ 1
- 1
modules/juce_gui_basics/keyboard/juce_ModifierKeys.h View File

@@ -177,7 +177,7 @@ public:
ModifierKeys withFlags (int rawFlagsToSet) const noexcept { return ModifierKeys (flags | rawFlagsToSet); } ModifierKeys withFlags (int rawFlagsToSet) const noexcept { return ModifierKeys (flags | rawFlagsToSet); }
/** Tests a combination of flags and returns true if any of them are set. */ /** Tests a combination of flags and returns true if any of them are set. */
bool testFlags (const int flagsToTest) const noexcept { return (flags & flagsToTest) != 0; }
bool testFlags (int flagsToTest) const noexcept { return (flags & flagsToTest) != 0; }
/** Returns the total number of mouse buttons that are down. */ /** Returns the total number of mouse buttons that are down. */
int getNumMouseButtonsDown() const noexcept; int getNumMouseButtonsDown() const noexcept;


+ 1
- 1
modules/juce_gui_basics/mouse/juce_ComponentDragger.cpp View File

@@ -49,7 +49,7 @@ void ComponentDragger::dragComponent (Component* const componentToDrag, const Mo
// so their coordinates become wrong after the first one moves the window, so in that case, we'll use // so their coordinates become wrong after the first one moves the window, so in that case, we'll use
// the current mouse position instead of the one that the event contains... // the current mouse position instead of the one that the event contains...
if (componentToDrag->isOnDesktop()) if (componentToDrag->isOnDesktop())
bounds += componentToDrag->getMouseXYRelative() - mouseDownWithinTarget;
bounds += componentToDrag->getLocalPoint (nullptr, e.source.getScreenPosition()) - mouseDownWithinTarget;
else else
bounds += e.getEventRelativeTo (componentToDrag).getPosition() - mouseDownWithinTarget; bounds += e.getEventRelativeTo (componentToDrag).getPosition() - mouseDownWithinTarget;


+ 7
- 4
modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp View File

@@ -27,8 +27,9 @@ class MouseInputSourceInternal : private AsyncUpdater
public: public:
//============================================================================== //==============================================================================
MouseInputSourceInternal (const int i, const bool isMouse) MouseInputSourceInternal (const int i, const bool isMouse)
: index (i), isMouseDevice (isMouse), lastPeer (nullptr),
isUnboundedMouseModeOn (false), isCursorVisibleUntilOffscreen (false), currentCursorHandle (nullptr),
: index (i), isMouseDevice (isMouse),
isUnboundedMouseModeOn (false), isCursorVisibleUntilOffscreen (false),
lastPeer (nullptr), currentCursorHandle (nullptr),
mouseEventCounter (0), mouseMovedSignificantlySincePressed (false) mouseEventCounter (0), mouseMovedSignificantlySincePressed (false)
{ {
} }
@@ -463,12 +464,13 @@ public:
Point<int> lastScreenPos; Point<int> lastScreenPos;
ModifierKeys buttonState; ModifierKeys buttonState;
Point<int> unboundedMouseOffset;
bool isUnboundedMouseModeOn, isCursorVisibleUntilOffscreen;
private: private:
WeakReference<Component> componentUnderMouse; WeakReference<Component> componentUnderMouse;
ComponentPeer* lastPeer; ComponentPeer* lastPeer;
Point<int> unboundedMouseOffset;
bool isUnboundedMouseModeOn, isCursorVisibleUntilOffscreen;
void* currentCursorHandle; void* currentCursorHandle;
int mouseEventCounter; int mouseEventCounter;
@@ -550,6 +552,7 @@ bool MouseInputSource::hasMouseMovedSignificantlySincePressed() const noexcept
bool MouseInputSource::canDoUnboundedMovement() const noexcept { return isMouse(); } bool MouseInputSource::canDoUnboundedMovement() const noexcept { return isMouse(); }
void MouseInputSource::enableUnboundedMouseMovement (bool isEnabled, bool keepCursorVisibleUntilOffscreen) const void MouseInputSource::enableUnboundedMouseMovement (bool isEnabled, bool keepCursorVisibleUntilOffscreen) const
{ pimpl->enableUnboundedMouseMovement (isEnabled, keepCursorVisibleUntilOffscreen); } { pimpl->enableUnboundedMouseMovement (isEnabled, keepCursorVisibleUntilOffscreen); }
bool MouseInputSource::isUnboundedMouseMovementEnabled() const { return pimpl->isUnboundedMouseModeOn; }
bool MouseInputSource::hasMouseCursor() const noexcept { return isMouse(); } bool MouseInputSource::hasMouseCursor() const noexcept { return isMouse(); }
void MouseInputSource::showMouseCursor (const MouseCursor& cursor) { pimpl->showMouseCursor (cursor, false); } void MouseInputSource::showMouseCursor (const MouseCursor& cursor) { pimpl->showMouseCursor (cursor, false); }
void MouseInputSource::hideCursor() { pimpl->hideCursor(); } void MouseInputSource::hideCursor() { pimpl->hideCursor(); }


+ 3
- 0
modules/juce_gui_basics/mouse/juce_MouseInputSource.h View File

@@ -158,6 +158,9 @@ public:
*/ */
void enableUnboundedMouseMovement (bool isEnabled, bool keepCursorVisibleUntilOffscreen = false) const; void enableUnboundedMouseMovement (bool isEnabled, bool keepCursorVisibleUntilOffscreen = false) const;
/** Returns true if this source is currently in "unbounded" mode. */
bool isUnboundedMouseMovementEnabled() const;
/** Attempts to set this mouse pointer's screen position. */ /** Attempts to set this mouse pointer's screen position. */
void setScreenPosition (Point<int> newPosition); void setScreenPosition (Point<int> newPosition);


+ 38
- 40
modules/juce_gui_basics/widgets/juce_Slider.cpp View File

@@ -818,13 +818,11 @@ public:
valueWhenLastDragged = owner.proportionOfLengthToValue (jlimit (0.0, 1.0, currentPos + speed)); valueWhenLastDragged = owner.proportionOfLengthToValue (jlimit (0.0, 1.0, currentPos + speed));
e.source.enableUnboundedMouseMovement (true, false); e.source.enableUnboundedMouseMovement (true, false);
mouseWasHidden = true;
} }
} }
void mouseDown (const MouseEvent& e) void mouseDown (const MouseEvent& e)
{ {
mouseWasHidden = false;
incDecDragged = false; incDecDragged = false;
useDragEvents = false; useDragEvents = false;
mouseDragStartPos = mousePosWhenLastDragged = e.getPosition(); mouseDragStartPos = mousePosWhenLastDragged = e.getPosition();
@@ -880,9 +878,9 @@ public:
void mouseDrag (const MouseEvent& e) void mouseDrag (const MouseEvent& e)
{ {
if (useDragEvents
&& maximum > minimum
&& ! ((style == LinearBar || style == LinearBarVertical) && e.mouseWasClicked() && valueBox != nullptr && valueBox->isEditable()))
if (useDragEvents && maximum > minimum
&& ! ((style == LinearBar || style == LinearBarVertical)
&& e.mouseWasClicked() && valueBox != nullptr && valueBox->isEditable()))
{ {
if (style == Rotary) if (style == Rotary)
{ {
@@ -899,10 +897,7 @@ public:
mouseDragStartPos = e.getPosition(); mouseDragStartPos = e.getPosition();
} }
if (isVelocityBased == (userKeyOverridesVelocity && e.mods.testFlags (ModifierKeys::ctrlModifier
| ModifierKeys::commandModifier
| ModifierKeys::altModifier))
|| (maximum - minimum) / sliderRegionSize < interval)
if (isAbsoluteDragMode (e.mods) || (maximum - minimum) / sliderRegionSize < interval)
handleAbsoluteDrag (e); handleAbsoluteDrag (e);
else else
handleVelocityDrag (e); handleVelocityDrag (e);
@@ -1019,50 +1014,54 @@ public:
void modifierKeysChanged (const ModifierKeys& modifiers) void modifierKeysChanged (const ModifierKeys& modifiers)
{ {
if (style != IncDecButtons
&& style != Rotary
&& isVelocityBased == modifiers.isAnyModifierKeyDown())
{
if (style != IncDecButtons && style != Rotary && isAbsoluteDragMode (modifiers))
restoreMouseIfHidden(); restoreMouseIfHidden();
}
}
bool isAbsoluteDragMode (ModifierKeys mods) const
{
return isVelocityBased == (userKeyOverridesVelocity
&& mods.testFlags (ModifierKeys::ctrlAltCommandModifiers));
} }
void restoreMouseIfHidden() void restoreMouseIfHidden()
{ {
if (mouseWasHidden)
const Array<MouseInputSource>& mouseSources = Desktop::getInstance().getMouseSources();
for (MouseInputSource* mi = mouseSources.begin(), * const e = mouseSources.end(); mi != e; ++mi)
{ {
mouseWasHidden = false;
if (mi->isUnboundedMouseMovementEnabled())
{
mi->enableUnboundedMouseMovement (false);
const Array<MouseInputSource>& mouseSources = Desktop::getInstance().getMouseSources();
const double pos = sliderBeingDragged == 2 ? getMaxValue()
: (sliderBeingDragged == 1 ? getMinValue()
: (double) currentValue.getValue());
Point<int> mousePos;
for (MouseInputSource* mi = mouseSources.begin(), * const e = mouseSources.end(); mi != e; ++mi)
mi->enableUnboundedMouseMovement (false);
if (isRotary())
{
mousePos = mi->getLastMouseDownPosition();
const double pos = sliderBeingDragged == 2 ? getMaxValue()
: (sliderBeingDragged == 1 ? getMinValue()
: (double) currentValue.getValue());
Point<int> mousePos;
const int delta = roundToInt (pixelsForFullDragExtent * (owner.valueToProportionOfLength (valueOnMouseDown)
- owner.valueToProportionOfLength (pos)));
if (isRotary())
{
mousePos = Desktop::getLastMouseDownPosition();
if (style == RotaryHorizontalDrag) mousePos += Point<int> (-delta, 0);
else if (style == RotaryVerticalDrag) mousePos += Point<int> (0, delta);
else mousePos += Point<int> (delta / -2, delta / 2);
const int delta = roundToInt (pixelsForFullDragExtent * (owner.valueToProportionOfLength (valueOnMouseDown)
- owner.valueToProportionOfLength (pos)));
mousePos = owner.getScreenBounds().getConstrainedPoint (mousePos);
}
else
{
const int pixelPos = (int) getLinearSliderPos (pos);
if (style == RotaryHorizontalDrag) mousePos += Point<int> (-delta, 0);
else if (style == RotaryVerticalDrag) mousePos += Point<int> (0, delta);
else mousePos += Point<int> (delta / -2, delta / 2);
}
else
{
const int pixelPos = (int) getLinearSliderPos (pos);
mousePos = owner.localPointToGlobal (Point<int> (isHorizontal() ? pixelPos : (owner.getWidth() / 2),
isVertical() ? pixelPos : (owner.getHeight() / 2)));
}
mousePos = owner.localPointToGlobal (Point<int> (isHorizontal() ? pixelPos : (owner.getWidth() / 2),
isVertical() ? pixelPos : (owner.getHeight() / 2)));
mi->setScreenPosition (mousePos);
} }
Desktop::setMousePosition (mousePos);
} }
} }
@@ -1254,7 +1253,6 @@ public:
bool popupDisplayEnabled; bool popupDisplayEnabled;
bool menuEnabled; bool menuEnabled;
bool useDragEvents; bool useDragEvents;
bool mouseWasHidden;
bool incDecDragged; bool incDecDragged;
bool scrollWheelEnabled; bool scrollWheelEnabled;
bool snapsToMousePos; bool snapsToMousePos;


Loading…
Cancel
Save