macOS: Don't refuse key window for direct transient parent of modal window
As explain in detail in 1bde2036051b3aaf5896ef1ff50c08c11ea1eba9, AppKit doesn't treat non-direct transient parents of a window modal window as being blocked by that modal window, but Qt does. To align with Qt, we worked around it by returning NO from canBecomeKeyWindow for windows that were blocked by a modal window. This however had an unintended side effect for native dialogs, due to the way we hide these dialogs. When a native dialog is closed, AppKit will look for another window to make key, and as part of that it checks canBecomeKeyWindow. The problem is that the modal blocked status has not been updated in QGuiApplicationPrivate at that point, so we tell AppKit it can't make the transient parent key. The modal blocked status is only updated once we hit QWidget::setVisible, at which point dialogs like QMessageBox and QColorDialog has already called setNativeDialogVisible(false) in its setVisible() override, triggering the close logic described above. To fix this properly we need to have the dialogs call the base class first when hiding, and then setNativeDialogVisible(), and also have the macOS native dialog helpers react to hide() by ordering out the window in case it didn't work at an earlier point. This kind of change is risky for Qt 6.5/6.6 however, so we opt for a simpler solution for now. By limiting the original workaround for non-direct transient parents not being blocked to just those transient parents, and only for window modal dialogs, we avoid the issue with failing to transfer key status. Task-number: QTBUG-104905 Fixes: QTBUG-118320 Pick-to: 6.5 Change-Id: Iabbca0b74a7db4e9821a9b60730d01fbad1425db Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io> (cherry picked from commit 4a16e51bc3e248c6f82b70e176d605d54b9b2cad) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
f89a2f41e7
commit
ed1def47a2
@ -1983,8 +1983,21 @@ bool QCocoaWindow::shouldRefuseKeyWindowAndFirstResponder()
|
||||
if (window()->flags() & (Qt::WindowDoesNotAcceptFocus | Qt::WindowTransparentForInput))
|
||||
return true;
|
||||
|
||||
if (QWindowPrivate::get(window())->blockedByModalWindow)
|
||||
return true;
|
||||
// For application modal windows, as well as direct parent windows
|
||||
// of window modal windows, AppKit takes care of blocking interaction.
|
||||
// The Qt expectation however, is that all transient parents of a
|
||||
// window modal window is blocked, as reflected by QGuiApplication.
|
||||
// We reflect this by returning false from this function for transient
|
||||
// parents blocked by a modal window, but limit it to the cases not
|
||||
// covered by AppKit to avoid potential unwanted side effects.
|
||||
QWindow *modalWindow = nullptr;
|
||||
if (QGuiApplicationPrivate::instance()->isWindowBlocked(window(), &modalWindow)) {
|
||||
if (modalWindow->modality() == Qt::WindowModal && modalWindow->transientParent() != window()) {
|
||||
qCDebug(lcQpaWindow) << "Refusing key window for" << this << "due to being"
|
||||
<< "blocked by" << modalWindow;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_inSetVisible) {
|
||||
QVariant showWithoutActivating = window()->property("_q_showWithoutActivating");
|
||||
|
Loading…
x
Reference in New Issue
Block a user