summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/windows')
-rw-r--r--src/plugins/platforms/windows/main.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.cpp5
-rw-r--r--src/plugins/platforms/windows/qwindowsclipboard.cpp18
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp138
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h14
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.cpp16
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp198
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp41
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.h2
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.cpp40
-rw-r--r--src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp50
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.cpp25
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h3
-rw-r--r--src/plugins/platforms/windows/qwindowsinternalmimedata.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp25
-rw-r--r--src/plugins/platforms/windows/qwindowsmenu.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.cpp18
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp34
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.cpp25
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsole.cpp16
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.cpp154
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.h2
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.cpp499
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.h10
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp22
-rw-r--r--src/plugins/platforms/windows/qwindowsservices.cpp12
-rw-r--r--src/plugins/platforms/windows/qwindowssystemtrayicon.cpp62
-rw-r--r--src/plugins/platforms/windows/qwindowssystemtrayicon.h2
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp47
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp157
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h8
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp2
-rw-r--r--src/plugins/platforms/windows/windows.pri2
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 &region,
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 &region)
void QWindowsWindow::setMask(const QRegion &region)
{
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 &parameters,
@@ -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 += \