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.cpp388
1 files changed, 252 insertions, 136 deletions
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 7f45b4817a..d9a7586096 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1,31 +1,37 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
@@ -37,6 +43,7 @@
#include "qwindowsdrag.h"
#include "qwindowsscreen.h"
#include "qwindowsintegration.h"
+#include "qwindowsnativeinterface.h"
#include "qwindowsopenglcontext.h"
#ifdef QT_NO_CURSOR
# include "qwindowscursor.h"
@@ -183,7 +190,7 @@ static QPoint windowPlacementOffset(HWND hwnd, const QPoint &point)
return QPoint(0, 0);
const QWindowsScreenManager &screenManager = QWindowsContext::instance()->screenManager();
const QWindowsScreen *screen = screenManager.screens().size() == 1
- ? screenManager.screens().first() : screenManager.screenAtDp(point);
+ ? screenManager.screens().constFirst() : screenManager.screenAtDp(point);
if (screen)
return screen->availableGeometry().topLeft() - screen->geometry().topLeft();
#else
@@ -248,13 +255,6 @@ static QWindow::Visibility windowVisibility_sys(HWND hwnd)
return QWindow::Windowed;
}
-static inline QSize clientSize(HWND hwnd)
-{
- RECT rect = { 0, 0, 0, 0 };
- GetClientRect(hwnd, &rect); // Always returns point 0,0, thus unusable for geometry.
- return qSizeOfRect(rect);
-}
-
static inline bool windowIsOpenGL(const QWindow *w)
{
switch (w->surfaceType()) {
@@ -377,12 +377,13 @@ static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, bo
Q_UNUSED(level);
#else
if (QWindowsWindow::setWindowLayered(hwnd, flags, hasAlpha, level)) {
+ const BYTE alpha = BYTE(qRound(255.0 * level));
if (hasAlpha && !openGL && (flags & Qt::FramelessWindowHint)) {
// Non-GL windows with alpha: Use blend function to update.
- BLENDFUNCTION blend = {AC_SRC_OVER, 0, (BYTE)(255.0 * level), AC_SRC_ALPHA};
+ BLENDFUNCTION blend = {AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA};
QWindowsContext::user32dll.updateLayeredWindow(hwnd, NULL, NULL, NULL, NULL, NULL, 0, &blend, ULW_ALPHA);
} else {
- QWindowsContext::user32dll.setLayeredWindowAttributes(hwnd, 0, (int)(level * 255), LWA_ALPHA);
+ QWindowsContext::user32dll.setLayeredWindowAttributes(hwnd, 0, alpha, LWA_ALPHA);
}
} else if (IsWindowVisible(hwnd)) { // Repaint when switching from layered.
InvalidateRect(hwnd, NULL, TRUE);
@@ -436,7 +437,7 @@ struct WindowCreationData
enum Flags { ForceChild = 0x1, ForceTopLevel = 0x2 };
WindowCreationData() : parentHandle(0), type(Qt::Widget), style(0), exStyle(0),
- topLevel(false), popup(false), dialog(false), desktop(false),
+ topLevel(false), popup(false), dialog(false),
tool(false), embedded(false), hasAlpha(false) {}
void fromWindow(const QWindow *w, const Qt::WindowFlags flags, unsigned creationFlags = 0);
@@ -452,7 +453,6 @@ struct WindowCreationData
bool topLevel;
bool popup;
bool dialog;
- bool desktop;
bool tool;
bool embedded;
bool hasAlpha;
@@ -467,7 +467,7 @@ QDebug operator<<(QDebug debug, const WindowCreationData &d)
<< "\n topLevel=" << d.topLevel;
if (d.parentHandle)
debug << " parent=" << d.parentHandle;
- debug << " popup=" << d.popup << " dialog=" << d.dialog << " desktop=" << d.desktop
+ debug << " popup=" << d.popup << " dialog=" << d.dialog
<< " embedded=" << d.embedded << " tool=" << d.tool
<< "\n style=" << debugWinStyle(d.style);
if (d.exStyle)
@@ -507,7 +507,7 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
QVariant prop = w->property("_q_embedded_native_parent_handle");
if (prop.isValid()) {
embedded = true;
- parentHandle = (HWND)prop.value<WId>();
+ parentHandle = reinterpret_cast<HWND>(prop.value<WId>());
}
if (creationFlags & ForceChild) {
@@ -536,9 +536,6 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
case Qt::Popup:
popup = true;
break;
- case Qt::Desktop:
- desktop = true;
- break;
default:
break;
}
@@ -555,7 +552,7 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
if (popup || (type == Qt::ToolTip) || (type == Qt::SplashScreen)) {
style = WS_POPUP;
- } else if (topLevel && !desktop) {
+ } else if (topLevel) {
if (flags & Qt::FramelessWindowHint)
style = WS_POPUP; // no border
else if (flags & Qt::WindowTitleHint)
@@ -566,7 +563,6 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
style = WS_CHILD;
}
- if (!desktop) {
// if (!testAttribute(Qt::WA_PaintUnclipped))
// ### Commented out for now as it causes some problems, but
// this should be correct anyway, so dig some more into this
@@ -612,7 +608,6 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
if (flagsIn & Qt::WindowTransparentForInput)
exStyle |= WS_EX_LAYERED | WS_EX_TRANSPARENT;
#endif
- }
}
}
@@ -624,26 +619,6 @@ QWindowsWindowData
WindowData result;
result.flags = flags;
- if (desktop) { // desktop widget. No frame, hopefully?
- result.hwnd = GetDesktopWindow();
- result.geometry = frameGeometry(result.hwnd, true);
- result.embedded = false;
- qCDebug(lcQpaWindows) << "Created desktop window " << w << result.hwnd;
- return result;
- }
- if ((flags & Qt::WindowType_Mask) == Qt::ForeignWindow) {
- result.hwnd = reinterpret_cast<HWND>(w->winId());
- Q_ASSERT(result.hwnd);
- const LONG_PTR style = GetWindowLongPtr(result.hwnd, GWL_STYLE);
- const LONG_PTR exStyle = GetWindowLongPtr(result.hwnd, GWL_EXSTYLE);
- result.embedded = false;
- result.frame = QWindowsGeometryHint::frame(style, exStyle);
- result.geometry = frameGeometry(result.hwnd, !GetParent(result.hwnd))
- .marginsRemoved(result.frame);
- qCDebug(lcQpaWindows) << "Foreign window: " << w << result.hwnd << result.geometry;
- return result;
- }
-
const HINSTANCE appinst = (HINSTANCE)GetModuleHandle(0);
const QString windowClassName = QWindowsContext::instance()->registerWindowClass(w);
@@ -707,15 +682,15 @@ void WindowCreationData::applyWindowFlags(HWND hwnd) const
if (newExStyle != oldExStyle)
SetWindowLongPtr(hwnd, GWL_EXSTYLE, newExStyle);
qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << hwnd << *this
- << "\n Style from " << debugWinStyle(oldStyle) << "\n to "
- << debugWinStyle(newStyle) << "\n ExStyle from "
- << debugWinExStyle(oldExStyle) << " to "
- << debugWinExStyle(newExStyle);
+ << "\n Style from " << debugWinStyle(DWORD(oldStyle)) << "\n to "
+ << debugWinStyle(DWORD(newStyle)) << "\n ExStyle from "
+ << debugWinExStyle(DWORD(oldExStyle)) << " to "
+ << debugWinExStyle(DWORD(newExStyle));
}
void WindowCreationData::initialize(const QWindow *w, HWND hwnd, bool frameChange, qreal opacityLevel) const
{
- if (desktop || !hwnd)
+ if (!hwnd)
return;
UINT swpFlags = SWP_NOMOVE | SWP_NOSIZE;
if (frameChange)
@@ -829,8 +804,8 @@ bool QWindowsGeometryHint::handleCalculateSize(const QMargins &customMargins, co
#ifndef Q_OS_WINCE
void QWindowsGeometryHint::applyToMinMaxInfo(HWND hwnd, MINMAXINFO *mmi) const
{
- return applyToMinMaxInfo(GetWindowLong(hwnd, GWL_STYLE),
- GetWindowLong(hwnd, GWL_EXSTYLE), mmi);
+ return applyToMinMaxInfo(DWORD(GetWindowLong(hwnd, GWL_STYLE)),
+ DWORD(GetWindowLong(hwnd, GWL_EXSTYLE)), mmi);
}
void QWindowsGeometryHint::applyToMinMaxInfo(DWORD style, DWORD exStyle, MINMAXINFO *mmi) const
@@ -867,6 +842,153 @@ bool QWindowsGeometryHint::positionIncludesFrame(const QWindow *w)
}
/*!
+ \class QWindowsBaseWindow
+ \brief Base class for QWindowsForeignWindow, QWindowsWindow
+
+ The class provides some _sys() getters for querying window
+ data from a HWND and some _sys() setters.
+
+ Derived classes wrapping foreign windows may use them directly
+ to calculate geometry, margins, etc.
+
+ Derived classes representing windows created by Qt may defer
+ expensive calculations until change notifications are received.
+
+ \since 5.6
+ \internal
+ \ingroup qt-lighthouse-win
+*/
+
+QWindowsBaseWindow *QWindowsBaseWindow::baseWindowOf(const QWindow *w)
+{
+ if (w) {
+ if (QPlatformWindow *pw = w->handle())
+ return static_cast<QWindowsBaseWindow *>(pw);
+ }
+ return Q_NULLPTR;
+}
+
+HWND QWindowsBaseWindow::handleOf(const QWindow *w)
+{
+ const QWindowsBaseWindow *bw = QWindowsBaseWindow::baseWindowOf(w);
+ return bw ? bw->handle() : HWND(0);
+}
+
+bool QWindowsBaseWindow::isTopLevel_sys() const
+{
+ const HWND parent = parentHwnd();
+ return !parent || parent == GetDesktopWindow();
+}
+
+QRect QWindowsBaseWindow::frameGeometry_sys() const
+{
+ return frameGeometry(handle(), isTopLevel());
+}
+
+QRect QWindowsBaseWindow::geometry_sys() const
+{
+ return frameGeometry_sys().marginsRemoved(frameMargins());
+}
+
+QMargins QWindowsBaseWindow::frameMargins_sys() const
+{
+ return QWindowsGeometryHint::frame(style(), exStyle());
+}
+
+void QWindowsBaseWindow::hide_sys() // Normal hide, do not activate other windows.
+{
+ SetWindowPos(handle(),0 , 0, 0, 0, 0,
+ SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
+}
+
+void QWindowsBaseWindow::raise_sys()
+{
+ qCDebug(lcQpaWindows) << __FUNCTION__ << this << window();
+ SetWindowPos(handle(), HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+}
+
+void QWindowsBaseWindow::lower_sys()
+{
+ qCDebug(lcQpaWindows) << __FUNCTION__ << this << window();
+ SetWindowPos(handle(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+}
+
+void QWindowsBaseWindow::setWindowTitle_sys(const QString &title)
+{
+ qCDebug(lcQpaWindows) << __FUNCTION__ << this << window() << title;
+ SetWindowText(handle(), reinterpret_cast<const wchar_t *>(title.utf16()));
+}
+
+QPoint QWindowsBaseWindow::mapToGlobal(const QPoint &pos) const
+{
+ return QWindowsGeometryHint::mapToGlobal(handle(), pos);
+}
+
+QPoint QWindowsBaseWindow::mapFromGlobal(const QPoint &pos) const
+{
+ return QWindowsGeometryHint::mapFromGlobal(handle(), pos);
+}
+
+/*!
+ \class QWindowsDesktopWindow
+ \brief Window wrapping GetDesktopWindow not allowing any manipulation.
+ \since 5.6
+ \internal
+ \ingroup qt-lighthouse-win
+*/
+
+/*!
+ \class QWindowsForeignWindow
+ \brief Window wrapping a foreign native window.
+
+ QWindowsForeignWindow stores a native HWND and implements getters for
+ geometry, margins, etc. reparenting and geometry manipulation for use as a
+ child window in Qt.
+
+ \since 5.6
+ \internal
+ \ingroup qt-lighthouse-win
+*/
+
+QWindowsForeignWindow::QWindowsForeignWindow(QWindow *window, HWND hwnd)
+ : QWindowsBaseWindow(window)
+ , m_hwnd(hwnd)
+ , m_topLevelStyle(0)
+{
+}
+
+void QWindowsForeignWindow::setParent(const QPlatformWindow *newParentWindow)
+{
+ const bool wasTopLevel = isTopLevel_sys();
+ const HWND newParent = newParentWindow ? reinterpret_cast<HWND>(newParentWindow->winId()) : HWND(0);
+ const bool isTopLevel = !newParent;
+ const DWORD oldStyle = style();
+ qCDebug(lcQpaWindows) << __FUNCTION__ << window() << "newParent="
+ << newParentWindow << newParent << "oldStyle=" << debugWinStyle(oldStyle);
+ SetParent(m_hwnd, newParent);
+ if (wasTopLevel != isTopLevel) { // Top level window flags need to be set/cleared manually.
+ DWORD newStyle = oldStyle;
+ if (isTopLevel) {
+ newStyle = m_topLevelStyle;
+ } else {
+ m_topLevelStyle = oldStyle;
+ newStyle &= ~(WS_OVERLAPPEDWINDOW | WS_POPUPWINDOW);
+ newStyle |= WS_CHILD;
+ }
+ SetWindowLongPtr(m_hwnd, GWL_STYLE, newStyle);
+ }
+}
+
+void QWindowsForeignWindow::setVisible(bool visible)
+{
+ qCDebug(lcQpaWindows) << __FUNCTION__ << window() << visible;
+ if (visible)
+ ShowWindow(handle(), SW_SHOWNOACTIVATE);
+ else
+ hide_sys();
+}
+
+/*!
\class QWindowCreationContext
\brief Active Context for creating windows.
@@ -946,7 +1068,7 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w,
*/
QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) :
- QPlatformWindow(aWindow),
+ QWindowsBaseWindow(aWindow),
m_data(data),
m_flags(WithinCreate),
m_hdc(0),
@@ -1024,7 +1146,7 @@ void QWindowsWindow::destroyWindow()
setFlag(WithinDestroy);
// Clear any transient child relationships as Windows will otherwise destroy them (QTBUG-35499, QTBUG-36666)
if (QWindow *transientChild = findTransientChild(window()))
- if (QWindowsWindow *tw = QWindowsWindow::baseWindowOf(transientChild))
+ if (QWindowsWindow *tw = QWindowsWindow::windowsWindowOf(transientChild))
tw->updateTransientParent();
QWindowsContext *context = QWindowsContext::instance();
if (context->windowUnderMouse() == window())
@@ -1047,8 +1169,7 @@ void QWindowsWindow::destroyWindow()
}
}
#endif // !Q_OS_WINCE
- if (m_data.hwnd != GetDesktopWindow() && window()->type() != Qt::ForeignWindow)
- DestroyWindow(m_data.hwnd);
+ DestroyWindow(m_data.hwnd);
context->removeWindow(m_data.hwnd);
m_data.hwnd = 0;
}
@@ -1161,7 +1282,10 @@ void QWindowsWindow::setVisible(bool visible)
} else {
if (hasMouseCapture())
setMouseGrabEnabled(false);
- hide_sys();
+ if (window()->flags() & Qt::Popup) // from QWidgetPrivate::hide_sys(), activate other
+ ShowWindow(m_data.hwnd, SW_HIDE);
+ else
+ hide_sys();
fireExpose(QRegion());
}
}
@@ -1237,11 +1361,11 @@ void QWindowsWindow::updateTransientParent() const
const HWND oldTransientParent = transientParentHwnd(m_data.hwnd);
HWND newTransientParent = 0;
if (const QWindow *tp = window()->transientParent())
- if (const QWindowsWindow *tw = QWindowsWindow::baseWindowOf(tp))
+ if (const QWindowsWindow *tw = QWindowsWindow::windowsWindowOf(tp))
if (!tw->testFlag(WithinDestroy)) // Prevent destruction by parent window (QTBUG-35499, QTBUG-36666)
newTransientParent = tw->handle();
if (newTransientParent != oldTransientParent)
- SetWindowLongPtr(m_data.hwnd, GWL_HWNDPARENT, (LONG_PTR)newTransientParent);
+ SetWindowLongPtr(m_data.hwnd, GWL_HWNDPARENT, LONG_PTR(newTransientParent));
#endif // !Q_OS_WINCE
}
@@ -1301,18 +1425,6 @@ void QWindowsWindow::show_sys() const
}
}
-// partially from QWidgetPrivate::hide_sys()
-void QWindowsWindow::hide_sys() const
-{
- const Qt::WindowFlags flags = window()->flags();
- if (flags != Qt::Desktop) {
- if (flags & Qt::Popup)
- ShowWindow(m_data.hwnd, SW_HIDE);
- else
- SetWindowPos(m_data.hwnd,0, 0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE);
- }
-}
-
void QWindowsWindow::setParent(const QPlatformWindow *newParent)
{
qCDebug(lcQpaWindows) << __FUNCTION__ << window() << newParent;
@@ -1324,7 +1436,7 @@ void QWindowsWindow::setParent(const QPlatformWindow *newParent)
void QWindowsWindow::setParent_sys(const QPlatformWindow *parent)
{
// Use GetAncestor instead of GetParent, as GetParent can return owner window for toplevels
- HWND oldParentHWND = GetAncestor(m_data.hwnd, GA_PARENT);
+ HWND oldParentHWND = parentHwnd();
HWND newParentHWND = 0;
if (parent) {
const QWindowsWindow *parentW = static_cast<const QWindowsWindow *>(parent);
@@ -1474,7 +1586,9 @@ void QWindowsWindow::handleGeometryChange()
// 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())) {
+ && m_data.geometry.size() != previousGeometry.size() // Exclude plain move
+ // One dimension grew -> Windows will send expose, no need to synthesize.
+ && !(m_data.geometry.width() > previousGeometry.width() || m_data.geometry.height() > previousGeometry.height())) {
fireExpose(QRect(QPoint(0, 0), m_data.geometry.size()), true);
}
if (previousGeometry.topLeft() != m_data.geometry.topLeft()) {
@@ -1488,7 +1602,7 @@ void QWindowsWindow::handleGeometryChange()
qCDebug(lcQpaEvents) << __FUNCTION__ << this << window() << m_data.geometry;
}
-void QWindowsWindow::setGeometry_sys(const QRect &rect) const
+void QWindowsBaseWindow::setGeometry_sys(const QRect &rect) const
{
const QMargins margins = frameMargins();
const QRect frameGeometry = rect + margins;
@@ -1500,38 +1614,28 @@ void QWindowsWindow::setGeometry_sys(const QRect &rect) const
bool result = false;
#ifndef Q_OS_WINCE
+ const HWND hwnd = handle();
WINDOWPLACEMENT windowPlacement;
windowPlacement.length = sizeof(WINDOWPLACEMENT);
- GetWindowPlacement(m_data.hwnd, &windowPlacement);
+ GetWindowPlacement(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))
+ if ((windowPlacement.showCmd == SW_MAXIMIZE && !IsWindowVisible(hwnd))
|| windowPlacement.showCmd == SW_SHOWMINIMIZED) {
windowPlacement.rcNormalPosition =
- RECTfromQRect(frameGeometry.translated(-windowPlacementOffset(m_data.hwnd, frameGeometry.topLeft())));
+ RECTfromQRect(frameGeometry.translated(-windowPlacementOffset(hwnd, frameGeometry.topLeft())));
windowPlacement.showCmd = windowPlacement.showCmd == SW_SHOWMINIMIZED ? SW_SHOWMINIMIZED : SW_HIDE;
- result = SetWindowPlacement(m_data.hwnd, &windowPlacement);
+ result = SetWindowPlacement(hwnd, &windowPlacement);
} else
#endif // !Q_OS_WINCE
{
- result = MoveWindow(m_data.hwnd, frameGeometry.x(), frameGeometry.y(),
+ result = MoveWindow(hwnd, frameGeometry.x(), frameGeometry.y(),
frameGeometry.width(), frameGeometry.height(), true);
}
qCDebug(lcQpaWindows) << '<' << __FUNCTION__ << window()
<< "\n resulting " << result << geometry_sys();
}
-QRect QWindowsWindow::frameGeometry_sys() const
-{
- bool isRealTopLevel = window()->isTopLevel() && !m_data.embedded;
- return frameGeometry(m_data.hwnd, isRealTopLevel);
-}
-
-QRect QWindowsWindow::geometry_sys() const
-{
- return frameGeometry_sys().marginsRemoved(frameMargins());
-}
-
/*!
Allocates a HDC for the window or returns the temporary one
obtained from WinAPI BeginPaint within a WM_PAINT event.
@@ -1590,11 +1694,7 @@ bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message,
void QWindowsWindow::setWindowTitle(const QString &title)
{
- qCDebug(lcQpaWindows) << __FUNCTION__ << this << window() <<title;
- if (m_data.hwnd) {
- const QString fullTitle = formatWindowTitle(title, QStringLiteral(" - "));
- SetWindowText(m_data.hwnd, (const wchar_t*)fullTitle.utf16());
- }
+ setWindowTitle_sys(QWindowsWindow::formatWindowTitle(title, QStringLiteral(" - ")));
}
void QWindowsWindow::setWindowFlags(Qt::WindowFlags flags)
@@ -1661,8 +1761,8 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowState state)
}
foreach (QWindow *child, QGuiApplication::allWindows()) {
if (child != w && child->isVisible() && child->transientParent() == w) {
- QWindowsWindow *platformWindow = QWindowsWindow::baseWindowOf(child);
- if (platformWindow->isLayered()) {
+ QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(child);
+ if (platformWindow && platformWindow->isLayered()) {
platformWindow->fireExpose(QRegion(0, 0, child->width(), child->height()));
exposeEventsSent = true;
}
@@ -1841,19 +1941,6 @@ void QWindowsWindow::setExStyle(unsigned s) const
SetWindowLongPtr(m_data.hwnd, GWL_EXSTYLE, s);
}
-void QWindowsWindow::raise()
-{
- qCDebug(lcQpaWindows) << __FUNCTION__ << this << window();
- SetWindowPos(m_data.hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
-}
-
-void QWindowsWindow::lower()
-{
- qCDebug(lcQpaWindows) << __FUNCTION__ << this << window();
- if (m_data.hwnd)
- SetWindowPos(m_data.hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
-}
-
void QWindowsWindow::windowEvent(QEvent *event)
{
switch (event->type()) {
@@ -1921,7 +2008,7 @@ QMargins QWindowsWindow::frameMargins() const
// Always skip calculating style-dependent margins for windows claimed to be frameless.
// This allows users to remove the margins by handling WM_NCCALCSIZE with WS_THICKFRAME set
// to ensure Areo snap still works (QTBUG-40578).
- m_data.frame = window()->flags() & Qt::FramelessWindowHint
+ m_data.frame = m_data.flags & Qt::FramelessWindowHint
? QMargins(0, 0, 0, 0)
: QWindowsGeometryHint::frame(style(), exStyle());
clearFlag(FrameDirty);
@@ -1932,7 +2019,7 @@ QMargins QWindowsWindow::frameMargins() const
void QWindowsWindow::setOpacity(qreal level)
{
qCDebug(lcQpaWindows) << __FUNCTION__ << level;
- if (m_opacity != level) {
+ if (!qFuzzyCompare(m_opacity, level)) {
m_opacity = level;
if (m_data.hwnd)
setWindowOpacity(m_data.hwnd, m_data.flags,
@@ -1997,8 +2084,30 @@ void QWindowsWindow::requestActivateWindow()
// 'Active' state handling is based in focus since it needs to work for
// child windows as well.
if (m_data.hwnd) {
+#ifndef Q_OS_WINCE
+ const DWORD currentThread = GetCurrentThreadId();
+ bool attached = false;
+ DWORD foregroundThread = 0;
+
+ // QTBUG-14062, QTBUG-37435: Windows normally only flashes the taskbar entry
+ // when activating windows of inactive applications. Attach to the input of the
+ // currently active window while setting the foreground window to always activate
+ // the window when desired.
+ if (QGuiApplication::applicationState() != Qt::ApplicationActive
+ && QWindowsNativeInterface::windowActivationBehavior() == QWindowsWindowFunctions::AlwaysActivateWindow) {
+ if (const HWND foregroundWindow = GetForegroundWindow()) {
+ foregroundThread = GetWindowThreadProcessId(foregroundWindow, NULL);
+ if (foregroundThread && foregroundThread != currentThread)
+ attached = AttachThreadInput(foregroundThread, currentThread, TRUE) == TRUE;
+ }
+ }
+#endif // !Q_OS_WINCE
SetForegroundWindow(m_data.hwnd);
SetFocus(m_data.hwnd);
+#ifndef Q_OS_WINCE
+ if (attached)
+ AttachThreadInput(foregroundThread, currentThread, FALSE);
+#endif // !Q_OS_WINCE
}
}
@@ -2094,14 +2203,15 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
// Documentation of MINMAXINFO states that it will only work for the primary screen
if (screen && screen == QGuiApplication::primaryScreen()) {
- mmi->ptMaxSize.y = screen->availableGeometry().height();
+ const QRect availableGeometry = QHighDpi::toNativePixels(screen->availableGeometry(), screen);
+ mmi->ptMaxSize.y = availableGeometry.height();
// Width, because you can have the taskbar on the sides too.
- mmi->ptMaxSize.x = screen->availableGeometry().width();
+ mmi->ptMaxSize.x = availableGeometry.width();
// If you have the taskbar on top, or on the left you don't want it at (0,0):
- mmi->ptMaxPosition.x = screen->availableGeometry().x();
- mmi->ptMaxPosition.y = screen->availableGeometry().y();
+ mmi->ptMaxPosition.x = availableGeometry.x();
+ mmi->ptMaxPosition.y = availableGeometry.y();
} else if (!screen){
qWarning() << "window()->screen() returned a null screen";
}
@@ -2174,7 +2284,8 @@ static inline bool applyNewCursor(const QWindow *w)
for (const QWindow *p = underMouse; p ; p = p->parent()) {
if (p == w)
return true;
- if (!QWindowsWindow::baseWindowOf(p)->cursor()->isNull())
+ const QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(p);
+ if (platformWindow && !platformWindow->cursor()->isNull())
return false;
}
return false;
@@ -2192,7 +2303,8 @@ void QWindowsWindow::applyCursor()
#ifndef QT_NO_CURSOR
if (m_cursor->isNull()) { // Recurse up to parent with non-null cursor. Set default for toplevel.
if (const QWindow *p = window()->parent()) {
- QWindowsWindow::baseWindowOf(p)->applyCursor();
+ if (QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(p))
+ platformWindow->applyCursor();
} else {
SetCursor(defaultCursor(window())->handle());
}
@@ -2232,7 +2344,7 @@ void QWindowsWindow::setAlertState(bool enabled)
void QWindowsWindow::alertWindow(int durationMs)
{
- DWORD timeOutMs = GetCaretBlinkTime();
+ UINT timeOutMs = GetCaretBlinkTime();
if (!timeOutMs || timeOutMs == INFINITE)
timeOutMs = 250;
@@ -2241,7 +2353,7 @@ void QWindowsWindow::alertWindow(int durationMs)
info.hwnd = m_data.hwnd;
info.dwFlags = FLASHW_TRAY;
info.dwTimeout = timeOutMs;
- info.uCount = durationMs == 0 ? 10 : durationMs / timeOutMs;
+ info.uCount = durationMs == 0 ? 10 : UINT(durationMs) / timeOutMs;
FlashWindowEx(&info);
}
@@ -2294,15 +2406,20 @@ void QWindowsWindow::setWindowIcon(const QIcon &icon)
m_iconBig = createHIcon(icon, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
if (m_iconBig) {
- SendMessage(m_data.hwnd, WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)m_iconSmall);
- SendMessage(m_data.hwnd, WM_SETICON, 1 /* ICON_BIG */, (LPARAM)m_iconBig);
+ SendMessage(m_data.hwnd, WM_SETICON, 0 /* ICON_SMALL */, LPARAM(m_iconSmall));
+ SendMessage(m_data.hwnd, WM_SETICON, 1 /* ICON_BIG */, LPARAM(m_iconBig));
} else {
- SendMessage(m_data.hwnd, WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)m_iconSmall);
- SendMessage(m_data.hwnd, WM_SETICON, 1 /* ICON_BIG */, (LPARAM)m_iconSmall);
+ SendMessage(m_data.hwnd, WM_SETICON, 0 /* ICON_SMALL */, LPARAM(m_iconSmall));
+ SendMessage(m_data.hwnd, WM_SETICON, 1 /* ICON_BIG */, LPARAM(m_iconSmall));
}
}
}
+bool QWindowsWindow::isTopLevel() const
+{
+ return window()->isTopLevel() && !m_data.embedded;
+}
+
/*!
\brief Sets custom margins to be added to the default margins determined by
the windows style in the handling of the WM_NCCALCSIZE message.
@@ -2367,15 +2484,14 @@ void QWindowsWindow::setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWind
void QWindowsWindow::registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes)
{
#ifndef Q_OS_WINCE
- if ((QWindowsContext::instance()->systemInfo() & QWindowsContext::SI_SupportsTouch)
- && window()->type() != Qt::ForeignWindow) {
+ if ((QWindowsContext::instance()->systemInfo() & QWindowsContext::SI_SupportsTouch)) {
ULONG touchFlags = 0;
const bool ret = QWindowsContext::user32dll.isTouchWindow(m_data.hwnd, &touchFlags);
// Return if it is not a touch window or the flags are already set by a hook
// such as HCBT_CREATEWND
if (ret || touchFlags != 0)
return;
- if (QWindowsContext::user32dll.registerTouchWindow(m_data.hwnd, (ULONG)touchTypes))
+ if (QWindowsContext::user32dll.registerTouchWindow(m_data.hwnd, ULONG(touchTypes)))
setFlag(TouchRegistered);
else
qErrnoWarning("RegisterTouchWindow() failed for window '%s'.", qPrintable(window()->objectName()));