For some transforms, the program could get stuck in the following loop:
- The content component emits a resized/moved notification, leading to
the initial call to Viewport::updateVisibleArea.
- New positions are computed for the viewport scrollbars, and scrollbar
listeners are notified synchronously that the scrollbars have been
updated.
- The viewport itself listens to the scrollbars, so it receives a
notification and updates the position of the content component.
- The scrollbar position (quantised to an integer) resolves to a
component position (also quantised to an integer) that differs from
the existing position, so the new position is applied.
- The viewport now attempts to set the scrollbars to the correct
position in response, and notifies listeners that the scrollbars
have moved...
Normally, the recursion would exit at the point where the component position
is set to its current position. If we're unlucky, though, converting
from view pos to scrollbar pos, then scrollbar pos back to view pos may
result in a view pos that differs from the original value.
This fix adds a new exit condition from the recursion. On receiving a
scrollbar move notification, we check whether the scrollbar position
computed from the current view position matches the incoming scrollbar
position. If it does, there's no need to compute and apply a new view
position from the incoming scrollbar position.
- Created a new detail namespace
- Moved shared module implementation details into the detail namespace
- Split dependencies so source files only rely on details in the detail namespace
- Removed all code from the juce_gui_basics.cpp file
An animated drag operation will now stop if the user interacts with
the content area again before the animation is finished. It is also
stopped if the user interacts with the scrollbars.
Some Windows 11 devices have both touch screens and mouse inputs, and
these can be used simultaneously.
The Viewport (and ListBox) now check the input source of each mouse
down. If the source is not a mouse, the viewport will always enter
drag-to-scroll mode, regardless of the result of isScrollOnDragEnabled.
Previously, a touch on a component outside the Viewport would interrupt
and cancel a scroll gesture inside the Viewport.
Now, the Viewport will respond to all drag events from the input source
that started the drag, allowing the Viewport to be scrolled with one
input source while adjusting other controls with another input source.
The FontsDemo is useful for testing this behaviour, as it has two
Viewports on a single screen, along with some other controls.