Merge remote-tracking branch 'origin/5.12' into 5.13

Change-Id: Id3d16035c9692af42e9c1bf512218f3c836ae2eb
This commit is contained in:
Friedemann Kleint 2019-05-14 08:23:41 +02:00
commit 00e1917f85
13 changed files with 278 additions and 97 deletions

View File

@ -41,7 +41,9 @@
#include "qguiapplication.h"
#include "qscreen.h"
#include "qplatformintegration.h"
#include "qplatformwindow.h"
#include "private/qscreen_p.h"
#include <private/qguiapplication_p.h>
#include <QtCore/qdebug.h>
@ -376,6 +378,46 @@ QPoint QHighDpiScaling::mapPositionFromNative(const QPoint &pos, const QPlatform
return (pos - topLeft) / scaleFactor + topLeft;
}
QPoint QHighDpiScaling::mapPositionToGlobal(const QPoint &pos, const QPoint &windowGlobalPosition, const QWindow *window)
{
QPoint globalPosCandidate = pos + windowGlobalPosition;
if (QGuiApplicationPrivate::screen_list.size() <= 1)
return globalPosCandidate;
// The global position may be outside device independent screen geometry
// in cases where a window spans screens. Detect this case and map via
// native coordinates to the correct screen.
auto currentScreen = window->screen();
if (currentScreen && !currentScreen->geometry().contains(globalPosCandidate)) {
auto nativeGlobalPos = QHighDpi::toNativePixels(globalPosCandidate, currentScreen);
if (auto actualPlatformScreen = currentScreen->handle()->screenForPosition(nativeGlobalPos))
return QHighDpi::fromNativePixels(nativeGlobalPos, actualPlatformScreen->screen());
}
return globalPosCandidate;
}
QPoint QHighDpiScaling::mapPositionFromGlobal(const QPoint &pos, const QPoint &windowGlobalPosition, const QWindow *window)
{
QPoint windowPosCandidate = pos - windowGlobalPosition;
if (QGuiApplicationPrivate::screen_list.size() <= 1)
return windowPosCandidate;
// Device independent global (screen) space may discontiguous when high-dpi scaling
// is active. This means that the normal subtracting of the window global position from the
// position-to-be-mapped may not work in cases where a window spans multiple screens.
// Map both positions to native global space (using the correct screens), subtract there,
// and then map the difference back using the scale factor for the window.
QScreen *posScreen = QGuiApplication::screenAt(pos);
if (posScreen && posScreen != window->screen()) {
QPoint nativePos = QHighDpi::toNativePixels(pos, posScreen);
QPoint windowNativePos = window->handle()->geometry().topLeft();
return QHighDpi::fromNativeLocalPosition(nativePos - windowNativePos, window);
}
return windowPosCandidate;
}
qreal QHighDpiScaling::screenSubfactor(const QPlatformScreen *screen)
{
qreal factor = qreal(1.0);

View File

@ -83,8 +83,10 @@ public:
static qreal factor(const QPlatformScreen *platformScreen);
static QPoint origin(const QScreen *screen);
static QPoint origin(const QPlatformScreen *platformScreen);
static QPoint mapPositionFromNative(const QPoint &pos, const QPlatformScreen *platformScreen);
static QPoint mapPositionToNative(const QPoint &pos, const QPlatformScreen *platformScreen);
static QPoint mapPositionFromNative(const QPoint &pos, const QPlatformScreen *platformScreen);
static QPoint mapPositionToGlobal(const QPoint &pos, const QPoint &windowGlobalPosition, const QWindow *window);
static QPoint mapPositionFromGlobal(const QPoint &pos, const QPoint &windowGlobalPosition, const QWindow *window);
static QDpi logicalDpi();
private:

View File

@ -1682,9 +1682,9 @@ void QWindow::setGeometry(const QRect &rect)
chicken and egg problem here: we cannot convert to native coordinates
before we know which screen we are on.
*/
QScreen *QWindowPrivate::screenForGeometry(const QRect &newGeometry)
QScreen *QWindowPrivate::screenForGeometry(const QRect &newGeometry) const
{
Q_Q(QWindow);
Q_Q(const QWindow);
QScreen *currentScreen = q->screen();
QScreen *fallback = currentScreen;
QPoint center = newGeometry.center();
@ -2554,6 +2554,10 @@ QPoint QWindow::mapToGlobal(const QPoint &pos) const
&& (d->platformWindow->isForeignWindow() || d->platformWindow->isEmbedded())) {
return QHighDpi::fromNativeLocalPosition(d->platformWindow->mapToGlobal(QHighDpi::toNativeLocalPosition(pos, this)), this);
}
if (QHighDpiScaling::isActive())
return QHighDpiScaling::mapPositionToGlobal(pos, d->globalPosition(), this);
return pos + d->globalPosition();
}
@ -2574,6 +2578,10 @@ QPoint QWindow::mapFromGlobal(const QPoint &pos) const
&& (d->platformWindow->isForeignWindow() || d->platformWindow->isEmbedded())) {
return QHighDpi::fromNativeLocalPosition(d->platformWindow->mapFromGlobal(QHighDpi::toNativeLocalPosition(pos, this)), this);
}
if (QHighDpiScaling::isActive())
return QHighDpiScaling::mapPositionFromGlobal(pos, d->globalPosition(), this);
return pos - d->globalPosition();
}

