| @@ -210,17 +210,15 @@ static SleepEvent sleepEvent; | |||
| void JUCE_CALLTYPE Thread::sleep (const int millisecs) | |||
| { | |||
| jassert (millisecs >= 0); | |||
| if (millisecs >= 10 || sleepEvent.handle == 0) | |||
| { | |||
| Sleep ((DWORD) millisecs); | |||
| } | |||
| else | |||
| { | |||
| // 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 | |||
| // to need to be accurate | |||
| WaitForSingleObject (sleepEvent.handle, (DWORD) millisecs); | |||
| } | |||
| } | |||
| void Thread::yield() | |||
| @@ -231,7 +229,7 @@ void Thread::yield() | |||
| //============================================================================== | |||
| 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. | |||
| void juce_repeatLastProcessPriority() | |||
| { | |||
| @@ -59,18 +59,15 @@ public: | |||
| ReadWriteLock() noexcept; | |||
| /** 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; | |||
| //============================================================================== | |||
| /** 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 | |||
| */ | |||
| @@ -78,7 +75,7 @@ public: | |||
| /** 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. | |||
| @returns true if the lock is successfully gained. | |||
| @@ -177,7 +177,7 @@ public: | |||
| ModifierKeys withFlags (int rawFlagsToSet) const noexcept { return ModifierKeys (flags | rawFlagsToSet); } | |||
| /** 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. */ | |||
| int getNumMouseButtonsDown() const noexcept; | |||
| @@ -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 | |||
| // the current mouse position instead of the one that the event contains... | |||
| if (componentToDrag->isOnDesktop()) | |||
| bounds += componentToDrag->getMouseXYRelative() - mouseDownWithinTarget; | |||
| bounds += componentToDrag->getLocalPoint (nullptr, e.source.getScreenPosition()) - mouseDownWithinTarget; | |||
| else | |||
| bounds += e.getEventRelativeTo (componentToDrag).getPosition() - mouseDownWithinTarget; | |||
| @@ -27,8 +27,9 @@ class MouseInputSourceInternal : private AsyncUpdater | |||
| public: | |||
| //============================================================================== | |||
| 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) | |||
| { | |||
| } | |||
| @@ -463,12 +464,13 @@ public: | |||
| Point<int> lastScreenPos; | |||
| ModifierKeys buttonState; | |||
| Point<int> unboundedMouseOffset; | |||
| bool isUnboundedMouseModeOn, isCursorVisibleUntilOffscreen; | |||
| private: | |||
| WeakReference<Component> componentUnderMouse; | |||
| ComponentPeer* lastPeer; | |||
| Point<int> unboundedMouseOffset; | |||
| bool isUnboundedMouseModeOn, isCursorVisibleUntilOffscreen; | |||
| void* currentCursorHandle; | |||
| int mouseEventCounter; | |||
| @@ -550,6 +552,7 @@ bool MouseInputSource::hasMouseMovedSignificantlySincePressed() const noexcept | |||
| bool MouseInputSource::canDoUnboundedMovement() const noexcept { return isMouse(); } | |||
| void MouseInputSource::enableUnboundedMouseMovement (bool isEnabled, bool keepCursorVisibleUntilOffscreen) const | |||
| { pimpl->enableUnboundedMouseMovement (isEnabled, keepCursorVisibleUntilOffscreen); } | |||
| bool MouseInputSource::isUnboundedMouseMovementEnabled() const { return pimpl->isUnboundedMouseModeOn; } | |||
| bool MouseInputSource::hasMouseCursor() const noexcept { return isMouse(); } | |||
| void MouseInputSource::showMouseCursor (const MouseCursor& cursor) { pimpl->showMouseCursor (cursor, false); } | |||
| void MouseInputSource::hideCursor() { pimpl->hideCursor(); } | |||
| @@ -158,6 +158,9 @@ public: | |||
| */ | |||
| 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. */ | |||
| void setScreenPosition (Point<int> newPosition); | |||
| @@ -818,13 +818,11 @@ public: | |||
| valueWhenLastDragged = owner.proportionOfLengthToValue (jlimit (0.0, 1.0, currentPos + speed)); | |||
| e.source.enableUnboundedMouseMovement (true, false); | |||
| mouseWasHidden = true; | |||
| } | |||
| } | |||
| void mouseDown (const MouseEvent& e) | |||
| { | |||
| mouseWasHidden = false; | |||
| incDecDragged = false; | |||
| useDragEvents = false; | |||
| mouseDragStartPos = mousePosWhenLastDragged = e.getPosition(); | |||
| @@ -880,9 +878,9 @@ public: | |||
| 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) | |||
| { | |||
| @@ -899,10 +897,7 @@ public: | |||
| 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); | |||
| else | |||
| handleVelocityDrag (e); | |||
| @@ -1019,50 +1014,54 @@ public: | |||
| void modifierKeysChanged (const ModifierKeys& modifiers) | |||
| { | |||
| if (style != IncDecButtons | |||
| && style != Rotary | |||
| && isVelocityBased == modifiers.isAnyModifierKeyDown()) | |||
| { | |||
| if (style != IncDecButtons && style != Rotary && isAbsoluteDragMode (modifiers)) | |||
| restoreMouseIfHidden(); | |||
| } | |||
| } | |||
| bool isAbsoluteDragMode (ModifierKeys mods) const | |||
| { | |||
| return isVelocityBased == (userKeyOverridesVelocity | |||
| && mods.testFlags (ModifierKeys::ctrlAltCommandModifiers)); | |||
| } | |||
| 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 menuEnabled; | |||
| bool useDragEvents; | |||
| bool mouseWasHidden; | |||
| bool incDecDragged; | |||
| bool scrollWheelEnabled; | |||
| bool snapsToMousePos; | |||