summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows/qwindowswindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/windows/qwindowswindow.cpp')
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp220
1 files changed, 109 insertions, 111 deletions
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 0382144cbe..06b566629b 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -44,19 +44,16 @@
#include "qwindowscontext.h"
#include "qwindowsdrag.h"
#include "qwindowsscreen.h"
+#include "qwindowsscaling.h"
#ifdef QT_NO_CURSOR
# include "qwindowscursor.h"
#endif
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
-# include "qwindowseglcontext.h"
-# include <QtGui/QOpenGLFunctions>
-#endif
-
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
#include <QtGui/QWindow>
#include <QtGui/QRegion>
+#include <QtGui/QOpenGLContext>
#include <private/qsystemlibrary_p.h>
#include <private/qwindow_p.h>
#include <private/qguiapplication_p.h>
@@ -110,6 +107,8 @@ static QByteArray debugWinExStyle(DWORD exStyle)
rc += " WS_EX_CONTEXTHELP";
if (exStyle & WS_EX_LAYERED)
rc += " WS_EX_LAYERED";
+ if (exStyle & WS_EX_DLGMODALFRAME)
+ rc += " WS_EX_DLGMODALFRAME";
return rc;
}
@@ -183,6 +182,15 @@ QDebug operator<<(QDebug d, const NCCALCSIZE_PARAMS &p)
static inline QRect frameGeometry(HWND hwnd, bool topLevel)
{
RECT rect = { 0, 0, 0, 0 };
+#ifndef Q_OS_WINCE
+ if (topLevel) {
+ WINDOWPLACEMENT windowPlacement;
+ windowPlacement.length = sizeof(WINDOWPLACEMENT);
+ GetWindowPlacement(hwnd, &windowPlacement);
+ if (windowPlacement.showCmd == SW_SHOWMINIMIZED)
+ return qrectFromRECT(windowPlacement.rcNormalPosition);
+ }
+#endif // !Q_OS_WINCE
GetWindowRect(hwnd, &rect); // Screen coordinates.
const HWND parent = GetParent(hwnd);
if (parent && !topLevel) {
@@ -513,6 +521,10 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
}
if (flags & Qt::WindowSystemMenuHint)
style |= WS_SYSMENU;
+ else if (dialog) {
+ style |= WS_SYSMENU | WS_BORDER; // QTBUG-2027, dialogs without system menu.
+ exStyle |= WS_EX_DLGMODALFRAME;
+ }
if (flags & Qt::WindowMinimizeButtonHint)
style |= WS_MINIMIZEBOX;
if (shouldShowMaximizeButton(w, flags))
@@ -566,7 +578,9 @@ QWindowsWindowData
const QString windowClassName = QWindowsContext::instance()->registerWindowClass(w, isGL);
- QRect rect = QPlatformWindow::initialGeometry(w, data.geometry, defaultWindowWidth, defaultWindowHeight);
+ const QRect geometryDip = QWindowsScaling::mapFromNative(data.geometry);
+ QRect fixedGeometryDip = QPlatformWindow::initialGeometry(w, geometryDip, defaultWindowWidth, defaultWindowHeight);
+ const QRect rect = fixedGeometryDip != geometryDip ? QWindowsScaling::mapToNative(fixedGeometryDip) : data.geometry;
if (title.isEmpty() && (result.flags & Qt::WindowTitleHint))
title = topLevel ? qAppName() : w->objectName();
@@ -673,11 +687,9 @@ void WindowCreationData::initialize(HWND hwnd, bool frameChange, qreal opacityLe
\ingroup qt-lighthouse-win
*/
-#define QWINDOWSIZE_MAX ((1<<24)-1)
-
QWindowsGeometryHint::QWindowsGeometryHint(const QWindow *w, const QMargins &cm) :
- minimumSize(w->minimumSize()),
- maximumSize(w->maximumSize()),
+ minimumSize(QWindowsScaling::mapToNativeConstrained(w->minimumSize())),
+ maximumSize(QWindowsScaling::mapToNativeConstrained(w->maximumSize())),
customMargins(cm)
{
}
@@ -758,9 +770,8 @@ void QWindowsGeometryHint::applyToMinMaxInfo(DWORD style, DWORD exStyle, MINMAXI
const int maximumHeight = qMax(maximumSize.height(), minimumSize.height());
if (maximumWidth < QWINDOWSIZE_MAX)
mmi->ptMaxTrackSize.x = maximumWidth + frameWidth;
- // windows with title bar have an implicit size limit of 112 pixels
if (maximumHeight < QWINDOWSIZE_MAX)
- mmi->ptMaxTrackSize.y = qMax(maximumHeight + frameHeight, 112);
+ mmi->ptMaxTrackSize.y = maximumHeight + frameHeight;
qCDebug(lcQpaWindows).nospace() << '<' << __FUNCTION__
<< " frame=" << margins << ' ' << frameWidth << ',' << frameHeight
<< " out " << *mmi;
@@ -861,15 +872,13 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
m_opacity(1.0),
m_dropTarget(0),
m_savedStyle(0),
- m_format(aWindow->format()),
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- m_eglSurface(0),
-#endif
+ m_format(aWindow->requestedFormat()),
#ifdef Q_OS_WINCE
m_previouslyHidden(false),
#endif
m_iconSmall(0),
- m_iconBig(0)
+ m_iconBig(0),
+ m_surface(0)
{
// Clear the creation context as the window can be found in QWindowsContext's map.
QWindowsContext::instance()->setWindowCreationContext(QSharedPointer<QWindowCreationContext>());
@@ -877,13 +886,14 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
const Qt::WindowType type = aWindow->type();
if (type == Qt::Desktop)
return; // No further handling for Qt::Desktop
+#ifndef QT_NO_OPENGL
if (aWindow->surfaceType() == QWindow::OpenGLSurface) {
- setFlag(OpenGLSurface);
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL)
+ if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL)
+ setFlag(OpenGLSurface);
+ else
setFlag(OpenGL_ES2);
-#endif
}
+#endif // QT_NO_OPENGL
updateDropSite();
#ifndef Q_OS_WINCE
@@ -921,7 +931,8 @@ void QWindowsWindow::fireExpose(const QRegion &region, bool force)
clearFlag(Exposed);
else
setFlag(Exposed);
- QWindowSystemInterface::handleExposeEvent(window(), region);
+ QWindowSystemInterface::handleExposeEvent(window(),
+ QWindowsScaling::mapFromNative(region));
}
static inline QWindow *findTransientChild(const QWindow *parent)
@@ -947,11 +958,10 @@ void QWindowsWindow::destroyWindow()
if (hasMouseCapture())
setMouseGrabEnabled(false);
setDropSiteEnabled(false);
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- if (m_eglSurface) {
- qCDebug(lcQpaGl) << __FUNCTION__ << "Freeing EGL surface " << m_eglSurface << window();
- eglDestroySurface(m_staticEglContext->display(), m_eglSurface);
- m_eglSurface = 0;
+#ifndef QT_NO_OPENGL
+ if (m_surface) {
+ m_data.staticOpenGLContext->destroyWindowSurface(m_surface);
+ m_surface = 0;
}
#endif
#ifdef Q_OS_WINCE
@@ -1098,7 +1108,7 @@ bool QWindowsWindow::isEmbedded(const QPlatformWindow *parentWindow) const
return m_data.embedded;
}
-QPoint QWindowsWindow::mapToGlobal(const QPoint &pos) const
+QPoint QWindowsWindow::mapToGlobalDp(const QPoint &pos) const
{
if (m_data.hwnd)
return QWindowsGeometryHint::mapToGlobal(m_data.hwnd, pos);
@@ -1106,7 +1116,7 @@ QPoint QWindowsWindow::mapToGlobal(const QPoint &pos) const
return pos;
}
-QPoint QWindowsWindow::mapFromGlobal(const QPoint &pos) const
+QPoint QWindowsWindow::mapFromGlobalDp(const QPoint &pos) const
{
if (m_data.hwnd)
return QWindowsGeometryHint::mapFromGlobal(m_data.hwnd, pos);
@@ -1278,22 +1288,22 @@ static QRect normalFrameGeometry(HWND hwnd)
return QRect();
}
-QRect QWindowsWindow::normalGeometry() const
+QRect QWindowsWindow::normalGeometryDp() 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();
+ const QMargins margins = fakeFullScreen ? QWindowsGeometryHint::frame(m_savedStyle, 0) : frameMarginsDp();
return frame.isValid() ? frame.marginsRemoved(margins) : frame;
}
-void QWindowsWindow::setGeometry(const QRect &rectIn)
+void QWindowsWindow::setGeometryDp(const QRect &rectIn)
{
QRect rect = rectIn;
// This means it is a call from QWindow::setFramePosition() and
// the coordinates include the frame (size is still the contents rectangle).
if (QWindowsGeometryHint::positionIncludesFrame(window())) {
- const QMargins margins = frameMargins();
+ const QMargins margins = frameMarginsDp();
rect.moveTopLeft(rect.topLeft() + QPoint(margins.left(), margins.top()));
}
const QSize oldSize = m_data.geometry.size();
@@ -1375,13 +1385,19 @@ void QWindowsWindow::handleGeometryChange()
return;
const QRect previousGeometry = m_data.geometry;
m_data.geometry = geometry_sys();
- QPlatformWindow::setGeometry(m_data.geometry);
- QWindowSystemInterface::handleGeometryChange(window(), m_data.geometry);
+ const QRect geometryDip = QWindowsScaling::mapFromNative(m_data.geometry);
+ QPlatformWindow::setGeometry(geometryDip);
+ QWindowSystemInterface::handleGeometryChange(window(), geometryDip);
// QTBUG-32121: OpenGL/normal windows (with exception of ANGLE) do not receive
// expose events when shrinking, synthesize.
if (!testFlag(OpenGL_ES2) && isExposed()
&& !(m_data.geometry.width() > previousGeometry.width() || m_data.geometry.height() > previousGeometry.height())) {
- fireExpose(QRegion(m_data.geometry), true);
+ fireExpose(QRect(QPoint(0, 0), m_data.geometry.size()), true);
+ }
+ if (previousGeometry.topLeft() != m_data.geometry.topLeft()) {
+ QPlatformScreen *newScreen = screenForGeometry(m_data.geometry);
+ if (newScreen != screen())
+ QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
}
if (testFlag(SynchronousGeometryChangeEvent))
QWindowSystemInterface::flushWindowSystemEvents();
@@ -1391,7 +1407,7 @@ void QWindowsWindow::handleGeometryChange()
void QWindowsWindow::setGeometry_sys(const QRect &rect) const
{
- const QMargins margins = frameMargins();
+ const QMargins margins = frameMarginsDp();
const QRect frameGeometry = rect + margins;
qCDebug(lcQpaWindows) << '>' << __FUNCTION__ << this << window()
@@ -1399,22 +1415,37 @@ void QWindowsWindow::setGeometry_sys(const QRect &rect) const
<< margins << " to " <<rect
<< " new frame: " << frameGeometry;
- const bool rc = MoveWindow(m_data.hwnd, frameGeometry.x(), frameGeometry.y(),
- frameGeometry.width(), frameGeometry.height(), true);
+ bool result = false;
+#ifndef Q_OS_WINCE
+ WINDOWPLACEMENT windowPlacement;
+ windowPlacement.length = sizeof(WINDOWPLACEMENT);
+ GetWindowPlacement(m_data.hwnd, &windowPlacement);
+ // If the window is hidden and in maximized state or minimized, instead of moving the
+ // window, set the normal position of the window.
+ if ((windowPlacement.showCmd == SW_MAXIMIZE && !IsWindowVisible(m_data.hwnd))
+ || windowPlacement.showCmd == SW_SHOWMINIMIZED) {
+ windowPlacement.rcNormalPosition = RECTfromQRect(frameGeometry);
+ windowPlacement.showCmd = windowPlacement.showCmd == SW_SHOWMINIMIZED ? SW_SHOWMINIMIZED : SW_HIDE;
+ result = SetWindowPlacement(m_data.hwnd, &windowPlacement);
+ } else
+#endif // !Q_OS_WINCE
+ {
+ result = MoveWindow(m_data.hwnd, frameGeometry.x(), frameGeometry.y(),
+ frameGeometry.width(), frameGeometry.height(), true);
+ }
qCDebug(lcQpaWindows) << '<' << __FUNCTION__ << this << window()
- << " \n resulting " << rc << geometry_sys();
+ << " \n resulting " << result << geometry_sys();
}
QRect QWindowsWindow::frameGeometry_sys() const
{
- // Warning: Returns bogus values when minimized.
bool isRealTopLevel = window()->isTopLevel() && !m_data.embedded;
return frameGeometry(m_data.hwnd, isRealTopLevel);
}
QRect QWindowsWindow::geometry_sys() const
{
- return frameGeometry_sys().marginsRemoved(frameMargins());
+ return frameGeometry_sys().marginsRemoved(frameMarginsDp());
}
/*!
@@ -1487,7 +1518,7 @@ void QWindowsWindow::setWindowFlags(Qt::WindowFlags flags)
qCDebug(lcQpaWindows) << '>' << __FUNCTION__ << this << window() << "\n from: "
<< QWindowsWindow::debugWindowFlags(m_data.flags)
<< "\n to: " << QWindowsWindow::debugWindowFlags(flags);
- const QRect oldGeometry = geometry();
+ const QRect oldGeometry = geometryDp();
if (m_data.flags != flags) {
m_data.flags = flags;
if (m_data.hwnd) {
@@ -1573,23 +1604,10 @@ void QWindowsWindow::setWindowState(Qt::WindowState state)
}
}
-// Return the effective screen for full screen mode in a virtual desktop.
-static const QScreen *effectiveScreen(const QWindow *w)
-{
- QPoint center = w->geometry().center();
- if (!w->isTopLevel())
- center = w->mapToGlobal(center);
- const QScreen *screen = w->screen();
- if (!screen->geometry().contains(center))
- foreach (const QScreen *sibling, screen->virtualSiblings())
- if (sibling->geometry().contains(center))
- return sibling;
- return screen;
-}
-
bool QWindowsWindow::isFullScreen_sys() const
{
- return window()->isTopLevel() && geometry_sys() == effectiveScreen(window())->geometry();
+ return window()->isTopLevel()
+ && geometry_sys() == QWindowsScaling::mapToNative(window()->screen()->geometry());
}
/*!
@@ -1669,15 +1687,16 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
setStyle(newStyle);
// Use geometry of QWindow::screen() within creation or the virtual screen the
// window is in (QTBUG-31166, QTBUG-30724).
- const QScreen *screen = testFlag(WithinCreate) ? window()->screen() : effectiveScreen(window());
- const QRect r = screen->geometry();
+ const QScreen *screen = window()->screen();
+ const QRect rDip = screen->geometry();
+ const QRect r = QWindowsScaling::mapToNative(rDip);
const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
setFlag(SynchronousGeometryChangeEvent);
SetWindowPos(m_data.hwnd, HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf);
if (!wasSync)
clearFlag(SynchronousGeometryChangeEvent);
- QWindowSystemInterface::handleGeometryChange(window(), r);
+ QWindowSystemInterface::handleGeometryChange(window(), rDip);
QWindowSystemInterface::flushWindowSystemEvents();
} else if (newState != Qt::WindowMinimized) {
// Restore saved state.
@@ -1765,7 +1784,7 @@ void QWindowsWindow::propagateSizeHints()
qCDebug(lcQpaWindows) << __FUNCTION__ << this << window();
}
-QMargins QWindowsWindow::frameMargins() const
+QMargins QWindowsWindow::frameMarginsDp() const
{
// Frames are invalidated by style changes (window state, flags).
// As they are also required for geometry calculations in resize
@@ -1807,17 +1826,17 @@ static inline void addRectToWinRegion(const QRect &rect, HRGN *winRegion)
}
}
-static HRGN qRegionToWinRegion(const QRegion &region)
+static HRGN qRegionToWinRegion(const QRegion &regionDip)
{
- const QVector<QRect> rects = region.rects();
+ const QVector<QRect> rects = regionDip.rects();
if (rects.isEmpty())
return NULL;
const int rectCount = rects.size();
if (rectCount == 1)
- return createRectRegion(region.boundingRect());
+ return createRectRegion(QWindowsScaling::mapToNative(regionDip.boundingRect()));
HRGN hRegion = createRectRegion(rects.front());
for (int i = 1; i < rectCount; ++i)
- addRectToWinRegion(rects.at(i), &hRegion);
+ addRectToWinRegion(QWindowsScaling::mapToNative(rects.at(i)), &hRegion);
return hRegion;
}
@@ -1831,7 +1850,7 @@ void QWindowsWindow::setMask(const QRegion &region)
// Mask is in client area coordinates, so offset it in case we have a frame
if (window()->isTopLevel()) {
- const QMargins margins = frameMargins();
+ const QMargins margins = frameMarginsDp();
OffsetRgn(winRegion, margins.left(), margins.top());
}
@@ -1939,7 +1958,7 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
&& (m_data.flags & Qt::FramelessWindowHint)) {
// This block fixes QTBUG-8361: Frameless windows shouldn't cover the
// taskbar when maximized
- const QScreen *screen = effectiveScreen(window());
+ const QScreen *screen = window()->screen();
// Documentation of MINMAXINFO states that it will only work for the primary screen
if (screen && screen == QGuiApplication::primaryScreen()) {
@@ -1968,23 +1987,23 @@ bool QWindowsWindow::handleNonClientHitTest(const QPoint &globalPos, LRESULT *re
|| (m_data.flags & Qt::FramelessWindowHint)) {
return false;
}
- const QSize minimumSize = w->minimumSize();
+ const QSize minimumSize = QWindowsScaling::mapToNativeConstrained(w->minimumSize());
if (minimumSize.isEmpty())
return false;
- const QSize maximumSize = w->maximumSize();
+ const QSize maximumSize = QWindowsScaling::mapToNativeConstrained(w->maximumSize());
const bool fixedWidth = minimumSize.width() == maximumSize.width();
const bool fixedHeight = minimumSize.height() == maximumSize.height();
if (!fixedWidth && !fixedHeight)
return false;
- const QPoint localPos = w->mapFromGlobal(globalPos);
- const QSize size = w->size();
+ const QPoint localPos = mapFromGlobalDp(globalPos);
+ const QSize size = w->size() * QWindowsScaling::factor();
if (fixedHeight) {
if (localPos.y() >= size.height()) {
*result = HTBORDER; // Unspecified border, no resize cursor.
return true;
}
if (localPos.y() < 0) {
- const QMargins margins = frameMargins();
+ const QMargins margins = frameMarginsDp();
const int topResizeBarPos = margins.left() - margins.top();
if (localPos.y() < topResizeBarPos) {
*result = HTCAPTION; // Extend caption over top resize bar, let's user move the window.
@@ -2065,26 +2084,6 @@ void QWindowsWindow::setCursor(const QWindowsWindowCursor &c)
#endif
}
-/*!
- \brief Find a child window using flags from ChildWindowFromPointEx.
-*/
-
-QWindowsWindow *QWindowsWindow::childAtScreenPoint(const QPoint &screenPoint,
- unsigned cwexflags) const
-{
- if (m_data.hwnd)
- return QWindowsContext::instance()->findPlatformWindowAt(m_data.hwnd, screenPoint, cwexflags);
- return 0;
-}
-
-QWindowsWindow *QWindowsWindow::childAt(const QPoint &clientPoint, unsigned cwexflags) const
-{
- if (m_data.hwnd)
- return childAtScreenPoint(QWindowsGeometryHint::mapToGlobal(m_data.hwnd, clientPoint),
- cwexflags);
- return 0;
-}
-
#ifndef Q_OS_WINCE
void QWindowsWindow::setAlertState(bool enabled)
{
@@ -2144,23 +2143,6 @@ void QWindowsWindow::setEnabled(bool enabled)
setStyle(newStyle);
}
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
-EGLSurface QWindowsWindow::ensureEglSurfaceHandle(const QWindowsWindow::QWindowsEGLStaticContextPtr &staticContext, EGLConfig config)
-{
- if (!m_eglSurface) {
- m_staticEglContext = staticContext;
- m_eglSurface = eglCreateWindowSurface(staticContext->display(), config, (EGLNativeWindowType)m_data.hwnd, NULL);
- if (m_eglSurface == EGL_NO_SURFACE)
- qWarning("%s: Could not create the egl surface for %s/'%s' (eglCreateWindowSurface failed): error = 0x%x\n",
- Q_FUNC_INFO, window()->metaObject()->className(),
- qPrintable(window()->objectName()), eglGetError());
-
- qCDebug(lcQpaGl) << __FUNCTION__<<"Created EGL surface "<< m_eglSurface <<window();
- }
- return m_eglSurface;
-}
-#endif // QT_OPENGL_ES_2
-
QByteArray QWindowsWindow::debugWindowFlags(Qt::WindowFlags wf)
{
const int iwf = int(wf);
@@ -2253,6 +2235,10 @@ void QWindowsWindow::setWindowIcon(const QIcon &icon)
The property can be set using QPlatformNativeInterface::setWindowProperty() or,
before platform window creation, by setting a dynamic property
on the QWindow (see QWindowsIntegration::createPlatformWindow()).
+
+ Note: The function uses (unscaled) device pixels since the QWizard also
+ uses AdjustWindowRect() and using device independent pixels would introduce
+ rounding errors.
*/
void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins)
@@ -2272,4 +2258,16 @@ void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins)
}
}
+void *QWindowsWindow::surface(void *nativeConfig)
+{
+#ifdef QT_NO_OPENGL
+ return 0;
+#else
+ if (!m_surface)
+ m_surface = m_data.staticOpenGLContext->createWindowSurface(m_data.hwnd, nativeConfig);
+
+ return m_surface;
+#endif
+}
+
QT_END_NAMESPACE