Skip to content

[Bug]: MouseEvent: mouseDownTime > eventTime #1585

@fyzix

Description

@fyzix

Detailed steps on how to reproduce the bug

It is possible that the eventTime of, e.g., a mouseUp event is overtaken by the mouseDownTime when the MouseEvent is created.

How to reproduce/debug: Put this assertion into the body of MouseEvent::MouseEvent

jassert (time >= mouseDownTime);

and start a juce app in the debugger, then click around a lot. You should break into the debugger then.

My suspicion is that this happens because the lastMouseDownTime in MouseInputSource is updated before other mouse events are processed. MouseInputSourceImpl::handleAsyncUpdate might have something to do with it, as it forms jmax (lastTime, Time::getCurrentTime()) which is not a value coming out of any OS timestamp, and if this asyncUpdate is processed before the mouse events, I suspect something like this could happen.

EDIT: Could be partly be related to the function getMouseTime (also mentioned in #1587)

   static int64 getMouseTime (NSEvent* e) noexcept
    {
        return (Time::currentTimeMillis() - Time::getMillisecondCounter())
                 + (int64) ([e timestamp] * 1000.0);
    }

The difference Time::currentTimeMillis() - Time::getMillisecondCounter() oscillates by at least 1 ms (proved this with DBG printouts). The reason is that getMillisecondCounteris a rounded value, and forming the difference after rounding makes it an unstable offset. Maybe it would be a good idea to cache a stable offset once that is then used consistently in order not to break monotony of timestamps that are causally connected such as mouseDown / mouseUp.

What is the expected behaviour?

I would expect a mouseUp event (and others) to always have an eventTime that is >= the corresponding mouseDownTime.

Operating systems

macOS

What versions of the operating systems?

Sequoia 15.5
macOS 26.0.1

Architectures

Arm64/aarch64

Stacktrace

TouchGestureTests!juce::MouseEvent::MouseEvent(juce::MouseInputSource, juce::Point<float>, juce::ModifierKeys, float, float, float, float, float, juce::Component*, juce::Component*, juce::Time, juce::Point<float>, juce::Time, int, bool) (JUCE/modules/juce_gui_basics/mouse/juce_MouseEvent.cpp:69)
TouchGestureTests!juce::MouseEvent::MouseEvent(juce::MouseInputSource, juce::Point<float>, juce::ModifierKeys, float, float, float, float, float, juce::Component*, juce::Component*, juce::Time, juce::Point<float>, juce::Time, int, bool) (JUCE/modules/juce_gui_basics/mouse/juce_MouseEvent.cpp:68)
TouchGestureTests!juce::detail::makeMouseEvent(juce::MouseInputSource, juce::detail::PointerState const&, juce::ModifierKeys, juce::Component*, juce::Component*, juce::Time, juce::Point<float>, juce::Time, int, bool) (JUCE/modules/juce_gui_basics/detail/juce_PointerState.h:96)
TouchGestureTests!juce::Component::internalMouseUp(juce::Component::SafePointer<juce::Component>, juce::MouseInputSource, juce::detail::PointerState const&, juce::Time, juce::ModifierKeys) (JUCE/modules/juce_gui_basics/components/juce_Component.cpp:2287)
TouchGestureTests!juce::detail::MouseInputSourceImpl::sendMouseUp(juce::Component&, juce::detail::PointerState const&, juce::Time, juce::ModifierKeys) (JUCE/modules/juce_gui_basics/detail/juce_MouseInputSourceImpl.h:165)
TouchGestureTests!juce::detail::MouseInputSourceImpl::setButtons(juce::detail::PointerState const&, juce::Time, juce::ModifierKeys) (JUCE/modules/juce_gui_basics/detail/juce_MouseInputSourceImpl.h:221)
TouchGestureTests!juce::detail::MouseInputSourceImpl::handleEvent(juce::ComponentPeer&, juce::Point<float>, juce::Time, juce::ModifierKeys, float, float, juce::PenDetails) (JUCE/modules/juce_gui_basics/detail/juce_MouseInputSourceImpl.h:348)
TouchGestureTests!juce::MouseInputSource::handleEvent(juce::ComponentPeer&, juce::Point<float>, long long, juce::ModifierKeys, float, float, juce::PenDetails const&) (JUCE/modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp:89)
TouchGestureTests!juce::ComponentPeer::handleMouseEvent(juce::MouseInputSource::InputSourceType, juce::Point<float>, juce::ModifierKeys, float, float, long long, juce::PenDetails, int) (JUCE/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp:99)
TouchGestureTests!juce::NSViewComponentPeer::sendMouseEvent(NSEvent*) (JUCE/modules/juce_gui_basics/native/juce_NSViewComponentPeer_mac.mm:868)
TouchGestureTests!juce::NSViewComponentPeer::redirectMouseUp(NSEvent*) (JUCE/modules/juce_gui_basics/native/juce_NSViewComponentPeer_mac.mm:741)
TouchGestureTests!void juce::JuceNSViewClass::callOnOwner<void (juce::NSViewComponentPeer::*)(NSEvent*), NSEvent*&>(objc_object*, void (juce::NSViewComponentPeer::*&&)(NSEvent*), NSEvent*&) (JUCE/modules/juce_gui_basics/native/juce_NSViewComponentPeer_mac.mm:2673)
TouchGestureTests!juce::JuceNSViewClass::asyncMouseUp(objc_object*, objc_selector*, NSEvent*) (JUCE/modules/juce_gui_basics/native/juce_NSViewComponentPeer_mac.mm:2678)
TouchGestureTests!juce::JuceNSViewClass::mouseUp(objc_object*, objc_selector*, NSEvent*) (JUCE/modules/juce_gui_basics/native/juce_NSViewComponentPeer_mac.mm:2702)
AppKit!_routeMouseUpEvent (Unknown Source:0)
AppKit!-[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] (Unknown Source:0)
AppKit!-[NSWindow(NSEventRouting) sendEvent:] (Unknown Source:0)
AppKit!-[NSApplication(NSEventRouting) sendEvent:] (Unknown Source:0)
AppKit!-[NSApplication _handleEvent:] (Unknown Source:0)
AppKit!-[NSApplication run] (Unknown Source:0)
TouchGestureTests!juce::MessageManager::runDispatchLoop() (JUCE/modules/juce_events/native/juce_MessageManager_mac.mm:347)
TouchGestureTests!juce::JUCEApplicationBase::main() (JUCE/modules/juce_events/messages/juce_ApplicationBase.cpp:277)
TouchGestureTests!juce::JUCEApplicationBase::main(int, char const**) (JUCE/modules/juce_events/messages/juce_ApplicationBase.cpp:255)
TouchGestureTests!main (.../TouchGestureTests/Main.cpp:104)
start (Unknown Source:0)

Plug-in formats (if applicable)

No response

Plug-in host applications (DAWs) (if applicable)

No response

Testing on the develop branch

The bug is present on the develop branch

Code of Conduct

  • I agree to follow the Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions