macOS: Make QCocoaWindow::setVisible idempotent
The implementation of QCocoaWindow::setVisible is not idempotent, as for modal windows it calls beginSheet/endSheet or starts/ends modal sessions, which will confuse the AppKit modal session stack. Once a window has been shown QWindowPrivate::setVisible hides/masks this issue, by returning early if the visibility has not changed, but during first show QWindowPrivate::setVisible will update the QWindow state, before creating the platform window. If the platform window then picks up the QWindow's visible state during creation, it will result in one QPlatformWindow::setVisible() call during creation, and another one via QWindowPrivate::setVisible after the platform window has been created. To fix this we can check the existing NSView.hidden state and skip the setVisible call if it's already up to date. But one complication is that our QCocoaWindow::setVisible has different behaviors depending on whether the window has been initialized yet or not, due to how handleGeometryChange skips sending geometry changes for uninitialized windows. So we need to also bail out if we're still initializing the window. This is fine, as we know we'll get a follow up setVisible call via QWindow, both when QWindow itself creates the platform window as part of setVisible, as well as when the user does a two step create and then show. For good measure we throw in a recursion check as well, in case some of the logic in QCocoaWindow::setVisible before we update NSView.hidden recurses back into QCocoaWindow::setVisible. Pick-to: 6.5 6.6 Change-Id: Ibdcf4859e58d6684aac4490126d35eb12fdd5943 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
This commit is contained in:
parent
342b37f388
commit
be268ae197
@ -305,6 +305,31 @@ void QCocoaWindow::setVisible(bool visible)
|
||||
{
|
||||
qCDebug(lcQpaWindow) << "QCocoaWindow::setVisible" << window() << visible;
|
||||
|
||||
// Our implementation of setVisible below is not idempotent, as for
|
||||
// modal windows it calls beginSheet/endSheet or starts/ends modal
|
||||
// sessions. However we can't simply guard for m_view.hidden already
|
||||
// having the right state, as the behavior of this function differs
|
||||
// based on whether the window has been initialized or not, as
|
||||
// handleGeometryChange will bail out if the window is still
|
||||
// initializing. Since we know we'll get a second setVisible
|
||||
// call after creation, we can check for that case specifically,
|
||||
// which means we can then safely guard on m_view.hidden changing.
|
||||
|
||||
if (!m_initialized) {
|
||||
qCDebug(lcQpaWindow) << "Window still initializing, skipping setting visibility";
|
||||
return; // We'll get another setVisible call after create is done
|
||||
}
|
||||
|
||||
if (visible == !m_view.hidden) {
|
||||
qCDebug(lcQpaWindow) << "No change in visible status. Ignoring.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_inSetVisible) {
|
||||
qCWarning(lcQpaWindow) << "Already setting window visible!";
|
||||
return;
|
||||
}
|
||||
|
||||
QScopedValueRollback<bool> rollback(m_inSetVisible, true);
|
||||
|
||||
QMacAutoReleasePool pool;
|
||||
|
Loading…
Reference in New Issue
Block a user