Previously, the vblank's thread loop would block on each iteration until
the current async callback had finished, at which point a new async
callback would be immediately triggered.
The new implementation only waits on the vblank event. If a vblank
callback is still in progress the next time the vblank event is
signalled, we assume the last frame is overrunning and avoid sending a
new async update.
The intention of this change is to avoid saturating the message thread
with expensive vblank callbacks. It's also nice to remove a lock,
although that's just an incidental change.
This bug could be observed by running the WidgetsDemo Drag+Drop pane on
Windows 10, and dragging an item between two displays at different scale
factors.
This is issue is a regression introduced in
9817a2bb66. The regression was caused by
the change in mouse position calculation. The incorrect version switched
to using ClientToScreen, but the correct version used
getPointFromLocalLParam.
The function getPointFromLocalLParam was replaced by clientLParamToPoint
in 24ab3cb6a3, and is restored by this
commit.
This change intends to address a bug observed only on Windows 10 with a
display scale factor of 125%.
When the native titlebar is enabled, and the window's border-resizer is
used to resize the window slowly the with mouse, the client area of the
window may move to the wrong location, or be drawn with some areas
obscured/clipped. This is especially observable when resizing the
WidgetsDemo to its smallest size, and then dragging the right border a
single pixel to the right. On my computer, this consistently causes the
client area to display at the wrong location.
I haven't been able to find any obvious bug in JUCE that might cause
this behaviour. In particular, it seems that the window begins
displaying incorrectly *before* the window ever actually resizes.
During the resize, the system sends events (WM_SIZING and
WM_WINDOWPOSCHANGING) to the window, and according to the documentation,
the window may modify the message parameters in order to constrain the
new window size. When running on a scaled display, JUCE attempts to map
the logical client area size to a sensible size in physical pixels, and
uses the sizing messages to enforce this size requirement.
In the case of the broken window rendering, the system requests a new
window size, which JUCE rejects. The window's display state doesn't
change, so the swap chain does not resize, and the swap chain does not
present. Put another way, the broken rendering happens *independently*
of JUCE modifying the swap chain in any way. Therefore, I believe that the
bug is introduced elsewhere, potentially by Windows itself.
I also checked to see whether the issue could be caused by mishandling
of the NCCALCSIZE message, which is normally used to configure the
relative positions of the client and nonclient areas. However, in the
buggy case, NCCALCSIZE is not sent until *after* the first 'broken'
frame is painted - and even then, the implementation immediately falls
back to DefWindowProc.
Given that the issue appears to be a bug in Windows, the proposed change
is a workaround, rather than a true fix. It appears as though the
problem goes away when WM_WINDOWPOSCHANGING does not modify the
requested bounds. Therefore, for windows with native titlebars, we rely
on the constraints to be applied in WM_SIZING only, when sizing the
window in a sizemove gesture.
Previously, for windows with a native titlebar and a constrainer, the
window could be restored at the wrong size. This happened because
findPhysicalBorderSize() may return nonsensical values when called
during a SC_RESTORE, which in turn produces an unexpected window size
when adding the bogus border size to the constrained client area size.
We now avoid trying to constrain the window if we're unable to determine
the correct border size. I think this is only likely to happen during
SC_RESTORE, in which case the system should have a pretty good idea of
where the window should go, and constraining should not be necessary.
The buggy behaviour could be seen in a blank GUI app project by setting
a native titlebar and calling setResizable (false, false). The resulting
window would still display a resize cursor when hovering the window
border.
This also fixes a bug introduced in f7c7225f5c
where the condition guarding the definition of traitCollectionDidChange
was incorrect. This function is never required if the deployment target
is at least 17.0.
This reverts 515e9b9f89.
In order to avoid recursive calls through WM_NCHITTEST, we remove calls
to Component::contains in DocumentWindow::findControlAtPoint.
This partially reverts commit 555b667d22.
Using ComponentPeer::isShowing instead of ComponentPeer::isMinimised
inside Component::isShowing can cause problems when displaying OpenGL
components.
Specifically, OpenGL components use a ComponentMovementWatcher to
determine when they should be attached/detached from the parent window.
The ComponentMovementWatcher updates whenever a component visibility
change event is emitted, which happens in two cases:
- Component::setVisible is called on the OpenGL component or an ancestor
- ComponentPeer::handleMovedOrResized is called in response to a
minimisation state change
When handling either of these events, the ComponentMovementWatcher will
call Component::isShowing to determine whether or not the component is
really showing.
The problem is that the result of ComponentPeer::isShowing may change
independently of changes to the Component visiblity state or
ComponentPeer minimisation state, so the ComponentPeerWatcher might not
notify its listeners when a component is really shown/hidden.
One potential workaround would be for the ComponentPeer to send
notifications when the showing state of the window changes, so that the
ComponentMovementWatcher can forward those notifications. The main
problem with this approach is that on Windows, the window doesn't seem
to receive a message on hide/show, and it's not clear whether there
exists some other approach to detect a hide/show event.
If there were some event we could listen for on Windows, then we could
call Component::sendVisibilityChangeMessage in response to this event
and things would *likely* work at that point, but this may still have
unintended side-effect. As a result, I think the best approach to
restore the old behaviour is to revert the change to
Component::isShowing. The implementations of ComponentPeer::isShowing
have been left in place so that users can do still query the real
visibility state of native windows if necessary.
toWideCharPointer() returns a pointer to a buffer managed by the String.
The wchar_t pointers are not read until the invocation of
TaskDialogIndirect, so the String instances must remain alive until this
point.
Previously, maximising a frameless window on a secondary display could
result in the window's coordinates being computed incorrectly, leading
to graphical glitches.