Merge remote-tracking branch 'origin/5.12' into 5.13
Change-Id: Id3d16035c9692af42e9c1bf512218f3c836ae2eb
This commit is contained in:
commit
00e1917f85
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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).
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 ®ion) 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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user