40 bool isDragging()
const noexcept
45 Component* getComponentUnderMouse()
const noexcept
47 return componentUnderMouse.get();
85 return SH::unscaledScreenPosToScaled (getRawScreenPosition());
90 return unboundedMouseOffset + (inputType != MouseInputSource::InputSourceType::touch ? MouseInputSource::getCurrentRawMousePosition()
91 : lastPointerState.position);
96 MouseInputSource::setRawMousePosition (SH::scaledScreenPosToUnscaled (p));
100 #if JUCE_DUMP_MOUSE_EVENTS
101 #define JUCE_MOUSE_EVENT_DBG(desc, screenPos) DBG ("Mouse " << desc << " #" << index \
102 << ": " << SH::screenPosToLocalPos (comp, screenPos).toString() \
103 << " - Comp: " << String::toHexString ((pointer_sized_int) &comp));
105 #define JUCE_MOUSE_EVENT_DBG(desc, screenPos)
159 JUCE_MOUSE_EVENT_DBG (
"wheel",
screenPos)
161 SH::screenPosToLocalPos (comp,
screenPos),
168 JUCE_MOUSE_EVENT_DBG (
"magnify",
screenPos)
170 SH::screenPosToLocalPos (comp,
screenPos),
175 #undef JUCE_MOUSE_EVENT_DBG
199 if (
auto* current = getComponentUnderMouse())
201 auto oldMods = getCurrentModifiers();
210 enableUnboundedMouseMovement (
false,
false);
219 if (
auto* current = getComponentUnderMouse())
222 inputType == MouseInputSource::InputSourceType::touch);
232 auto* current = getComponentUnderMouse();
239 if (current !=
nullptr)
256 if (current !=
nullptr)
259 revealCursor (
false);
267 || findComponentAt (
pointerState.position, lastPeer) ==
nullptr))
288 if (
auto* current = getComponentUnderMouse())
295 if (isUnboundedMouseModeOn)
296 handleUnboundedDrag (*current);
304 revealCursor (
false);
318 .withTiltX (pen.
tiltX)
319 .withTiltY (pen.
tiltY);
321 if (isDragging() &&
newMods.isAnyMouseButtonDown())
329 if (
auto* peer = getPeer())
354 return getComponentUnderMouse();
367 if (lastNonInertialWheelTarget ==
nullptr || !
wheel.isInertial)
372 if (
auto target = lastNonInertialWheelTarget.get())
386 Time getLastMouseDownTime()
const noexcept
388 return mouseDowns[0].time;
393 return SH::unscaledScreenPosToScaled (mouseDowns[0].position);
396 int getNumberOfMultipleClicks()
const noexcept
400 if (! isLongPressOrDrag())
414 bool isLongPressOrDrag()
const noexcept
416 return movedSignificantly ||
420 bool hasMovedSignificantlySincePressed()
const noexcept
422 return movedSignificantly;
426 bool hasMouseMovedSignificantlySincePressed()
const noexcept
428 return isLongPressOrDrag();
432 void triggerFakeMove()
439 setPointerState (lastPointerState,
446 enable = enable && isDragging();
449 if (enable != isUnboundedMouseModeOn)
451 if ((! enable) && ((! isCursorVisibleUntilOffscreen) || ! unboundedMouseOffset.
isOrigin()))
454 if (
auto* current = getComponentUnderMouse())
455 setScreenPosition (current->getScreenBounds().toFloat()
456 .getConstrainedPoint (SH::unscaledScreenPosToScaled (lastPointerState.position)));
459 isUnboundedMouseModeOn = enable;
460 unboundedMouseOffset = {};
466 void handleUnboundedDrag (Component& current)
474 auto componentCentre = current.getScreenBounds().toFloat().getCentre();
475 unboundedMouseOffset += (lastPointerState.position - SH::scaledScreenPosToUnscaled (
componentCentre));
478 else if (isCursorVisibleUntilOffscreen
479 && (! unboundedMouseOffset.
isOrigin())
482 MouseInputSource::setRawMousePosition (lastPointerState.position + unboundedMouseOffset);
483 unboundedMouseOffset = {};
488 void showMouseCursor (MouseCursor cursor,
bool forcedUpdate)
490 if (isUnboundedMouseModeOn && ((! unboundedMouseOffset.
isOrigin()) || ! isCursorVisibleUntilOffscreen))
496 if (
forcedUpdate || cursor.getHandle() != currentCursorHandle)
498 currentCursorHandle = cursor.getHandle();
499 cursor.showInWindow (getPeer());
512 if (
auto* current = getComponentUnderMouse())
513 mc = current->getLookAndFeel().getMouseCursorFor (*current);
521 Point<float> unboundedMouseOffset;
522 detail::PointerState lastPointerState;
523 ModifierKeys buttonState;
525 bool isUnboundedMouseModeOn =
false, isCursorVisibleUntilOffscreen =
false;
529 ComponentPeer* lastPeer =
nullptr;
531 void* currentCursorHandle =
nullptr;
532 int mouseEventCounter = 0;
534 struct RecentMouseDown
536 RecentMouseDown() =
default;
538 Point<float> position;
540 ModifierKeys buttons;
542 bool isTouch =
false;
544 bool canBePartOfMultipleClickWith (
const RecentMouseDown&
other,
int maxTimeBetweenMs)
const noexcept
547 && std::abs (position.x -
other.position.x) < (
float) getPositionToleranceForInputType()
548 && std::abs (position.y -
other.position.y) < (
float) getPositionToleranceForInputType()
549 && buttons ==
other.buttons
550 && peerID ==
other.peerID;
553 int getPositionToleranceForInputType()
const noexcept {
return isTouch ? 25 : 8; }
556 RecentMouseDown mouseDowns[4];
558 bool movedSignificantly =
false;
560 void registerMouseDown (Point<float>
screenPos, Time time, Component& component,
564 mouseDowns[i] = mouseDowns[i - 1];
567 mouseDowns[0].time =
time;
568 mouseDowns[0].buttons =
modifiers.withOnlyMouseButtons();
571 if (
auto* peer = component.getPeer())
574 mouseDowns[0].peerID = 0;
576 movedSignificantly =
false;
577 lastNonInertialWheelTarget =
nullptr;
580 void registerMouseDrag (Point<float>
screenPos)
noexcept
582 movedSignificantly = movedSignificantly || mouseDowns[0].position.getDistanceFrom (
screenPos) >= 4;