void setComponentUnderMouse (Component* const newComponent, const Point<int>& screenPos, const Time& time) { Component* current = getComponentUnderMouse(); if (newComponent != current) { WeakReference<Component> safeNewComp (newComponent); const ModifierKeys originalButtonState (buttonState); if (current != nullptr) { WeakReference<Component> safeOldComp (current); setButtons (screenPos, time, ModifierKeys()); if (safeOldComp != nullptr) sendMouseExit (current, screenPos, time); buttonState = originalButtonState; } componentUnderMouse = safeNewComp; current = getComponentUnderMouse(); if (current != nullptr) sendMouseEnter (current, screenPos, time); revealCursor (false); setButtons (screenPos, time, originalButtonState); } }
//============================================================================== // (returns true if the button change caused a modal event loop) bool setButtons (const Point<int>& screenPos, const Time& time, const ModifierKeys& newButtonState) { if (buttonState == newButtonState) return false; // (avoid sending a spurious mouse-drag when we receive a mouse-up) if (! (isDragging() && ! newButtonState.isAnyMouseButtonDown())) setScreenPos (screenPos, time, false); // (ignore secondary clicks when there's already a button down) if (buttonState.isAnyMouseButtonDown() == newButtonState.isAnyMouseButtonDown()) { buttonState = newButtonState; return false; } const int lastCounter = mouseEventCounter; if (buttonState.isAnyMouseButtonDown()) { Component* const current = getComponentUnderMouse(); if (current != nullptr) { const ModifierKeys oldMods (getCurrentModifiers()); buttonState = newButtonState; // must change this before calling sendMouseUp, in case it runs a modal loop sendMouseUp (current, screenPos + unboundedMouseOffset, time, oldMods); } enableUnboundedMouseMovement (false, false); } buttonState = newButtonState; if (buttonState.isAnyMouseButtonDown()) { Desktop::getInstance().incrementMouseClickCounter(); Component* const current = getComponentUnderMouse(); if (current != nullptr) { registerMouseDown (screenPos, time, current, buttonState); sendMouseDown (current, screenPos, time); } } return lastCounter != mouseEventCounter; }
void setScreenPos (Point<float> newScreenPos, Time time, const bool forceUpdate) { if (! isDragging()) setComponentUnderMouse (findComponentAt (newScreenPos), newScreenPos, time); if (newScreenPos != lastScreenPos || forceUpdate) { cancelPendingUpdate(); lastScreenPos = newScreenPos; if (Component* const current = getComponentUnderMouse()) { if (isDragging()) { registerMouseDrag (newScreenPos); sendMouseDrag (*current, newScreenPos + unboundedMouseOffset, time); if (isUnboundedMouseModeOn) handleUnboundedDrag (*current); } else { sendMouseMove (*current, newScreenPos, time); } } revealCursor (false); } }
void revealCursor (bool forcedUpdate) { MouseCursor mc (MouseCursor::NormalCursor); if (Component* current = getComponentUnderMouse()) mc = current->getLookAndFeel().getMouseCursorFor (*current); showMouseCursor (mc, forcedUpdate); }
void TooltipWindow::timerCallback() { auto& desktop = Desktop::getInstance(); auto mouseSource = desktop.getMainMouseSource(); auto now = Time::getApproximateMillisecondCounter(); auto* newComp = mouseSource.isTouch() ? nullptr : mouseSource.getComponentUnderMouse(); auto newTip = newComp != nullptr ? getTipFor (*newComp) : String(); bool tipChanged = (newTip != lastTipUnderMouse || newComp != lastComponentUnderMouse); lastComponentUnderMouse = newComp; lastTipUnderMouse = newTip; auto clickCount = desktop.getMouseButtonClickCounter(); auto wheelCount = desktop.getMouseWheelMoveCounter(); bool mouseWasClicked = (clickCount > mouseClicks || wheelCount > mouseWheelMoves); mouseClicks = clickCount; mouseWheelMoves = wheelCount; auto mousePos = mouseSource.getScreenPosition(); bool mouseMovedQuickly = mousePos.getDistanceFrom (lastMousePos) > 12; lastMousePos = mousePos; if (tipChanged || mouseWasClicked || mouseMovedQuickly) lastCompChangeTime = now; if (isVisible() || now < lastHideTime + 500) { // if a tip is currently visible (or has just disappeared), update to a new one // immediately if needed.. if (newComp == nullptr || mouseWasClicked || newTip.isEmpty()) { if (isVisible()) { lastHideTime = now; hideTip(); } } else if (tipChanged) { displayTip (mousePos.roundToInt(), newTip); } } else { // if there isn't currently a tip, but one is needed, only let it // appear after a timeout.. if (newTip.isNotEmpty() && newTip != tipShowing && now > lastCompChangeTime + (uint32) millisecondsBeforeTipAppears) { displayTip (mousePos.roundToInt(), newTip); } } }
Component* getTargetForGesture (ComponentPeer& peer, Point<float> positionWithinPeer, Time time, Point<float>& screenPos) { lastTime = time; ++mouseEventCounter; screenPos = peer.localToGlobal (positionWithinPeer); setPeer (peer, screenPos, time); setScreenPos (screenPos, time, false); triggerFakeMove(); return isDragging() ? nullptr : getComponentUnderMouse(); }
Component* getTargetForGesture (ComponentPeer* const peer, const Point<int>& positionWithinPeer, const Time& time, Point<int>& screenPos) { jassert (peer != nullptr); lastTime = time; ++mouseEventCounter; screenPos = peer->localToGlobal (positionWithinPeer); setPeer (peer, screenPos, time); setScreenPos (screenPos, time, false); triggerFakeMove(); return isDragging() ? nullptr : getComponentUnderMouse(); }
void handleWheel (ComponentPeer* const peer, const Point<int>& positionWithinPeer, const Time& time, float x, float y) { jassert (peer != nullptr); lastTime = time; ++mouseEventCounter; const Point<int> screenPos (peer->localToGlobal (positionWithinPeer)); setPeer (peer, screenPos, time); setScreenPos (screenPos, time, false); triggerFakeMove(); if (! isDragging()) { Component* current = getComponentUnderMouse(); if (current != nullptr) sendMouseWheel (current, screenPos, time, x, y); } }
void handleWheel (ComponentPeer* const peer, const Point<int>& positionWithinPeer, const Time& time, const MouseWheelDetails& wheel) { jassert (peer != nullptr); lastTime = time; ++mouseEventCounter; Desktop::getInstance().incrementMouseWheelCounter(); const Point<int> screenPos (peer->localToGlobal (positionWithinPeer)); setPeer (peer, screenPos, time); setScreenPos (screenPos, time, false); triggerFakeMove(); if (! isDragging()) { Component* current = getComponentUnderMouse(); if (current != nullptr) sendMouseWheel (current, screenPos, time, wheel); } }
//============================================================================== void enableUnboundedMouseMovement (bool enable, bool keepCursorVisibleUntilOffscreen) { enable = enable && isDragging(); isCursorVisibleUntilOffscreen = keepCursorVisibleUntilOffscreen; if (enable != isUnboundedMouseModeOn) { if ((! enable) && ((! isCursorVisibleUntilOffscreen) || ! unboundedMouseOffset.isOrigin())) { // when released, return the mouse to within the component's bounds if (Component* current = getComponentUnderMouse()) setScreenPosition (current->getScreenBounds().toFloat() .getConstrainedPoint (ScalingHelpers::unscaledScreenPosToScaled (lastScreenPos))); } isUnboundedMouseModeOn = enable; unboundedMouseOffset = Point<float>(); revealCursor (true); } }
//============================================================================== void enableUnboundedMouseMovement (bool enable, bool keepCursorVisibleUntilOffscreen) { enable = enable && isDragging(); isCursorVisibleUntilOffscreen = keepCursorVisibleUntilOffscreen; if (enable != isUnboundedMouseModeOn) { if ((! enable) && ((! isCursorVisibleUntilOffscreen) || ! unboundedMouseOffset.isOrigin())) { // when released, return the mouse to within the component's bounds Component* current = getComponentUnderMouse(); if (current != nullptr) Desktop::setMousePosition (current->getScreenBounds() .getConstrainedPoint (lastScreenPos)); } isUnboundedMouseModeOn = enable; unboundedMouseOffset = Point<int>(); revealCursor (true); } }