QPA: Introduce QPlatformWindow::normalGeometry().

QWidgetWindow stores the normal geometry obtained from the widget when
transiting to other states. This does not work reliably on Windows,
where this geometry is already that of the new state. Instead,
introduce  QPlatformWindow::normalGeometry(), add implementation
for Windows and use that in QWidgetWindow.

Task-number: QTBUG-21371

Change-Id: I3819ebaf55b4e7d2f7eef1affe6c20712ba45d7c
Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
bb10
Friedemann Kleint 2014-02-05 14:59:49 +01:00 committed by The Qt Project
parent b2d5e7805a
commit b9fe8e30cb
6 changed files with 61 additions and 12 deletions

View File

@ -127,6 +127,18 @@ QRect QPlatformWindow::geometry() const
return d->rect;
}
/*!
Returns the geometry of a window in 'normal' state
(neither maximized, fullscreen nor minimized) for saving geometries to
application settings.
\since 5.3
*/
QRect QPlatformWindow::normalGeometry() const
{
return QRect();
}
QMargins QPlatformWindow::frameMargins() const
{
return QMargins();

View File

@ -84,6 +84,7 @@ public:
virtual void setGeometry(const QRect &rect);
virtual QRect geometry() const;
virtual QRect normalGeometry() const;
virtual QMargins frameMargins() const;

View File

@ -1234,6 +1234,28 @@ void QWindowsWindow::handleCompositionSettingsChanged()
applyBlurBehindWindow(handle());
}
static QRect normalFrameGeometry(HWND hwnd)
{
#ifndef Q_OS_WINCE
WINDOWPLACEMENT wp;
wp.length = sizeof(WINDOWPLACEMENT);
if (GetWindowPlacement(hwnd, &wp))
return qrectFromRECT(wp.rcNormalPosition);
#else
Q_UNUSED(hwnd)
#endif
return QRect();
}
QRect QWindowsWindow::normalGeometry() const
{
// Check for fake 'fullscreen' mode.
const bool fakeFullScreen = m_savedFrameGeometry.isValid() && window()->windowState() == Qt::WindowFullScreen;
const QRect frame = fakeFullScreen ? m_savedFrameGeometry : normalFrameGeometry(m_data.hwnd);
const QMargins margins = fakeFullScreen ? QWindowsGeometryHint::frame(m_savedStyle, 0) : frameMargins();
return frame.isValid() ? frame.marginsRemoved(margins) : frame;
}
void QWindowsWindow::setGeometry(const QRect &rectIn)
{
QRect rect = rectIn;
@ -1593,10 +1615,9 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
m_savedStyle = style();
#ifndef Q_OS_WINCE
if (oldState == Qt::WindowMinimized) {
WINDOWPLACEMENT wp;
wp.length = sizeof(WINDOWPLACEMENT);
if (GetWindowPlacement(m_data.hwnd, &wp))
m_savedFrameGeometry = qrectFromRECT(wp.rcNormalPosition);
const QRect nf = normalFrameGeometry(m_data.hwnd);
if (nf.isValid())
m_savedFrameGeometry = nf;
} else {
#endif
m_savedFrameGeometry = frameGeometry_sys();

View File

@ -162,6 +162,7 @@ public:
virtual QSurfaceFormat format() const { return m_format; }
virtual void setGeometry(const QRect &rect);
virtual QRect geometry() const { return m_data.geometry; }
QRect normalGeometry() const Q_DECL_OVERRIDE;
virtual void setVisible(bool visible);
bool isVisible() const;

View File

@ -50,6 +50,7 @@
#include <private/qwidgetbackingstore_p.h>
#include <qpa/qwindowsysteminterface_p.h>
#include <qpa/qplatformtheme.h>
#include <qpa/qplatformwindow.h>
#include <private/qgesturemanager_p.h>
QT_BEGIN_NAMESPACE
@ -547,6 +548,24 @@ void QWidgetWindow::updateGeometry()
m_widget->data->fstrut_dirty = false;
}
Qt::WindowState effectiveState(Qt::WindowStates state);
// Store normal geometry used for saving application settings.
void QWidgetWindow::updateNormalGeometry()
{
QTLWExtra *tle = m_widget->d_func()->maybeTopData();
if (!tle)
return;
// Ask platform window, default to widget geometry.
QRect normalGeometry;
if (const QPlatformWindow *pw = handle())
normalGeometry = pw->normalGeometry();
if (!normalGeometry.isValid() && effectiveState(m_widget->windowState()) == Qt::WindowNoState)
normalGeometry = m_widget->geometry();
if (normalGeometry.isValid())
tle->normalGeometry = normalGeometry;
}
void QWidgetWindow::handleMoveEvent(QMoveEvent *event)
{
updateGeometry();
@ -692,8 +711,6 @@ void QWidgetWindow::handleExposeEvent(QExposeEvent *event)
}
}
Qt::WindowState effectiveState(Qt::WindowStates state);
void QWidgetWindow::handleWindowStateChangedEvent(QWindowStateChangeEvent *event)
{
// QWindow does currently not know 'active'.
@ -712,16 +729,12 @@ void QWidgetWindow::handleWindowStateChangedEvent(QWindowStateChangeEvent *event
widgetState |= Qt::WindowMinimized;
break;
case Qt::WindowMaximized:
if (effectiveState(widgetState) == Qt::WindowNoState)
if (QTLWExtra *tle = m_widget->d_func()->maybeTopData())
tle->normalGeometry = m_widget->geometry();
updateNormalGeometry();
widgetState |= Qt::WindowMaximized;
widgetState &= ~(Qt::WindowMinimized | Qt::WindowFullScreen);
break;
case Qt::WindowFullScreen:
if (effectiveState(widgetState) == Qt::WindowNoState)
if (QTLWExtra *tle = m_widget->d_func()->maybeTopData())
tle->normalGeometry = m_widget->geometry();
updateNormalGeometry();
widgetState |= Qt::WindowFullScreen;
widgetState &= ~(Qt::WindowMinimized);
break;

View File

@ -104,6 +104,7 @@ private slots:
private:
void updateGeometry();
void updateNormalGeometry();
enum FocusWidgets {
FirstFocusWidget,