View File

@ -148,7 +148,7 @@ public:
void connectToScreen(QScreen *topLevelScreen);
void disconnectFromScreen();
void emitScreenChangedRecursion(QScreen *newScreen);
QScreen *screenForGeometry(const QRect &rect);
QScreen *screenForGeometry(const QRect &rect) const;
void setTransientParent(QWindow *parent);
virtual void clearFocusObject();

View File

@ -189,6 +189,15 @@
- (void)displayLayer:(CALayer *)layer
{
if (!NSThread.isMainThread) {
// Qt is calling AppKit APIs such as -[NSOpenGLContext setView:] on secondary threads,
// which we shouldn't do. This may result in AppKit (wrongly) triggering a display on
// the thread where we made the call, so block it here and defer to the main thread.
qCWarning(lcQpaDrawing) << "Display non non-main thread! Deferring to main thread";
dispatch_async(dispatch_get_main_queue(), ^{ self.needsDisplay = YES; });
return;
}
Q_ASSERT(layer == self.layer);
if (!m_platformWindow)

View File

@ -210,6 +210,7 @@ void QWindowsUser32DLL::init()
if (QOperatingSystemVersion::current()
>= QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 14393)) {
adjustWindowRectExForDpi = (AdjustWindowRectExForDpi)library.resolve("AdjustWindowRectExForDpi");
enableNonClientDpiScaling = (EnableNonClientDpiScaling)library.resolve("EnableNonClientDpiScaling");
getWindowDpiAwarenessContext = (GetWindowDpiAwarenessContext)library.resolve("GetWindowDpiAwarenessContext");
getAwarenessFromDpiAwarenessContext = (GetAwarenessFromDpiAwarenessContext)library.resolve("GetAwarenessFromDpiAwarenessContext");
@ -977,7 +978,7 @@ static inline bool resizeOnDpiChanged(const QWindow *w)
return result;
}
static bool shouldHaveNonClientDpiScaling(const QWindow *window)
bool QWindowsContext::shouldHaveNonClientDpiScaling(const QWindow *window)
{
return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10
&& window->isTopLevel()
@ -1321,17 +1322,24 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
#endif
} break;
case QtWindows::DpiChangedEvent: {
if (!resizeOnDpiChanged(platformWindow->window()))
return false;
platformWindow->setFlag(QWindowsWindow::WithinDpiChanged);
const RECT *prcNewWindow = reinterpret_cast<RECT *>(lParam);
qCDebug(lcQpaWindows) << __FUNCTION__ << "WM_DPICHANGED"
<< platformWindow->window() << *prcNewWindow;
SetWindowPos(hwnd, nullptr, prcNewWindow->left, prcNewWindow->top,
prcNewWindow->right - prcNewWindow->left,
prcNewWindow->bottom - prcNewWindow->top, SWP_NOZORDER | SWP_NOACTIVATE);
platformWindow->clearFlag(QWindowsWindow::WithinDpiChanged);
return true;
// Try to apply the suggested size first and then notify ScreenChanged
// so that the resize event sent from QGuiApplication incorporates it
// WM_DPICHANGED is sent with a size that avoids resize loops (by
// snapping back to the previous screen, see QTBUG-65580).
const bool doResize = resizeOnDpiChanged(platformWindow->window());
if (doResize) {
platformWindow->setFlag(QWindowsWindow::WithinDpiChanged);
platformWindow->updateFullFrameMargins();
const auto prcNewWindow = reinterpret_cast<RECT *>(lParam);
qCDebug(lcQpaWindows) << __FUNCTION__ << "WM_DPICHANGED"
<< platformWindow->window() << *prcNewWindow;
SetWindowPos(hwnd, nullptr, prcNewWindow->left, prcNewWindow->top,
prcNewWindow->right - prcNewWindow->left,
prcNewWindow->bottom - prcNewWindow->top, SWP_NOZORDER | SWP_NOACTIVATE);
platformWindow->clearFlag(QWindowsWindow::WithinDpiChanged);
}
platformWindow->checkForScreenChanged(QWindowsWindow::FromDpiChange);
return doResize;
}
#if QT_CONFIG(sessionmanager)
case QtWindows::QueryEndSessionApplicationEvent: {
@ -1589,6 +1597,7 @@ extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPAR
marginsFromRects(ncCalcSizeFrame, rectFromNcCalcSize(message, wParam, lParam, 0));
if (margins.left() >= 0) {
if (platformWindow) {
qCDebug(lcQpaWindows) << __FUNCTION__ << "WM_NCCALCSIZE for" << hwnd << margins;
platformWindow->setFullFrameMargins(margins);
} else {
const QSharedPointer<QWindowCreationContext> ctx = QWindowsContext::instance()->windowCreationContext();

View File

@ -102,6 +102,7 @@ struct QWindowsUser32DLL
typedef BOOL (WINAPI *RemoveClipboardFormatListener)(HWND);
typedef BOOL (WINAPI *GetDisplayAutoRotationPreferences)(DWORD *);
typedef BOOL (WINAPI *SetDisplayAutoRotationPreferences)(DWORD);
typedef BOOL (WINAPI *AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
typedef BOOL (WINAPI *EnableNonClientDpiScaling)(HWND);
typedef int (WINAPI *GetWindowDpiAwarenessContext)(HWND);
typedef int (WINAPI *GetAwarenessFromDpiAwarenessContext)(int);
@ -131,6 +132,7 @@ struct QWindowsUser32DLL
GetDisplayAutoRotationPreferences getDisplayAutoRotationPreferences = nullptr;
SetDisplayAutoRotationPreferences setDisplayAutoRotationPreferences = nullptr;
AdjustWindowRectExForDpi adjustWindowRectExForDpi = nullptr;
EnableNonClientDpiScaling enableNonClientDpiScaling = nullptr;
GetWindowDpiAwarenessContext getWindowDpiAwarenessContext = nullptr;
GetAwarenessFromDpiAwarenessContext getAwarenessFromDpiAwarenessContext = nullptr;
@ -201,6 +203,8 @@ public:
QWindowsWindow *findPlatformWindowAt(HWND parent, const QPoint &screenPoint,
unsigned cwex_flags) const;
static bool shouldHaveNonClientDpiScaling(const QWindow *window);
QWindow *windowUnderMouse() const;
void clearWindowUnderMouse();

View File

@ -353,6 +353,9 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
QWindowsWindow *result = createPlatformWindowHelper(window, obtained);
Q_ASSERT(result);
if (window->isTopLevel() && !QWindowsContext::shouldHaveNonClientDpiScaling(window))
result->setFlag(QWindowsWindow::DisableNonClientScaling);
if (QWindowsMenuBar *menuBarToBeInstalled = QWindowsMenuBar::menuBarOf(window))
menuBarToBeInstalled->install(result);

View File

@ -435,6 +435,12 @@ QPlatformScreen::SubpixelAntialiasingType QWindowsScreen::subpixelAntialiasingTy
QWindowsScreenManager::QWindowsScreenManager() = default;
bool QWindowsScreenManager::isSingleScreen()
{
return QWindowsContext::instance()->screenManager().screens().size() < 2;
}
/*!
\brief Triggers synchronization of screens (WM_DISPLAYCHANGE).

View File

@ -138,6 +138,8 @@ public:
const QWindowsScreen *screenAtDp(const QPoint &p) const;
const QWindowsScreen *screenForHwnd(HWND hwnd) const;
static bool isSingleScreen();
private:
void removeScreen(int index);

View File

@ -870,26 +870,11 @@ static QSize toNativeSizeConstrained(QSize dip, const QWindow *w)
\ingroup qt-lighthouse-win
*/
QWindowsGeometryHint::QWindowsGeometryHint(const QWindow *w, const QMargins &cm) :
minimumSize(toNativeSizeConstrained(w->minimumSize(), w)),
maximumSize(toNativeSizeConstrained(w->maximumSize(), w)),
customMargins(cm)
{
}
bool QWindowsGeometryHint::validSize(const QSize &s) const
{
const int width = s.width();
const int height = s.height();
return width >= minimumSize.width() && width <= maximumSize.width()
&& height >= minimumSize.height() && height <= maximumSize.height();
}
QMargins QWindowsGeometryHint::frame(DWORD style, DWORD exStyle)
QMargins QWindowsGeometryHint::frameOnPrimaryScreen(DWORD style, DWORD exStyle)
{
RECT rect = {0,0,0,0};
style &= ~(WS_OVERLAPPED); // Not permitted, see docs.
if (!AdjustWindowRectEx(&rect, style, FALSE, exStyle))
style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
if (AdjustWindowRectEx(&rect, style, FALSE, exStyle) == FALSE)
qErrnoWarning("%s: AdjustWindowRectEx failed", __FUNCTION__);
const QMargins result(qAbs(rect.left), qAbs(rect.top),
qAbs(rect.right), qAbs(rect.bottom));
@ -899,6 +884,64 @@ QMargins QWindowsGeometryHint::frame(DWORD style, DWORD exStyle)
return result;
}
QMargins QWindowsGeometryHint::frameOnPrimaryScreen(HWND hwnd)
{
return frameOnPrimaryScreen(DWORD(GetWindowLongPtr(hwnd, GWL_STYLE)),
DWORD(GetWindowLongPtr(hwnd, GWL_EXSTYLE)));
}
QMargins QWindowsGeometryHint::frame(DWORD style, DWORD exStyle, qreal dpi)
{
if (QWindowsContext::user32dll.adjustWindowRectExForDpi == nullptr)
return frameOnPrimaryScreen(style, exStyle);
RECT rect = {0,0,0,0};
style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
if (QWindowsContext::user32dll.adjustWindowRectExForDpi(&rect, style, FALSE, exStyle,
unsigned(qRound(dpi))) == FALSE) {
qErrnoWarning("%s: AdjustWindowRectExForDpi failed", __FUNCTION__);
}
const QMargins result(qAbs(rect.left), qAbs(rect.top),
qAbs(rect.right), qAbs(rect.bottom));
qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << " style="
<< showbase << hex << style << " exStyle=" << exStyle << dec << noshowbase
<< " dpi=" << dpi
<< ' ' << rect << ' ' << result;
return result;
}
QMargins QWindowsGeometryHint::frame(HWND hwnd, DWORD style, DWORD exStyle)
{
if (QWindowsScreenManager::isSingleScreen())
return frameOnPrimaryScreen(style, exStyle);
auto screenManager = QWindowsContext::instance()->screenManager();
auto screen = screenManager.screenForHwnd(hwnd);
if (!screen)
screen = screenManager.screens().value(0);
const auto dpi = screen ? screen->logicalDpi().first : qreal(96);
return frame(style, exStyle, dpi);
}
// For newly created windows.
QMargins QWindowsGeometryHint::frame(const QWindow *w, const QRect &geometry,
DWORD style, DWORD exStyle)
{
if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint))
return {};
if (!QWindowsContext::user32dll.adjustWindowRectExForDpi
|| QWindowsScreenManager::isSingleScreen()
|| !QWindowsContext::shouldHaveNonClientDpiScaling(w)) {
return frameOnPrimaryScreen(style, exStyle);
}
qreal dpi = 96;
auto screenManager = QWindowsContext::instance()->screenManager();
auto screen = screenManager.screenAtDp(geometry.center());
if (!screen)
screen = screenManager.screens().value(0);
if (screen)
dpi = screen->logicalDpi().first;
return QWindowsGeometryHint::frame(style, exStyle, dpi);
}
bool QWindowsGeometryHint::handleCalculateSize(const QMargins &customMargins, const MSG &msg, LRESULT *result)
{
// NCCALCSIZE_PARAMS structure if wParam==TRUE
@ -918,36 +961,50 @@ bool QWindowsGeometryHint::handleCalculateSize(const QMargins &customMargins, co
return true;
}
void QWindowsGeometryHint::applyToMinMaxInfo(HWND hwnd, MINMAXINFO *mmi) const
void QWindowsGeometryHint::frameSizeConstraints(const QWindow *w, const QMargins &margins,
QSize *minimumSize, QSize *maximumSize)
{
return applyToMinMaxInfo(DWORD(GetWindowLong(hwnd, GWL_STYLE)),
DWORD(GetWindowLong(hwnd, GWL_EXSTYLE)), mmi);
*minimumSize = toNativeSizeConstrained(w->minimumSize(), w);
*maximumSize = toNativeSizeConstrained(w->maximumSize(), w);
const int maximumWidth = qMax(maximumSize->width(), minimumSize->width());
const int maximumHeight = qMax(maximumSize->height(), minimumSize->height());
const int frameWidth = margins.left() + margins.right();
const int frameHeight = margins.top() + margins.bottom();
if (minimumSize->width() > 0)
minimumSize->rwidth() += frameWidth;
if (minimumSize->height() > 0)
minimumSize->rheight() += frameHeight;
if (maximumWidth < QWINDOWSIZE_MAX)
maximumSize->setWidth(maximumWidth + frameWidth);
if (maximumHeight < QWINDOWSIZE_MAX)
maximumSize->setHeight(maximumHeight + frameHeight);
}
void QWindowsGeometryHint::applyToMinMaxInfo(DWORD style, DWORD exStyle, MINMAXINFO *mmi) const
void QWindowsGeometryHint::applyToMinMaxInfo(const QWindow *w,
const QMargins &margins,
MINMAXINFO *mmi)
{
QSize minimumSize;
QSize maximumSize;
frameSizeConstraints(w, margins, &minimumSize, &maximumSize);
qCDebug(lcQpaWindows).nospace() << '>' << __FUNCTION__ << '<' << " min="
<< minimumSize.width() << ',' << minimumSize.height()
<< " max=" << maximumSize.width() << ',' << maximumSize.height()
<< " margins=" << margins
<< " in " << *mmi;
const QMargins margins = QWindowsGeometryHint::frame(style, exStyle);
const int frameWidth = margins.left() + margins.right() + customMargins.left() + customMargins.right();
const int frameHeight = margins.top() + margins.bottom() + customMargins.top() + customMargins.bottom();
if (minimumSize.width() > 0)
mmi->ptMinTrackSize.x = minimumSize.width() + frameWidth;
mmi->ptMinTrackSize.x = minimumSize.width();
if (minimumSize.height() > 0)
mmi->ptMinTrackSize.y = minimumSize.height() + frameHeight;
mmi->ptMinTrackSize.y = minimumSize.height();
const int maximumWidth = qMax(maximumSize.width(), minimumSize.width());
const int maximumHeight = qMax(maximumSize.height(), minimumSize.height());
if (maximumWidth < QWINDOWSIZE_MAX)
mmi->ptMaxTrackSize.x = maximumWidth + frameWidth;
if (maximumHeight < QWINDOWSIZE_MAX)
mmi->ptMaxTrackSize.y = maximumHeight + frameHeight;
qCDebug(lcQpaWindows).nospace() << '<' << __FUNCTION__
<< " frame=" << margins << ' ' << frameWidth << ',' << frameHeight
<< " out " << *mmi;
if (maximumSize.width() < QWINDOWSIZE_MAX)
mmi->ptMaxTrackSize.x = maximumSize.width();
if (maximumSize.height() < QWINDOWSIZE_MAX)
mmi->ptMaxTrackSize.y = maximumSize.height();
qCDebug(lcQpaWindows).nospace() << '<' << __FUNCTION__ << " out " << *mmi;
}
bool QWindowsGeometryHint::positionIncludesFrame(const QWindow *w)
@ -1007,7 +1064,7 @@ QRect QWindowsBaseWindow::geometry_sys() const
QMargins QWindowsBaseWindow::frameMargins_sys() const
{
return QWindowsGeometryHint::frame(style(), exStyle());
return QWindowsGeometryHint::frame(handle(), style(), exStyle());
}
void QWindowsBaseWindow::hide_sys() // Normal hide, do not activate other windows.
@ -1133,11 +1190,12 @@ void QWindowsForeignWindow::setVisible(bool visible)
QWindowCreationContext::QWindowCreationContext(const QWindow *w,
const QRect &geometryIn, const QRect &geometry,
const QMargins &cm,
DWORD style_, DWORD exStyle_) :
geometryHint(w, cm), window(w), style(style_), exStyle(exStyle_),
DWORD style, DWORD exStyle) :
window(w),
requestedGeometryIn(geometryIn),
requestedGeometry(geometry), obtainedGeometry(geometry),
margins(QWindowsGeometryHint::frame(style, exStyle)), customMargins(cm)
margins(QWindowsGeometryHint::frame(w, geometry, style, exStyle)),
customMargins(cm)
{
// Geometry of toplevels does not consider window frames.
// TODO: No concept of WA_wasMoved yet that would indicate a
@ -1166,8 +1224,12 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w,
<< " pos incl. frame=" << QWindowsGeometryHint::positionIncludesFrame(w)
<< " frame=" << frameWidth << 'x' << frameHeight << '+'
<< frameX << '+' << frameY
<< " min=" << geometryHint.minimumSize << " max=" << geometryHint.maximumSize
<< " custom margins=" << customMargins;
<< " margins=" << margins << " custom margins=" << customMargins;
}
void QWindowCreationContext::applyToMinMaxInfo(MINMAXINFO *mmi) const
{
QWindowsGeometryHint::applyToMinMaxInfo(window, margins + customMargins, mmi);
}
/*!
@ -1683,7 +1745,9 @@ QRect QWindowsWindow::normalGeometry() const
const bool fakeFullScreen =
m_savedFrameGeometry.isValid() && (window()->windowStates() & Qt::WindowFullScreen);
const QRect frame = fakeFullScreen ? m_savedFrameGeometry : normalFrameGeometry(m_data.hwnd);
const QMargins margins = fakeFullScreen ? QWindowsGeometryHint::frame(m_savedStyle, 0) : fullFrameMargins();
const QMargins margins = fakeFullScreen
? QWindowsGeometryHint::frame(handle(), m_savedStyle, 0)
: fullFrameMargins();
return frame.isValid() ? frame.marginsRemoved(margins) : frame;
}
@ -1798,27 +1862,41 @@ void QWindowsWindow::handleResized(int wParam)
}
}
void QWindowsWindow::checkForScreenChanged()
static inline bool equalDpi(const QDpi &d1, const QDpi &d2)
{
if (parent())
return qFuzzyCompare(d1.first, d2.first) && qFuzzyCompare(d1.second, d2.second);
}
void QWindowsWindow::checkForScreenChanged(ScreenChangeMode mode)
{
if (parent() || QWindowsScreenManager::isSingleScreen())
return;
QPlatformScreen *currentScreen = screen();
const auto &screenManager = QWindowsContext::instance()->screenManager();
const QWindowsScreen *newScreen = screenManager.screenForHwnd(m_data.hwnd);
if (newScreen != nullptr && newScreen != currentScreen) {
qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__
<< ' ' << window() << " \"" << currentScreen->name()
<< "\"->\"" << newScreen->name() << '"';
setFlag(SynchronousGeometryChangeEvent);
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
const QWindowsScreen *newScreen =
QWindowsContext::instance()->screenManager().screenForHwnd(m_data.hwnd);
if (newScreen == nullptr || newScreen == currentScreen)
return;
// For screens with different DPI: postpone until WM_DPICHANGE
if (mode == FromGeometryChange
&& !equalDpi(currentScreen->logicalDpi(), newScreen->logicalDpi())) {
return;
}
qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__
<< ' ' << window() << " \"" << currentScreen->name()
<< "\"->\"" << newScreen->name() << '"';
if (mode == FromGeometryChange)
setFlag(SynchronousGeometryChangeEvent);
updateFullFrameMargins();
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
}
void QWindowsWindow::handleGeometryChange()
{
const QRect previousGeometry = m_data.geometry;
m_data.geometry = geometry_sys();
if (testFlag(WithinDpiChanged))
return; // QGuiApplication will send resize
QWindowSystemInterface::handleGeometryChange(window(), m_data.geometry);
// QTBUG-32121: OpenGL/normal windows (with exception of ANGLE) do not receive
// expose events when shrinking, synthesize.
@ -2281,6 +2359,15 @@ void QWindowsWindow::setFullFrameMargins(const QMargins &newMargins)
}
}
void QWindowsWindow::updateFullFrameMargins()
{
// Normally obtained from WM_NCCALCSIZE
const auto systemMargins = testFlag(DisableNonClientScaling)
? QWindowsGeometryHint::frameOnPrimaryScreen(m_data.hwnd)
: frameMargins_sys();
setFullFrameMargins(systemMargins + m_data.customMargins);
}
QMargins QWindowsWindow::frameMargins() const
{
QMargins result = fullFrameMargins();
@ -2491,10 +2578,8 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
{
// We don't apply the min/max size hint as we change the dpi, because we did not adjust the
// QScreen of the window yet so we don't have the min/max with the right ratio
if (!testFlag(QWindowsWindow::WithinDpiChanged)) {
const QWindowsGeometryHint hint(window(), m_data.customMargins);
hint.applyToMinMaxInfo(m_data.hwnd, mmi);
}
if (!testFlag(QWindowsWindow::WithinDpiChanged))
QWindowsGeometryHint::applyToMinMaxInfo(window(), fullFrameMargins(), mmi);
// This block fixes QTBUG-8361, QTBUG-4362: Frameless/title-less windows shouldn't cover the
// taskbar when maximized

View File

@ -59,24 +59,23 @@ class QDebug;
struct QWindowsGeometryHint
{
QWindowsGeometryHint() = default;
explicit QWindowsGeometryHint(const QWindow *w, const QMargins &customMargins);
static QMargins frame(DWORD style, DWORD exStyle);
static QMargins frameOnPrimaryScreen(DWORD style, DWORD exStyle);
static QMargins frameOnPrimaryScreen(HWND hwnd);
static QMargins frame(DWORD style, DWORD exStyle, qreal dpi);
static QMargins frame(HWND hwnd, DWORD style, DWORD exStyle);
static QMargins frame(const QWindow *w, const QRect &geometry,
DWORD style, DWORD exStyle);
static bool handleCalculateSize(const QMargins &customMargins, const MSG &msg, LRESULT *result);
void applyToMinMaxInfo(DWORD style, DWORD exStyle, MINMAXINFO *mmi) const;
void applyToMinMaxInfo(HWND hwnd, MINMAXINFO *mmi) const;
bool validSize(const QSize &s) const;
static void applyToMinMaxInfo(const QWindow *w, const QMargins &margins,
MINMAXINFO *mmi);
static void frameSizeConstraints(const QWindow *w, const QMargins &margins,
QSize *minimumSize, QSize *maximumSize);
static inline QPoint mapToGlobal(HWND hwnd, const QPoint &);
static inline QPoint mapToGlobal(const QWindow *w, const QPoint &);
static inline QPoint mapFromGlobal(const HWND hwnd, const QPoint &);
static inline QPoint mapFromGlobal(const QWindow *w, const QPoint &);
static bool positionIncludesFrame(const QWindow *w);
QSize minimumSize;
QSize maximumSize;
QMargins customMargins;
};
struct QWindowCreationContext
@ -85,13 +84,9 @@ struct QWindowCreationContext
const QRect &geometryIn, const QRect &geometry,
const QMargins &customMargins,
DWORD style, DWORD exStyle);
void applyToMinMaxInfo(MINMAXINFO *mmi) const
{ geometryHint.applyToMinMaxInfo(style, exStyle, mmi); }
void applyToMinMaxInfo(MINMAXINFO *mmi) const;
QWindowsGeometryHint geometryHint;
const QWindow *window;
DWORD style;
DWORD exStyle;
QRect requestedGeometryIn; // QWindow scaled
QRect requestedGeometry; // after QPlatformWindow::initialGeometry()
QRect obtainedGeometry;
@ -221,7 +216,8 @@ public:
HasBorderInFullScreen = 0x200000,
WithinDpiChanged = 0x400000,
VulkanSurface = 0x800000,
ResizeMoveActive = 0x1000000
ResizeMoveActive = 0x1000000,
DisableNonClientScaling = 0x2000000
};
QWindowsWindow(QWindow *window, const QWindowsWindowData &data);
@ -262,6 +258,7 @@ public:
QMargins frameMargins() const override;
QMargins fullFrameMargins() const override;
void setFullFrameMargins(const QMargins &newMargins);
void updateFullFrameMargins();
void setOpacity(qreal level) override;
void setMask(const QRegion &region) override;
@ -337,7 +334,8 @@ public:
void alertWindow(int durationMs = 0);
void stopAlertWindow();
void checkForScreenChanged();
enum ScreenChangeMode { FromGeometryChange, FromDpiChange };
void checkForScreenChanged(ScreenChangeMode mode = FromGeometryChange);
static void setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes);
void registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes = QWindowsWindowFunctions::NormalTouch);

View File

@ -897,11 +897,15 @@ QHeaderView *QAccessibleTableCell::verticalHeader() const
int QAccessibleTableCell::columnIndex() const
{
if (!isValid())
return -1;
return m_index.column();
}
int QAccessibleTableCell::rowIndex() const
{
if (!isValid())
return -1;
#if QT_CONFIG(treeview)
if (role() == QAccessible::TreeItem) {
const QTreeView *treeView = qobject_cast<const QTreeView*>(view);
@ -915,6 +919,8 @@ int QAccessibleTableCell::rowIndex() const
bool QAccessibleTableCell::isSelected() const
{
if (!isValid())
return false;
return view->selectionModel()->isSelected(m_index);
}
@ -943,8 +949,10 @@ QStringList QAccessibleTableCell::keyBindingsForAction(const QString &) const
void QAccessibleTableCell::selectCell()
{
if (!isValid())
return;
QAbstractItemView::SelectionMode selectionMode = view->selectionMode();
if (!m_index.isValid() || (selectionMode == QAbstractItemView::NoSelection))
if (selectionMode == QAbstractItemView::NoSelection)
return;
Q_ASSERT(table());
QAccessibleTableInterface *cellTable = table()->tableInterface();
@ -971,9 +979,10 @@ void QAccessibleTableCell::selectCell()
void QAccessibleTableCell::unselectCell()
{
if (!isValid())
return;
QAbstractItemView::SelectionMode selectionMode = view->selectionMode();
if (!m_index.isValid() || (selectionMode == QAbstractItemView::NoSelection))
if (selectionMode == QAbstractItemView::NoSelection)
return;
QAccessibleTableInterface *cellTable = table()->tableInterface();
@ -1014,7 +1023,7 @@ QAccessible::Role QAccessibleTableCell::role() const
QAccessible::State QAccessibleTableCell::state() const
{
QAccessible::State st;
if (!view)
if (!isValid())
return st;
QRect globalRect = view->rect();
@ -1054,6 +1063,8 @@ QAccessible::State QAccessibleTableCell::state() const
QRect QAccessibleTableCell::rect() const
{
QRect r;
if (!isValid())
return r;
r = view->visualRect(m_index);
if (!r.isNull()) {
@ -1065,8 +1076,10 @@ QRect QAccessibleTableCell::rect() const
QString QAccessibleTableCell::text(QAccessible::Text t) const
{
QAbstractItemModel *model = view->model();
QString value;
if (!isValid())
return value;
QAbstractItemModel *model = view->model();
switch (t) {
case QAccessible::Name:
value = model->data(m_index, Qt::AccessibleTextRole).toString();
@ -1084,7 +1097,7 @@ QString QAccessibleTableCell::text(QAccessible::Text t) const
void QAccessibleTableCell::setText(QAccessible::Text /*t*/, const QString &text)
{
if (!(m_index.flags() & Qt::ItemIsEditable))
if (!isValid() || !(m_index.flags() & Qt::ItemIsEditable))
return;
view->model()->setData(m_index, text);
}