Windows: Prevent hidden transient children from being re-shown by Windows.
Bring back code from Qt 4 to handle WM_SHOWWINDOW / SW_PARENTOPENING correctly. Task-number: QTBUG-40696 Change-Id: If018bf90573f495dbe32d0c46f522ccde0691ebb Reviewed-by: Laszlo Agocs <laszlo.agocs@digia.com>bb10
parent
2d12ef0be0
commit
4354fef3d4
|
|
@ -77,6 +77,7 @@ enum WindowsEventType // Simplify event types
|
|||
LeaveEvent = WindowEventFlag + 5,
|
||||
CloseEvent = WindowEventFlag + 6,
|
||||
ShowEvent = WindowEventFlag + 7,
|
||||
ShowEventOnParentRestoring = WindowEventFlag + 20,
|
||||
HideEvent = WindowEventFlag + 8,
|
||||
DestroyEvent = WindowEventFlag + 9,
|
||||
MoveEvent = WindowEventFlag + 10,
|
||||
|
|
@ -128,7 +129,7 @@ enum ProcessDpiAwareness
|
|||
|
||||
} // namespace QtWindows
|
||||
|
||||
inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamIn)
|
||||
inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamIn, LPARAM lParamIn)
|
||||
{
|
||||
switch (message) {
|
||||
case WM_PAINT:
|
||||
|
|
@ -156,7 +157,9 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI
|
|||
case WM_MOVE:
|
||||
return QtWindows::MoveEvent;
|
||||
case WM_SHOWWINDOW:
|
||||
return wParamIn ? QtWindows::ShowEvent : QtWindows::HideEvent;
|
||||
if (wParamIn)
|
||||
return lParamIn == SW_PARENTOPENING ? QtWindows::ShowEventOnParentRestoring : QtWindows::ShowEvent;
|
||||
return QtWindows::HideEvent;
|
||||
case WM_SIZE:
|
||||
return QtWindows::ResizeEvent;
|
||||
case WM_NCCALCSIZE:
|
||||
|
|
|
|||
|
|
@ -1052,6 +1052,12 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
|
|||
case QtWindows::FocusOutEvent:
|
||||
handleFocusEvent(et, platformWindow);
|
||||
return true;
|
||||
case QtWindows::ShowEventOnParentRestoring: // QTBUG-40696, prevent Windows from re-showing hidden transient children (dialogs).
|
||||
if (!platformWindow->window()->isVisible()) {
|
||||
*result = 0;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case QtWindows::HideEvent:
|
||||
platformWindow->handleHidden();
|
||||
return false;// Indicate transient children should be hidden by windows (SW_PARENTCLOSING)
|
||||
|
|
@ -1243,7 +1249,7 @@ void QWindowsContext::setAsyncExpose(bool value)
|
|||
extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
LRESULT result;
|
||||
const QtWindows::WindowsEventType et = windowsEventType(message, wParam);
|
||||
const QtWindows::WindowsEventType et = windowsEventType(message, wParam, lParam);
|
||||
const bool handled = QWindowsContext::instance()->windowsProc(hwnd, message, et, wParam, lParam, &result);
|
||||
if (QWindowsContext::verbose > 1 && lcQpaEvents().isDebugEnabled()) {
|
||||
if (const char *eventName = QWindowsGuiEventDispatcher::windowsMessageName(message)) {
|
||||
|
|
|
|||
|
|
@ -39,10 +39,11 @@
|
|||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <qwindow.h>
|
||||
#include <qrasterwindow.h>
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
#include <qpa/qplatformintegration.h>
|
||||
#include <private/qguiapplication_p.h>
|
||||
#include <QtGui/QPainter>
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
|
|
@ -51,6 +52,8 @@
|
|||
|
||||
#if defined(Q_OS_QNX)
|
||||
#include <QOpenGLContext>
|
||||
#elif defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
|
||||
# include <QtCore/qt_windows.h>
|
||||
#endif
|
||||
|
||||
// For QSignalSpy slot connections.
|
||||
|
|
@ -94,6 +97,7 @@ private slots:
|
|||
void modalWithChildWindow();
|
||||
void modalWindowModallity();
|
||||
void modalWindowPosition();
|
||||
void windowsTransientChildren();
|
||||
void initTestCase();
|
||||
void cleanup();
|
||||
|
||||
|
|
@ -1539,6 +1543,59 @@ void tst_QWindow::modalWindowPosition()
|
|||
QCOMPARE(window.geometry(), origGeo);
|
||||
}
|
||||
|
||||
class ColoredWindow : public QRasterWindow {
|
||||
public:
|
||||
explicit ColoredWindow(const QColor &color, QWindow *parent = 0) : QRasterWindow(parent), m_color(color) {}
|
||||
void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE
|
||||
{
|
||||
QPainter p(this);
|
||||
p.fillRect(QRect(QPoint(0, 0), size()), m_color);
|
||||
}
|
||||
|
||||
private:
|
||||
const QColor m_color;
|
||||
};
|
||||
|
||||
static bool isNativeWindowVisible(const QWindow *window)
|
||||
{
|
||||
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
|
||||
return IsWindowVisible(reinterpret_cast<HWND>(window->winId()));
|
||||
#else
|
||||
Q_UNIMPLEMENTED();
|
||||
return window->isVisible();
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QWindow::windowsTransientChildren()
|
||||
{
|
||||
if (QGuiApplication::platformName().compare(QStringLiteral("windows"), Qt::CaseInsensitive))
|
||||
QSKIP("Windows only test");
|
||||
|
||||
ColoredWindow mainWindow(Qt::yellow);
|
||||
mainWindow.setGeometry(QRect(m_availableTopLeft + QPoint(100, 100), m_testWindowSize));
|
||||
mainWindow.setTitle(QStringLiteral("Main"));
|
||||
ColoredWindow child(Qt::blue, &mainWindow);
|
||||
child.setGeometry(QRect(QPoint(0, 0), m_testWindowSize / 2));
|
||||
|
||||
ColoredWindow dialog(Qt::red);
|
||||
dialog.setGeometry(QRect(m_availableTopLeft + QPoint(200, 200), m_testWindowSize));
|
||||
dialog.setTitle(QStringLiteral("Dialog"));
|
||||
dialog.setTransientParent(&mainWindow);
|
||||
|
||||
mainWindow.show();
|
||||
child.show();
|
||||
dialog.show();
|
||||
|
||||
QVERIFY(QTest::qWaitForWindowExposed(&dialog));
|
||||
mainWindow.setWindowState(Qt::WindowMinimized);
|
||||
QVERIFY(!isNativeWindowVisible(&dialog));
|
||||
dialog.hide();
|
||||
mainWindow.setWindowState(Qt::WindowNoState);
|
||||
// QTBUG-40696, transient children hidden by Qt should not be re-shown by Windows.
|
||||
QVERIFY(!isNativeWindowVisible(&dialog));
|
||||
QVERIFY(isNativeWindowVisible(&child)); // Real children should be visible.
|
||||
}
|
||||
|
||||
#include <tst_qwindow.moc>
|
||||
QTEST_MAIN(tst_QWindow)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue