diff options
Diffstat (limited to 'src/plugins/platforms/windows')
37 files changed, 1032 insertions, 637 deletions
diff --git a/src/plugins/platforms/windows/main.cpp b/src/plugins/platforms/windows/main.cpp index 8bde87c975..1929f800a4 100644 --- a/src/plugins/platforms/windows/main.cpp +++ b/src/plugins/platforms/windows/main.cpp @@ -112,7 +112,7 @@ QPlatformIntegration *QWindowsIntegrationPlugin::create(const QString& system, c { if (system.compare(system, QLatin1String("windows"), Qt::CaseInsensitive) == 0) return new QWindowsGdiIntegration(paramList); - return 0; + return nullptr; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp index 03b44458ac..68807fabdd 100644 --- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp +++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp @@ -102,7 +102,8 @@ void QWindowsBackingStore::flush(QWindow *window, const QRegion ®ion, BLENDFUNCTION blend = {AC_SRC_OVER, 0, BYTE(qRound(255.0 * rw->opacity())), AC_SRC_ALPHA}; RECT dirty = {dirtyRect.x(), dirtyRect.y(), dirtyRect.x() + dirtyRect.width(), dirtyRect.y() + dirtyRect.height()}; - UPDATELAYEREDWINDOWINFO info = {sizeof(info), NULL, &ptDst, &size, m_image->hdc(), &ptSrc, 0, &blend, ULW_ALPHA, &dirty}; + UPDATELAYEREDWINDOWINFO info = {sizeof(info), nullptr, &ptDst, &size, + m_image->hdc(), &ptSrc, 0, &blend, ULW_ALPHA, &dirty}; const BOOL result = UpdateLayeredWindowIndirect(rw->handle(), &info); if (!result) qErrnoWarning("UpdateLayeredWindowIndirect failed for ptDst=(%d, %d)," @@ -207,7 +208,7 @@ HDC QWindowsBackingStore::getDC() const { if (!m_image.isNull()) return m_image->hdc(); - return 0; + return nullptr; } QImage QWindowsBackingStore::toImage() const diff --git a/src/plugins/platforms/windows/qwindowsclipboard.cpp b/src/plugins/platforms/windows/qwindowsclipboard.cpp index 8b386da9f7..b87e43f3f7 100644 --- a/src/plugins/platforms/windows/qwindowsclipboard.cpp +++ b/src/plugins/platforms/windows/qwindowsclipboard.cpp @@ -115,13 +115,13 @@ static QDebug operator<<(QDebug d, const QMimeData *mimeData) IDataObject *QWindowsClipboardRetrievalMimeData::retrieveDataObject() const { - IDataObject * pDataObj = 0; + IDataObject * pDataObj = nullptr; if (OleGetClipboard(&pDataObj) == S_OK) { if (QWindowsContext::verbose > 1) qCDebug(lcQpaMime) << __FUNCTION__ << pDataObj; return pDataObj; } - return 0; + return nullptr; } void QWindowsClipboardRetrievalMimeData::releaseDataObject(IDataObject *dataObject) const @@ -148,7 +148,7 @@ static void cleanClipboardPostRoutine() cl->cleanup(); } -QWindowsClipboard *QWindowsClipboard::m_instance = 0; +QWindowsClipboard *QWindowsClipboard::m_instance = nullptr; QWindowsClipboard::QWindowsClipboard() { @@ -159,7 +159,7 @@ QWindowsClipboard::QWindowsClipboard() QWindowsClipboard::~QWindowsClipboard() { cleanup(); - QWindowsClipboard::m_instance = 0; + QWindowsClipboard::m_instance = nullptr; } void QWindowsClipboard::cleanup() @@ -174,7 +174,7 @@ void QWindowsClipboard::releaseIData() delete m_data->mimeData(); m_data->releaseQt(); m_data->Release(); - m_data = 0; + m_data = nullptr; } } @@ -207,10 +207,10 @@ void QWindowsClipboard::unregisterViewer() m_formatListenerRegistered = false; } else { ChangeClipboardChain(m_clipboardViewer, m_nextClipboardViewer); - m_nextClipboardViewer = 0; + m_nextClipboardViewer = nullptr; } DestroyWindow(m_clipboardViewer); - m_clipboardViewer = 0; + m_clipboardViewer = nullptr; } } @@ -300,7 +300,7 @@ QMimeData *QWindowsClipboard::mimeData(QClipboard::Mode mode) { qCDebug(lcQpaMime) << __FUNCTION__ << mode; if (mode != QClipboard::Clipboard) - return 0; + return nullptr; if (ownsClipboard()) return m_data->mimeData(); return &m_retrievalData; @@ -341,7 +341,7 @@ void QWindowsClipboard::setMimeData(QMimeData *mimeData, QClipboard::Mode mode) void QWindowsClipboard::clear() { - const HRESULT src = OleSetClipboard(0); + const HRESULT src = OleSetClipboard(nullptr); if (src != S_OK) qErrnoWarning("OleSetClipboard: Failed to clear the clipboard: 0x%lx", src); } diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 13a60af5a7..e14a0c1984 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -112,7 +112,7 @@ static inline bool useRTL_Extensions() { // Since the IsValidLanguageGroup/IsValidLocale functions always return true on // Vista, check the Keyboard Layouts for enabling RTL. - if (const int nLayouts = GetKeyboardLayoutList(0, 0)) { + if (const int nLayouts = GetKeyboardLayoutList(0, nullptr)) { QScopedArrayPointer<HKL> lpList(new HKL[nLayouts]); GetKeyboardLayoutList(nLayouts, lpList.data()); for (int i = 0; i < nLayouts; ++i) { @@ -148,7 +148,7 @@ static inline bool sessionManagerInteractionBlocked() { return false; } static inline int windowDpiAwareness(HWND hwnd) { - return QWindowsContext::user32dll.getWindowDpiAwarenessContext && QWindowsContext::user32dll.getWindowDpiAwarenessContext + return QWindowsContext::user32dll.getWindowDpiAwarenessContext && QWindowsContext::user32dll.getAwarenessFromDpiAwarenessContext ? QWindowsContext::user32dll.getAwarenessFromDpiAwarenessContext(QWindowsContext::user32dll.getWindowDpiAwarenessContext(hwnd)) : -1; } @@ -213,6 +213,7 @@ void QWindowsUser32DLL::init() enableNonClientDpiScaling = (EnableNonClientDpiScaling)library.resolve("EnableNonClientDpiScaling"); getWindowDpiAwarenessContext = (GetWindowDpiAwarenessContext)library.resolve("GetWindowDpiAwarenessContext"); getAwarenessFromDpiAwarenessContext = (GetAwarenessFromDpiAwarenessContext)library.resolve("GetAwarenessFromDpiAwarenessContext"); + systemParametersInfoForDpi = (SystemParametersInfoForDpi)library.resolve("SystemParametersInfoForDpi"); } } @@ -236,7 +237,7 @@ void QWindowsShcoreDLL::init() QWindowsUser32DLL QWindowsContext::user32dll; QWindowsShcoreDLL QWindowsContext::shcoredll; -QWindowsContext *QWindowsContext::m_instance = 0; +QWindowsContext *QWindowsContext::m_instance = nullptr; /*! \class QWindowsContext @@ -256,7 +257,7 @@ struct QWindowsContextPrivate { unsigned m_systemInfo = 0; QSet<QString> m_registeredWindowClassNames; HandleBaseWindowHash m_windows; - HDC m_displayContext = 0; + HDC m_displayContext = nullptr; int m_defaultDPI = 96; QWindowsKeyMapper m_keyMapper; QWindowsMouseHandler m_mouseHandler; @@ -273,14 +274,14 @@ struct QWindowsContextPrivate { }; QWindowsContextPrivate::QWindowsContextPrivate() - : m_oleInitializeResult(OleInitialize(NULL)) + : m_oleInitializeResult(OleInitialize(nullptr)) { QWindowsContext::user32dll.init(); QWindowsContext::shcoredll.init(); if (m_pointerHandler.touchDevice() || m_mouseHandler.touchDevice()) m_systemInfo |= QWindowsContext::SI_SupportsTouch; - m_displayContext = GetDC(0); + m_displayContext = GetDC(nullptr); m_defaultDPI = GetDeviceCaps(m_displayContext, LOGPIXELSY); if (useRTL_Extensions()) { m_systemInfo |= QWindowsContext::SI_RTL_Extensions; @@ -315,7 +316,7 @@ QWindowsContext::~QWindowsContext() OleUninitialize(); d->m_screenManager.clearScreens(); // Order: Potentially calls back to the windows. - m_instance = 0; + m_instance = nullptr; } bool QWindowsContext::initTouch() @@ -333,12 +334,8 @@ bool QWindowsContext::initTouch(unsigned integrationOptions) if (!touchDevice) return false; - if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) { - QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false); - } else { - if (!(integrationOptions & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch)) - touchDevice->setCapabilities(touchDevice->capabilities() | QTouchDevice::MouseEmulation); - } + if (!(integrationOptions & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch)) + touchDevice->setCapabilities(touchDevice->capabilities() | QTouchDevice::MouseEmulation); QWindowSystemInterface::registerTouchDevice(touchDevice); @@ -375,7 +372,6 @@ bool QWindowsContext::initPointer(unsigned integrationOptions) if (!QWindowsContext::user32dll.supportsPointerApi()) return false; - QWindowsContext::user32dll.enableMouseInPointer(TRUE); d->m_systemInfo |= QWindowsContext::SI_SupportsPointer; return true; } @@ -399,7 +395,7 @@ int QWindowsContext::processDpiAwareness() { int result; if (QWindowsContext::shcoredll.getProcessDpiAwareness - && SUCCEEDED(QWindowsContext::shcoredll.getProcessDpiAwareness(NULL, &result))) { + && SUCCEEDED(QWindowsContext::shcoredll.getProcessDpiAwareness(nullptr, &result))) { return result; } return -1; @@ -548,7 +544,7 @@ QString QWindowsContext::registerWindowClass(QString cname, // add an instance-specific ID, the address of the window proc. static int classExists = -1; - const HINSTANCE appInstance = static_cast<HINSTANCE>(GetModuleHandle(0)); + const HINSTANCE appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr)); if (classExists == -1) { WNDCLASS wcinfo; classExists = GetClassInfo(appInstance, reinterpret_cast<LPCWSTR>(cname.utf16()), &wcinfo); @@ -568,7 +564,7 @@ QString QWindowsContext::registerWindowClass(QString cname, wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = appInstance; - wc.hCursor = 0; + wc.hCursor = nullptr; wc.hbrBackground = brush; if (icon) { wc.hIcon = static_cast<HICON>(LoadImage(appInstance, L"IDI_ICON1", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE)); @@ -577,15 +573,15 @@ QString QWindowsContext::registerWindowClass(QString cname, int sh = GetSystemMetrics(SM_CYSMICON); wc.hIconSm = static_cast<HICON>(LoadImage(appInstance, L"IDI_ICON1", IMAGE_ICON, sw, sh, 0)); } else { - wc.hIcon = static_cast<HICON>(LoadImage(0, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED)); - wc.hIconSm = 0; + wc.hIcon = static_cast<HICON>(LoadImage(nullptr, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED)); + wc.hIconSm = nullptr; } } else { - wc.hIcon = 0; - wc.hIconSm = 0; + wc.hIcon = nullptr; + wc.hIconSm = nullptr; } - wc.lpszMenuName = 0; + wc.lpszMenuName = nullptr; wc.lpszClassName = reinterpret_cast<LPCWSTR>(cname.utf16()); ATOM atom = RegisterClassEx(&wc); if (!atom) @@ -601,7 +597,7 @@ QString QWindowsContext::registerWindowClass(QString cname, void QWindowsContext::unregisterWindowClasses() { - const HINSTANCE appInstance = static_cast<HINSTANCE>(GetModuleHandle(0)); + const HINSTANCE appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr)); for (const QString &name : qAsConst(d->m_registeredWindowClassNames)) { if (!UnregisterClass(reinterpret_cast<LPCWSTR>(name.utf16()), appInstance) && QWindowsContext::verbose) @@ -622,7 +618,7 @@ QString QWindowsContext::windowsErrorMessage(unsigned long errorCode) const DWORD len = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, errorCode, 0, reinterpret_cast<LPTSTR>(&lpMsgBuf), 0, NULL); + nullptr, errorCode, 0, reinterpret_cast<LPTSTR>(&lpMsgBuf), 0, nullptr); if (len) { rc = QString::fromUtf16(lpMsgBuf, int(len)); LocalFree(lpMsgBuf); @@ -642,7 +638,7 @@ void QWindowsContext::removeWindow(HWND hwnd) const HandleBaseWindowHash::iterator it = d->m_windows.find(hwnd); if (it != d->m_windows.end()) { if (d->m_keyMapper.keyGrabber() == it.value()->window()) - d->m_keyMapper.setKeyGrabber(0); + d->m_keyMapper.setKeyGrabber(nullptr); d->m_windows.erase(it); } } @@ -682,7 +678,7 @@ QWindow *QWindowsContext::findWindow(HWND hwnd) const { if (const QWindowsWindow *bw = findPlatformWindow(hwnd)) return bw->window(); - return 0; + return nullptr; } QWindow *QWindowsContext::windowUnderMouse() const @@ -749,7 +745,7 @@ QWindowsWindow *QWindowsContext::findPlatformWindowAt(HWND parent, const QPoint &screenPointIn, unsigned cwex_flags) const { - QWindowsWindow *result = 0; + QWindowsWindow *result = nullptr; const POINT screenPoint = { screenPointIn.x(), screenPointIn.y() }; while (findPlatformWindowHelper(screenPoint, cwex_flags, this, &parent, &result)) {} return result; @@ -821,7 +817,7 @@ HWND QWindowsContext::createDummyWindow(const QString &classNameIn, windowName, style, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - HWND_MESSAGE, NULL, static_cast<HINSTANCE>(GetModuleHandle(0)), NULL); + HWND_MESSAGE, nullptr, static_cast<HINSTANCE>(GetModuleHandle(nullptr)), nullptr); } // Re-engineered from the inline function _com_error::ErrorMessage(). @@ -831,8 +827,8 @@ static inline QString errorMessageFromComError(const _com_error &comError) { TCHAR *message = nullptr; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, DWORD(comError.Error()), MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), - message, 0, NULL); + nullptr, DWORD(comError.Error()), MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), + message, 0, nullptr); if (message) { const QString result = QString::fromWCharArray(message).trimmed(); LocalFree(static_cast<HLOCAL>(message)); @@ -916,6 +912,45 @@ QByteArray QWindowsContext::comErrorString(HRESULT hr) return result; } +bool QWindowsContext::systemParametersInfo(unsigned action, unsigned param, void *out, + unsigned dpi) +{ + const BOOL result = QWindowsContext::user32dll.systemParametersInfoForDpi != nullptr && dpi != 0 + ? QWindowsContext::user32dll.systemParametersInfoForDpi(action, param, out, 0, dpi) + : SystemParametersInfo(action, param, out, 0); + return result == TRUE; +} + +bool QWindowsContext::systemParametersInfoForScreen(unsigned action, unsigned param, void *out, + const QPlatformScreen *screen) +{ + return systemParametersInfo(action, param, out, screen ? screen->logicalDpi().first : 0); +} + +bool QWindowsContext::systemParametersInfoForWindow(unsigned action, unsigned param, void *out, + const QPlatformWindow *win) +{ + return systemParametersInfoForScreen(action, param, out, win ? win->screen() : nullptr); +} + +bool QWindowsContext::nonClientMetrics(NONCLIENTMETRICS *ncm, unsigned dpi) +{ + memset(ncm, 0, sizeof(NONCLIENTMETRICS)); + ncm->cbSize = sizeof(NONCLIENTMETRICS); + return systemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm->cbSize, ncm, dpi); +} + +bool QWindowsContext::nonClientMetricsForScreen(NONCLIENTMETRICS *ncm, + const QPlatformScreen *screen) +{ + return nonClientMetrics(ncm, screen ? screen->logicalDpi().first : 0); +} + +bool QWindowsContext::nonClientMetricsForWindow(NONCLIENTMETRICS *ncm, const QPlatformWindow *win) +{ + return nonClientMetricsForScreen(ncm, win ? win->screen() : nullptr); +} + static inline QWindowsInputContext *windowsInputContext() { return qobject_cast<QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext()); @@ -960,6 +995,7 @@ static inline bool isInputMessage(UINT m) case WM_IME_STARTCOMPOSITION: case WM_IME_ENDCOMPOSITION: case WM_IME_COMPOSITION: + case WM_INPUT: case WM_TOUCH: case WM_MOUSEHOVER: case WM_MOUSELEAVE: @@ -1063,6 +1099,12 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, return false; case QtWindows::ClipboardEvent: return false; + case QtWindows::CursorEvent: // Sent to windows that do not have capture (see QTBUG-58590). + if (QWindowsCursor::hasOverrideCursor()) { + QWindowsCursor::enforceOverrideCursor(); + return true; + } + break; case QtWindows::UnknownEvent: return false; case QtWindows::AccessibleObjectFromWindowRequest: @@ -1074,8 +1116,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, case QtWindows::DisplayChangedEvent: if (QWindowsTheme *t = QWindowsTheme::instance()) t->displayChanged(); + QWindowsWindow::displayChanged(); return d->m_screenManager.handleDisplayChange(wParam, lParam); case QtWindows::SettingChangedEvent: + QWindowsWindow::settingsChanged(); return d->m_screenManager.handleScreenChanges(); default: break; @@ -1175,9 +1219,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, case QtWindows::ExposeEvent: return platformWindow->handleWmPaint(hwnd, message, wParam, lParam); case QtWindows::NonClientMouseEvent: - if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled()) + if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled()) + return sessionManagerInteractionBlocked() || d->m_pointerHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); + else return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); - break; case QtWindows::NonClientPointerEvent: if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled()) return sessionManagerInteractionBlocked() || d->m_pointerHandler.translatePointerEvent(platformWindow->window(), hwnd, et, msg, result); @@ -1203,10 +1248,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, window = window->parent(); if (!window) return false; - if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer)) - return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(window, hwnd, et, msg, result); - else + if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) return sessionManagerInteractionBlocked() || d->m_pointerHandler.translateMouseEvent(window, hwnd, et, msg, result); + else + return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(window, hwnd, et, msg, result); } break; case QtWindows::TouchEvent: @@ -1280,7 +1325,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, return false; platformWindow->setFlag(QWindowsWindow::WithinDpiChanged); const RECT *prcNewWindow = reinterpret_cast<RECT *>(lParam); - SetWindowPos(hwnd, NULL, prcNewWindow->left, prcNewWindow->top, + SetWindowPos(hwnd, nullptr, prcNewWindow->left, prcNewWindow->top, prcNewWindow->right - prcNewWindow->left, prcNewWindow->bottom - prcNewWindow->top, SWP_NOZORDER | SWP_NOACTIVATE); platformWindow->clearFlag(QWindowsWindow::WithinDpiChanged); @@ -1302,7 +1347,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, qGuiAppPriv->commitData(); if (lParam & ENDSESSION_LOGOFF) - fflush(NULL); + fflush(nullptr); *result = sessionManager->wasCanceled() ? 0 : 1; return true; @@ -1320,7 +1365,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, if (endsession && !qGuiAppPriv->aboutToQuitEmitted) { qGuiAppPriv->aboutToQuitEmitted = true; int index = QGuiApplication::staticMetaObject.indexOfSignal("aboutToQuit()"); - qApp->qt_metacall(QMetaObject::InvokeMetaMethod, index,0); + qApp->qt_metacall(QMetaObject::InvokeMetaMethod, index, nullptr); // since the process will be killed immediately quit() has no real effect QGuiApplication::quit(); } @@ -1341,10 +1386,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, void QWindowsContext::handleFocusEvent(QtWindows::WindowsEventType et, QWindowsWindow *platformWindow) { - QWindow *nextActiveWindow = 0; + QWindow *nextActiveWindow = nullptr; if (et == QtWindows::FocusInEvent) { QWindow *topWindow = QWindowsWindow::topLevelOf(platformWindow->window()); - QWindow *modalWindow = 0; + QWindow *modalWindow = nullptr; if (QGuiApplicationPrivate::instance()->isWindowBlocked(topWindow, &modalWindow) && topWindow != modalWindow) { modalWindow->requestActivate(); return; @@ -1457,10 +1502,11 @@ static DWORD readDwordRegistrySetting(const wchar_t *regKey, const wchar_t *subK HKEY handle; if (RegOpenKeyEx(HKEY_CURRENT_USER, regKey, 0, KEY_READ, &handle) == ERROR_SUCCESS) { DWORD type; - if (RegQueryValueEx(handle, subKey, 0, &type, 0, 0) == ERROR_SUCCESS && type == REG_DWORD) { + if (RegQueryValueEx(handle, subKey, nullptr, &type, nullptr, nullptr) == ERROR_SUCCESS + && type == REG_DWORD) { DWORD value; DWORD size = sizeof(result); - if (RegQueryValueEx(handle, subKey, 0, 0, reinterpret_cast<unsigned char *>(&value), &size) == ERROR_SUCCESS) + if (RegQueryValueEx(handle, subKey, nullptr, nullptr, reinterpret_cast<unsigned char *>(&value), &size) == ERROR_SUCCESS) result = value; } RegCloseKey(handle); @@ -1559,7 +1605,11 @@ static inline QByteArray nativeEventType() { return QByteArrayLiteral("windows_g bool QWindowsContext::filterNativeEvent(MSG *msg, LRESULT *result) { QAbstractEventDispatcher *dispatcher = QAbstractEventDispatcher::instance(); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + qintptr filterResult = 0; +#else long filterResult = 0; +#endif if (dispatcher && dispatcher->filterNativeEvent(nativeEventType(), msg, &filterResult)) { *result = LRESULT(filterResult); return true; @@ -1570,7 +1620,11 @@ bool QWindowsContext::filterNativeEvent(MSG *msg, LRESULT *result) // Send to QWindowSystemInterface bool QWindowsContext::filterNativeEvent(QWindow *window, MSG *msg, LRESULT *result) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + qintptr filterResult = 0; +#else long filterResult = 0; +#endif if (QWindowSystemInterface::handleNativeEvent(window, nativeEventType(), msg, &filterResult)) { *result = LRESULT(filterResult); return true; diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index 19e9c26130..fd6c72668c 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -70,6 +70,7 @@ Q_DECLARE_LOGGING_CATEGORY(lcQpaTrayIcon) class QWindow; class QPlatformScreen; +class QPlatformWindow; class QWindowsMenuBar; class QWindowsScreenManager; class QWindowsTabletSupport; @@ -104,6 +105,7 @@ struct QWindowsUser32DLL typedef BOOL (WINAPI *EnableNonClientDpiScaling)(HWND); typedef int (WINAPI *GetWindowDpiAwarenessContext)(HWND); typedef int (WINAPI *GetAwarenessFromDpiAwarenessContext)(int); + typedef BOOL (WINAPI *SystemParametersInfoForDpi)(UINT, UINT, PVOID, UINT, UINT); // Windows pointer functions (Windows 8 or later). EnableMouseInPointer enableMouseInPointer = nullptr; @@ -132,6 +134,7 @@ struct QWindowsUser32DLL EnableNonClientDpiScaling enableNonClientDpiScaling = nullptr; GetWindowDpiAwarenessContext getWindowDpiAwarenessContext = nullptr; GetAwarenessFromDpiAwarenessContext getAwarenessFromDpiAwarenessContext = nullptr; + SystemParametersInfoForDpi systemParametersInfoForDpi = nullptr; }; // Shell scaling library (Windows 8.1 onwards) @@ -237,6 +240,17 @@ public: bool asyncExpose() const; void setAsyncExpose(bool value); + static bool systemParametersInfo(unsigned action, unsigned param, void *out, unsigned dpi = 0); + static bool systemParametersInfoForScreen(unsigned action, unsigned param, void *out, + const QPlatformScreen *screen = nullptr); + static bool systemParametersInfoForWindow(unsigned action, unsigned param, void *out, + const QPlatformWindow *win = nullptr); + static bool nonClientMetrics(NONCLIENTMETRICS *ncm, unsigned dpi = 0); + static bool nonClientMetricsForScreen(NONCLIENTMETRICS *ncm, + const QPlatformScreen *screen = nullptr); + static bool nonClientMetricsForWindow(NONCLIENTMETRICS *ncm, + const QPlatformWindow *win = nullptr); + static DWORD readAdvancedExplorerSettings(const wchar_t *subKey, DWORD defaultValue); QTouchDevice *touchDevice() const; diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index 4f669a5509..00d011ccec 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -102,7 +102,7 @@ QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c) HCURSOR QWindowsCursor::createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor) { - HCURSOR cur = 0; + HCURSOR cur = nullptr; const qreal pixmapScaleFactor = scaleFactor / pixmap.devicePixelRatioF(); if (!qFuzzyCompare(pixmapScaleFactor, 1)) { pixmap = pixmap.scaled((pixmapScaleFactor * QSizeF(pixmap.size())).toSize(), @@ -161,7 +161,7 @@ static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits, ++x; } } - return CreateCursor(GetModuleHandle(0), hotSpot.x(), hotSpot.y(), width, height, + return CreateCursor(GetModuleHandle(nullptr), hotSpot.x(), hotSpot.y(), width, height, xBits.data(), xMask.data()); } @@ -456,7 +456,7 @@ QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursor const QSize cursorSize = systemCursorSize(screen); const QWindowsCustomPngCursor *sEnd = pngCursors + sizeof(pngCursors) / sizeof(pngCursors[0]); - const QWindowsCustomPngCursor *bestFit = 0; + const QWindowsCustomPngCursor *bestFit = nullptr; int sizeDelta = INT_MAX; for (const QWindowsCustomPngCursor *s = pngCursors; s < sEnd; ++s) { if (s->shape != cursorShape) @@ -532,7 +532,7 @@ HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape, const } qWarning("%s: Invalid cursor shape %d", __FUNCTION__, cursorShape); - return 0; + return nullptr; } /*! @@ -741,10 +741,10 @@ QPixmap QWindowsCursor::dragDefaultCursor(Qt::DropAction action) const "...............XXXX....."}; if (m_ignoreDragCursor.isNull()) { - HCURSOR cursor = LoadCursor(NULL, IDC_NO); - ICONINFO iconInfo = {0, 0, 0, 0, 0}; + HCURSOR cursor = LoadCursor(nullptr, IDC_NO); + ICONINFO iconInfo = {0, 0, 0, nullptr, nullptr}; GetIconInfo(cursor, &iconInfo); - BITMAP bmColor = {0, 0, 0, 0, 0, 0, 0}; + BITMAP bmColor = {0, 0, 0, 0, 0, 0, nullptr}; if (iconInfo.hbmColor && GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bmColor) @@ -780,7 +780,7 @@ HCURSOR QWindowsCursor::hCursor(const QCursor &c) const if (sit != m_standardCursorCache.constEnd()) return sit.value()->handle(); } - return HCURSOR(0); + return HCURSOR(nullptr); } /*! diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h index 8495b51a5a..2e57c80def 100644 --- a/src/plugins/platforms/windows/qwindowscursor.h +++ b/src/plugins/platforms/windows/qwindowscursor.h @@ -61,7 +61,7 @@ inline bool operator==(const QWindowsPixmapCursorCacheKey &k1, const QWindowsPix return k1.bitmapCacheKey == k2.bitmapCacheKey && k1.maskCacheKey == k2.maskCacheKey; } -inline uint qHash(const QWindowsPixmapCursorCacheKey &k, uint seed) Q_DECL_NOTHROW +inline uint qHash(const QWindowsPixmapCursorCacheKey &k, uint seed) noexcept { return (uint(k.bitmapCacheKey) + uint(k.maskCacheKey)) ^ seed; } diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index 681b35eb7c..9de3268fc8 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -133,8 +133,8 @@ namespace QWindowsDialogs void eatMouseMove() { - MSG msg = {0, 0, 0, 0, 0, {0, 0} }; - while (PeekMessage(&msg, 0, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) + MSG msg = {nullptr, 0, 0, 0, 0, {0, 0} }; + while (PeekMessage(&msg, nullptr, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) ; if (msg.message == WM_MOUSEMOVE) PostMessage(msg.hwnd, msg.message, 0, msg.lParam); @@ -180,7 +180,7 @@ class QWindowsNativeDialogBase : public QObject public: virtual void setWindowTitle(const QString &title) = 0; bool executed() const { return m_executed; } - void exec(HWND owner = 0) { doExec(owner); m_executed = true; } + void exec(HWND owner = nullptr) { doExec(owner); m_executed = true; } signals: void accepted(); @@ -193,7 +193,7 @@ protected: QWindowsNativeDialogBase() : m_executed(false) {} private: - virtual void doExec(HWND owner = 0) = 0; + virtual void doExec(HWND owner = nullptr) = 0; bool m_executed; }; @@ -229,7 +229,7 @@ void QWindowsDialogHelperBase<BaseClass>::cleanupThread() qCWarning(lcQpaDialogs) << __FUNCTION__ << "Thread terminated."; } delete m_thread; - m_thread = 0; + m_thread = nullptr; } } @@ -238,7 +238,7 @@ QWindowsNativeDialogBase *QWindowsDialogHelperBase<BaseClass>::nativeDialog() co { if (m_nativeDialog.isNull()) { qWarning("%s invoked with no native dialog present.", __FUNCTION__); - return 0; + return nullptr; } return m_nativeDialog.data(); } @@ -300,7 +300,7 @@ bool QWindowsDialogHelperBase<BaseClass>::show(Qt::WindowFlags, if (parent) { m_ownerWindow = QWindowsWindow::handleOf(parent); } else { - m_ownerWindow = 0; + m_ownerWindow = nullptr; } qCDebug(lcQpaDialogs) << __FUNCTION__ << "modal=" << modal << " modal supported? " << supportsNonModalDialog(parent) @@ -347,7 +347,7 @@ void QWindowsDialogHelperBase<BaseClass>::stopTimer() struct FindDialogContext { explicit FindDialogContext(const QString &titleIn) - : title(qStringToWCharArray(titleIn)), processId(GetCurrentProcessId()), hwnd(0) {} + : title(qStringToWCharArray(titleIn)), processId(GetCurrentProcessId()), hwnd(nullptr) {} const QScopedArrayPointer<wchar_t> title; const DWORD processId; @@ -382,7 +382,7 @@ void QWindowsDialogHelperBase<BaseClass>::hide() { if (m_nativeDialog) m_nativeDialog->close(); - m_ownerWindow = 0; + m_ownerWindow = nullptr; } template <class BaseClass> @@ -534,7 +534,7 @@ IFileDialogEvents *QWindowsNativeFileDialogEventHandler::create(QWindowsNativeFi QWindowsNativeFileDialogEventHandler *eventHandler = new QWindowsNativeFileDialogEventHandler(nativeFileDialog); if (FAILED(eventHandler->QueryInterface(IID_IFileDialogEvents, reinterpret_cast<void **>(&result)))) { qErrnoWarning("Unable to obtain IFileDialogEvents"); - return 0; + return nullptr; } eventHandler->Release(); return result; @@ -558,6 +558,10 @@ public: SFGAOF attributes() const { return m_attributes; } QString normalDisplay() const // base name, usually { return displayName(m_item, SIGDN_NORMALDISPLAY); } + QString urlString() const + { return displayName(m_item, SIGDN_URL); } + QString fileSysPath() const + { return displayName(m_item, SIGDN_FILESYSPATH); } QString desktopAbsoluteParsing() const { return displayName(m_item, SIGDN_DESKTOPABSOLUTEPARSING); } QString path() const; // Only set for 'FileSystem' (SFGAO_FILESYSTEM) items @@ -565,12 +569,10 @@ public: bool isFileSystem() const { return (m_attributes & SFGAO_FILESYSTEM) != 0; } bool isDir() const { return (m_attributes & SFGAO_FOLDER) != 0; } - // Copy using IFileOperation - bool canCopy() const { return (m_attributes & SFGAO_CANCOPY) != 0; } // Supports IStream bool canStream() const { return (m_attributes & SFGAO_STREAM) != 0; } - bool copyData(QIODevice *out); + bool copyData(QIODevice *out, QString *errorMessage); static IShellItems itemsFromItemArray(IShellItemArray *items); @@ -662,14 +664,19 @@ QWindowsShellItem::IShellItems QWindowsShellItem::itemsFromItemArray(IShellItemA return result; } -bool QWindowsShellItem::copyData(QIODevice *out) +bool QWindowsShellItem::copyData(QIODevice *out, QString *errorMessage) { - if (!canCopy() || !canStream()) + if (!canStream()) { + *errorMessage = QLatin1String("Item not streamable"); return false; + } IStream *istream = nullptr; - HRESULT hr = m_item->BindToHandler(NULL, BHID_Stream, IID_PPV_ARGS(&istream)); - if (FAILED(hr)) + HRESULT hr = m_item->BindToHandler(nullptr, BHID_Stream, IID_PPV_ARGS(&istream)); + if (FAILED(hr)) { + *errorMessage = QLatin1String("BindToHandler() failed: ") + + QLatin1String(QWindowsContext::comErrorString(hr)); return false; + } enum : ULONG { bufSize = 102400 }; char buffer[bufSize]; ULONG bytesRead; @@ -682,7 +689,12 @@ bool QWindowsShellItem::copyData(QIODevice *out) break; } istream->Release(); - return hr == S_OK || hr == S_FALSE; + if (hr != S_OK && hr != S_FALSE) { + *errorMessage = QLatin1String("Read() failed: ") + + QLatin1String(QWindowsContext::comErrorString(hr)); + return false; + } + return true; } // Helper for "Libraries": collections of folders appearing from Windows 7 @@ -698,7 +710,7 @@ static IShellLibrary *sHLoadLibraryFromItem(IShellItem *libraryItem, DWORD mode) IShellLibrary *helper = nullptr; IShellLibrary *result = nullptr; - if (SUCCEEDED(CoCreateInstance(classId_ShellLibrary, NULL, CLSCTX_INPROC_SERVER, iId_IShellLibrary, reinterpret_cast<void **>(&helper)))) + if (SUCCEEDED(CoCreateInstance(classId_ShellLibrary, nullptr, CLSCTX_INPROC_SERVER, iId_IShellLibrary, reinterpret_cast<void **>(&helper)))) if (SUCCEEDED(helper->LoadLibraryFromItem(libraryItem, mode))) helper->QueryInterface(iId_IShellLibrary, reinterpret_cast<void **>(&result)); if (helper) @@ -731,10 +743,9 @@ void QWindowsShellItem::format(QDebug &d) const d << " [dir]"; if (canStream()) d << " [stream]"; - if (canCopy()) - d << " [copyable]"; d << ", normalDisplay=\"" << normalDisplay() - << "\", desktopAbsoluteParsing=\"" << desktopAbsoluteParsing() << '"'; + << "\", desktopAbsoluteParsing=\"" << desktopAbsoluteParsing() + << "\", urlString=\"" << urlString() << "\", fileSysPath=\"" << fileSysPath() << '"'; const QString pathS = path(); if (!pathS.isEmpty()) d << ", path=\"" << pathS << '"'; @@ -795,7 +806,7 @@ public: inline void setDirectory(const QUrl &directory); inline void updateDirectory() { setDirectory(m_data.directory()); } inline QString directory() const; - void doExec(HWND owner = 0) override; + void doExec(HWND owner = nullptr) override; virtual void setNameFilters(const QStringList &f); inline void selectNameFilter(const QString &filter); inline void updateSelectedNameFilter() { selectNameFilter(m_data.selectedNameFilter()); } @@ -864,7 +875,7 @@ QWindowsNativeFileDialogBase::~QWindowsNativeFileDialogBase() bool QWindowsNativeFileDialogBase::init(const CLSID &clsId, const IID &iid) { - HRESULT hr = CoCreateInstance(clsId, NULL, CLSCTX_INPROC_SERVER, + HRESULT hr = CoCreateInstance(clsId, nullptr, CLSCTX_INPROC_SERVER, iid, reinterpret_cast<void **>(&m_fileDialog)); if (FAILED(hr)) { qErrnoWarning("CoCreateInstance failed"); @@ -897,7 +908,7 @@ IShellItem *QWindowsNativeFileDialogBase::shellItem(const QUrl &url) const QString native = QDir::toNativeSeparators(url.toLocalFile()); const HRESULT hr = SHCreateItemFromParsingName(reinterpret_cast<const wchar_t *>(native.utf16()), - NULL, IID_IShellItem, + nullptr, IID_IShellItem, reinterpret_cast<void **>(&result)); if (FAILED(hr)) { qErrnoWarning("%s: SHCreateItemFromParsingName(%s)) failed", __FUNCTION__, qPrintable(url.toString())); @@ -915,7 +926,7 @@ IShellItem *QWindowsNativeFileDialogBase::shellItem(const QUrl &url) return nullptr; } PIDLIST_ABSOLUTE idList; - HRESULT hr = SHGetKnownFolderIDList(uuid, 0, 0, &idList); + HRESULT hr = SHGetKnownFolderIDList(uuid, 0, nullptr, &idList); if (FAILED(hr)) { qErrnoWarning("%s: SHGetKnownFolderIDList(%s)) failed", __FUNCTION__, qPrintable(url.toString())); return nullptr; @@ -930,7 +941,7 @@ IShellItem *QWindowsNativeFileDialogBase::shellItem(const QUrl &url) } else { qWarning() << __FUNCTION__ << ": Unhandled scheme: " << url.scheme(); } - return 0; + return nullptr; } void QWindowsNativeFileDialogBase::setDirectory(const QUrl &directory) @@ -946,7 +957,7 @@ void QWindowsNativeFileDialogBase::setDirectory(const QUrl &directory) QString QWindowsNativeFileDialogBase::directory() const { QString result; - IShellItem *item = 0; + IShellItem *item = nullptr; if (m_fileDialog && SUCCEEDED(m_fileDialog->GetFolder(&item)) && item) { result = QWindowsShellItem(item).path(); item->Release(); @@ -962,7 +973,9 @@ void QWindowsNativeFileDialogBase::doExec(HWND owner) const HRESULT hr = m_fileDialog->Show(owner); QWindowsDialogs::eatMouseMove(); qCDebug(lcQpaDialogs) << '<' << __FUNCTION__ << " returns " << hex << hr; - if (hr == S_OK) { + // Emit accepted() only if there is a result as otherwise UI hangs occur. + // For example, typing in invalid URLs results in empty result lists. + if (hr == S_OK && !m_data.selectedFiles().isEmpty()) { emit accepted(); } else { emit rejected(); @@ -1334,7 +1347,7 @@ void QWindowsNativeSaveFileDialog::setNameFilters(const QStringList &f) QList<QUrl> QWindowsNativeSaveFileDialog::dialogResult() const { QList<QUrl> result; - IShellItem *item = 0; + IShellItem *item = nullptr; if (SUCCEEDED(fileDialog()->GetResult(&item)) && item) result.append(QWindowsShellItem(item).url()); return result; @@ -1343,7 +1356,7 @@ QList<QUrl> QWindowsNativeSaveFileDialog::dialogResult() const QList<QUrl> QWindowsNativeSaveFileDialog::selectedFiles() const { QList<QUrl> result; - IShellItem *item = 0; + IShellItem *item = nullptr; const HRESULT hr = fileDialog()->GetCurrentSelection(&item); if (SUCCEEDED(hr) && item) { result.append(QWindowsShellItem(item).url()); @@ -1388,21 +1401,50 @@ static void cleanupTemporaryItemCopies() QFile::remove(file); } -static QString createTemporaryItemCopy(QWindowsShellItem &qItem) +// Determine temporary file pattern from a shell item's display +// name. This can be a URL. + +static bool validFileNameCharacter(QChar c) +{ + return c.isLetterOrNumber() || c == QLatin1Char('_') || c == QLatin1Char('-'); +} + +QString tempFilePattern(QString name) { - if (!qItem.canCopy() || !qItem.canStream()) + const int lastSlash = qMax(name.lastIndexOf(QLatin1Char('/')), + name.lastIndexOf(QLatin1Char('\\'))); + if (lastSlash != -1) + name.remove(0, lastSlash + 1); + + int lastDot = name.lastIndexOf(QLatin1Char('.')); + if (lastDot < 0) + lastDot = name.size(); + name.insert(lastDot, QStringLiteral("_XXXXXX")); + + for (int i = lastDot - 1; i >= 0; --i) { + if (!validFileNameCharacter(name.at(i))) + name[i] = QLatin1Char('_'); + } + + name.prepend(QDir::tempPath() + QLatin1Char('/')); + return name; +} + +static QString createTemporaryItemCopy(QWindowsShellItem &qItem, QString *errorMessage) +{ + if (!qItem.canStream()) { + *errorMessage = QLatin1String("Item not streamable"); return QString(); - QString pattern = qItem.normalDisplay(); - const int lastDot = pattern.lastIndexOf(QLatin1Char('.')); - const QString placeHolder = QStringLiteral("_XXXXXX"); - if (lastDot >= 0) - pattern.insert(lastDot, placeHolder); - else - pattern.append(placeHolder); - - QTemporaryFile targetFile(QDir::tempPath() + QLatin1Char('/') + pattern); + } + + QTemporaryFile targetFile(tempFilePattern(qItem.normalDisplay())); targetFile.setAutoRemove(false); - if (!targetFile.open() || !qItem.copyData(&targetFile)) + if (!targetFile.open()) { + *errorMessage = QLatin1String("Cannot create temporary file: ") + + targetFile.errorString(); + return QString(); + } + if (!qItem.copyData(&targetFile, errorMessage)) return QString(); const QString result = targetFile.fileName(); if (temporaryItemCopies()->isEmpty()) @@ -1411,23 +1453,41 @@ static QString createTemporaryItemCopy(QWindowsShellItem &qItem) return result; } +static QUrl itemToDialogUrl(QWindowsShellItem &qItem, QString *errorMessage) +{ + QUrl url = qItem.url(); + if (url.isLocalFile() || url.scheme().startsWith(QLatin1String("http"))) + return url; + const QString path = qItem.path(); + if (path.isEmpty() && !qItem.isDir() && qItem.canStream()) { + const QString temporaryCopy = createTemporaryItemCopy(qItem, errorMessage); + if (temporaryCopy.isEmpty()) { + QDebug(errorMessage).noquote() << "Unable to create a local copy of" + << qItem << ": " << errorMessage; + return QUrl(); + } + return QUrl::fromLocalFile(temporaryCopy); + } + if (!url.isValid()) + QDebug(errorMessage).noquote() << "Invalid URL obtained from" << qItem; + return url; +} + QList<QUrl> QWindowsNativeOpenFileDialog::dialogResult() const { QList<QUrl> result; - IShellItemArray *items = 0; + IShellItemArray *items = nullptr; if (SUCCEEDED(openFileDialog()->GetResults(&items)) && items) { + QString errorMessage; for (IShellItem *item : QWindowsShellItem::itemsFromItemArray(items)) { QWindowsShellItem qItem(item); - const QString path = qItem.path(); - if (path.isEmpty() && !qItem.isDir()) { - const QString temporaryCopy = createTemporaryItemCopy(qItem); - if (temporaryCopy.isEmpty()) - qWarning() << "Unable to create a local copy of" << qItem; - else - result.append(QUrl::fromLocalFile(temporaryCopy)); - } else { - result.append(qItem.url()); + const QUrl url = itemToDialogUrl(qItem, &errorMessage); + if (!url.isValid()) { + qWarning("%s", qPrintable(errorMessage)); + result.clear(); + break; } + result.append(url); } } return result; @@ -1436,7 +1496,7 @@ QList<QUrl> QWindowsNativeOpenFileDialog::dialogResult() const QList<QUrl> QWindowsNativeOpenFileDialog::selectedFiles() const { QList<QUrl> result; - IShellItemArray *items = 0; + IShellItemArray *items = nullptr; const HRESULT hr = openFileDialog()->GetSelectedItems(&items); if (SUCCEEDED(hr) && items) { for (IShellItem *item : QWindowsShellItem::itemsFromItemArray(items)) { @@ -1460,18 +1520,18 @@ QList<QUrl> QWindowsNativeOpenFileDialog::selectedFiles() const QWindowsNativeFileDialogBase *QWindowsNativeFileDialogBase::create(QFileDialogOptions::AcceptMode am, const QWindowsFileDialogSharedData &data) { - QWindowsNativeFileDialogBase *result = 0; + QWindowsNativeFileDialogBase *result = nullptr; if (am == QFileDialogOptions::AcceptOpen) { result = new QWindowsNativeOpenFileDialog(data); if (!result->init(CLSID_FileOpenDialog, IID_IFileOpenDialog)) { delete result; - return 0; + return nullptr; } } else { result = new QWindowsNativeSaveFileDialog(data); if (!result->init(CLSID_FileSaveDialog, IID_IFileSaveDialog)) { delete result; - return 0; + return nullptr; } } return result; @@ -1492,7 +1552,7 @@ class QWindowsFileDialogHelper : public QWindowsDialogHelperBase<QPlatformFileDi { public: QWindowsFileDialogHelper() {} - bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const override { return false; } + bool supportsNonModalDialog(const QWindow * /* parent */ = nullptr) const override { return false; } bool defaultNameFilterDisables() const override { return false; } void setDirectory(const QUrl &directory) override; @@ -1516,7 +1576,7 @@ QWindowsNativeDialogBase *QWindowsFileDialogHelper::createNativeDialog() { QWindowsNativeFileDialogBase *result = QWindowsNativeFileDialogBase::create(options()->acceptMode(), m_data); if (!result) - return 0; + return nullptr; QObject::connect(result, &QWindowsNativeDialogBase::accepted, this, &QPlatformDialogHelper::accept); QObject::connect(result, &QWindowsNativeDialogBase::rejected, this, &QPlatformDialogHelper::reject); QObject::connect(result, &QWindowsNativeFileDialogBase::directoryEntered, @@ -1633,7 +1693,7 @@ public: static QWindowsXpNativeFileDialog *create(const OptionsPtr &options, const QWindowsFileDialogSharedData &data); void setWindowTitle(const QString &t) override { m_title = t; } - void doExec(HWND owner = 0) override; + void doExec(HWND owner = nullptr) override; int existingDirCallback(HWND hwnd, UINT uMsg, LPARAM lParam); @@ -1658,8 +1718,8 @@ private: static PtrGetSaveFileNameW m_getSaveFileNameW; }; -QWindowsXpNativeFileDialog::PtrGetOpenFileNameW QWindowsXpNativeFileDialog::m_getOpenFileNameW = 0; -QWindowsXpNativeFileDialog::PtrGetSaveFileNameW QWindowsXpNativeFileDialog::m_getSaveFileNameW = 0; +QWindowsXpNativeFileDialog::PtrGetOpenFileNameW QWindowsXpNativeFileDialog::m_getOpenFileNameW = nullptr; +QWindowsXpNativeFileDialog::PtrGetSaveFileNameW QWindowsXpNativeFileDialog::m_getSaveFileNameW = nullptr; QWindowsXpNativeFileDialog *QWindowsXpNativeFileDialog::create(const OptionsPtr &options, const QWindowsFileDialogSharedData &data) { @@ -1673,7 +1733,7 @@ QWindowsXpNativeFileDialog *QWindowsXpNativeFileDialog::create(const OptionsPtr } if (m_getOpenFileNameW && m_getSaveFileNameW) return new QWindowsXpNativeFileDialog(options, data); - return 0; + return nullptr; } QWindowsXpNativeFileDialog::QWindowsXpNativeFileDialog(const OptionsPtr &options, @@ -1750,8 +1810,8 @@ QList<QUrl> QWindowsXpNativeFileDialog::execExistingDir(HWND owner) wchar_t initPath[MAX_PATH]; initPath[0] = 0; bi.hwndOwner = owner; - bi.pidlRoot = NULL; - bi.lpszTitle = 0; + bi.pidlRoot = nullptr; + bi.lpszTitle = nullptr; bi.pszDisplayName = initPath; bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NEWDIALOGSTYLE; bi.lpfn = xpFileDialogGetExistingDirCallbackProc; @@ -1874,7 +1934,7 @@ class QWindowsXpFileDialogHelper : public QWindowsDialogHelperBase<QPlatformFile { public: QWindowsXpFileDialogHelper() = default; - bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const override { return false; } + bool supportsNonModalDialog(const QWindow * /* parent */ = nullptr) const override { return false; } bool defaultNameFilterDisables() const override { return true; } void setDirectory(const QUrl &directory) override; @@ -1901,7 +1961,7 @@ QWindowsNativeDialogBase *QWindowsXpFileDialogHelper::createNativeDialog() QObject::connect(result, &QWindowsNativeDialogBase::rejected, this, &QPlatformDialogHelper::reject); return result; } - return 0; + return nullptr; } void QWindowsXpFileDialogHelper::setDirectory(const QUrl &directory) @@ -2084,7 +2144,7 @@ bool useHelper(QPlatformTheme::DialogType type) QPlatformDialogHelper *createHelper(QPlatformTheme::DialogType type) { if (QWindowsIntegration::instance()->options() & QWindowsIntegration::NoNativeDialogs) - return 0; + return nullptr; switch (type) { case QPlatformTheme::FileDialog: if (QWindowsIntegration::instance()->options() & QWindowsIntegration::XpNativeDialogs) @@ -2102,7 +2162,7 @@ QPlatformDialogHelper *createHelper(QPlatformTheme::DialogType type) default: break; } - return 0; + return nullptr; } } // namespace QWindowsDialogs diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index b7d225cb00..322865b0f3 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -49,6 +49,7 @@ #include "qwindowswindow.h" #include "qwindowsmousehandler.h" #include "qwindowscursor.h" +#include "qwindowskeymapper.h" #include <QtGui/qevent.h> #include <QtGui/qpixmap.h> @@ -80,7 +81,7 @@ QT_BEGIN_NAMESPACE class QWindowsDragCursorWindow : public QRasterWindow { public: - explicit QWindowsDragCursorWindow(QWindow *parent = 0); + explicit QWindowsDragCursorWindow(QWindow *parent = nullptr); void setPixmap(const QPixmap &p); @@ -205,6 +206,9 @@ static inline Qt::MouseButtons toQtMouseButtons(DWORD keyState) return buttons; } +static Qt::KeyboardModifiers lastModifiers = Qt::NoModifier; +static Qt::MouseButtons lastButtons = Qt::NoButton; + /*! \class QWindowsOleDropSource \brief Implementation of IDropSource @@ -264,7 +268,7 @@ QWindowsOleDropSource::QWindowsOleDropSource(QWindowsDrag *drag) , m_drag(drag) , m_windowUnderMouse(QWindowsContext::instance()->windowUnderMouse()) , m_currentButtons(Qt::NoButton) - , m_touchDragWindow(0) + , m_touchDragWindow(nullptr) { qCDebug(lcQpaMime) << __FUNCTION__ << m_mode; } @@ -403,7 +407,7 @@ QWindowsOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState) case DRAGDROP_S_DROP: case DRAGDROP_S_CANCEL: if (!m_windowUnderMouse.isNull() && m_mode != TouchDrag && fEscapePressed == FALSE - && buttons != QGuiApplicationPrivate::mouse_buttons) { + && buttons != lastButtons) { // QTBUG 66447: Synthesize a mouse release to the window under mouse at // start of the DnD operation as Windows does not send any. const QPoint globalPos = QWindowsCursor::mousePosition(); @@ -503,13 +507,14 @@ void QWindowsOleDropTarget::handleDrag(QWindow *window, DWORD grfKeyState, QWindowsDrag *windowsDrag = QWindowsDrag::instance(); const Qt::DropActions actions = translateToQDragDropActions(*pdwEffect); - const Qt::KeyboardModifiers keyboardModifiers = toQtKeyboardModifiers(grfKeyState); - const Qt::MouseButtons mouseButtons = toQtMouseButtons(grfKeyState); + + lastModifiers = toQtKeyboardModifiers(grfKeyState); + lastButtons = toQtMouseButtons(grfKeyState); const QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(window, windowsDrag->dropData(), m_lastPoint, actions, - mouseButtons, keyboardModifiers); + lastButtons, lastModifiers); m_answerRect = response.answerRect(); const Qt::DropAction action = response.acceptedAction(); @@ -521,7 +526,7 @@ void QWindowsOleDropTarget::handleDrag(QWindow *window, DWORD grfKeyState, *pdwEffect = m_chosenEffect; qCDebug(lcQpaMime) << __FUNCTION__ << m_window << windowsDrag->dropData() << " supported actions=" << actions - << " mods=" << keyboardModifiers << " mouse=" << mouseButtons + << " mods=" << lastModifiers << " mouse=" << lastButtons << " accepted: " << response.isAccepted() << action << m_answerRect << " effect" << *pdwEffect; } @@ -572,7 +577,10 @@ QWindowsOleDropTarget::DragLeave() qCDebug(lcQpaMime) << __FUNCTION__ << ' ' << m_window; - QWindowSystemInterface::handleDrag(m_window, 0, QPoint(), Qt::IgnoreAction, + lastModifiers = QWindowsKeyMapper::queryKeyboardModifiers(); + lastButtons = QWindowsMouseHandler::queryMouseButtons(); + + QWindowSystemInterface::handleDrag(m_window, nullptr, QPoint(), Qt::IgnoreAction, Qt::NoButton, Qt::NoModifier); if (!QDragManager::self()->source()) @@ -598,12 +606,15 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState, QWindowsDrag *windowsDrag = QWindowsDrag::instance(); + lastModifiers = toQtKeyboardModifiers(grfKeyState); + lastButtons = toQtMouseButtons(grfKeyState); + const QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(m_window, windowsDrag->dropData(), m_lastPoint, translateToQDragDropActions(*pdwEffect), - toQtMouseButtons(grfKeyState), - toQtKeyboardModifiers(grfKeyState)); + lastButtons, + lastModifiers); m_lastKeyState = grfKeyState; @@ -626,7 +637,7 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState, FORMATETC format; format.cfFormat = CLIPFORMAT(RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT)); format.tymed = TYMED_HGLOBAL; - format.ptd = 0; + format.ptd = nullptr; format.dwAspect = 1; format.lindex = -1; windowsDrag->dropDataObject()->SetData(&format, &medium, true); @@ -652,6 +663,7 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState, */ bool QWindowsDrag::m_canceled = false; +bool QWindowsDrag::m_dragging = false; QWindowsDrag::QWindowsDrag() = default; @@ -677,7 +689,7 @@ QMimeData *QWindowsDrag::dropData() */ IDropTargetHelper* QWindowsDrag::dropHelper() { if (!m_cachedDropTargetHelper) { - CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER, + CoCreateInstance(CLSID_DragDropHelper, nullptr, CLSCTX_INPROC_SERVER, IID_IDropTargetHelper, reinterpret_cast<void**>(&m_cachedDropTargetHelper)); } @@ -699,7 +711,10 @@ Qt::DropAction QWindowsDrag::drag(QDrag *drag) const DWORD allowedEffects = translateToWinDragEffects(possibleActions); qCDebug(lcQpaMime) << '>' << __FUNCTION__ << "possible Actions=0x" << hex << int(possibleActions) << "effects=0x" << allowedEffects << dec; + // Indicate message handlers we are in DoDragDrop() event loop. + QWindowsDrag::m_dragging = true; const HRESULT r = DoDragDrop(dropDataObject, windowDropSource, allowedEffects, &resultEffect); + QWindowsDrag::m_dragging = false; const DWORD reportedPerformedEffect = dropDataObject->reportedPerformedEffect(); if (r == DRAGDROP_S_DROP) { if (reportedPerformedEffect == DROPEFFECT_MOVE && resultEffect != DROPEFFECT_MOVE) { @@ -735,7 +750,7 @@ void QWindowsDrag::releaseDropDataObject() qCDebug(lcQpaMime) << __FUNCTION__ << m_dropDataObject; if (m_dropDataObject) { m_dropDataObject->Release(); - m_dropDataObject = 0; + m_dropDataObject = nullptr; } } diff --git a/src/plugins/platforms/windows/qwindowsdrag.h b/src/plugins/platforms/windows/qwindowsdrag.h index f116e50cbf..5f30c59882 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.h +++ b/src/plugins/platforms/windows/qwindowsdrag.h @@ -92,6 +92,7 @@ public: static QWindowsDrag *instance(); void cancelDrag() override { QWindowsDrag::m_canceled = true; } static bool isCanceled() { return QWindowsDrag::m_canceled; } + static bool isDragging() { return QWindowsDrag::m_dragging; } IDataObject *dropDataObject() const { return m_dropDataObject; } void setDropDataObject(IDataObject *dataObject) { m_dropDataObject = dataObject; } @@ -102,6 +103,7 @@ public: private: static bool m_canceled; + static bool m_dragging; QWindowsDropMimeData m_dropData; IDataObject *m_dropDataObject = nullptr; diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index 52f3c56beb..063e81150e 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -103,7 +103,7 @@ static inline void *resolveFunc(HMODULE lib, const char *name) void *QWindowsLibEGL::resolve(const char *name) { - return m_lib ? resolveFunc(m_lib, name) : 0; + return m_lib ? resolveFunc(m_lib, name) : nullptr; } #endif // !QT_STATIC @@ -155,7 +155,7 @@ bool QWindowsLibEGL::init() if (!eglGetError || !eglGetDisplay || !eglInitialize || !eglGetProcAddress) return false; - eglGetPlatformDisplayEXT = 0; + eglGetPlatformDisplayEXT = nullptr; #ifdef EGL_ANGLE_platform_angle eglGetPlatformDisplayEXT = reinterpret_cast<EGLDisplay (EGLAPIENTRY *)(EGLenum, void *, const EGLint *)>(eglGetProcAddress("eglGetPlatformDisplayEXT")); #endif @@ -166,7 +166,7 @@ bool QWindowsLibEGL::init() #if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC) void *QWindowsLibGLESv2::resolve(const char *name) { - return m_lib ? resolveFunc(m_lib, name) : 0; + return m_lib ? resolveFunc(m_lib, name) : nullptr; } #endif // !QT_STATIC @@ -213,7 +213,7 @@ bool QWindowsEGLStaticContext::initializeAngle(QWindowsOpenGLTester::Renderers p { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE, EGL_NONE } }; - const EGLint *attributes = 0; + const EGLint *attributes = nullptr; if (preferredType & QWindowsOpenGLTester::AngleRendererD3d11) attributes = anglePlatformAttributes[0]; else if (preferredType & QWindowsOpenGLTester::AngleRendererD3d9) @@ -245,16 +245,16 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester: const HDC dc = QWindowsContext::instance()->displayContext(); if (!dc){ qWarning("%s: No Display", __FUNCTION__); - return 0; + return nullptr; } if (!libEGL.init()) { qWarning("%s: Failed to load and resolve libEGL functions", __FUNCTION__); - return 0; + return nullptr; } if (!libGLESv2.init()) { qWarning("%s: Failed to load and resolve libGLESv2 functions", __FUNCTION__); - return 0; + return nullptr; } EGLDisplay display = EGL_NO_DISPLAY; @@ -271,7 +271,7 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester: display = libEGL.eglGetDisplay(dc); if (!display) { qWarning("%s: Could not obtain EGL display", __FUNCTION__); - return 0; + return nullptr; } if (!major && !libEGL.eglInitialize(display, &major, &minor)) { @@ -279,7 +279,7 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester: qWarning("%s: Could not initialize EGL display: error 0x%x", __FUNCTION__, err); if (err == 0x3001) qWarning("%s: When using ANGLE, check if d3dcompiler_4x.dll is available", __FUNCTION__); - return 0; + return nullptr; } qCDebug(lcQpaGl) << __FUNCTION__ << "Created EGL display" << display << 'v' <<major << '.' << minor; @@ -301,7 +301,7 @@ void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *na { *err = 0; EGLSurface surface = libEGL.eglCreateWindowSurface(m_display, nativeConfig, - static_cast<EGLNativeWindowType>(nativeWindow), 0); + static_cast<EGLNativeWindowType>(nativeWindow), nullptr); if (surface == EGL_NO_SURFACE) { *err = libEGL.eglGetError(); qWarning("%s: Could not create the EGL window surface: 0x%x", __FUNCTION__, *err); @@ -390,18 +390,24 @@ QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext, m_eglConfig = chooseConfig(format); m_format = m_staticContext->formatFromConfig(m_eglDisplay, m_eglConfig, format); - m_shareContext = share ? static_cast<QWindowsEGLContext *>(share)->m_eglContext : 0; + m_shareContext = share ? static_cast<QWindowsEGLContext *>(share)->m_eglContext : nullptr; QVector<EGLint> contextAttrs; - contextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); - contextAttrs.append(m_format.majorVersion()); + const int major = m_format.majorVersion(); + const int minor = m_format.minorVersion(); + if (major > 3 || (major == 3 && minor > 0)) + qWarning("QWindowsEGLContext: ANGLE only partially supports OpenGL ES > 3.0"); + contextAttrs.append(EGL_CONTEXT_MAJOR_VERSION); + contextAttrs.append(major); + contextAttrs.append(EGL_CONTEXT_MINOR_VERSION); + contextAttrs.append(minor); contextAttrs.append(EGL_NONE); QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api); m_eglContext = QWindowsEGLStaticContext::libEGL.eglCreateContext(m_eglDisplay, m_eglConfig, m_shareContext, contextAttrs.constData()); if (m_eglContext == EGL_NO_CONTEXT && m_shareContext != EGL_NO_CONTEXT) { - m_shareContext = 0; - m_eglContext = QWindowsEGLStaticContext::libEGL.eglCreateContext(m_eglDisplay, m_eglConfig, 0, contextAttrs.constData()); + m_shareContext = nullptr; + m_eglContext = QWindowsEGLStaticContext::libEGL.eglCreateContext(m_eglDisplay, m_eglConfig, nullptr, contextAttrs.constData()); } if (m_eglContext == EGL_NO_CONTEXT) { @@ -862,11 +868,11 @@ EGLConfig QWindowsEGLContext::chooseConfig(const QSurfaceFormat &format) configureAttributes.append(EGL_NONE); EGLDisplay display = m_staticContext->display(); - EGLConfig cfg = 0; + EGLConfig cfg = nullptr; do { // Get the number of matching configurations for this set of properties. EGLint matching = 0; - if (!QWindowsEGLStaticContext::libEGL.eglChooseConfig(display, configureAttributes.constData(), 0, 0, &matching) || !matching) + if (!QWindowsEGLStaticContext::libEGL.eglChooseConfig(display, configureAttributes.constData(), nullptr, 0, &matching) || !matching) continue; // Fetch all of the matching configurations and find the diff --git a/src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp b/src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp index 4ba7108f45..08e11c5e39 100644 --- a/src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp +++ b/src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp @@ -48,13 +48,13 @@ void *QWindowsGdiNativeInterface::nativeResourceForBackingStore(const QByteArray { if (!bs || !bs->handle()) { qWarning("%s: '%s' requested for null backingstore or backingstore without handle.", __FUNCTION__, resource.constData()); - return 0; + return nullptr; } QWindowsBackingStore *wbs = static_cast<QWindowsBackingStore *>(bs->handle()); if (resource == "getDC") return wbs->getDC(); qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData()); - return 0; + return nullptr; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index 851a6c961e..e95eaef420 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -322,7 +322,7 @@ static inline bool static void describeFormats(HDC hdc) { - const int pfiMax = DescribePixelFormat(hdc, 0, 0, NULL); + const int pfiMax = DescribePixelFormat(hdc, 0, 0, nullptr); for (int i = 0; i < pfiMax; i++) { PIXELFORMATDESCRIPTOR pfd; initPixelFormatDescriptor(&pfd); @@ -335,7 +335,7 @@ static void describeFormats(HDC hdc) namespace GDI { static QSurfaceFormat qSurfaceFormatFromPixelFormat(const PIXELFORMATDESCRIPTOR &pfd, - QWindowsOpenGLAdditionalFormat *additionalIn = 0) + QWindowsOpenGLAdditionalFormat *additionalIn = nullptr) { QSurfaceFormat format; format.setRenderableType(QSurfaceFormat::OpenGL); @@ -437,7 +437,7 @@ static int choosePixelFormat(HDC hdc, const QSurfaceFormat &format, return pixelFormat; } // 2) No matching format found, manual search loop. - const int pfiMax = DescribePixelFormat(hdc, 0, 0, NULL); + const int pfiMax = DescribePixelFormat(hdc, 0, 0, nullptr); int bestScore = -1; int bestPfi = -1; const bool stereoRequested = format.stereo(); @@ -479,7 +479,7 @@ static inline HGLRC createContext(HDC hdc, HGLRC shared) HGLRC result = QOpenGLStaticContext::opengl32.wglCreateContext(hdc); if (!result) { qErrnoWarning("%s: wglCreateContext failed.", __FUNCTION__); - return 0; + return nullptr; } if (shared && !QOpenGLStaticContext::opengl32.wglShareLists(shared, result)) qErrnoWarning("%s: wglShareLists() failed.", __FUNCTION__); @@ -590,7 +590,7 @@ static int choosePixelFormat(HDC hdc, uint numFormats = 0; while (true) { const bool valid = - staticContext.wglChoosePixelFormatARB(hdc, iAttributes, 0, 1, + staticContext.wglChoosePixelFormatARB(hdc, iAttributes, nullptr, 1, &pixelFormat, &numFormats) && numFormats >= 1; if (valid || (!sampleBuffersRequested && !srgbRequested)) @@ -646,7 +646,7 @@ static int choosePixelFormat(HDC hdc, static QSurfaceFormat qSurfaceFormatFromHDC(const QOpenGLStaticContext &staticContext, HDC hdc, int pixelFormat, - QWindowsOpenGLAdditionalFormat *additionalIn = 0) + QWindowsOpenGLAdditionalFormat *additionalIn = nullptr) { enum { attribSize = 42 }; @@ -720,12 +720,12 @@ static HGLRC createContext(const QOpenGLStaticContext &staticContext, HDC hdc, const QSurfaceFormat &format, const QWindowsOpenGLAdditionalFormat &, - HGLRC shared = 0) + HGLRC shared = nullptr) { enum { attribSize = 11 }; if (!staticContext.hasExtensions()) - return 0; + return nullptr; int attributes[attribSize]; int attribIndex = 0; std::fill(attributes, attributes + attribSize, int(0)); @@ -797,14 +797,14 @@ static inline HWND createDummyGLWindow() { return QWindowsContext::instance()-> createDummyWindow(QStringLiteral("QtOpenGLDummyWindow"), - L"OpenGLDummyWindow", 0, WS_OVERLAPPED | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); + L"OpenGLDummyWindow", nullptr, WS_OVERLAPPED | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); } // Create a dummy GL context (see QOpenGLTemporaryContext). static inline HGLRC createDummyGLContext(HDC dc) { if (!dc) - return 0; + return nullptr; PIXELFORMATDESCRIPTOR pixelFormDescriptor; initPixelFormatDescriptor(&pixelFormDescriptor); pixelFormDescriptor.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_GENERIC_FORMAT; @@ -813,16 +813,16 @@ static inline HGLRC createDummyGLContext(HDC dc) const int pixelFormat = ChoosePixelFormat(dc, &pixelFormDescriptor); if (!pixelFormat) { qErrnoWarning("%s: ChoosePixelFormat failed.", __FUNCTION__); - return 0; + return nullptr; } if (!QOpenGLStaticContext::opengl32.setPixelFormat(dc, pixelFormat, &pixelFormDescriptor)) { qErrnoWarning("%s: SetPixelFormat failed.", __FUNCTION__); - return 0; + return nullptr; } HGLRC rc = QOpenGLStaticContext::opengl32.wglCreateContext(dc); if (!rc) { qErrnoWarning("%s: wglCreateContext failed.", __FUNCTION__); - return 0; + return nullptr; } return rc; } @@ -1002,7 +1002,7 @@ QOpenGLStaticContext *QOpenGLStaticContext::create(bool softwareRendering) { if (!opengl32.init(softwareRendering)) { qWarning("Failed to load and resolve WGL/OpenGL functions"); - return 0; + return nullptr; } // We need a current context for wglGetProcAdress()/getGLString() to work. @@ -1033,12 +1033,12 @@ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext, QOpenGLContext *context) : m_staticContext(staticContext), m_context(context), - m_renderingContext(0), + m_renderingContext(nullptr), m_pixelFormat(0), m_extensionsUsed(false), m_swapInterval(-1), m_ownsContext(true), - m_getGraphicsResetStatus(0), + m_getGraphicsResetStatus(nullptr), m_lost(false) { if (!m_staticContext) // Something went very wrong. Stop here, isValid() will return false. @@ -1081,7 +1081,7 @@ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext, if (ok) m_ownsContext = false; else - m_renderingContext = 0; + m_renderingContext = nullptr; return; } @@ -1105,8 +1105,8 @@ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext, // Create a dummy one as we are not associated with a window yet. // Try to find a suitable pixel format using preferably ARB extensions // (default to GDI) and store that. - HWND dummyWindow = 0; - HDC hdc = 0; + HWND dummyWindow = nullptr; + HDC hdc = nullptr; bool tryExtensions = false; int obtainedSwapInterval = -1; do { @@ -1163,7 +1163,7 @@ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext, break; } // Create context with sharing, again preferably using ARB. - HGLRC sharingRenderingContext = 0; + HGLRC sharingRenderingContext = nullptr; if (const QPlatformOpenGLContext *sc = context->shareHandle()) sharingRenderingContext = static_cast<const QWindowsGLContext *>(sc)->renderingContext(); @@ -1190,7 +1190,7 @@ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext, // Make the HGLRC retrievable via QOpenGLContext::nativeHandle(). // Do not provide the window since it is the dummy one and it is about to disappear. if (m_renderingContext) - context->setNativeHandle(QVariant::fromValue<QWGLNativeContext>(QWGLNativeContext(m_renderingContext, 0))); + context->setNativeHandle(QVariant::fromValue<QWGLNativeContext>(QWGLNativeContext(m_renderingContext, nullptr))); if (hdc) ReleaseDC(dummyWindow, hdc); @@ -1281,7 +1281,7 @@ static inline const QOpenGLContextData * if (e.hwnd == hwnd) return &e; } - return 0; + return nullptr; } void QWindowsGLContext::swapBuffers(QPlatformSurface *surface) @@ -1350,10 +1350,10 @@ bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface) // Set the swap interval if (m_staticContext->wglSwapInternalExt) { const int interval = surface->format().swapInterval(); - if (interval >= 0 && m_swapInterval != interval) { + if (m_swapInterval != interval) m_swapInterval = interval; + if (interval >= 0) m_staticContext->wglSwapInternalExt(interval); - } } return success; @@ -1365,7 +1365,7 @@ void QWindowsGLContext::doneCurrent() if (QWindowsContext::verbose > 1) qCDebug(lcQpaGl) << __FUNCTION__ << this << m_windowContexts.size() << "contexts"; #endif // DEBUG_GL - QOpenGLStaticContext::opengl32.wglMakeCurrent(0, 0); + QOpenGLStaticContext::opengl32.wglMakeCurrent(nullptr, nullptr); releaseDCs(); } diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index 30da0da1de..878f55e56b 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -242,7 +242,18 @@ QRectF QWindowsInputContext::keyboardRect() const bool QWindowsInputContext::isInputPanelVisible() const { HWND hwnd = getVirtualKeyboardWindowHandle(); - return hwnd && ::IsWindowEnabled(hwnd) && ::IsWindowVisible(hwnd); + if (hwnd && ::IsWindowEnabled(hwnd) && ::IsWindowVisible(hwnd)) + return true; + // check if the Input Method Editor is open + if (inputMethodAccepted()) { + if (QWindow *window = QGuiApplication::focusWindow()) { + if (QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(window)) { + if (HIMC himc = ImmGetContext(platformWindow->handle())) + return ImmGetOpenStatus(himc); + } + } + } + return false; } void QWindowsInputContext::showInputPanel() @@ -300,10 +311,10 @@ void QWindowsInputContext::setWindowsImeEnabled(QWindowsWindow *platformWindow, return; if (enabled) { // Re-enable Windows IME by associating default context. - ImmAssociateContextEx(platformWindow->handle(), 0, IACE_DEFAULT); + ImmAssociateContextEx(platformWindow->handle(), nullptr, IACE_DEFAULT); } else { // Disable Windows IME by associating 0 context. - ImmAssociateContext(platformWindow->handle(), 0); + ImmAssociateContext(platformWindow->handle(), nullptr); } } @@ -434,7 +445,7 @@ static inline QTextFormat standardFormat(StandardFormat format) const QPalette palette = QGuiApplication::palette(); const QColor background = palette.text().color(); result.setBackground(QBrush(background)); - result.setForeground(palette.background()); + result.setForeground(palette.window()); break; } } @@ -528,7 +539,7 @@ bool QWindowsInputContext::composition(HWND hwnd, LPARAM lParamIn) // attribute sequence specifying the formatting of the converted part. int selStart, selLength; m_compositionContext.composition = getCompositionString(himc, GCS_COMPSTR); - m_compositionContext.position = ImmGetCompositionString(himc, GCS_CURSORPOS, 0, 0); + m_compositionContext.position = ImmGetCompositionString(himc, GCS_CURSORPOS, nullptr, 0); getCompositionStringConvertedRange(himc, &selStart, &selLength); if ((lParam & CS_INSERTCHAR) && (lParam & CS_NOMOVECARET)) { // make Korean work correctly. Hope this is correct for all IMEs @@ -609,11 +620,11 @@ void QWindowsInputContext::doneContext() { if (!m_compositionContext.hwnd) return; - m_compositionContext.hwnd = 0; + m_compositionContext.hwnd = nullptr; m_compositionContext.composition.clear(); m_compositionContext.position = 0; m_compositionContext.isComposing = false; - m_compositionContext.focusObject = 0; + m_compositionContext.focusObject = nullptr; } bool QWindowsInputContext::handleIME_Request(WPARAM wParam, diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 9e03d09607..2c90b0484e 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -312,7 +312,7 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co case AllGLFunctionsQueryable: return true; case SwitchableWidgetComposition: - return true; + return false; // QTBUG-68329 QTBUG-53515 QTBUG-54734 default: return QPlatformIntegration::hasCapability(cap); } @@ -461,7 +461,7 @@ QPlatformOpenGLContext *QWindowsIntegration::createPlatformOpenGLContext(QOpenGL if (result->isValid()) return result.take(); } - return 0; + return nullptr; } QOpenGLContext::OpenGLModuleType QWindowsIntegration::openGLModuleType() @@ -481,7 +481,7 @@ QWindowsStaticOpenGLContext *QWindowsIntegration::staticOpenGLContext() { QWindowsIntegration *integration = QWindowsIntegration::instance(); if (!integration) - return 0; + return nullptr; QWindowsIntegrationPrivate *d = integration->d.data(); QMutexLocker lock(&d->m_staticContextLock); if (d->m_staticOpenGLContext.isNull()) diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h index da86852766..e28b2c2fb3 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.h +++ b/src/plugins/platforms/windows/qwindowsintegration.h @@ -107,9 +107,6 @@ public: static QWindowsIntegration *instance() { return m_instance; } - inline void emitScreenAdded(QPlatformScreen *s, bool isPrimary = false) { screenAdded(s, isPrimary); } - inline void emitDestroyScreen(QPlatformScreen *s) { destroyScreen(s); } - unsigned options() const; void beep() const override; diff --git a/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp b/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp index 8f1d8f73d9..44b7523fa6 100644 --- a/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp +++ b/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp @@ -70,7 +70,7 @@ bool QWindowsInternalMimeData::hasFormat_sys(const QString &mime) const return false; const QWindowsMimeConverter &mc = QWindowsContext::instance()->mimeConverter(); - const bool has = mc.converterToMime(mime, pDataObj) != 0; + const bool has = mc.converterToMime(mime, pDataObj) != nullptr; releaseDataObject(pDataObj); qCDebug(lcQpaMime) << __FUNCTION__ << mime << has; return has; diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index 9e6101b758..c050369801 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -97,7 +97,7 @@ QT_BEGIN_NAMESPACE static void clearKeyRecorderOnApplicationInActive(Qt::ApplicationState state); QWindowsKeyMapper::QWindowsKeyMapper() - : m_useRTLExtensions(false), m_keyGrabber(0) + : m_useRTLExtensions(false), m_keyGrabber(nullptr) { memset(keyLayout, 0, sizeof(keyLayout)); QGuiApplication *app = static_cast<QGuiApplication *>(QGuiApplication::instance()); @@ -162,7 +162,7 @@ static void clearKeyRecorderOnApplicationInActive(Qt::ApplicationState state) KeyRecord *KeyRecorder::findKey(int code, bool remove) { - KeyRecord *result = 0; + KeyRecord *result = nullptr; for (int i = 0; i < nrecs; ++i) { if (records[i].code == code) { if (remove) { @@ -605,7 +605,7 @@ inline quint32 winceKeyBend(quint32 keyCode) } // Translate a VK into a Qt key code, or unicode character -static inline quint32 toKeyOrUnicode(quint32 vk, quint32 scancode, unsigned char *kbdBuffer, bool *isDeadkey = 0) +static inline quint32 toKeyOrUnicode(quint32 vk, quint32 scancode, unsigned char *kbdBuffer, bool *isDeadkey = nullptr) { Q_ASSERT(vk > 0 && vk < 256); quint32 code = 0; @@ -822,7 +822,7 @@ static void showSystemMenu(QWindow* w) TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD, pos.x(), pos.y(), topLevelHwnd, - 0); + nullptr); if (ret) qWindowsWndProc(topLevelHwnd, WM_SYSCOMMAND, WPARAM(ret), 0); } @@ -1023,13 +1023,15 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg, if (dirStatus == VK_LSHIFT && ((msg.wParam == VK_SHIFT && GetKeyState(VK_LCONTROL)) || (msg.wParam == VK_CONTROL && GetKeyState(VK_LSHIFT)))) { - sendExtendedPressRelease(receiver, Qt::Key_Direction_L, 0, scancode, vk_key, nModifiers, QString(), false); + sendExtendedPressRelease(receiver, Qt::Key_Direction_L, nullptr, + scancode, vk_key, nModifiers, QString(), false); result = true; dirStatus = 0; } else if (dirStatus == VK_RSHIFT && ( (msg.wParam == VK_SHIFT && GetKeyState(VK_RCONTROL)) || (msg.wParam == VK_CONTROL && GetKeyState(VK_RSHIFT)))) { - sendExtendedPressRelease(receiver, Qt::Key_Direction_R, 0, scancode, vk_key, nModifiers, QString(), false); + sendExtendedPressRelease(receiver, Qt::Key_Direction_R, nullptr, + scancode, vk_key, nModifiers, QString(), false); result = true; dirStatus = 0; } else { @@ -1140,7 +1142,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg, // This will stop the auto-repeat of the key, should a modifier change, for example if (rec && rec->state != state) { key_recorder.findKey(int(msg.wParam), true); - rec = 0; + rec = nullptr; } // Find unicode character from Windows Message Queue @@ -1150,7 +1152,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg, : msgType == WM_IME_KEYDOWN ? WM_IME_CHAR : WM_SYSCHAR); QChar uch; - if (PeekMessage(&wm_char, 0, charType, charType, PM_REMOVE)) { + if (PeekMessage(&wm_char, nullptr, charType, charType, PM_REMOVE)) { if (QWindowsContext::filterNativeEvent(&wm_char, lResult)) return true; if (receiver && QWindowsContext::filterNativeEvent(receiver, &wm_char, lResult)) @@ -1263,6 +1265,13 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg, } #endif // !QT_NO_SHORTCUT key_recorder.storeKey(int(msg.wParam), a, state, text); + + // QTBUG-71210 + // VK_PACKET specifies multiple characters. The system only sends the first + // character of this sequence for each. + if (msg.wParam == VK_PACKET) + code = asciiToKeycode(char(uch.cell()), state); + QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyPress, code, modifiers, scancode, quint32(msg.wParam), nModifiers, text, false); result =true; diff --git a/src/plugins/platforms/windows/qwindowsmenu.cpp b/src/plugins/platforms/windows/qwindowsmenu.cpp index 71802b9017..17a1b94101 100644 --- a/src/plugins/platforms/windows/qwindowsmenu.cpp +++ b/src/plugins/platforms/windows/qwindowsmenu.cpp @@ -784,7 +784,7 @@ void QWindowsMenuBar::handleReparent(QWindow *newParentWindow) if (QPlatformWindow *platWin = newParentWindow->handle()) install(static_cast<QWindowsWindow *>(platWin)); else // Store for later creation, see menuBarOf() - newParentWindow->setProperty(menuBarPropertyName, qVariantFromValue<QObject *>(this)); + newParentWindow->setProperty(menuBarPropertyName, QVariant::fromValue<QObject *>(this)); } QWindowsMenuBar *QWindowsMenuBar::menuBarOf(const QWindow *notYetCreatedWindow) @@ -797,7 +797,7 @@ QWindowsMenuBar *QWindowsMenuBar::menuBarOf(const QWindow *notYetCreatedWindow) static inline void forceNcCalcSize(HWND hwnd) { // Force WM_NCCALCSIZE to adjust margin: Does not appear to work? - SetWindowPos(hwnd, 0, 0, 0, 0, 0, + SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER); } diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp index ff0dccb0d9..96e34fb44c 100644 --- a/src/plugins/platforms/windows/qwindowsmime.cpp +++ b/src/plugins/platforms/windows/qwindowsmime.cpp @@ -312,7 +312,7 @@ static FORMATETC setCf(int cf) formatetc.cfFormat = CLIPFORMAT(cf); formatetc.dwAspect = DVASPECT_CONTENT; formatetc.lindex = -1; - formatetc.ptd = NULL; + formatetc.ptd = nullptr; formatetc.tymed = TYMED_HGLOBAL; return formatetc; } @@ -328,7 +328,7 @@ static bool setData(const QByteArray &data, STGMEDIUM *pmedium) GlobalUnlock(hData); pmedium->tymed = TYMED_HGLOBAL; pmedium->hGlobal = hData; - pmedium->pUnkForRelease = 0; + pmedium->pUnkForRelease = nullptr; return true; } @@ -352,7 +352,7 @@ static QByteArray getData(int cf, IDataObject *pDataObj, int lindex = -1) ULONG actualRead = 0; LARGE_INTEGER pos = {{0, 0}}; //Move to front (can fail depending on the data model implemented) - HRESULT hr = s.pstm->Seek(pos, STREAM_SEEK_SET, NULL); + HRESULT hr = s.pstm->Seek(pos, STREAM_SEEK_SET, nullptr); while(SUCCEEDED(hr)){ hr = s.pstm->Read(szBuffer, sizeof(szBuffer), &actualRead); if (SUCCEEDED(hr) && actualRead > 0) { @@ -1123,11 +1123,11 @@ bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeD bool QWindowsMimeImage::hasOriginalDIBV5(IDataObject *pDataObj) const { bool isSynthesized = true; - IEnumFORMATETC *pEnum =NULL; + IEnumFORMATETC *pEnum = nullptr; HRESULT res = pDataObj->EnumFormatEtc(1, &pEnum); if (res == S_OK && pEnum) { FORMATETC fc; - while ((res = pEnum->Next(1, &fc, 0)) == S_OK) { + while ((res = pEnum->Next(1, &fc, nullptr)) == S_OK) { if (fc.ptd) CoTaskMemFree(fc.ptd); if (fc.cfFormat == CF_DIB) @@ -1398,7 +1398,7 @@ static bool isCustomMimeType(const QString &mimeType) return mimeType.startsWith(QLatin1String(x_qt_windows_mime), Qt::CaseInsensitive); } -static QString customMimeType(const QString &mimeType, int *lindex = 0) +static QString customMimeType(const QString &mimeType, int *lindex = nullptr) { int len = sizeof(x_qt_windows_mime) - 1; int n = mimeType.lastIndexOf(QLatin1Char('\"')) - len; @@ -1510,7 +1510,7 @@ QWindowsMime * QWindowsMimeConverter::converterToMime(const QString &mimeType, I if (m_mimes.at(i)->canConvertToMime(mimeType, pDataObj)) return m_mimes.at(i); } - return 0; + return nullptr; } QStringList QWindowsMimeConverter::allMimesForFormats(IDataObject *pDataObj) const @@ -1523,7 +1523,7 @@ QStringList QWindowsMimeConverter::allMimesForFormats(IDataObject *pDataObj) con if (hr == NOERROR) { FORMATETC fmtetc; - while (S_OK == fmtenum->Next(1, &fmtetc, 0)) { + while (S_OK == fmtenum->Next(1, &fmtetc, nullptr)) { for (int i= m_mimes.size() - 1; i >= 0; --i) { QString format = m_mimes.at(i)->mimeForFormat(fmtetc); if (!format.isEmpty() && !formats.contains(format)) { @@ -1550,7 +1550,7 @@ QWindowsMime * QWindowsMimeConverter::converterFromMime(const FORMATETC &formate if (m_mimes.at(i)->canConvertFromMime(formatetc, mimeData)) return m_mimes.at(i); } - return 0; + return nullptr; } QVector<FORMATETC> QWindowsMimeConverter::allFormatsForMime(const QMimeData *mimeData) const diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index c1c275144f..737fd1d2a9 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -75,11 +75,11 @@ static inline void compressMouseMove(MSG *msg) // key release events (kls 2003-05-13): MSG keyMsg; bool done = false; - while (PeekMessage(&keyMsg, 0, WM_KEYFIRST, WM_KEYLAST, + while (PeekMessage(&keyMsg, nullptr, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE)) { if (keyMsg.time < mouseMsg.time) { if ((keyMsg.lParam & 0xC0000000) == 0x40000000) { - PeekMessage(&keyMsg, 0, keyMsg.message, + PeekMessage(&keyMsg, nullptr, keyMsg.message, keyMsg.message, PM_REMOVE); } else { done = true; @@ -121,7 +121,7 @@ static inline QTouchDevice *createTouchDevice() { const int digitizers = GetSystemMetrics(SM_DIGITIZER); if (!(digitizers & (NID_INTEGRATED_TOUCH | NID_EXTERNAL_TOUCH))) - return 0; + return nullptr; const int tabletPc = GetSystemMetrics(SM_TABLETPC); const int maxTouchPoints = GetSystemMetrics(SM_MAXIMUMTOUCHES); qCDebug(lcQpaEvents) << "Digitizers:" << hex << showbase << (digitizers & ~NID_READY) @@ -159,7 +159,7 @@ QTouchDevice *QWindowsMouseHandler::ensureTouchDevice() Qt::MouseButtons QWindowsMouseHandler::queryMouseButtons() { - Qt::MouseButtons result = 0; + Qt::MouseButtons result = nullptr; const bool mouseSwapped = GetSystemMetrics(SM_SWAPBUTTON); if (GetAsyncKeyState(VK_LBUTTON) < 0) result |= mouseSwapped ? Qt::RightButton: Qt::LeftButton; @@ -207,26 +207,26 @@ static inline MouseEvent eventFromMsg(const MSG &msg) return {QEvent::MouseButtonPress, Qt::LeftButton}; case WM_LBUTTONUP: return {QEvent::MouseButtonRelease, Qt::LeftButton}; - case WM_LBUTTONDBLCLK: - return {QEvent::MouseButtonDblClick, Qt::LeftButton}; + case WM_LBUTTONDBLCLK: // Qt QPA does not handle double clicks, send as press + return {QEvent::MouseButtonPress, Qt::LeftButton}; case WM_MBUTTONDOWN: return {QEvent::MouseButtonPress, Qt::MidButton}; case WM_MBUTTONUP: return {QEvent::MouseButtonRelease, Qt::MidButton}; case WM_MBUTTONDBLCLK: - return {QEvent::MouseButtonDblClick, Qt::MidButton}; + return {QEvent::MouseButtonPress, Qt::MidButton}; case WM_RBUTTONDOWN: return {QEvent::MouseButtonPress, Qt::RightButton}; case WM_RBUTTONUP: return {QEvent::MouseButtonRelease, Qt::RightButton}; case WM_RBUTTONDBLCLK: - return {QEvent::MouseButtonDblClick, Qt::RightButton}; + return {QEvent::MouseButtonPress, Qt::RightButton}; case WM_XBUTTONDOWN: return {QEvent::MouseButtonPress, extraButton(msg.wParam)}; case WM_XBUTTONUP: return {QEvent::MouseButtonRelease, extraButton(msg.wParam)}; case WM_XBUTTONDBLCLK: - return {QEvent::MouseButtonDblClick, extraButton(msg.wParam)}; + return {QEvent::MouseButtonPress, extraButton(msg.wParam)}; case WM_NCMOUSEMOVE: return {QEvent::NonClientAreaMouseMove, Qt::NoButton}; case WM_NCLBUTTONDOWN: @@ -234,19 +234,19 @@ static inline MouseEvent eventFromMsg(const MSG &msg) case WM_NCLBUTTONUP: return {QEvent::NonClientAreaMouseButtonRelease, Qt::LeftButton}; case WM_NCLBUTTONDBLCLK: - return {QEvent::NonClientAreaMouseButtonDblClick, Qt::LeftButton}; + return {QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton}; case WM_NCMBUTTONDOWN: return {QEvent::NonClientAreaMouseButtonPress, Qt::MidButton}; case WM_NCMBUTTONUP: return {QEvent::NonClientAreaMouseButtonRelease, Qt::MidButton}; case WM_NCMBUTTONDBLCLK: - return {QEvent::NonClientAreaMouseButtonDblClick, Qt::MidButton}; + return {QEvent::NonClientAreaMouseButtonPress, Qt::MidButton}; case WM_NCRBUTTONDOWN: return {QEvent::NonClientAreaMouseButtonPress, Qt::RightButton}; case WM_NCRBUTTONUP: return {QEvent::NonClientAreaMouseButtonRelease, Qt::RightButton}; case WM_NCRBUTTONDBLCLK: - return {QEvent::NonClientAreaMouseButtonDblClick, Qt::RightButton}; + return {QEvent::NonClientAreaMouseButtonPress, Qt::RightButton}; default: // WM_MOUSELEAVE break; } @@ -327,8 +327,8 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, QWindow *leaveTarget = m_windowUnderMouse ? m_windowUnderMouse : m_trackedWindow; qCDebug(lcQpaEvents) << "Generating leave event for " << leaveTarget; QWindowSystemInterface::handleLeaveEvent(leaveTarget); - m_trackedWindow = 0; - m_windowUnderMouse = 0; + m_trackedWindow = nullptr; + m_windowUnderMouse = nullptr; } return true; } @@ -430,7 +430,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, if (currentNotCapturing) { // Clear tracking if capturing and current window is not the capturing window // to avoid leave when mouse actually leaves the application. - m_trackedWindow = 0; + m_trackedWindow = nullptr; // We are not officially in any window, but we need to set some cursor to clear // whatever cursor the left window had, so apply the cursor of the capture window. platformWindow->applyCursor(); @@ -464,7 +464,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, QWindowsKeyMapper::queryKeyboardModifiers(), source); } - m_previousCaptureWindow = hasCapture ? window : 0; + m_previousCaptureWindow = hasCapture ? window : nullptr; // QTBUG-48117, force synchronous handling for the extra buttons so that WM_APPCOMMAND // is sent for unhandled WM_XBUTTONDOWN. return (msg.message != WM_XBUTTONUP && msg.message != WM_XBUTTONDOWN && msg.message != WM_XBUTTONDBLCLK) @@ -595,7 +595,7 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, QTouchPointList touchPoints; touchPoints.reserve(winTouchPointCount); - Qt::TouchPointStates allStates = 0; + Qt::TouchPointStates allStates = nullptr; GetTouchInputInfo(reinterpret_cast<HTOUCHINPUT>(msg.lParam), UINT(msg.wParam), winTouchInputs.data(), sizeof(TOUCHINPUT)); diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp index de11356fd4..b8ab7f8779 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp @@ -95,7 +95,7 @@ void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resourc { if (!window || !window->handle()) { qWarning("%s: '%s' requested for null window or window without handle.", __FUNCTION__, resource.constData()); - return 0; + return nullptr; } QWindowsWindow *bw = static_cast<QWindowsWindow *>(window->handle()); int type = resourceType(resource); @@ -108,7 +108,7 @@ void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resourc return bw->getDC(); if (type == ReleaseDCType) { bw->releaseDC(); - return 0; + return nullptr; } break; case QWindow::VulkanSurface: @@ -121,7 +121,7 @@ void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resourc break; } qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData()); - return 0; + return nullptr; } #ifndef QT_NO_CURSOR @@ -143,7 +143,7 @@ QVariant QWindowsNativeInterface::windowProperty(QPlatformWindow *window, const { QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window); if (name == QLatin1String(customMarginPropertyC)) - return qVariantFromValue(platformWindow->customMargins()); + return QVariant::fromValue(platformWindow->customMargins()); return QVariant(); } @@ -179,7 +179,7 @@ void *QWindowsNativeInterface::nativeResourceForIntegration(const QByteArray &re } #endif - return 0; + return nullptr; } #ifndef QT_NO_OPENGL @@ -187,7 +187,7 @@ void *QWindowsNativeInterface::nativeResourceForContext(const QByteArray &resour { if (!context || !context->handle()) { qWarning("%s: '%s' requested for null context or context without handle.", __FUNCTION__, resource.constData()); - return 0; + return nullptr; } QWindowsOpenGLContext *glcontext = static_cast<QWindowsOpenGLContext *>(context->handle()); @@ -204,7 +204,7 @@ void *QWindowsNativeInterface::nativeResourceForContext(const QByteArray &resour } qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData()); - return 0; + return nullptr; } #endif // !QT_NO_OPENGL @@ -277,6 +277,8 @@ QFunctionPointer QWindowsNativeInterface::platformFunction(const QByteArray &fun return QFunctionPointer(QWindowsWindow::setTouchWindowTouchTypeStatic); if (function == QWindowsWindowFunctions::setHasBorderInFullScreenIdentifier()) return QFunctionPointer(QWindowsWindow::setHasBorderInFullScreenStatic); + if (function == QWindowsWindowFunctions::setHasBorderInFullScreenDefaultIdentifier()) + return QFunctionPointer(QWindowsWindow::setHasBorderInFullScreenDefault); if (function == QWindowsWindowFunctions::setWindowActivationBehaviorIdentifier()) return QFunctionPointer(QWindowsNativeInterface::setWindowActivationBehavior); if (function == QWindowsWindowFunctions::isTabletModeIdentifier()) @@ -289,4 +291,13 @@ QVariant QWindowsNativeInterface::gpu() const return GpuDescription::detect().toVariant(); } +QVariant QWindowsNativeInterface::gpuList() const +{ + QVariantList result; + const auto gpus = GpuDescription::detectAll(); + for (const auto &gpu : gpus) + result.append(gpu.toVariant()); + return result; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.h b/src/plugins/platforms/windows/qwindowsnativeinterface.h index d085a4afb3..e6f8aae8fb 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.h +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.h @@ -66,6 +66,7 @@ class QWindowsNativeInterface : public QPlatformNativeInterface Q_OBJECT Q_PROPERTY(bool asyncExpose READ asyncExpose WRITE setAsyncExpose) Q_PROPERTY(QVariant gpu READ gpu STORED false) + Q_PROPERTY(QVariant gpuList READ gpuList STORED false) public: void *nativeResourceForIntegration(const QByteArray &resource) override; @@ -91,6 +92,7 @@ public: void setAsyncExpose(bool value); QVariant gpu() const; + QVariant gpuList() const; QVariantMap windowProperties(QPlatformWindow *window) const override; QVariant windowProperty(QPlatformWindow *window, const QString &name) const override; diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp index ad0442c8bd..e9c3f2cbf6 100644 --- a/src/plugins/platforms/windows/qwindowsole.cpp +++ b/src/plugins/platforms/windows/qwindowsole.cpp @@ -84,7 +84,7 @@ QWindowsOleDataObject::~QWindowsOleDataObject() = default; void QWindowsOleDataObject::releaseQt() { - data = 0; + data = nullptr; } QMimeData *QWindowsOleDataObject::mimeData() const @@ -142,7 +142,7 @@ QWindowsOleDataObject::QueryGetData(LPFORMATETC pformatetc) STDMETHODIMP QWindowsOleDataObject::GetCanonicalFormatEtc(LPFORMATETC, LPFORMATETC pformatetcOut) { - pformatetcOut->ptd = NULL; + pformatetcOut->ptd = nullptr; return ResultFromScode(E_NOTIMPL); } @@ -188,7 +188,7 @@ QWindowsOleDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppe formatetc.cfFormat = CLIPFORMAT(CF_PERFORMEDDROPEFFECT); formatetc.dwAspect = DVASPECT_CONTENT; formatetc.lindex = -1; - formatetc.ptd = NULL; + formatetc.ptd = nullptr; formatetc.tymed = TYMED_HGLOBAL; fmtetcs.append(formatetc); } @@ -197,7 +197,7 @@ QWindowsOleDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppe *ppenumFormatEtc = enumFmtEtc; if (enumFmtEtc->isNull()) { delete enumFmtEtc; - *ppenumFormatEtc = NULL; + *ppenumFormatEtc = nullptr; sc = E_OUTOFMEMORY; } @@ -295,7 +295,7 @@ QWindowsOleEnumFmtEtc::Next(ULONG celt, LPFORMATETC rgelt, ULONG FAR* pceltFetch ULONG i=0; ULONG nOffset; - if (rgelt == NULL) + if (rgelt == nullptr) return ResultFromScode(E_INVALIDARG); while (i < celt) { @@ -311,7 +311,7 @@ QWindowsOleEnumFmtEtc::Next(ULONG celt, LPFORMATETC rgelt, ULONG FAR* pceltFetch m_nIndex += i; - if (pceltFetched != NULL) + if (pceltFetched != nullptr) *pceltFetched = i; if (i != celt) @@ -354,7 +354,7 @@ QWindowsOleEnumFmtEtc::Reset() STDMETHODIMP QWindowsOleEnumFmtEtc::Clone(LPENUMFORMATETC FAR* newEnum) { - if (newEnum == NULL) + if (newEnum == nullptr) return ResultFromScode(E_INVALIDARG); QWindowsOleEnumFmtEtc *result = new QWindowsOleEnumFmtEtc(m_lpfmtetcs); @@ -371,7 +371,7 @@ QWindowsOleEnumFmtEtc::Clone(LPENUMFORMATETC FAR* newEnum) bool QWindowsOleEnumFmtEtc::copyFormatEtc(LPFORMATETC dest, const FORMATETC *src) const { - if (dest == NULL || src == NULL) + if (dest == nullptr || src == nullptr) return false; *dest = *src; diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp index 3efccf0f32..840a3a11c4 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.cpp +++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp @@ -62,19 +62,70 @@ QT_BEGIN_NAMESPACE static const DWORD VENDOR_ID_AMD = 0x1002; -GpuDescription GpuDescription::detect() +static GpuDescription adapterIdentifierToGpuDescription(const D3DADAPTER_IDENTIFIER9 &adapterIdentifier) +{ + GpuDescription result; + result.vendorId = adapterIdentifier.VendorId; + result.deviceId = adapterIdentifier.DeviceId; + result.revision = adapterIdentifier.Revision; + result.subSysId = adapterIdentifier.SubSysId; + QVector<int> version(4, 0); + version[0] = HIWORD(adapterIdentifier.DriverVersion.HighPart); // Product + version[1] = LOWORD(adapterIdentifier.DriverVersion.HighPart); // Version + version[2] = HIWORD(adapterIdentifier.DriverVersion.LowPart); // Sub version + version[3] = LOWORD(adapterIdentifier.DriverVersion.LowPart); // build + result.driverVersion = QVersionNumber(version); + result.driverName = adapterIdentifier.Driver; + result.description = adapterIdentifier.Description; + return result; +} + +class QDirect3D9Handle +{ +public: + Q_DISABLE_COPY(QDirect3D9Handle) + + QDirect3D9Handle(); + ~QDirect3D9Handle(); + + bool isValid() const { return m_direct3D9 != nullptr; } + + UINT adapterCount() const { return m_direct3D9 ? m_direct3D9->GetAdapterCount() : 0u; } + bool retrieveAdapterIdentifier(UINT n, D3DADAPTER_IDENTIFIER9 *adapterIdentifier) const; + +private: + QSystemLibrary m_d3d9lib; + IDirect3D9 *m_direct3D9 = nullptr; +}; + +QDirect3D9Handle::QDirect3D9Handle() : + m_d3d9lib(QStringLiteral("d3d9")) { - typedef IDirect3D9 * (WINAPI *PtrDirect3DCreate9)(UINT); + using PtrDirect3DCreate9 = IDirect3D9 *(WINAPI *)(UINT); + if (m_d3d9lib.load()) { + if (auto direct3DCreate9 = (PtrDirect3DCreate9)m_d3d9lib.resolve("Direct3DCreate9")) + m_direct3D9 = direct3DCreate9(D3D_SDK_VERSION); + } +} + +QDirect3D9Handle::~QDirect3D9Handle() +{ + if (m_direct3D9) + m_direct3D9->Release(); +} + +bool QDirect3D9Handle::retrieveAdapterIdentifier(UINT n, D3DADAPTER_IDENTIFIER9 *adapterIdentifier) const +{ + return m_direct3D9 + && SUCCEEDED(m_direct3D9->GetAdapterIdentifier(n, 0, adapterIdentifier)); +} + +GpuDescription GpuDescription::detect() +{ GpuDescription result; - QSystemLibrary d3d9lib(QStringLiteral("d3d9")); - if (!d3d9lib.load()) - return result; - PtrDirect3DCreate9 direct3DCreate9 = (PtrDirect3DCreate9)d3d9lib.resolve("Direct3DCreate9"); - if (!direct3DCreate9) - return result; - IDirect3D9 *direct3D9 = direct3DCreate9(D3D_SDK_VERSION); - if (!direct3D9) + QDirect3D9Handle direct3D9; + if (!direct3D9.isValid()) return result; D3DADAPTER_IDENTIFIER9 adapterIdentifier; @@ -85,20 +136,8 @@ GpuDescription GpuDescription::detect() // and D3D uses by default. Therefore querying any additional adapters is // futile and not useful for our purposes in general, except for // identifying a few special cases later on. - HRESULT hr = direct3D9->GetAdapterIdentifier(0, 0, &adapterIdentifier); - if (SUCCEEDED(hr)) { - result.vendorId = adapterIdentifier.VendorId; - result.deviceId = adapterIdentifier.DeviceId; - result.revision = adapterIdentifier.Revision; - result.subSysId = adapterIdentifier.SubSysId; - QVector<int> version(4, 0); - version[0] = HIWORD(adapterIdentifier.DriverVersion.HighPart); // Product - version[1] = LOWORD(adapterIdentifier.DriverVersion.HighPart); // Version - version[2] = HIWORD(adapterIdentifier.DriverVersion.LowPart); // Sub version - version[3] = LOWORD(adapterIdentifier.DriverVersion.LowPart); // build - result.driverVersion = QVersionNumber(version); - result.driverName = adapterIdentifier.Driver; - result.description = adapterIdentifier.Description; + if (direct3D9.retrieveAdapterIdentifier(0, &adapterIdentifier)) { + result = adapterIdentifierToGpuDescription(adapterIdentifier); isAMD = result.vendorId == VENDOR_ID_AMD; } @@ -106,30 +145,41 @@ GpuDescription GpuDescription::detect() // when starting apps on a screen connected to the Intel card) by looking // for a default AMD adapter and an additional non-AMD one. if (isAMD) { - const UINT adapterCount = direct3D9->GetAdapterCount(); + const UINT adapterCount = direct3D9.adapterCount(); for (UINT adp = 1; adp < adapterCount; ++adp) { - hr = direct3D9->GetAdapterIdentifier(adp, 0, &adapterIdentifier); - if (SUCCEEDED(hr)) { - if (adapterIdentifier.VendorId != VENDOR_ID_AMD) { - // Bingo. Now figure out the display for the AMD card. - DISPLAY_DEVICE dd; - memset(&dd, 0, sizeof(dd)); - dd.cb = sizeof(dd); - for (int dev = 0; EnumDisplayDevices(nullptr, dev, &dd, 0); ++dev) { - if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) { - // DeviceName is something like \\.\DISPLAY1 which can be used to - // match with the MONITORINFOEX::szDevice queried by QWindowsScreen. - result.gpuSuitableScreen = QString::fromWCharArray(dd.DeviceName); - break; - } + if (direct3D9.retrieveAdapterIdentifier(adp, &adapterIdentifier) + && adapterIdentifier.VendorId != VENDOR_ID_AMD) { + // Bingo. Now figure out the display for the AMD card. + DISPLAY_DEVICE dd; + memset(&dd, 0, sizeof(dd)); + dd.cb = sizeof(dd); + for (int dev = 0; EnumDisplayDevices(nullptr, dev, &dd, 0); ++dev) { + if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) { + // DeviceName is something like \\.\DISPLAY1 which can be used to + // match with the MONITORINFOEX::szDevice queried by QWindowsScreen. + result.gpuSuitableScreen = QString::fromWCharArray(dd.DeviceName); + break; } - break; } + break; } } } - direct3D9->Release(); + return result; +} + +QVector<GpuDescription> GpuDescription::detectAll() +{ + QVector<GpuDescription> result; + QDirect3D9Handle direct3D9; + if (const UINT adapterCount = direct3D9.adapterCount()) { + for (UINT adp = 0; adp < adapterCount; ++adp) { + D3DADAPTER_IDENTIFIER9 adapterIdentifier; + if (direct3D9.retrieveAdapterIdentifier(adp, &adapterIdentifier)) + result.append(adapterIdentifierToGpuDescription(adapterIdentifier)); + } + } return result; } @@ -330,10 +380,10 @@ bool QWindowsOpenGLTester::testDesktopGL() typedef BOOL (WINAPI *MakeCurrentType)(HDC, HGLRC); typedef PROC (WINAPI *WglGetProcAddressType)(LPCSTR); - HMODULE lib = 0; - HWND wnd = 0; - HDC dc = 0; - HGLRC context = 0; + HMODULE lib = nullptr; + HWND wnd = nullptr; + HDC dc = nullptr; + HGLRC context = nullptr; LPCTSTR className = L"qtopengltest"; CreateContextType CreateContext = nullptr; @@ -367,18 +417,18 @@ bool QWindowsOpenGLTester::testDesktopGL() WNDCLASS wclass; wclass.cbClsExtra = 0; wclass.cbWndExtra = 0; - wclass.hInstance = static_cast<HINSTANCE>(GetModuleHandle(0)); - wclass.hIcon = 0; - wclass.hCursor = 0; + wclass.hInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr)); + wclass.hIcon = nullptr; + wclass.hCursor = nullptr; wclass.hbrBackground = HBRUSH(COLOR_BACKGROUND); - wclass.lpszMenuName = 0; + wclass.lpszMenuName = nullptr; wclass.lpfnWndProc = DefWindowProc; wclass.lpszClassName = className; wclass.style = CS_OWNDC; if (!RegisterClass(&wclass)) goto cleanup; wnd = CreateWindow(className, L"qtopenglproxytest", WS_OVERLAPPED, - 0, 0, 640, 480, 0, 0, wclass.hInstance, 0); + 0, 0, 640, 480, nullptr, nullptr, wclass.hInstance, nullptr); if (!wnd) goto cleanup; dc = GetDC(wnd); @@ -447,14 +497,14 @@ bool QWindowsOpenGLTester::testDesktopGL() cleanup: if (MakeCurrent) - MakeCurrent(0, 0); + MakeCurrent(nullptr, nullptr); if (context) DeleteContext(context); if (dc && wnd) ReleaseDC(wnd, dc); if (wnd) { DestroyWindow(wnd); - UnregisterClass(className, GetModuleHandle(0)); + UnregisterClass(className, GetModuleHandle(nullptr)); } // No FreeLibrary. Some implementations, Mesa in particular, deadlock when trying to unload. diff --git a/src/plugins/platforms/windows/qwindowsopengltester.h b/src/plugins/platforms/windows/qwindowsopengltester.h index 08628c2586..9576dfbae0 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.h +++ b/src/plugins/platforms/windows/qwindowsopengltester.h @@ -42,6 +42,7 @@ #include <QtCore/qbytearray.h> #include <QtCore/qflags.h> +#include <QtCore/qvector.h> #include <QtCore/qversionnumber.h> QT_BEGIN_NAMESPACE @@ -52,6 +53,7 @@ class QVariant; struct GpuDescription { static GpuDescription detect(); + static QVector<GpuDescription> detectAll(); QString toString() const; QVariant toVariant() const; diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp index c5acc38e7c..f1960f1585 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp +++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -51,7 +51,6 @@ #include "qwindowsintegration.h" #include "qwindowsscreen.h" -#include <qpa/qwindowsysteminterface.h> #include <QtGui/qguiapplication.h> #include <QtGui/qscreen.h> #include <QtGui/qtouchdevice.h> @@ -60,6 +59,7 @@ #include <QtCore/qvarlengtharray.h> #include <QtCore/qloggingcategory.h> #include <QtCore/qoperatingsystemversion.h> +#include <QtCore/qqueue.h> #include <algorithm> @@ -90,12 +90,8 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q case QT_PT_POINTER: case QT_PT_MOUSE: case QT_PT_TOUCHPAD: { - POINTER_INFO pointerInfo; - if (!QWindowsContext::user32dll.getPointerInfo(pointerId, &pointerInfo)) { - qWarning() << "GetPointerInfo() failed:" << qt_error_string(); - return false; - } - return translateMouseTouchPadEvent(window, hwnd, et, msg, &pointerInfo); + // Let Mouse/TouchPad be handled using legacy messages. + return false; } case QT_PT_TOUCH: { quint32 pointerCount = 0; @@ -171,82 +167,87 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q return false; } -static void getMouseEventInfo(UINT message, POINTER_BUTTON_CHANGE_TYPE changeType, QPoint globalPos, QEvent::Type *eventType, Qt::MouseButton *mouseButton) +namespace { +struct MouseEvent { + QEvent::Type type; + Qt::MouseButton button; +}; +} // namespace + +static inline Qt::MouseButton extraButton(WPARAM wParam) // for WM_XBUTTON... { - static const QHash<POINTER_BUTTON_CHANGE_TYPE, Qt::MouseButton> buttonMapping { - {POINTER_CHANGE_FIRSTBUTTON_DOWN, Qt::LeftButton}, - {POINTER_CHANGE_FIRSTBUTTON_UP, Qt::LeftButton}, - {POINTER_CHANGE_SECONDBUTTON_DOWN, Qt::RightButton}, - {POINTER_CHANGE_SECONDBUTTON_UP, Qt::RightButton}, - {POINTER_CHANGE_THIRDBUTTON_DOWN, Qt::MiddleButton}, - {POINTER_CHANGE_THIRDBUTTON_UP, Qt::MiddleButton}, - {POINTER_CHANGE_FOURTHBUTTON_DOWN, Qt::XButton1}, - {POINTER_CHANGE_FOURTHBUTTON_UP, Qt::XButton1}, - {POINTER_CHANGE_FIFTHBUTTON_DOWN, Qt::XButton2}, - {POINTER_CHANGE_FIFTHBUTTON_UP, Qt::XButton2}, - }; - - static const POINTER_BUTTON_CHANGE_TYPE downChanges[] = { - POINTER_CHANGE_FIRSTBUTTON_DOWN, - POINTER_CHANGE_SECONDBUTTON_DOWN, - POINTER_CHANGE_THIRDBUTTON_DOWN, - POINTER_CHANGE_FOURTHBUTTON_DOWN, - POINTER_CHANGE_FIFTHBUTTON_DOWN, - }; - - static const POINTER_BUTTON_CHANGE_TYPE upChanges[] = { - POINTER_CHANGE_FIRSTBUTTON_UP, - POINTER_CHANGE_SECONDBUTTON_UP, - POINTER_CHANGE_THIRDBUTTON_UP, - POINTER_CHANGE_FOURTHBUTTON_UP, - POINTER_CHANGE_FIFTHBUTTON_UP, - }; - - if (!eventType || !mouseButton) - return; - - const bool nonClient = message == WM_NCPOINTERUPDATE || - message == WM_NCPOINTERDOWN || - message == WM_NCPOINTERUP; - - if (std::find(std::begin(downChanges), - std::end(downChanges), changeType) < std::end(downChanges)) { - *eventType = nonClient ? QEvent::NonClientAreaMouseButtonPress : - QEvent::MouseButtonPress; - } else if (std::find(std::begin(upChanges), - std::end(upChanges), changeType) < std::end(upChanges)) { - *eventType = nonClient ? QEvent::NonClientAreaMouseButtonRelease : - QEvent::MouseButtonRelease; - } else if (message == WM_POINTERWHEEL || message == WM_POINTERHWHEEL) { - *eventType = QEvent::Wheel; - } else { - *eventType = nonClient ? QEvent::NonClientAreaMouseMove : - QEvent::MouseMove; - } + return GET_XBUTTON_WPARAM(wParam) == XBUTTON1 ? Qt::BackButton : Qt::ForwardButton; +} - *mouseButton = buttonMapping.value(changeType, Qt::NoButton); - - // Pointer messages lack a double click indicator. Check if this is the case here. - if (*eventType == QEvent::MouseButtonPress || - *eventType == QEvent::NonClientAreaMouseButtonPress) { - static LONG lastTime = 0; - static Qt::MouseButton lastButton = Qt::NoButton; - static QEvent::Type lastEvent = QEvent::None; - static QPoint lastPos; - LONG messageTime = GetMessageTime(); - if (*mouseButton == lastButton - && *eventType == lastEvent - && messageTime - lastTime < (LONG)GetDoubleClickTime() - && qAbs(globalPos.x() - lastPos.x()) < GetSystemMetrics(SM_CXDOUBLECLK) - && qAbs(globalPos.y() - lastPos.y()) < GetSystemMetrics(SM_CYDOUBLECLK)) { - *eventType = nonClient ? QEvent::NonClientAreaMouseButtonDblClick : - QEvent::MouseButtonDblClick; - } - lastTime = messageTime; - lastButton = *mouseButton; - lastEvent = *eventType; - lastPos = globalPos; +static inline MouseEvent eventFromMsg(const MSG &msg) +{ + switch (msg.message) { + case WM_MOUSEMOVE: + return {QEvent::MouseMove, Qt::NoButton}; + case WM_LBUTTONDOWN: + return {QEvent::MouseButtonPress, Qt::LeftButton}; + case WM_LBUTTONUP: + return {QEvent::MouseButtonRelease, Qt::LeftButton}; + case WM_LBUTTONDBLCLK: // Qt QPA does not handle double clicks, send as press + return {QEvent::MouseButtonPress, Qt::LeftButton}; + case WM_MBUTTONDOWN: + return {QEvent::MouseButtonPress, Qt::MidButton}; + case WM_MBUTTONUP: + return {QEvent::MouseButtonRelease, Qt::MidButton}; + case WM_MBUTTONDBLCLK: + return {QEvent::MouseButtonPress, Qt::MidButton}; + case WM_RBUTTONDOWN: + return {QEvent::MouseButtonPress, Qt::RightButton}; + case WM_RBUTTONUP: + return {QEvent::MouseButtonRelease, Qt::RightButton}; + case WM_RBUTTONDBLCLK: + return {QEvent::MouseButtonPress, Qt::RightButton}; + case WM_XBUTTONDOWN: + return {QEvent::MouseButtonPress, extraButton(msg.wParam)}; + case WM_XBUTTONUP: + return {QEvent::MouseButtonRelease, extraButton(msg.wParam)}; + case WM_XBUTTONDBLCLK: + return {QEvent::MouseButtonPress, extraButton(msg.wParam)}; + case WM_NCMOUSEMOVE: + return {QEvent::NonClientAreaMouseMove, Qt::NoButton}; + case WM_NCLBUTTONDOWN: + return {QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton}; + case WM_NCLBUTTONUP: + return {QEvent::NonClientAreaMouseButtonRelease, Qt::LeftButton}; + case WM_NCLBUTTONDBLCLK: + return {QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton}; + case WM_NCMBUTTONDOWN: + return {QEvent::NonClientAreaMouseButtonPress, Qt::MidButton}; + case WM_NCMBUTTONUP: + return {QEvent::NonClientAreaMouseButtonRelease, Qt::MidButton}; + case WM_NCMBUTTONDBLCLK: + return {QEvent::NonClientAreaMouseButtonPress, Qt::MidButton}; + case WM_NCRBUTTONDOWN: + return {QEvent::NonClientAreaMouseButtonPress, Qt::RightButton}; + case WM_NCRBUTTONUP: + return {QEvent::NonClientAreaMouseButtonRelease, Qt::RightButton}; + case WM_NCRBUTTONDBLCLK: + return {QEvent::NonClientAreaMouseButtonPress, Qt::RightButton}; + default: // WM_MOUSELEAVE + break; } + return {QEvent::None, Qt::NoButton}; +} + +static Qt::MouseButtons mouseButtonsFromKeyState(WPARAM keyState) +{ + Qt::MouseButtons result = Qt::NoButton; + if (keyState & MK_LBUTTON) + result |= Qt::LeftButton; + if (keyState & MK_RBUTTON) + result |= Qt::RightButton; + if (keyState & MK_MBUTTON) + result |= Qt::MiddleButton; + if (keyState & MK_XBUTTON1) + result |= Qt::XButton1; + if (keyState & MK_XBUTTON2) + result |= Qt::XButton2; + return result; } static QWindow *getWindowUnderPointer(QWindow *window, QPoint globalPos) @@ -318,102 +319,101 @@ QTouchDevice *QWindowsPointerHandler::ensureTouchDevice() return m_touchDevice; } -Qt::MouseButtons QWindowsPointerHandler::queryMouseButtons() -{ - Qt::MouseButtons result = 0; - const bool mouseSwapped = GetSystemMetrics(SM_SWAPBUTTON); - if (GetAsyncKeyState(VK_LBUTTON) < 0) - result |= mouseSwapped ? Qt::RightButton: Qt::LeftButton; - if (GetAsyncKeyState(VK_RBUTTON) < 0) - result |= mouseSwapped ? Qt::LeftButton : Qt::RightButton; - if (GetAsyncKeyState(VK_MBUTTON) < 0) - result |= Qt::MidButton; - if (GetAsyncKeyState(VK_XBUTTON1) < 0) - result |= Qt::XButton1; - if (GetAsyncKeyState(VK_XBUTTON2) < 0) - result |= Qt::XButton2; - return result; -} - -bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND hwnd, - QtWindows::WindowsEventType et, - MSG msg, PVOID vPointerInfo) +void QWindowsPointerHandler::handleCaptureRelease(QWindow *window, + QWindow *currentWindowUnderPointer, + HWND hwnd, + QEvent::Type eventType, + Qt::MouseButtons mouseButtons) { - POINTER_INFO *pointerInfo = static_cast<POINTER_INFO *>(vPointerInfo); - const QPoint globalPos = QPoint(pointerInfo->ptPixelLocation.x, pointerInfo->ptPixelLocation.y); - const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos); - const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers(); - const Qt::MouseButtons mouseButtons = queryMouseButtons(); - - QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos); QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle()); - switch (msg.message) { - case WM_NCPOINTERDOWN: - case WM_NCPOINTERUP: - case WM_NCPOINTERUPDATE: - case WM_POINTERDOWN: - case WM_POINTERUP: - case WM_POINTERUPDATE: { + // Qt expects the platform plugin to capture the mouse on any button press until release. + if (!platformWindow->hasMouseCapture() && eventType == QEvent::MouseButtonPress) { - QEvent::Type eventType; - Qt::MouseButton button; - getMouseEventInfo(msg.message, pointerInfo->ButtonChangeType, globalPos, &eventType, &button); + platformWindow->setMouseGrabEnabled(true); + platformWindow->setFlag(QWindowsWindow::AutoMouseCapture); + qCDebug(lcQpaEvents) << "Automatic mouse capture " << window; - if (et & QtWindows::NonClientEventFlag) { - QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, mouseButtons, button, eventType, - keyModifiers, Qt::MouseEventNotSynthesized); - return false; // To allow window dragging, etc. - } else { - if (currentWindowUnderPointer != m_windowUnderPointer) { - if (m_windowUnderPointer && m_windowUnderPointer == m_currentWindow) { - QWindowSystemInterface::handleLeaveEvent(m_windowUnderPointer); - m_currentWindow = nullptr; - } - - if (currentWindowUnderPointer) { - if (currentWindowUnderPointer != m_currentWindow) { - QWindowSystemInterface::handleEnterEvent(currentWindowUnderPointer, localPos, globalPos); - m_currentWindow = currentWindowUnderPointer; - if (QWindowsWindow *wumPlatformWindow = QWindowsWindow::windowsWindowOf(currentWindowUnderPointer)) - wumPlatformWindow->applyCursor(); - trackLeave(hwnd); - } - } else { - platformWindow->applyCursor(); - } - m_windowUnderPointer = currentWindowUnderPointer; - } + // Implement "Click to focus" for native child windows (unless it is a native widget window). + if (!window->isTopLevel() && !window->inherits("QWidgetWindow") && QGuiApplication::focusWindow() != window) + window->requestActivate(); - QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, button, eventType, - keyModifiers, Qt::MouseEventNotSynthesized); + } else if (platformWindow->hasMouseCapture() + && platformWindow->testFlag(QWindowsWindow::AutoMouseCapture) + && eventType == QEvent::MouseButtonRelease + && !mouseButtons) { - // The initial down click over the QSizeGrip area, which posts a resize WM_SYSCOMMAND - // has go to through DefWindowProc() for resizing to work, so we return false here, - // unless the mouse is captured, as it would mess with menu processing. - return msg.message != WM_POINTERDOWN || GetCapture(); - } + platformWindow->setMouseGrabEnabled(false); + qCDebug(lcQpaEvents) << "Releasing automatic mouse capture " << window; } - case WM_POINTERHWHEEL: - case WM_POINTERWHEEL: { - int delta = GET_WHEEL_DELTA_WPARAM(msg.wParam); + // Enter new window: track to generate leave event. + // If there is an active capture, only track if the current window is capturing, + // so we don't get extra leave when cursor leaves the application. + if (window != m_currentWindow && + (!platformWindow->hasMouseCapture() || currentWindowUnderPointer == window)) { + trackLeave(hwnd); + m_currentWindow = window; + } +} - // Qt horizontal wheel rotation orientation is opposite to the one in WM_POINTERHWHEEL - if (msg.message == WM_POINTERHWHEEL) - delta = -delta; +void QWindowsPointerHandler::handleEnterLeave(QWindow *window, + QWindow *currentWindowUnderPointer, + QPoint globalPos) +{ + QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle()); + const bool hasCapture = platformWindow->hasMouseCapture(); + + // No enter or leave events are sent as long as there is an autocapturing window. + if (!hasCapture || !platformWindow->testFlag(QWindowsWindow::AutoMouseCapture)) { + + // Leave is needed if: + // 1) There is no capture and we move from a window to another window. + // Note: Leaving the application entirely is handled in translateMouseEvent(WM_MOUSELEAVE). + // 2) There is capture and we move out of the capturing window. + // 3) There is a new capture and we were over another window. + if ((m_windowUnderPointer && m_windowUnderPointer != currentWindowUnderPointer + && (!hasCapture || window == m_windowUnderPointer)) + || (hasCapture && m_previousCaptureWindow != window && m_windowUnderPointer + && m_windowUnderPointer != window)) { + + qCDebug(lcQpaEvents) << "Leaving window " << m_windowUnderPointer; + QWindowSystemInterface::handleLeaveEvent(m_windowUnderPointer); - const QPoint angleDelta = (msg.message == WM_POINTERHWHEEL || (keyModifiers & Qt::AltModifier)) ? - QPoint(delta, 0) : QPoint(0, delta); + if (hasCapture && currentWindowUnderPointer != window) { + // Clear tracking if capturing and current window is not the capturing window + // to avoid leave when mouse actually leaves the application. + m_currentWindow = nullptr; + // We are not officially in any window, but we need to set some cursor to clear + // whatever cursor the left window had, so apply the cursor of the capture window. + platformWindow->applyCursor(); + } + } - if (isValidWheelReceiver(window)) - QWindowSystemInterface::handleWheelEvent(window, localPos, globalPos, QPoint(), angleDelta, keyModifiers); - return true; - } - case WM_POINTERLEAVE: - return true; + // Enter is needed if: + // 1) There is no capture and we move to a new window. + // 2) There is capture and we move into the capturing window. + // 3) The capture just ended and we are over non-capturing window. + if ((currentWindowUnderPointer && m_windowUnderPointer != currentWindowUnderPointer + && (!hasCapture || currentWindowUnderPointer == window)) + || (m_previousCaptureWindow && !hasCapture && currentWindowUnderPointer + && currentWindowUnderPointer != m_previousCaptureWindow)) { + + QPoint wumLocalPos; + if (QWindowsWindow *wumPlatformWindow = QWindowsWindow::windowsWindowOf(currentWindowUnderPointer)) { + wumLocalPos = wumPlatformWindow->mapFromGlobal(globalPos); + wumPlatformWindow->applyCursor(); + } + qCDebug(lcQpaEvents) << "Entering window " << currentWindowUnderPointer; + QWindowSystemInterface::handleEnterEvent(currentWindowUnderPointer, wumLocalPos, globalPos); + } + + // We need to track m_windowUnderPointer separately from m_currentWindow, as Windows + // mouse tracking will not trigger WM_MOUSELEAVE for leaving window when mouse capture is set. + m_windowUnderPointer = currentWindowUnderPointer; } - return false; + + m_previousCaptureWindow = hasCapture ? window : nullptr; } bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd, @@ -421,7 +421,6 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd, MSG msg, PVOID vTouchInfo, quint32 count) { Q_UNUSED(hwnd); - Q_UNUSED(et); if (et & QtWindows::NonClientEventFlag) return false; // Let DefWindowProc() handle Non Client messages. @@ -458,6 +457,8 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd, << " message=" << hex << msg.message << " count=" << dec << count; + Qt::TouchPointStates allStates = 0; + for (quint32 i = 0; i < count; ++i) { if (QWindowsContext::verbose > 1) qCDebug(lcQpaEvents).noquote().nospace() << showbase @@ -466,7 +467,13 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd, << " flags=" << hex << touchInfo[i].pointerInfo.pointerFlags; QWindowSystemInterface::TouchPoint touchPoint; - touchPoint.id = touchInfo[i].pointerInfo.pointerId; + const quint32 pointerId = touchInfo[i].pointerInfo.pointerId; + int id = m_touchInputIDToTouchPointID.value(pointerId, -1); + if (id == -1) { + id = m_touchInputIDToTouchPointID.size(); + m_touchInputIDToTouchPointID.insert(pointerId, id); + } + touchPoint.id = id; touchPoint.pressure = (touchInfo[i].touchMask & TOUCH_MASK_PRESSURE) ? touchInfo[i].pressure / 1024.0 : 1.0; if (m_lastTouchPositions.contains(touchPoint.id)) @@ -494,21 +501,27 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd, touchPoint.state = stationaryTouchPoint ? Qt::TouchPointStationary : Qt::TouchPointMoved; m_lastTouchPositions.insert(touchPoint.id, touchPoint.normalPosition); } + allStates |= touchPoint.state; + touchPoints.append(touchPoint); // Avoid getting repeated messages for this frame if there are multiple pointerIds QWindowsContext::user32dll.skipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId); } + // all touch points released, forget the ids we've seen. + if (allStates == Qt::TouchPointReleased) + m_touchInputIDToTouchPointID.clear(); + QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, touchPoints, QWindowsKeyMapper::queryKeyboardModifiers()); - - return true; + return false; // Allow mouse messages to be generated. } bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPenInfo) { +#if QT_CONFIG(tabletevent) if (et & QtWindows::NonClientEventFlag) return false; // Let DefWindowProc() handle Non Client messages. @@ -595,73 +608,135 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin QWindowSystemInterface::handleTabletEvent(target, localPos, hiResGlobalPos, device, type, mouseButtons, pressure, xTilt, yTilt, tangentialPressure, rotation, z, pointerId, keyModifiers); - break; + return false; // Allow mouse messages to be generated. } } return true; +#else + Q_UNUSED(window); + Q_UNUSED(hwnd); + Q_UNUSED(et); + Q_UNUSED(msg); + Q_UNUSED(vPenInfo); + return false; +#endif } -// SetCursorPos()/TrackMouseEvent() will generate old-style WM_MOUSE messages. Handle them here. -bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result) +static inline bool isMouseEventSynthesizedFromPenOrTouch() { - Q_UNUSED(et); + // For details, see + // https://docs.microsoft.com/en-us/windows/desktop/tablet/system-events-and-mouse-messages + const LONG_PTR SIGNATURE_MASK = 0xFFFFFF00; + const LONG_PTR MI_WP_SIGNATURE = 0xFF515700; - *result = 0; - if (msg.message != WM_MOUSELEAVE && msg.message != WM_MOUSEMOVE) - return false; + return ((::GetMessageExtraInfo() & SIGNATURE_MASK) == MI_WP_SIGNATURE); +} - const QPoint localPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam)); - const QPoint globalPos = QWindowsGeometryHint::mapToGlobal(hwnd, localPos); +bool QWindowsPointerHandler::translateMouseWheelEvent(QWindow *window, + QWindow *currentWindowUnderPointer, + MSG msg, + QPoint globalPos, + Qt::KeyboardModifiers keyModifiers) +{ + QWindow *receiver = currentWindowUnderPointer; + if (!isValidWheelReceiver(receiver)) + receiver = window; + if (!isValidWheelReceiver(receiver)) + return true; - QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle()); + int delta = GET_WHEEL_DELTA_WPARAM(msg.wParam); - if (msg.message == WM_MOUSELEAVE) { - if (window == m_currentWindow) { - QWindowSystemInterface::handleLeaveEvent(window); - m_windowUnderPointer = nullptr; - m_currentWindow = nullptr; - platformWindow->applyCursor(); - } - return false; + // Qt horizontal wheel rotation orientation is opposite to the one in WM_MOUSEHWHEEL + if (msg.message == WM_MOUSEHWHEEL) + delta = -delta; + + const QPoint angleDelta = (msg.message == WM_MOUSEHWHEEL || (keyModifiers & Qt::AltModifier)) ? + QPoint(delta, 0) : QPoint(0, delta); + + QPoint localPos = QWindowsGeometryHint::mapFromGlobal(receiver, globalPos); + + QWindowSystemInterface::handleWheelEvent(window, localPos, globalPos, QPoint(), angleDelta, keyModifiers); + return true; +} + +// Process legacy mouse messages here. +bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, + HWND hwnd, + QtWindows::WindowsEventType et, + MSG msg, + LRESULT *result) +{ + *result = 0; + + const QPoint eventPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam)); + QPoint localPos; + QPoint globalPos; + + if ((et == QtWindows::MouseWheelEvent) || (et & QtWindows::NonClientEventFlag)) { + globalPos = eventPos; + localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, eventPos); + } else { + localPos = eventPos; + globalPos = QWindowsGeometryHint::mapToGlobal(hwnd, eventPos); } + const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers(); + const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam); + QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos); + + if (et == QtWindows::MouseWheelEvent) + return translateMouseWheelEvent(window, currentWindowUnderPointer, msg, globalPos, keyModifiers); + // Windows sends a mouse move with no buttons pressed to signal "Enter" // when a window is shown over the cursor. Discard the event and only use // it for generating QEvent::Enter to be consistent with other platforms - // X11 and macOS. - static QPoint lastMouseMovePos; - const bool discardEvent = msg.wParam == 0 && (m_windowUnderPointer.isNull() || globalPos == lastMouseMovePos); - lastMouseMovePos = globalPos; + bool discardEvent = false; + if (msg.message == WM_MOUSEMOVE) { + static QPoint lastMouseMovePos; + if (msg.wParam == 0 && (m_windowUnderPointer.isNull() || globalPos == lastMouseMovePos)) + discardEvent = true; + lastMouseMovePos = globalPos; + } - QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos); + Qt::MouseEventSource source = Qt::MouseEventNotSynthesized; + if (isMouseEventSynthesizedFromPenOrTouch()) { + if (QWindowsIntegration::instance()->options() & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch) + return false; + source = Qt::MouseEventSynthesizedBySystem; + } - if (currentWindowUnderPointer != m_windowUnderPointer) { - if (m_windowUnderPointer && m_windowUnderPointer == m_currentWindow) { - QWindowSystemInterface::handleLeaveEvent(m_windowUnderPointer); - m_currentWindow = nullptr; - } + const MouseEvent mouseEvent = eventFromMsg(msg); - if (currentWindowUnderPointer) { - if (currentWindowUnderPointer != m_currentWindow) { - QWindowSystemInterface::handleEnterEvent(currentWindowUnderPointer, localPos, globalPos); - m_currentWindow = currentWindowUnderPointer; - if (QWindowsWindow *wumPlatformWindow = QWindowsWindow::windowsWindowOf(currentWindowUnderPointer)) - wumPlatformWindow->applyCursor(); - trackLeave(hwnd); - } - } else { - platformWindow->applyCursor(); + if (mouseEvent.type >= QEvent::NonClientAreaMouseMove && mouseEvent.type <= QEvent::NonClientAreaMouseButtonDblClick) { + QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, mouseButtons, + mouseEvent.button, mouseEvent.type, keyModifiers, source); + return false; // Allow further event processing + } + + if (msg.message == WM_MOUSELEAVE) { + if (window == m_currentWindow) { + QWindow *leaveTarget = m_windowUnderPointer ? m_windowUnderPointer : m_currentWindow; + qCDebug(lcQpaEvents) << "Leaving window " << leaveTarget; + QWindowSystemInterface::handleLeaveEvent(leaveTarget); + m_windowUnderPointer = nullptr; + m_currentWindow = nullptr; } - m_windowUnderPointer = currentWindowUnderPointer; + return true; } - const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers(); - const Qt::MouseButtons mouseButtons = queryMouseButtons(); + handleCaptureRelease(window, currentWindowUnderPointer, hwnd, mouseEvent.type, mouseButtons); + handleEnterLeave(window, currentWindowUnderPointer, globalPos); - if (!discardEvent) - QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, Qt::NoButton, QEvent::MouseMove, - keyModifiers, Qt::MouseEventNotSynthesized); - return false; + if (!discardEvent && mouseEvent.type != QEvent::None) { + QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, + mouseEvent.button, mouseEvent.type, keyModifiers, source); + } + + // QTBUG-48117, force synchronous handling for the extra buttons so that WM_APPCOMMAND + // is sent for unhandled WM_XBUTTONDOWN. + return (msg.message != WM_XBUTTONUP && msg.message != WM_XBUTTONDOWN && msg.message != WM_XBUTTONDBLCLK) + || QWindowSystemInterface::flushWindowSystemEvents(); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.h b/src/plugins/platforms/windows/qwindowspointerhandler.h index c4d0e0ce4a..aebef062bc 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.h +++ b/src/plugins/platforms/windows/qwindowspointerhandler.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -46,6 +46,7 @@ #include <QtCore/qpointer.h> #include <QtCore/qscopedpointer.h> #include <QtCore/qhash.h> +#include <qpa/qwindowsysteminterface.h> QT_BEGIN_NAMESPACE @@ -61,19 +62,22 @@ public: bool translateMouseEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result); QTouchDevice *touchDevice() const { return m_touchDevice; } QTouchDevice *ensureTouchDevice(); - Qt::MouseButtons queryMouseButtons(); QWindow *windowUnderMouse() const { return m_windowUnderPointer.data(); } void clearWindowUnderMouse() { m_windowUnderPointer = nullptr; } private: - bool translateMouseTouchPadEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPointerInfo); bool translateTouchEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vTouchInfo, unsigned int count); bool translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPenInfo); + bool translateMouseWheelEvent(QWindow *window, QWindow *currentWindowUnderPointer, MSG msg, QPoint globalPos, Qt::KeyboardModifiers keyModifiers); + void handleCaptureRelease(QWindow *window, QWindow *currentWindowUnderPointer, HWND hwnd, QEvent::Type eventType, Qt::MouseButtons mouseButtons); + void handleEnterLeave(QWindow *window, QWindow *currentWindowUnderPointer, QPoint globalPos); QTouchDevice *m_touchDevice = nullptr; QHash<int, QPointF> m_lastTouchPositions; + QHash<DWORD, int> m_touchInputIDToTouchPointID; QPointer<QWindow> m_windowUnderPointer; QPointer<QWindow> m_currentWindow; + QWindow *m_previousCaptureWindow = nullptr; bool m_needsEnterOnPointerUpdate = false; }; diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index 2eaf386d42..0520f88935 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -89,7 +89,7 @@ static bool monitorData(HMONITOR hMonitor, QWindowsScreenData *data) if (data->name == QLatin1String("WinDisc")) { data->flags |= QWindowsScreenData::LockScreen; } else { - if (const HDC hdc = CreateDC(info.szDevice, NULL, NULL, NULL)) { + if (const HDC hdc = CreateDC(info.szDevice, nullptr, nullptr, nullptr)) { const QDpi dpi = monitorDPI(hMonitor); data->dpi = dpi.first ? dpi : deviceDPI(hdc); data->depth = GetDeviceCaps(hdc, BITSPIXEL); @@ -121,7 +121,7 @@ BOOL QT_WIN_CALLBACK monitorEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM QWindowsScreenData data; if (monitorData(hMonitor, &data)) { WindowsScreenDataList *result = reinterpret_cast<WindowsScreenDataList *>(p); - // QPlatformIntegration::screenAdded() documentation specifies that first + // QWindowSystemInterface::handleScreenAdded() documentation specifies that first // added screen will be the primary screen, so order accordingly. // Note that the side effect of this policy is that there is no way to change primary // screen reported by Qt, unless we want to delete all existing screens and add them @@ -137,7 +137,7 @@ BOOL QT_WIN_CALLBACK monitorEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM static inline WindowsScreenDataList monitorData() { WindowsScreenDataList result; - EnumDisplayMonitors(0, 0, monitorEnumCallback, reinterpret_cast<LPARAM>(&result)); + EnumDisplayMonitors(nullptr, nullptr, monitorEnumCallback, reinterpret_cast<LPARAM>(&result)); return result; } @@ -209,7 +209,7 @@ QPixmap QWindowsScreen::grabWindow(WId window, int xIn, int yIn, int width, int height = windowSize.height() - yIn; // Create and setup bitmap - HDC display_dc = GetDC(0); + HDC display_dc = GetDC(nullptr); HDC bitmap_dc = CreateCompatibleDC(display_dc); HBITMAP bitmap = CreateCompatibleBitmap(display_dc, width, height); HGDIOBJ null_bitmap = SelectObject(bitmap_dc, bitmap); @@ -226,7 +226,7 @@ QPixmap QWindowsScreen::grabWindow(WId window, int xIn, int yIn, int width, int const QPixmap pixmap = qt_pixmapFromWinHBITMAP(bitmap); DeleteObject(bitmap); - ReleaseDC(0, display_dc); + ReleaseDC(nullptr, display_dc); return pixmap; } @@ -237,7 +237,7 @@ QPixmap QWindowsScreen::grabWindow(WId window, int xIn, int yIn, int width, int QWindow *QWindowsScreen::topLevelAt(const QPoint &point) const { - QWindow *result = 0; + QWindow *result = nullptr; if (QWindow *child = QWindowsScreen::windowAt(point, CWP_SKIPINVISIBLE)) result = QWindowsWindow::topLevelOf(child); qCDebug(lcQpaWindows) <<__FUNCTION__ << point << result; @@ -246,7 +246,7 @@ QWindow *QWindowsScreen::topLevelAt(const QPoint &point) const QWindow *QWindowsScreen::windowAt(const QPoint &screenPoint, unsigned flags) { - QWindow* result = 0; + QWindow* result = nullptr; if (QPlatformWindow *bw = QWindowsContext::instance()-> findPlatformWindowAt(GetDesktopWindow(), screenPoint, flags)) result = bw->window(); @@ -521,7 +521,7 @@ void QWindowsScreenManager::removeScreen(int index) if (movedWindowCount) QWindowSystemInterface::flushWindowSystemEvents(); } - QWindowsIntegration::instance()->emitDestroyScreen(m_screens.takeAt(index)); + QWindowSystemInterface::handleScreenRemoved(m_screens.takeAt(index)); } /*! @@ -541,7 +541,7 @@ bool QWindowsScreenManager::handleScreenChanges() } else { QWindowsScreen *newScreen = new QWindowsScreen(newData); m_screens.push_back(newScreen); - QWindowsIntegration::instance()->emitScreenAdded(newScreen, + QWindowSystemInterface::handleScreenAdded(newScreen, newData.flags & QWindowsScreenData::PrimaryScreen); qCDebug(lcQpaWindows) << "New Monitor: " << newData; } // exists @@ -561,7 +561,7 @@ void QWindowsScreenManager::clearScreens() { // Delete screens in reverse order to avoid crash in case of multiple screens while (!m_screens.isEmpty()) - QWindowsIntegration::instance()->emitDestroyScreen(m_screens.takeLast()); + QWindowSystemInterface::handleScreenRemoved(m_screens.takeLast()); } const QWindowsScreen *QWindowsScreenManager::screenAtDp(const QPoint &p) const @@ -576,7 +576,7 @@ const QWindowsScreen *QWindowsScreenManager::screenAtDp(const QPoint &p) const const QWindowsScreen *QWindowsScreenManager::screenForHwnd(HWND hwnd) const { HMONITOR hMonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL); - if (hMonitor == NULL) + if (hMonitor == nullptr) return nullptr; const auto it = std::find_if(m_screens.cbegin(), m_screens.cend(), diff --git a/src/plugins/platforms/windows/qwindowsservices.cpp b/src/plugins/platforms/windows/qwindowsservices.cpp index b6ed27464e..9504513a5e 100644 --- a/src/plugins/platforms/windows/qwindowsservices.cpp +++ b/src/plugins/platforms/windows/qwindowsservices.cpp @@ -58,9 +58,9 @@ static inline bool shellExecute(const QUrl &url) ? QDir::toNativeSeparators(url.toLocalFile()) : url.toString(QUrl::FullyEncoded); const quintptr result = - reinterpret_cast<quintptr>(ShellExecute(0, 0, + reinterpret_cast<quintptr>(ShellExecute(nullptr, nullptr, reinterpret_cast<const wchar_t *>(nativeFilePath.utf16()), - 0, 0, SW_SHOWNORMAL)); + nullptr, nullptr, SW_SHOWNORMAL)); // ShellExecute returns a value greater than 32 if successful if (result <= 32) { qWarning("ShellExecute '%s' failed (error %s).", qPrintable(url.toString()), qPrintable(QString::number(result))); @@ -84,7 +84,7 @@ static inline QString mailCommand() QString keyName; if (!RegOpenKeyEx(HKEY_CURRENT_USER, mailUserKey, 0, KEY_READ, &handle)) { DWORD bufferSize = BufferSize; - if (!RegQueryValueEx(handle, L"Progid", 0, 0, reinterpret_cast<unsigned char*>(command), &bufferSize)) + if (!RegQueryValueEx(handle, L"Progid", nullptr, nullptr, reinterpret_cast<unsigned char*>(command), &bufferSize)) keyName = QString::fromWCharArray(command); RegCloseKey(handle); } @@ -95,7 +95,7 @@ static inline QString mailCommand() command[0] = 0; if (!RegOpenKeyExW(HKEY_CLASSES_ROOT, reinterpret_cast<const wchar_t*>(keyName.utf16()), 0, KEY_READ, &handle)) { DWORD bufferSize = BufferSize; - RegQueryValueEx(handle, L"", 0, 0, reinterpret_cast<unsigned char*>(command), &bufferSize); + RegQueryValueEx(handle, L"", nullptr, nullptr, reinterpret_cast<unsigned char*>(command), &bufferSize); RegCloseKey(handle); } // QTBUG-57816: As of Windows 10, if there is no mail client installed, an entry like @@ -136,8 +136,8 @@ static inline bool launchMail(const QUrl &url) STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); - if (!CreateProcess(NULL, reinterpret_cast<wchar_t *>(const_cast<ushort *>(command.utf16())), - NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { + if (!CreateProcess(nullptr, reinterpret_cast<wchar_t *>(const_cast<ushort *>(command.utf16())), + nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi)) { qErrnoWarning("Unable to launch '%s'", qPrintable(command)); return false; } diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp index 901d132ea5..c0f4e4d014 100644 --- a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp +++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp @@ -103,6 +103,13 @@ static void setIconContents(NOTIFYICONDATA &tnd, const QString &tip, HICON hIcon qStringToLimitedWCharArray(tip, tnd.szTip, sizeof(tnd.szTip) / sizeof(wchar_t)); } +static void setIconVisibility(NOTIFYICONDATA &tnd, bool v) +{ + tnd.uFlags |= NIF_STATE; + tnd.dwStateMask = NIS_HIDDEN; + tnd.dwState = v ? 0 : NIS_HIDDEN; +} + // Match the HWND of the dummy window to the instances struct QWindowsHwndSystemTrayIconEntry { @@ -153,7 +160,7 @@ static inline HWND createTrayIconMessageWindow() { QWindowsContext *ctx = QWindowsContext::instance(); if (!ctx) - return 0; + return nullptr; // Register window class in the platform plugin. const QString className = ctx->registerWindowClass(QStringLiteral("QTrayIconMessageWindowClass"), @@ -163,7 +170,8 @@ static inline HWND createTrayIconMessageWindow() windowName, WS_OVERLAPPED, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - NULL, NULL, (HINSTANCE)GetModuleHandle(0), NULL); + nullptr, nullptr, + static_cast<HINSTANCE>(GetModuleHandle(nullptr)), nullptr); } /*! @@ -176,12 +184,6 @@ static inline HWND createTrayIconMessageWindow() QWindowsSystemTrayIcon::QWindowsSystemTrayIcon() { - // For restoring the tray icon after explorer crashes - if (!MYWM_TASKBARCREATED) - MYWM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated"); - // Allow the WM_TASKBARCREATED message through the UIPI filter - ChangeWindowMessageFilterEx(m_hwnd, MYWM_TASKBARCREATED, MSGFLT_ALLOW, 0); - qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this << "MYWM_TASKBARCREATED=" << MYWM_TASKBARCREATED; } QWindowsSystemTrayIcon::~QWindowsSystemTrayIcon() @@ -193,12 +195,15 @@ QWindowsSystemTrayIcon::~QWindowsSystemTrayIcon() void QWindowsSystemTrayIcon::init() { qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this; - ensureInstalled(); + m_visible = true; + if (!setIconVisible(m_visible)) + ensureInstalled(); } void QWindowsSystemTrayIcon::cleanup() { qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this; + m_visible = false; ensureCleanup(); } @@ -310,6 +315,13 @@ bool QWindowsSystemTrayIcon::ensureInstalled() m_hwnd = createTrayIconMessageWindow(); if (Q_UNLIKELY(m_hwnd == nullptr)) return false; + // For restoring the tray icon after explorer crashes + if (!MYWM_TASKBARCREATED) + MYWM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated"); + // Allow the WM_TASKBARCREATED message through the UIPI filter + ChangeWindowMessageFilterEx(m_hwnd, MYWM_TASKBARCREATED, MSGFLT_ALLOW, nullptr); + qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this << "MYWM_TASKBARCREATED=" << MYWM_TASKBARCREATED; + QWindowsHwndSystemTrayIconEntry entry{m_hwnd, this}; hwndTrayIconEntries()->append(entry); sendTrayMessage(NIM_ADD); @@ -333,6 +345,18 @@ void QWindowsSystemTrayIcon::ensureCleanup() m_toolTip.clear(); } +bool QWindowsSystemTrayIcon::setIconVisible(bool visible) +{ + if (!isInstalled()) + return false; + NOTIFYICONDATA tnd; + initNotifyIconData(tnd); + tnd.uID = q_uNOTIFYICONID; + tnd.hWnd = m_hwnd; + setIconVisibility(tnd, visible); + return Shell_NotifyIcon(NIM_MODIFY, &tnd) == TRUE; +} + bool QWindowsSystemTrayIcon::sendTrayMessage(DWORD msg) { NOTIFYICONDATA tnd; @@ -340,6 +364,8 @@ bool QWindowsSystemTrayIcon::sendTrayMessage(DWORD msg) tnd.uID = q_uNOTIFYICONID; tnd.hWnd = m_hwnd; tnd.uFlags = NIF_SHOWTIP; + if (msg != NIM_DELETE && !m_visible) + setIconVisibility(tnd, m_visible); if (msg == NIM_ADD || msg == NIM_MODIFY) setIconContents(tnd, m_toolTip, m_hIcon); if (!Shell_NotifyIcon(msg, &tnd)) @@ -382,12 +408,20 @@ bool QWindowsSystemTrayIcon::winEvent(const MSG &message, long *result) emit activated(DoubleClick); // release we must ignore it break; case WM_CONTEXTMENU: { + // QTBUG-67966: Coordinates may be out of any screen in PROCESS_DPI_UNAWARE mode + // since hi-res coordinates are delivered in this case (Windows issue). + // Default to primary screen with check to prevent a crash. const QPoint globalPos = QPoint(GET_X_LPARAM(message.wParam), GET_Y_LPARAM(message.wParam)); - const QPlatformScreen *screen = QWindowsContext::instance()->screenManager().screenAtDp(globalPos); - emit contextMenuRequested(globalPos, screen); - emit activated(Context); - if (m_menu) - m_menu->trackPopupMenu(message.hwnd, globalPos.x(), globalPos.y()); + const auto &screenManager = QWindowsContext::instance()->screenManager(); + const QPlatformScreen *screen = screenManager.screenAtDp(globalPos); + if (!screen) + screen = screenManager.screens().value(0); + if (screen) { + emit contextMenuRequested(globalPos, screen); + emit activated(Context); + if (m_menu) + m_menu->trackPopupMenu(message.hwnd, globalPos.x(), globalPos.y()); + } } break; case NIN_BALLOONUSERCLICK: diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.h b/src/plugins/platforms/windows/qwindowssystemtrayicon.h index a8adb9641f..44e1bcc761 100644 --- a/src/plugins/platforms/windows/qwindowssystemtrayicon.h +++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.h @@ -84,6 +84,7 @@ private: bool ensureInstalled(); void ensureCleanup(); bool sendTrayMessage(DWORD msg); + bool setIconVisible(bool visible); HICON createIcon(const QIcon &icon); QIcon m_icon; @@ -92,6 +93,7 @@ private: HICON m_hIcon = nullptr; mutable QPointer<QWindowsPopupMenu> m_menu; bool m_ignoreNextMouseRelease = false; + bool m_visible = false; }; #ifndef QT_NO_DEBUG_STREAM diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index d01a7b0a8a..a6b9781252 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -159,7 +159,7 @@ public: void run() override { - m_init = CoInitializeEx(NULL, COINIT_MULTITHREADED); + m_init = CoInitializeEx(nullptr, COINIT_MULTITHREADED); QMutexLocker readyLocker(&m_readyMutex); while (!m_cancelled.load()) { @@ -284,24 +284,24 @@ static inline QPalette systemPalette() result.setColor(QPalette::Link, Qt::blue); result.setColor(QPalette::LinkVisited, Qt::magenta); result.setColor(QPalette::Inactive, QPalette::Button, result.button().color()); - result.setColor(QPalette::Inactive, QPalette::Window, result.background().color()); + result.setColor(QPalette::Inactive, QPalette::Window, result.window().color()); result.setColor(QPalette::Inactive, QPalette::Light, result.light().color()); result.setColor(QPalette::Inactive, QPalette::Dark, result.dark().color()); if (result.midlight() == result.button()) result.setColor(QPalette::Midlight, result.button().color().lighter(110)); - if (result.background() != result.base()) { + if (result.window() != result.base()) { result.setColor(QPalette::Inactive, QPalette::Highlight, result.color(QPalette::Inactive, QPalette::Window)); result.setColor(QPalette::Inactive, QPalette::HighlightedText, result.color(QPalette::Inactive, QPalette::Text)); } const QColor disabled = - mixColors(result.foreground().color(), result.button().color()); + mixColors(result.windowText().color(), result.button().color()); - result.setColorGroup(QPalette::Disabled, result.foreground(), result.button(), + result.setColorGroup(QPalette::Disabled, result.windowText(), result.button(), result.light(), result.dark(), result.mid(), result.text(), result.brightText(), result.base(), - result.background()); + result.window()); result.setColor(QPalette::Disabled, QPalette::WindowText, disabled); result.setColor(QPalette::Disabled, QPalette::Text, disabled); result.setColor(QPalette::Disabled, QPalette::ButtonText, disabled); @@ -310,7 +310,7 @@ static inline QPalette systemPalette() result.setColor(QPalette::Disabled, QPalette::HighlightedText, getSysColor(COLOR_HIGHLIGHTTEXT)); result.setColor(QPalette::Disabled, QPalette::Base, - result.background().color()); + result.window().color()); return result; } @@ -333,7 +333,7 @@ static inline QPalette toolTipPalette(const QPalette &systemPalette) result.setColor(QPalette::All, QPalette::ToolTipBase, tipBgColor); result.setColor(QPalette::All, QPalette::ToolTipText, tipTextColor); const QColor disabled = - mixColors(result.foreground().color(), result.button().color()); + mixColors(result.windowText().color(), result.button().color()); result.setColor(QPalette::Disabled, QPalette::WindowText, disabled); result.setColor(QPalette::Disabled, QPalette::Text, disabled); result.setColor(QPalette::Disabled, QPalette::ToolTipText, disabled); @@ -381,7 +381,7 @@ static inline QPalette menuPalette(const QPalette &systemPalette) static inline QPalette *menuBarPalette(const QPalette &menuPalette) { - QPalette *result = 0; + QPalette *result = nullptr; if (booleanSystemParametersInfo(SPI_GETFLATMENU, false)) { result = new QPalette(menuPalette); const QColor menubar(getSysColor(COLOR_MENUBAR)); @@ -393,13 +393,13 @@ static inline QPalette *menuBarPalette(const QPalette &menuPalette) } const char *QWindowsTheme::name = "windows"; -QWindowsTheme *QWindowsTheme::m_instance = 0; +QWindowsTheme *QWindowsTheme::m_instance = nullptr; QWindowsTheme::QWindowsTheme() { m_instance = this; - std::fill(m_fonts, m_fonts + NFonts, static_cast<QFont *>(0)); - std::fill(m_palettes, m_palettes + NPalettes, static_cast<QPalette *>(0)); + std::fill(m_fonts, m_fonts + NFonts, nullptr); + std::fill(m_palettes, m_palettes + NPalettes, nullptr); refresh(); refreshIconPixmapSizes(); } @@ -408,7 +408,7 @@ QWindowsTheme::~QWindowsTheme() { clearPalettes(); clearFonts(); - m_instance = 0; + m_instance = nullptr; } static inline QStringList iconThemeSearchPaths() @@ -481,7 +481,7 @@ QVariant QWindowsTheme::themeHint(ThemeHint hint) const void QWindowsTheme::clearPalettes() { qDeleteAll(m_palettes, m_palettes + NPalettes); - std::fill(m_palettes, m_palettes + NPalettes, static_cast<QPalette *>(0)); + std::fill(m_palettes, m_palettes + NPalettes, nullptr); } void QWindowsTheme::refreshPalettes() @@ -498,7 +498,7 @@ void QWindowsTheme::refreshPalettes() void QWindowsTheme::clearFonts() { qDeleteAll(m_fonts, m_fonts + NFonts); - std::fill(m_fonts, m_fonts + NFonts, static_cast<QFont *>(0)); + std::fill(m_fonts, m_fonts + NFonts, nullptr); } void QWindowsTheme::refreshFonts() @@ -507,9 +507,7 @@ void QWindowsTheme::refreshFonts() if (!QGuiApplication::desktopSettingsAware()) return; NONCLIENTMETRICS ncm; - ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); - SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0); - + QWindowsContext::nonClientMetrics(&ncm); const QFont menuFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMenuFont); const QFont messageBoxFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMessageFont); const QFont statusFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfStatusFont); @@ -608,7 +606,7 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz int resourceId = -1; SHSTOCKICONID stockId = SIID_INVALID; UINT stockFlags = 0; - LPCTSTR iconName = 0; + LPCTSTR iconName = nullptr; switch (sp) { case DriveCDIcon: stockId = SIID_DRIVECD; @@ -718,7 +716,7 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz } if (iconName) { - HICON iconHandle = LoadIcon(NULL, iconName); + HICON iconHandle = LoadIcon(nullptr, iconName); QPixmap pixmap = qt_pixmapFromWinHICON(iconHandle); DestroyIcon(iconHandle); if (!pixmap.isNull()) @@ -778,7 +776,7 @@ static QPixmap pixmapFromShellImageList(int iImageList, const SHFILEINFO &info) // For MinGW: static const IID iID_IImageList = {0x46eb5926, 0x582e, 0x4017, {0x9f, 0xdf, 0xe8, 0x99, 0x8d, 0xaa, 0x9, 0x50}}; - IImageList *imageList = 0; + IImageList *imageList = nullptr; HRESULT hr = SHGetImageList(iImageList, iID_IImageList, reinterpret_cast<void **>(&imageList)); if (hr != S_OK) return result; @@ -834,7 +832,7 @@ QPixmap QWindowsFileIconEngine::filePixmap(const QSize &size, QIcon::Mode, QIcon { /* We don't use the variable, but by storing it statically, we * ensure CoInitialize is only called once. */ - static HRESULT comInit = CoInitialize(NULL); + static HRESULT comInit = CoInitialize(nullptr); Q_UNUSED(comInit); static QCache<QString, FakePointer<int> > dirIconEntryCache(1000); @@ -860,7 +858,8 @@ QPixmap QWindowsFileIconEngine::filePixmap(const QSize &size, QIcon::Mode, QIcon int iIcon = (useDefaultFolderIcon && defaultFolderIIcon >= 0) ? defaultFolderIIcon : **dirIconEntryCache.object(filePath); if (iIcon) { - QPixmapCache::find(dirIconPixmapCacheKey(iIcon, iconSize, requestedImageListSize), pixmap); + QPixmapCache::find(dirIconPixmapCacheKey(iIcon, iconSize, requestedImageListSize), + &pixmap); if (pixmap.isNull()) // Let's keep both caches in sync dirIconEntryCache.remove(filePath); else @@ -891,7 +890,7 @@ QPixmap QWindowsFileIconEngine::filePixmap(const QSize &size, QIcon::Mode, QIcon //using the unique icon index provided by windows save us from duplicate keys key = dirIconPixmapCacheKey(info.iIcon, iconSize, requestedImageListSize); - QPixmapCache::find(key, pixmap); + QPixmapCache::find(key, &pixmap); if (!pixmap.isNull()) { QMutexLocker locker(&mx); dirIconEntryCache.insert(filePath, FakePointer<int>::create(info.iIcon)); diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 9c31409644..338e594c7b 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -347,7 +347,7 @@ static bool applyBlurBehindWindow(HWND hwnd) if (DwmIsCompositionEnabled(&compositionEnabled) != S_OK) return false; - DWM_BLURBEHIND blurBehind = {0, 0, 0, 0}; + DWM_BLURBEHIND blurBehind = {0, 0, nullptr, 0}; if (compositionEnabled) { blurBehind.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION; @@ -403,12 +403,12 @@ static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, bo if (hasAlpha && !accelerated && (flags & Qt::FramelessWindowHint)) { // Non-GL windows with alpha: Use blend function to update. BLENDFUNCTION blend = {AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA}; - UpdateLayeredWindow(hwnd, NULL, NULL, NULL, NULL, NULL, 0, &blend, ULW_ALPHA); + UpdateLayeredWindow(hwnd, nullptr, nullptr, nullptr, nullptr, nullptr, 0, &blend, ULW_ALPHA); } else { SetLayeredWindowAttributes(hwnd, 0, alpha, LWA_ALPHA); } } else if (IsWindowVisible(hwnd)) { // Repaint when switching from layered. - InvalidateRect(hwnd, NULL, TRUE); + InvalidateRect(hwnd, nullptr, TRUE); } } @@ -482,26 +482,22 @@ struct WindowCreationData typedef QWindowsWindowData WindowData; enum Flags { ForceChild = 0x1, ForceTopLevel = 0x2 }; - WindowCreationData() : parentHandle(0), type(Qt::Widget), style(0), exStyle(0), - topLevel(false), popup(false), dialog(false), - tool(false), embedded(false), hasAlpha(false) {} - void fromWindow(const QWindow *w, const Qt::WindowFlags flags, unsigned creationFlags = 0); inline WindowData create(const QWindow *w, const WindowData &data, QString title) const; inline void applyWindowFlags(HWND hwnd) const; void initialize(const QWindow *w, HWND h, bool frameChange, qreal opacityLevel) const; Qt::WindowFlags flags; - HWND parentHandle; - Qt::WindowType type; - unsigned style; - unsigned exStyle; - bool topLevel; - bool popup; - bool dialog; - bool tool; - bool embedded; - bool hasAlpha; + HWND parentHandle = nullptr; + Qt::WindowType type = Qt::Widget; + unsigned style = 0; + unsigned exStyle = 0; + bool topLevel = false; + bool popup = false; + bool dialog = false; + bool tool = false; + bool embedded = false; + bool hasAlpha = false; }; QDebug operator<<(QDebug debug, const WindowCreationData &d) @@ -555,12 +551,6 @@ static QScreen *screenForName(const QWindow *w, const QString &name) return winScreen; } -static QScreen *forcedScreenForGLWindow(const QWindow *w) -{ - const QString forceToScreen = GpuDescription::detect().gpuSuitableScreen; - return forceToScreen.isEmpty() ? nullptr : screenForName(w, forceToScreen); -} - static QPoint calcPosition(const QWindow *w, const QWindowCreationContextPtr &context, const QMargins &invMargins) { const QPoint orgPos(context->frameX - invMargins.left(), context->frameY - invMargins.top()); @@ -569,7 +559,7 @@ static QPoint calcPosition(const QWindow *w, const QWindowCreationContextPtr &co return orgPos; // Workaround for QTBUG-50371 - const QScreen *screenForGL = forcedScreenForGLWindow(w); + const QScreen *screenForGL = QWindowsWindow::forcedScreenForGLWindow(w); if (!screenForGL) return orgPos; @@ -756,7 +746,8 @@ QWindowsWindowData const QWindowCreationContextPtr context(new QWindowCreationContext(w, data.geometry, rect, data.customMargins, style, exStyle)); QWindowsContext::instance()->setWindowCreationContext(context); - QMargins invMargins = topLevel && !(result.flags & Qt::FramelessWindowHint) && QWindowsGeometryHint::positionIncludesFrame(w) + const bool hasFrame = (style & (WS_DLGFRAME | WS_THICKFRAME)); + QMargins invMargins = topLevel && hasFrame && QWindowsGeometryHint::positionIncludesFrame(w) ? invisibleMargins(QPoint(context->frameX, context->frameY)) : QMargins(); qCDebug(lcQpaWindows).nospace() @@ -774,7 +765,7 @@ QWindowsWindowData style, pos.x(), pos.y(), context->frameWidth, context->frameHeight, - parentHandle, NULL, appinst, NULL); + parentHandle, nullptr, appinst, nullptr); qCDebug(lcQpaWindows).nospace() << "CreateWindowEx: returns " << w << ' ' << result.hwnd << " obtained geometry: " << context->obtainedGeometry << ' ' << context->margins; @@ -787,6 +778,7 @@ QWindowsWindowData result.geometry = context->obtainedGeometry; result.fullFrameMargins = context->margins; result.embedded = embedded; + result.hasFrame = hasFrame; result.customMargins = context->customMargins; return result; @@ -908,7 +900,7 @@ bool QWindowsGeometryHint::handleCalculateSize(const QMargins &customMargins, co ncp->rgrc[0].top += customMargins.top(); ncp->rgrc[0].right -= customMargins.right(); ncp->rgrc[0].bottom -= customMargins.bottom(); - result = 0; + result = nullptr; qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << oldClientArea << '+' << customMargins << "-->" << ncp->rgrc[0] << ' ' << ncp->rgrc[1] << ' ' << ncp->rgrc[2] << ' ' << ncp->lppos->cx << ',' << ncp->lppos->cy; @@ -983,7 +975,7 @@ QWindowsBaseWindow *QWindowsBaseWindow::baseWindowOf(const QWindow *w) HWND QWindowsBaseWindow::handleOf(const QWindow *w) { const QWindowsBaseWindow *bw = QWindowsBaseWindow::baseWindowOf(w); - return bw ? bw->handle() : HWND(0); + return bw ? bw->handle() : HWND(nullptr); } bool QWindowsBaseWindow::isTopLevel_sys() const @@ -1009,7 +1001,7 @@ QMargins QWindowsBaseWindow::frameMargins_sys() const void QWindowsBaseWindow::hide_sys() // Normal hide, do not activate other windows. { - SetWindowPos(handle(),0 , 0, 0, 0, 0, + SetWindowPos(handle(), nullptr , 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); } @@ -1078,7 +1070,7 @@ QWindowsForeignWindow::QWindowsForeignWindow(QWindow *window, HWND hwnd) void QWindowsForeignWindow::setParent(const QPlatformWindow *newParentWindow) { const bool wasTopLevel = isTopLevel_sys(); - const HWND newParent = newParentWindow ? reinterpret_cast<HWND>(newParentWindow->winId()) : HWND(0); + const HWND newParent = newParentWindow ? reinterpret_cast<HWND>(newParentWindow->winId()) : HWND(nullptr); const bool isTopLevel = !newParent; const DWORD oldStyle = style(); qCDebug(lcQpaWindows) << __FUNCTION__ << window() << "newParent=" @@ -1140,7 +1132,8 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w, // TODO: No concept of WA_wasMoved yet that would indicate a // CW_USEDEFAULT unless set. For now, assume that 0,0 means 'default' // for toplevels. - if (geometry.isValid()) { + if (geometry.isValid() + || !qt_window_private(const_cast<QWindow *>(w))->resizeAutomatic) { frameX = geometry.x(); frameY = geometry.y(); const QMargins effectiveMargins = margins + customMargins; @@ -1190,6 +1183,7 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w, const char *QWindowsWindow::embeddedNativeParentHandleProperty = "_q_embedded_native_parent_handle"; const char *QWindowsWindow::hasBorderInFullScreenProperty = "_q_has_border_in_fullscreen"; +bool QWindowsWindow::m_borderInFullScreenDefault = false; QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) : QWindowsBaseWindow(aWindow), @@ -1227,7 +1221,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) if (aWindow->isTopLevel()) setWindowIcon(aWindow->icon()); - if (aWindow->property(hasBorderInFullScreenProperty).toBool()) + if (m_borderInFullScreenDefault || aWindow->property(hasBorderInFullScreenProperty).toBool()) setFlag(HasBorderInFullScreen); clearFlag(WithinCreate); } @@ -1309,7 +1303,7 @@ void QWindowsWindow::destroyWindow() #endif DestroyWindow(m_data.hwnd); context->removeWindow(m_data.hwnd); - m_data.hwnd = 0; + m_data.hwnd = nullptr; } } @@ -1358,11 +1352,33 @@ void QWindowsWindow::setDropSiteEnabled(bool dropEnabled) CoLockObjectExternal(m_dropTarget, false, true); m_dropTarget->Release(); RevokeDragDrop(m_data.hwnd); - m_dropTarget = 0; + m_dropTarget = nullptr; } #endif // QT_CONFIG(clipboard) && QT_CONFIG(draganddrop) } +bool QWindowsWindow::m_screenForGLInitialized = false; + +void QWindowsWindow::displayChanged() +{ + m_screenForGLInitialized = false; +} + +void QWindowsWindow::settingsChanged() +{ + m_screenForGLInitialized = false; +} + +QScreen *QWindowsWindow::forcedScreenForGLWindow(const QWindow *w) +{ + static QString forceToScreen; + if (!m_screenForGLInitialized) { + forceToScreen = GpuDescription::detect().gpuSuitableScreen; + m_screenForGLInitialized = true; + } + return forceToScreen.isEmpty() ? nullptr : screenForName(w, forceToScreen); +} + // Returns topmost QWindowsWindow ancestor even if there are embedded windows in the chain. // Returns this window if it is the topmost ancestor. QWindow *QWindowsWindow::topLevelOf(QWindow *w) @@ -1479,7 +1495,7 @@ void QWindowsWindow::updateTransientParent() const return; // QTBUG-34503, // a popup stays on top, no parent, see also WindowCreationData::fromWindow(). // Update transient parent. const HWND oldTransientParent = GetWindow(m_data.hwnd, GW_OWNER); - HWND newTransientParent = 0; + HWND newTransientParent = nullptr; if (const QWindow *tp = window()->transientParent()) if (const QWindowsWindow *tw = QWindowsWindow::windowsWindowOf(tp)) if (!tw->testFlag(WithinDestroy)) // Prevent destruction by parent window (QTBUG-35499, QTBUG-36666) @@ -1572,7 +1588,7 @@ void QWindowsWindow::show_sys() const if (fakedMaximize) { setStyle(style() & ~WS_MAXIMIZEBOX); - SetWindowPos(m_data.hwnd, 0, 0, 0, 0, 0, + SetWindowPos(m_data.hwnd, nullptr, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED); } @@ -1592,7 +1608,7 @@ void QWindowsWindow::setParent_sys(const QPlatformWindow *parent) { // Use GetAncestor instead of GetParent, as GetParent can return owner window for toplevels HWND oldParentHWND = parentHwnd(); - HWND newParentHWND = 0; + HWND newParentHWND = nullptr; if (parent) { const QWindowsWindow *parentW = static_cast<const QWindowsWindow *>(parent); newParentHWND = parentW->handle(); @@ -1602,13 +1618,13 @@ void QWindowsWindow::setParent_sys(const QPlatformWindow *parent) // NULL handle means desktop window, which also has its proper handle -> disambiguate HWND desktopHwnd = GetDesktopWindow(); if (oldParentHWND == desktopHwnd) - oldParentHWND = 0; + oldParentHWND = nullptr; if (newParentHWND == desktopHwnd) - newParentHWND = 0; + newParentHWND = nullptr; if (newParentHWND != oldParentHWND) { - const bool wasTopLevel = oldParentHWND == 0; - const bool isTopLevel = newParentHWND == 0; + const bool wasTopLevel = oldParentHWND == nullptr; + const bool isTopLevel = newParentHWND == nullptr; setFlag(WithinSetParent); SetParent(m_data.hwnd, newParentHWND); @@ -1744,15 +1760,12 @@ void QWindowsWindow::checkForScreenChanged() QPlatformScreen *currentScreen = screen(); const auto &screenManager = QWindowsContext::instance()->screenManager(); - // QTBUG-62971: When dragging a window by its border, detect by mouse position - // to prevent it from oscillating between screens when it resizes - const QWindowsScreen *newScreen = testFlag(ResizeMoveActive) - ? screenManager.screenAtDp(QWindowsCursor::mousePosition()) - : screenManager.screenForHwnd(m_data.hwnd); + 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()); } } @@ -1771,11 +1784,14 @@ void QWindowsWindow::handleGeometryChange() fireExpose(QRect(QPoint(0, 0), m_data.geometry.size()), true); } + const bool wasSync = testFlag(SynchronousGeometryChangeEvent); checkForScreenChanged(); if (testFlag(SynchronousGeometryChangeEvent)) QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); + if (!wasSync) + clearFlag(SynchronousGeometryChangeEvent); qCDebug(lcQpaEvents) << __FUNCTION__ << this << window() << m_data.geometry; } @@ -1835,7 +1851,7 @@ void QWindowsWindow::releaseDC() { if (m_hdc) { ReleaseDC(handle(), m_hdc); - m_hdc = 0; + m_hdc = nullptr; } } @@ -1869,7 +1885,7 @@ bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message, // GL software rendering (QTBUG-58178) and Windows 7/Aero off with some AMD cards // (QTBUG-60527) need InvalidateRect() to suppress artifacts while resizing. if (testFlag(OpenGLSurface) && (isSoftwareGl() || !dwmIsCompositionEnabled())) - InvalidateRect(hwnd, 0, false); + InvalidateRect(hwnd, nullptr, false); BeginPaint(hwnd, &ps); @@ -1877,7 +1893,7 @@ bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message, if (Q_UNLIKELY(!dwmIsCompositionEnabled()) && ((testFlag(OpenGLSurface) && testFlag(OpenGLDoubleBuffered)) || testFlag(VulkanSurface))) { - SelectClipRgn(ps.hdc, NULL); + SelectClipRgn(ps.hdc, nullptr); } // If the a window is obscured by another window (such as a child window) @@ -2088,7 +2104,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowStates newState) // it before applying the normal geometry. if (windowVisibility_sys(m_data.hwnd) == QWindow::Maximized) ShowWindow(m_data.hwnd, SW_SHOWNOACTIVATE); - SetWindowPos(m_data.hwnd, 0, m_savedFrameGeometry.x(), m_savedFrameGeometry.y(), + SetWindowPos(m_data.hwnd, nullptr, m_savedFrameGeometry.x(), m_savedFrameGeometry.y(), m_savedFrameGeometry.width(), m_savedFrameGeometry.height(), swpf); if (!wasSync) clearFlag(SynchronousGeometryChangeEvent); @@ -2220,7 +2236,7 @@ void QWindowsWindow::setFullFrameMargins(const QMargins &newMargins) QMargins QWindowsWindow::frameMargins() const { QMargins result = fullFrameMargins(); - if (isTopLevel() && !(m_data.flags & Qt::FramelessWindowHint)) + if (isTopLevel() && m_data.hasFrame) result -= invisibleMargins(geometry().topLeft()); return result; } @@ -2274,7 +2290,7 @@ static HRGN qRegionToWinRegion(const QRegion ®ion) void QWindowsWindow::setMask(const QRegion ®ion) { if (region.isEmpty()) { - SetWindowRgn(m_data.hwnd, 0, true); + SetWindowRgn(m_data.hwnd, nullptr, true); return; } const HRGN winRegion = qRegionToWinRegion(region); @@ -2307,7 +2323,7 @@ void QWindowsWindow::requestActivateWindow() if (QGuiApplication::applicationState() != Qt::ApplicationActive && QWindowsNativeInterface::windowActivationBehavior() == QWindowsWindowFunctions::AlwaysActivateWindow) { if (const HWND foregroundWindow = GetForegroundWindow()) { - foregroundThread = GetWindowThreadProcessId(foregroundWindow, NULL); + foregroundThread = GetWindowThreadProcessId(foregroundWindow, nullptr); if (foregroundThread && foregroundThread != currentThread) attached = AttachThreadInput(foregroundThread, currentThread, TRUE) == TRUE; if (attached) { @@ -2341,7 +2357,7 @@ bool QWindowsWindow::setKeyboardGrabEnabled(bool grab) context->setKeyGrabber(window()); } else { if (context->keyGrabber() == window()) - context->setKeyGrabber(0); + context->setKeyGrabber(nullptr); } return true; } @@ -2416,6 +2432,13 @@ void QWindowsWindow::setFrameStrutEventsEnabled(bool enabled) } } +static int getBorderWidth(const QPlatformScreen *screen) +{ + NONCLIENTMETRICS ncm; + QWindowsContext::nonClientMetricsForScreen(&ncm, screen); + return ncm.iBorderWidth + ncm.iPaddedBorderWidth + 2; +} + 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 @@ -2425,10 +2448,11 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const hint.applyToMinMaxInfo(m_data.hwnd, mmi); } - if ((testFlag(WithinMaximize) || (window()->windowStates() & Qt::WindowMinimized)) - && (m_data.flags & Qt::FramelessWindowHint)) { - // This block fixes QTBUG-8361: Frameless windows shouldn't cover the - // taskbar when maximized + // This block fixes QTBUG-8361, QTBUG-4362: Frameless/title-less windows shouldn't cover the + // taskbar when maximized + if ((testFlag(WithinMaximize) || window()->windowStates().testFlag(Qt::WindowMinimized)) + && (m_data.flags.testFlag(Qt::FramelessWindowHint) + || (m_data.flags.testFlag(Qt::CustomizeWindowHint) && !m_data.flags.testFlag(Qt::WindowTitleHint)))) { const QScreen *screen = window()->screen(); // Documentation of MINMAXINFO states that it will only work for the primary screen @@ -2442,6 +2466,14 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const // If you have the taskbar on top, or on the left you don't want it at (0,0): mmi->ptMaxPosition.x = availableGeometry.x(); mmi->ptMaxPosition.y = availableGeometry.y(); + if (!m_data.flags.testFlag(Qt::FramelessWindowHint)) { + const int borderWidth = getBorderWidth(screen->handle()); + mmi->ptMaxSize.x += borderWidth * 2; + mmi->ptMaxSize.y += borderWidth * 2; + mmi->ptMaxTrackSize = mmi->ptMaxSize; + mmi->ptMaxPosition.x -= borderWidth; + mmi->ptMaxPosition.y -= borderWidth; + } } else if (!screen){ qWarning("window()->screen() returned a null screen"); } @@ -2625,7 +2657,7 @@ static HICON createHIcon(const QIcon &icon, int xSize, int ySize) if (!pm.isNull()) return qt_pixmapToWinHICON(pm); } - return 0; + return nullptr; } void QWindowsWindow::setWindowIcon(const QIcon &icon) @@ -2683,7 +2715,7 @@ void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins) newFrame.moveTo(topLeft); qCDebug(lcQpaWindows) << __FUNCTION__ << oldCustomMargins << "->" << newCustomMargins << currentFrameGeometry << "->" << newFrame; - SetWindowPos(m_data.hwnd, 0, newFrame.x(), newFrame.y(), newFrame.width(), newFrame.height(), SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE); + SetWindowPos(m_data.hwnd, nullptr, newFrame.x(), newFrame.y(), newFrame.width(), newFrame.height(), SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE); } } @@ -2788,6 +2820,11 @@ void QWindowsWindow::setHasBorderInFullScreenStatic(QWindow *window, bool border window->setProperty(hasBorderInFullScreenProperty, QVariant(border)); } +void QWindowsWindow::setHasBorderInFullScreenDefault(bool border) +{ + m_borderInFullScreenDefault = border; +} + void QWindowsWindow::setHasBorderInFullScreen(bool border) { if (testFlag(HasBorderInFullScreen) == border) diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index e8c30bd44b..0d8096ddfa 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -112,6 +112,7 @@ struct QWindowsWindowData QMargins customMargins; // User-defined, additional frame for NCCALCSIZE HWND hwnd = 0; bool embedded = false; + bool hasFrame = false; static QWindowsWindowData create(const QWindow *w, const QWindowsWindowData ¶meters, @@ -297,6 +298,9 @@ public: void handleHidden(); void handleCompositionSettingsChanged(); + static void displayChanged(); + static void settingsChanged(); + static QScreen *forcedScreenForGLWindow(const QWindow *w); static QWindowsWindow *windowsWindowOf(const QWindow *w); static QWindow *topLevelOf(QWindow *w); static inline void *userDataOf(HWND hwnd); @@ -338,6 +342,7 @@ public: static void setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes); void registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes = QWindowsWindowFunctions::NormalTouch); static void setHasBorderInFullScreenStatic(QWindow *window, bool border); + static void setHasBorderInFullScreenDefault(bool border); void setHasBorderInFullScreen(bool border); static QString formatWindowTitle(const QString &title); @@ -377,10 +382,13 @@ private: HICON m_iconBig = 0; void *m_surface = nullptr; + static bool m_screenForGLInitialized; + #if QT_CONFIG(vulkan) // note: intentionally not using void * in order to avoid breaking x86 VkSurfaceKHR m_vkSurface = 0; #endif + static bool m_borderInFullScreenDefault; }; #ifndef QT_NO_DEBUG_STREAM diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp index fbb5c3b9ec..7980826b49 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp @@ -90,7 +90,7 @@ HWND hwndForAccessible(const QAccessibleInterface *accessible) return QWindowsBaseWindow::handleOf(window); } } - return NULL; + return nullptr; } void clearVariant(VARIANT *variant) diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri index db06a6a2a3..7004d7e854 100644 --- a/src/plugins/platforms/windows/windows.pri +++ b/src/plugins/platforms/windows/windows.pri @@ -9,6 +9,8 @@ mingw: LIBS *= -luuid # For the dialog helpers: LIBS += -lshlwapi -lshell32 -ladvapi32 -lwtsapi32 +QMAKE_USE_PRIVATE += d3d9/nolink + DEFINES *= QT_NO_CAST_FROM_ASCII QT_NO_FOREACH SOURCES += \ |