diff options
Diffstat (limited to 'src/plugins/platforms/windows')
50 files changed, 1394 insertions, 1338 deletions
diff --git a/src/plugins/platforms/windows/accessible/accessible.pri b/src/plugins/platforms/windows/accessible/accessible.pri index e26c6614e2..0774d907f2 100644 --- a/src/plugins/platforms/windows/accessible/accessible.pri +++ b/src/plugins/platforms/windows/accessible/accessible.pri @@ -1,17 +1,20 @@ SOURCES += \ - $$PWD/qwindowsmsaaaccessible.cpp \ $$PWD/qwindowsaccessibility.cpp \ $$PWD/comutils.cpp HEADERS += \ - $$PWD/qwindowsmsaaaccessible.h \ $$PWD/qwindowsaccessibility.h \ $$PWD/comutils.h -!mingw: { - SOURCES += $$PWD/iaccessible2.cpp - HEADERS += $$PWD/iaccessible2.h - include(../../../../3rdparty/iaccessible2/iaccessible2.pri) +!wince: { + SOURCES += $$PWD/qwindowsmsaaaccessible.cpp + HEADERS += $$PWD/qwindowsmsaaaccessible.h + + !mingw: { + SOURCES += $$PWD/iaccessible2.cpp + HEADERS += $$PWD/iaccessible2.h + include(../../../../3rdparty/iaccessible2/iaccessible2.pri) + } } -mingw: LIBS *= -luuid
\ No newline at end of file +mingw: LIBS *= -luuid diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp index 0bf3c27350..0437290dcb 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp @@ -50,10 +50,12 @@ #include <QtGui/qguiapplication.h> #include "qwindowsaccessibility.h" -#ifdef Q_CC_MINGW -# include "qwindowsmsaaaccessible.h" -#else -# include "iaccessible2.h" +#if !defined(Q_OS_WINCE) +# ifdef Q_CC_MINGW +# include "qwindowsmsaaaccessible.h" +# else +# include "iaccessible2.h" +# endif #endif #include "comutils.h" @@ -68,8 +70,9 @@ #if !defined(WINABLEAPI) # if defined(Q_OS_WINCE) # include <bldver.h> +# else +# include <winable.h> # endif -# include <winable.h> #endif #include <servprov.h> @@ -151,7 +154,7 @@ void QWindowsAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event) // An event has to be associated with a window, // so find the first parent that is a widget and that has a WId QAccessibleInterface *iface = event->accessibleInterface(); - if (!iface || !iface->isValid()) + if (!isActive() || !iface || !iface->isValid()) return; QWindow *window = QWindowsAccessibility::windowHelper(iface); @@ -193,6 +196,11 @@ QWindow *QWindowsAccessibility::windowHelper(const QAccessibleInterface *iface) */ IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc) { +#if defined(Q_OS_WINCE) + Q_UNUSED(acc); + + return 0; +#else if (!acc) return 0; @@ -200,14 +208,15 @@ IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc) if (!QAccessible::uniqueId(acc)) QAccessible::registerAccessibleInterface(acc); -#ifdef Q_CC_MINGW +# ifdef Q_CC_MINGW QWindowsMsaaAccessible *wacc = new QWindowsMsaaAccessible(acc); -#else +# else QWindowsIA2Accessible *wacc = new QWindowsIA2Accessible(acc); -#endif +# endif IAccessible *iacc = 0; wacc->QueryInterface(IID_IAccessible, (void**)&iacc); return iacc; +#endif // defined(Q_OS_WINCE) } /* @@ -230,6 +239,7 @@ void QWindowsAccessibility::cleanup() bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult) { +#if !defined(Q_OS_WINCE) if (static_cast<long>(lParam) == static_cast<long>(UiaRootObjectId)) { /* For UI Automation */ } else if ((DWORD)lParam == DWORD(OBJID_CLIENT)) { @@ -248,9 +258,7 @@ bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, W if (!oleaccChecked) { oleaccChecked = true; -#if !defined(Q_OS_WINCE) ptrLresultFromObject = (PtrLresultFromObject)QSystemLibrary::resolve(QLatin1String("oleacc"), "LresultFromObject"); -#endif } if (ptrLresultFromObject) { @@ -269,6 +277,12 @@ bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, W } } } +#else + Q_UNUSED(hwnd); + Q_UNUSED(wParam); + Q_UNUSED(lParam); + Q_UNUSED(lResult); +#endif // !defined(Q_OS_WINCE) return false; } diff --git a/src/plugins/platforms/windows/openglblacklists/default.json b/src/plugins/platforms/windows/openglblacklists/default.json index 23607523bd..767eac161c 100644 --- a/src/plugins/platforms/windows/openglblacklists/default.json +++ b/src/plugins/platforms/windows/openglblacklists/default.json @@ -1,10 +1,10 @@ { "name": "Qt built-in GPU driver blacklist", - "version": "5.5", + "version": "5.6", "entries": [ { "id": 1, - "description": "Desktop OpenGL is unreliable on some Intel HD laptops (QTBUG-43263, QTBUG-42240)", + "description": "Desktop OpenGL is unreliable on some Intel HD laptops (QTBUG-43263)", "vendor_id": "0x8086", "device_id": [ "0x0A16" ], "os": { @@ -17,6 +17,67 @@ "features": [ "disable_desktopgl" ] + }, + { + "id": 2, + "description": "Intel Q965/Q963 - GMA 3000 has insufficient support of opengl and directx", + "vendor_id": "0x8086", + "device_id": [ "0x2992" ], + "os": { + "type": "win" + }, + "features": [ + "disable_desktopgl", + "disable_angle" + ] + }, + { + "id": 3, + "description": "No OpenGL on Intel G33/G31 (QTBUG-47522)", + "vendor_id": "0x8086", + "device_id": [ "0x29C2" ], + "os": { + "type": "win" + }, + "features": [ + "disable_desktopgl" + ] + }, + { + "id": 4, + "description": "Intel HD Graphics 3000 crashes when initializing the OpenGL driver (QTBUG-42240)", + "vendor_id": "0x8086", + "device_id": [ "0x0102", "0x0106", "0x010A", "0x0112", "0x0116", "0x0122", "0x0126" ], + "os": { + "type": "win" + }, + "features": [ + "disable_desktopgl" + ] + }, + { + "id": 5, + "description": "Intel GMA 3150 (QTBUG-43243), Mobile Intel 945GM (QTBUG-47435) crash", + "vendor_id": "0x8086", + "device_id": [ "0xA001", "0xA011", "0x27A0" ], + "os": { + "type": "win" + }, + "features": [ + "disable_desktopgl", "disable_angle" + ] + }, + { + "id": 6, + "description": "Intel(R) HD Graphics 4000 / 5500 cause crashes on orientation changes in fullscreen mode (QTBUG-49541)", + "vendor_id": "0x8086", + "device_id": [ "0x0166", "0x1616" ], + "os": { + "type": "win" + }, + "features": [ + "disable_rotation" + ] } ] } diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp index 16c278d9df..a6b1d0af26 100644 --- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp +++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp @@ -35,10 +35,11 @@ #include "qwindowswindow.h" #include "qwindowsnativeimage.h" #include "qwindowscontext.h" -#include "qwindowsscaling.h" #include <QtGui/QWindow> #include <QtGui/QPainter> +#include <private/qhighdpiscaling_p.h> +#include <private/qimage_p.h> #include <QtCore/QDebug> @@ -52,7 +53,8 @@ QT_BEGIN_NAMESPACE */ QWindowsBackingStore::QWindowsBackingStore(QWindow *window) : - QPlatformBackingStore(window) + QPlatformBackingStore(window), + m_alphaNeedsFill(false) { qCDebug(lcQpaBackingStore) << __FUNCTION__ << this << window; } @@ -68,10 +70,12 @@ QPaintDevice *QWindowsBackingStore::paintDevice() return &m_image->image(); } -void QWindowsBackingStore::flushDp(QWindow *window, const QRect &br, const QPoint &offset) +void QWindowsBackingStore::flush(QWindow *window, const QRegion ®ion, + const QPoint &offset) { Q_ASSERT(window); + const QRect br = region.boundingRect(); if (QWindowsContext::verbose > 1) qCDebug(lcQpaBackingStore) << __FUNCTION__ << this << window << offset << br; QWindowsWindow *rw = QWindowsWindow::baseWindowOf(window); @@ -81,9 +85,9 @@ void QWindowsBackingStore::flushDp(QWindow *window, const QRect &br, const QPoin const Qt::WindowFlags flags = window->flags(); if ((flags & Qt::FramelessWindowHint) && QWindowsWindow::setWindowLayered(rw->handle(), flags, hasAlpha, rw->opacity()) && hasAlpha) { // Windows with alpha: Use blend function to update. - const QMargins marginsDP = rw->frameMarginsDp(); - const QRect r = rw->geometryDp() + marginsDP; - const QPoint frameOffset(marginsDP.left(), marginsDP.top()); + QRect r = QHighDpi::toNativePixels(window->frameGeometry(), window); + QPoint frameOffset(QHighDpi::toNativePixels(QPoint(window->frameMargins().left(), window->frameMargins().top()), + static_cast<const QWindow *>(Q_NULLPTR))); QRect dirtyRect = br.translated(offset + frameOffset); SIZE size = {r.width(), r.height()}; @@ -94,7 +98,12 @@ void QWindowsBackingStore::flushDp(QWindow *window, const QRect &br, const QPoin 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}; - QWindowsContext::user32dll.updateLayeredWindowIndirect(rw->handle(), &info); + const BOOL result = QWindowsContext::user32dll.updateLayeredWindowIndirect(rw->handle(), &info); + if (!result) + qErrnoWarning("UpdateLayeredWindowIndirect failed for ptDst=(%d, %d)," + " size=(%dx%d), dirty=(%dx%d %d, %d)", r.x(), r.y(), + r.width(), r.height(), dirtyRect.width(), dirtyRect.height(), + dirtyRect.x(), dirtyRect.y()); } else { QWindowsContext::user32dll.updateLayeredWindow(rw->handle(), NULL, &ptDst, &size, m_image->hdc(), &ptSrc, 0, &blend, ULW_ALPHA); } @@ -127,27 +136,34 @@ void QWindowsBackingStore::flushDp(QWindow *window, const QRect &br, const QPoin } } -void QWindowsBackingStore::resize(const QSize &sizeDip, const QRegion ®ionDip) +void QWindowsBackingStore::resize(const QSize &size, const QRegion ®ion) { - const QSize size = sizeDip * QWindowsScaling::factor(); if (m_image.isNull() || m_image->image().size() != size) { #ifndef QT_NO_DEBUG_OUTPUT if (QWindowsContext::verbose && lcQpaBackingStore().isDebugEnabled()) { qCDebug(lcQpaBackingStore) - << __FUNCTION__ << ' ' << window() << ' ' << size << ' ' << sizeDip << ' ' - << regionDip << " from: " << (m_image.isNull() ? QSize() : m_image->image().size()); + << __FUNCTION__ << ' ' << window() << ' ' << size << ' ' << region + << " from: " << (m_image.isNull() ? QSize() : m_image->image().size()); } #endif - const QImage::Format format = window()->format().hasAlpha() ? - QImage::Format_ARGB32_Premultiplied : QWindowsNativeImage::systemFormat(); + QImage::Format format = window()->format().hasAlpha() ? + QImage::Format_ARGB32_Premultiplied : QWindowsNativeImage::systemFormat(); + + // The backingstore composition (enabling render-to-texture widgets) + // punches holes in the backingstores using the alpha channel. Hence + // the need for a true alpha format. + if (QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::UsesAlpha) + m_alphaNeedsFill = true; + else // upgrade but here we know app painting does not rely on alpha hence no need to fill + format = qt_alphaVersionForPainting(format); QWindowsNativeImage *oldwni = m_image.data(); QWindowsNativeImage *newwni = new QWindowsNativeImage(size.width(), size.height(), format); - if (oldwni && !regionDip.isEmpty()) { + if (oldwni && !region.isEmpty()) { const QImage &oldimg(oldwni->image()); QImage &newimg(newwni->image()); - QRegion staticRegion = QWindowsScaling::mapToNative(regionDip); + QRegion staticRegion(region); staticRegion &= QRect(0, 0, oldimg.width(), oldimg.height()); staticRegion &= QRect(0, 0, newimg.width(), newimg.height()); QPainter painter(&newimg); @@ -156,38 +172,36 @@ void QWindowsBackingStore::resize(const QSize &sizeDip, const QRegion ®ionDip painter.drawImage(rect, oldimg, rect); } - if (QWindowsScaling::isActive()) - newwni->setDevicePixelRatio(QWindowsScaling::factor()); m_image.reset(newwni); } } Q_GUI_EXPORT void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset); -bool QWindowsBackingStore::scroll(const QRegion &areaDip, int dxDip, int dyDip) +bool QWindowsBackingStore::scroll(const QRegion &area, int dx, int dy) { if (m_image.isNull() || m_image->image().isNull()) return false; - const QPoint dp = QPoint(dxDip, dyDip) * QWindowsScaling::factor(); - const QVector<QRect> rects = areaDip.rects(); + const QVector<QRect> rects = area.rects(); + const QPoint offset(dx, dy); for (int i = 0; i < rects.size(); ++i) - qt_scrollRectInImage(m_image->image(), QWindowsScaling::mapToNative(rects.at(i)), dp); + qt_scrollRectInImage(m_image->image(), rects.at(i), offset); return true; } -void QWindowsBackingStore::beginPaint(const QRegion ®ionDip) +void QWindowsBackingStore::beginPaint(const QRegion ®ion) { if (QWindowsContext::verbose > 1) - qCDebug(lcQpaBackingStore) <<__FUNCTION__ << regionDip; + qCDebug(lcQpaBackingStore) <<__FUNCTION__ << region; - if (m_image->image().hasAlphaChannel()) { + if (m_alphaNeedsFill) { QPainter p(&m_image->image()); p.setCompositionMode(QPainter::CompositionMode_Source); const QColor blank = Qt::transparent; - foreach (const QRect &r, regionDip.rects()) - p.fillRect(QWindowsScaling::mapToNative(r), blank); + foreach (const QRect &r, region.rects()) + p.fillRect(r, blank); } } diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.h b/src/plugins/platforms/windows/qwindowsbackingstore.h index 41ad29babc..1d644923bb 100644 --- a/src/plugins/platforms/windows/qwindowsbackingstore.h +++ b/src/plugins/platforms/windows/qwindowsbackingstore.h @@ -35,7 +35,6 @@ #define QWINDOWSBACKINGSTORE_H #include "qtwindows_additional.h" -#include "qwindowsscaling.h" #include <qpa/qplatformbackingstore.h> #include <QtCore/QScopedPointer> @@ -53,12 +52,7 @@ public: ~QWindowsBackingStore(); QPaintDevice *paintDevice() Q_DECL_OVERRIDE; - void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE - { - flushDp(window, QWindowsScaling::mapToNative(region.boundingRect()), - offset * QWindowsScaling::factor()); - } - void flushDp(QWindow *window, const QRect &boundingRect, const QPoint &offset); + void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE; void resize(const QSize &size, const QRegion &r) Q_DECL_OVERRIDE; bool scroll(const QRegion &area, int dx, int dy) Q_DECL_OVERRIDE; void beginPaint(const QRegion &) Q_DECL_OVERRIDE; @@ -71,6 +65,7 @@ public: private: QScopedPointer<QWindowsNativeImage> m_image; + bool m_alphaNeedsFill; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsclipboard.cpp b/src/plugins/platforms/windows/qwindowsclipboard.cpp index 925427ac30..1071a2e038 100644 --- a/src/plugins/platforms/windows/qwindowsclipboard.cpp +++ b/src/plugins/platforms/windows/qwindowsclipboard.cpp @@ -35,7 +35,6 @@ #include "qwindowscontext.h" #include "qwindowsole.h" #include "qwindowsmime.h" -#include "qwindowsguieventdispatcher.h" #include <QtGui/QGuiApplication> #include <QtGui/QClipboard> @@ -48,6 +47,8 @@ #include <QtCore/QVariant> #include <QtCore/QUrl> +#include <QtPlatformSupport/private/qwindowsguieventdispatcher_p.h> + QT_BEGIN_NAMESPACE static const char formatTextPlainC[] = "text/plain"; @@ -69,6 +70,7 @@ static const char formatTextHtmlC[] = "text/html"; \ingroup qt-lighthouse-win */ +#ifndef QT_NO_DEBUG_STREAM static QDebug operator<<(QDebug d, const QMimeData *mimeData) { QDebugStateSaver saver(d); @@ -93,6 +95,7 @@ static QDebug operator<<(QDebug d, const QMimeData *mimeData) d << ')'; return d; } +#endif // !QT_NO_DEBUG_STREAM /*! \class QWindowsClipboardRetrievalMimeData @@ -109,8 +112,11 @@ static QDebug operator<<(QDebug d, const QMimeData *mimeData) IDataObject *QWindowsClipboardRetrievalMimeData::retrieveDataObject() const { IDataObject * pDataObj = 0; - if (OleGetClipboard(&pDataObj) == S_OK) + if (OleGetClipboard(&pDataObj) == S_OK) { + if (QWindowsContext::verbose > 1) + qCDebug(lcQpaMime) << __FUNCTION__ << pDataObj; return pDataObj; + } return 0; } @@ -230,7 +236,7 @@ void QWindowsClipboard::propagateClipboardMessage(UINT message, WPARAM wParam, L // suspended by a shell prompt 'Select' or debugger). if (QWindowsContext::user32dll.isHungAppWindow && QWindowsContext::user32dll.isHungAppWindow(m_nextClipboardViewer)) { - qWarning("%s: Cowardly refusing to send clipboard message to hung application...", Q_FUNC_INFO); + qWarning("Cowardly refusing to send clipboard message to hung application..."); return; } // Do not block if the process is being debugged, specifically, if it is diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 00049bd0d6..4934b6c6e4 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -36,7 +36,6 @@ #include "qwindowsintegration.h" #include "qwindowswindow.h" #include "qwindowskeymapper.h" -#include "qwindowsguieventdispatcher.h" #include "qwindowsmousehandler.h" #include "qtwindowsglobal.h" #include "qwindowsmime.h" @@ -52,7 +51,6 @@ #endif #include "qwindowsscreen.h" #include "qwindowstheme.h" -#include "qwindowsscaling.h" #include <QtGui/QWindow> #include <qpa/qwindowsysteminterface.h> @@ -67,6 +65,8 @@ #include <QtCore/QScopedArrayPointer> #include <QtCore/private/qsystemlibrary_p.h> +#include <QtPlatformSupport/private/qwindowsguieventdispatcher_p.h> + #include <stdlib.h> #include <stdio.h> #include <windowsx.h> @@ -177,7 +177,8 @@ QWindowsUser32DLL::QWindowsUser32DLL() : isHungAppWindow(0), isTouchWindow(0), registerTouchWindow(0), unregisterTouchWindow(0), getTouchInputInfo(0), closeTouchInputHandle(0), setProcessDPIAware(0), - addClipboardFormatListener(0), removeClipboardFormatListener(0) + addClipboardFormatListener(0), removeClipboardFormatListener(0), + getDisplayAutoRotationPreferences(0), setDisplayAutoRotationPreferences(0) { } @@ -198,6 +199,8 @@ void QWindowsUser32DLL::init() addClipboardFormatListener = (AddClipboardFormatListener)library.resolve("AddClipboardFormatListener"); removeClipboardFormatListener = (RemoveClipboardFormatListener)library.resolve("RemoveClipboardFormatListener"); } + getDisplayAutoRotationPreferences = (GetDisplayAutoRotationPreferences)library.resolve("GetDisplayAutoRotationPreferences"); + setDisplayAutoRotationPreferences = (SetDisplayAutoRotationPreferences)library.resolve("SetDisplayAutoRotationPreferences"); } bool QWindowsUser32DLL::initTouch() @@ -402,14 +405,29 @@ void QWindowsContext::setTabletAbsoluteRange(int a) #endif } +int QWindowsContext::processDpiAwareness() +{ +#ifndef Q_OS_WINCE + int result; + if (QWindowsContext::shcoredll.getProcessDpiAwareness + && SUCCEEDED(QWindowsContext::shcoredll.getProcessDpiAwareness(NULL, &result))) { + return result; + } +#endif // !Q_OS_WINCE + return -1; +} + void QWindowsContext::setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness) { #ifndef Q_OS_WINCE qCDebug(lcQpaWindows) << __FUNCTION__ << dpiAwareness; if (QWindowsContext::shcoredll.isValid()) { const HRESULT hr = QWindowsContext::shcoredll.setProcessDpiAwareness(dpiAwareness); - if (FAILED(hr)) - qWarning() << "SetProcessDpiAwareness failed:" << QWindowsContext::comErrorString(hr); + if (FAILED(hr)) { + qWarning().noquote().nospace() << "SetProcessDpiAwareness(" + << dpiAwareness << ") failed: " << QWindowsContext::comErrorString(hr) + << ", using " << QWindowsContext::processDpiAwareness(); + } } else { if (dpiAwareness != QtWindows::ProcessDpiUnaware && QWindowsContext::user32dll.setProcessDPIAware) { if (!QWindowsContext::user32dll.setProcessDPIAware()) @@ -893,6 +911,11 @@ QByteArray QWindowsContext::comErrorString(HRESULT hr) return result; } +static inline QWindowsInputContext *windowsInputContext() +{ + return qobject_cast<QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext()); +} + /*! \brief Main windows procedure registered for windows. @@ -941,16 +964,29 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, return true; } } + if (et & QtWindows::InputMethodEventFlag) { + QWindowsInputContext *windowsInputContext = ::windowsInputContext(); + // Disable IME assuming this is a special implementation hooking into keyboard input. + // "Real" IME implementations should use a native event filter intercepting IME events. + if (!windowsInputContext) { + QWindowsInputContext::setWindowsImeEnabled(platformWindow, false); + return false; + } + switch (et) { + case QtWindows::InputMethodStartCompositionEvent: + return windowsInputContext->startComposition(hwnd); + case QtWindows::InputMethodCompositionEvent: + return windowsInputContext->composition(hwnd, lParam); + case QtWindows::InputMethodEndCompositionEvent: + return windowsInputContext->endComposition(hwnd); + case QtWindows::InputMethodRequest: + return windowsInputContext->handleIME_Request(wParam, lParam, result); + default: + break; + } + } // InputMethodEventFlag switch (et) { - case QtWindows::InputMethodStartCompositionEvent: - return QWindowsInputContext::instance()->startComposition(hwnd); - case QtWindows::InputMethodCompositionEvent: - return QWindowsInputContext::instance()->composition(hwnd, lParam); - case QtWindows::InputMethodEndCompositionEvent: - return QWindowsInputContext::instance()->endComposition(hwnd); - case QtWindows::InputMethodRequest: - return QWindowsInputContext::instance()->handleIME_Request(wParam, lParam, result); case QtWindows::GestureEvent: #if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateGestureEvent(platformWindow->window(), hwnd, et, msg, result); @@ -1025,11 +1061,13 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, } switch (et) { + case QtWindows::KeyboardLayoutChangeEvent: + if (QWindowsInputContext *wic = windowsInputContext()) + wic->handleInputLanguageChanged(wParam, lParam); // fallthrough intended. case QtWindows::KeyDownEvent: case QtWindows::KeyEvent: case QtWindows::InputMethodKeyEvent: case QtWindows::InputMethodKeyDownEvent: - case QtWindows::KeyboardLayoutChangeEvent: case QtWindows::AppCommandEvent: #if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) return platformSessionManager()->isInteractionBlocked() ? true : d->m_keyMapper.translateKeyEvent(platformWindow->window(), hwnd, msg, result); @@ -1265,9 +1303,7 @@ bool QWindowsContext::handleContextMenuEvent(QWindow *window, const MSG &msg) } } - QWindowSystemInterface::handleContextMenuEvent(window, mouseTriggered, - pos / QWindowsScaling::factor(), - globalPos / QWindowsScaling::factor(), + QWindowSystemInterface::handleContextMenuEvent(window, mouseTriggered, pos, globalPos, QWindowsKeyMapper::queryKeyboardModifiers()); return true; } diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index 641e3ed41f..14baec96d8 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -94,6 +94,8 @@ struct QWindowsUser32DLL typedef BOOL (WINAPI *SetProcessDPIAware)(); typedef BOOL (WINAPI *AddClipboardFormatListener)(HWND); typedef BOOL (WINAPI *RemoveClipboardFormatListener)(HWND); + typedef BOOL (WINAPI *GetDisplayAutoRotationPreferences)(DWORD *); + typedef BOOL (WINAPI *SetDisplayAutoRotationPreferences)(DWORD); // Functions missing in Q_CC_GNU stub libraries. SetLayeredWindowAttributes setLayeredWindowAttributes; @@ -116,6 +118,10 @@ struct QWindowsUser32DLL // Clipboard listeners, Windows Vista onwards AddClipboardFormatListener addClipboardFormatListener; RemoveClipboardFormatListener removeClipboardFormatListener; + + // Rotation API + GetDisplayAutoRotationPreferences getDisplayAutoRotationPreferences; + SetDisplayAutoRotationPreferences setDisplayAutoRotationPreferences; }; struct QWindowsShell32DLL @@ -142,7 +148,7 @@ struct QWindowsShcoreDLL { void init(); inline bool isValid() const { return getProcessDpiAwareness && setProcessDpiAwareness && getDpiForMonitor; } - typedef HRESULT (WINAPI *GetProcessDpiAwareness)(HANDLE,int); + typedef HRESULT (WINAPI *GetProcessDpiAwareness)(HANDLE,int *); typedef HRESULT (WINAPI *SetProcessDpiAwareness)(int); typedef HRESULT (WINAPI *GetDpiForMonitor)(HMONITOR,int,UINT *,UINT *); @@ -213,6 +219,7 @@ public: void setTabletAbsoluteRange(int a); void setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness); + static int processDpiAwareness(); // Returns a combination of SystemInfoFlags unsigned systemInfo() const; diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index 5f443f2675..c769eb04a4 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -36,7 +36,6 @@ #include "qwindowscontext.h" #include "qwindowswindow.h" #include "qwindowsscreen.h" -#include "qwindowsscaling.h" #include <QtGui/QBitmap> #include <QtGui/QImage> @@ -44,15 +43,17 @@ #include <QtGui/QGuiApplication> #include <QtGui/QScreen> #include <QtGui/private/qguiapplication_p.h> // getPixmapCursor() +#include <QtGui/private/qhighdpiscaling_p.h> #include <QtCore/QDebug> #include <QtCore/QScopedArrayPointer> -static void initResources() +static bool initResources() { #if !defined (Q_OS_WINCE) && !defined (QT_NO_IMAGEFORMAT_PNG) Q_INIT_RESOURCE(cursors); #endif + return true; } QT_BEGIN_NAMESPACE @@ -68,19 +69,14 @@ Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap); \ingroup qt-lighthouse-win */ -QWindowsCursorCacheKey::QWindowsCursorCacheKey(const QCursor &c) - : shape(c.shape()), bitmapCacheKey(0), maskCacheKey(0) +QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c) + : bitmapCacheKey(c.pixmap().cacheKey()), maskCacheKey(0) { - if (shape == Qt::BitmapCursor) { - const qint64 pixmapCacheKey = c.pixmap().cacheKey(); - if (pixmapCacheKey) { - bitmapCacheKey = pixmapCacheKey; - } else { - Q_ASSERT(c.bitmap()); - Q_ASSERT(c.mask()); - bitmapCacheKey = c.bitmap()->cacheKey(); - maskCacheKey = c.mask()->cacheKey(); - } + if (!bitmapCacheKey) { + Q_ASSERT(c.bitmap()); + Q_ASSERT(c.mask()); + bitmapCacheKey = c.bitmap()->cacheKey(); + maskCacheKey = c.mask()->cacheKey(); } } @@ -98,9 +94,14 @@ QWindowsCursorCacheKey::QWindowsCursorCacheKey(const QCursor &c) \sa QWindowsWindowCursor */ -HCURSOR QWindowsCursor::createPixmapCursor(const QPixmap &pixmap, const QPoint &hotSpot) +HCURSOR QWindowsCursor::createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor) { HCURSOR cur = 0; + scaleFactor /= pixmap.devicePixelRatioF(); + if (!qFuzzyCompare(scaleFactor, 1)) { + pixmap = pixmap.scaled((scaleFactor * QSizeF(pixmap.size())).toSize(), + Qt::KeepAspectRatio, Qt::SmoothTransformation); + } QBitmap mask = pixmap.mask(); if (mask.isNull()) { mask = QBitmap(pixmap.size()); @@ -207,7 +208,44 @@ static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits, #endif } -static inline QSize systemCursorSize() { return QSize(GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR)); } +// Create a cursor from image and mask of the format QImage::Format_Mono. +static HCURSOR createBitmapCursor(const QCursor &cursor, qreal scaleFactor = 1) +{ + Q_ASSERT(cursor.shape() == Qt::BitmapCursor && cursor.bitmap()); + QImage bbits = cursor.bitmap()->toImage(); + QImage mbits = cursor.mask()->toImage(); + scaleFactor /= bbits.devicePixelRatioF(); + if (!qFuzzyCompare(scaleFactor, 1)) { + const QSize scaledSize = (QSizeF(bbits.size()) * scaleFactor).toSize(); + bbits = bbits.scaled(scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); + mbits = mbits.scaled(scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); + } + bbits = bbits.convertToFormat(QImage::Format_Mono); + mbits = mbits.convertToFormat(QImage::Format_Mono); + const bool invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1)); + const bool invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1)); + return createBitmapCursor(bbits, mbits, cursor.hotSpot(), invb, invm); +} + +static QSize systemCursorSize(const QPlatformScreen *screen = Q_NULLPTR) +{ + const QSize primaryScreenCursorSize(GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR)); + if (screen) { + // Correct the size if the DPI value of the screen differs from + // that of the primary screen. + if (const QScreen *primaryQScreen = QGuiApplication::primaryScreen()) { + const QPlatformScreen *primaryScreen = primaryQScreen->handle(); + if (screen != primaryScreen) { + const qreal logicalDpi = screen->logicalDpi().first; + const qreal primaryScreenLogicalDpi = primaryScreen->logicalDpi().first; + if (!qFuzzyCompare(logicalDpi, primaryScreenLogicalDpi)) + return (QSizeF(primaryScreenCursorSize) * logicalDpi / primaryScreenLogicalDpi).toSize(); + } + } + } + return primaryScreenCursorSize; +} + static inline QSize standardCursorSize() { return QSize(32, 32); } #if defined (Q_OS_WINCE) || defined (QT_NO_IMAGEFORMAT_PNG) @@ -216,7 +254,7 @@ static inline QSize standardCursorSize() { return QSize(32, 32); } // createBitmapCursor() only work for standard sizes (32,48,64...), which does // not work when scaling the 16x16 openhand cursor bitmaps to 150% (resulting // in a non-standard 24x24 size). -static QCursor createPixmapCursorFromData(const QSize &systemCursorSize, +static QWindowsCursor::PixmapCursor createPixmapCursorFromData(const QSize &systemCursorSize, // The cursor size the bitmap is targeted for const QSize &bitmapTargetCursorSize, // The actual size of the bitmap data @@ -234,10 +272,11 @@ static QCursor createPixmapCursorFromData(const QSize &systemCursorSize, rawImage = rawImage.transformed(transform, Qt::SmoothTransformation); } const QPoint hotSpot(rawImage.width() / 2, rawImage.height() / 2); - return QCursor(rawImage, hotSpot.x(), hotSpot.y()); + return QWindowsCursor::PixmapCursor(rawImage, hotSpot); } -QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape) +QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape, + const QPlatformScreen *screen) { // Non-standard Windows cursors are created from bitmaps static const uchar vsplit_bits[] = { @@ -405,22 +444,22 @@ QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape) switch (cursorShape) { case Qt::SplitVCursor: - return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 32, vsplit_bits, vsplitm_bits); + return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 32, vsplit_bits, vsplitm_bits); case Qt::SplitHCursor: - return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 32, hsplit_bits, hsplitm_bits); + return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 32, hsplit_bits, hsplitm_bits); case Qt::OpenHandCursor: - return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 16, openhand_bits, openhandm_bits); + return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 16, openhand_bits, openhandm_bits); case Qt::ClosedHandCursor: - return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 16, closedhand_bits, closedhandm_bits); + return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 16, closedhand_bits, closedhandm_bits); case Qt::DragCopyCursor: - return QCursor(QPixmap(copyDragCursorXpmC), 0, 0); + return QWindowsCursor::PixmapCursor(QPixmap(copyDragCursorXpmC), QPoint(0, 0)); case Qt::DragMoveCursor: - return QCursor(QPixmap(moveDragCursorXpmC), 0, 0); + return QWindowsCursor::PixmapCursor(QPixmap(moveDragCursorXpmC), QPoint(0, 0)); case Qt::DragLinkCursor: - return QCursor(QPixmap(linkDragCursorXpmC), 0, 0); + return QWindowsCursor::PixmapCursor(QPixmap(linkDragCursorXpmC), QPoint(0, 0)); } - return QCursor(); + return QWindowsCursor::PixmapCursor(); } #else // Q_OS_WINCE || QT_NO_IMAGEFORMAT_PNG struct QWindowsCustomPngCursor { @@ -431,7 +470,7 @@ struct QWindowsCustomPngCursor { int hotSpotY; }; -QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape) +QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape, const QPlatformScreen *screen) { static const QWindowsCustomPngCursor pngCursors[] = { { Qt::SplitVCursor, 32, "splitvcursor_32.png", 11, 11 }, @@ -457,14 +496,14 @@ QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape) { Qt::DragLinkCursor, 64, "draglinkcursor_64.png", 0, 0 } }; - const int cursorSize = GetSystemMetrics(SM_CXCURSOR); + const QSize cursorSize = systemCursorSize(screen); const QWindowsCustomPngCursor *sEnd = pngCursors + sizeof(pngCursors) / sizeof(pngCursors[0]); const QWindowsCustomPngCursor *bestFit = 0; int sizeDelta = INT_MAX; for (const QWindowsCustomPngCursor *s = pngCursors; s < sEnd; ++s) { if (s->shape != cursorShape) continue; - const int currentSizeDelta = qMax(s->size, cursorSize) - qMin(s->size, cursorSize); + const int currentSizeDelta = qMax(s->size, cursorSize.width()) - qMin(s->size, cursorSize.width()); if (currentSizeDelta < sizeDelta) { bestFit = s; if (currentSizeDelta == 0) @@ -474,11 +513,11 @@ QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape) } if (!bestFit) - return QCursor(); + return PixmapCursor(); const QPixmap rawImage(QStringLiteral(":/qt-project.org/windows/cursors/images/") + QString::fromLatin1(bestFit->fileName)); - return QCursor(rawImage, bestFit->hotSpotX, bestFit->hotSpotY); + return PixmapCursor(rawImage, QPoint(bestFit->hotSpotX, bestFit->hotSpotY)); } #endif // Q_OS_WINCE || QT_NO_IMAGEFORMAT_PNG @@ -487,8 +526,10 @@ struct QWindowsStandardCursorMapping { LPCWSTR resource; }; -HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c) +HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape, const QPlatformScreen *screen) { + Q_ASSERT(cursorShape != Qt::BitmapCursor); + static const QWindowsStandardCursorMapping standardCursors[] = { { Qt::ArrowCursor, IDC_ARROW}, { Qt::UpArrowCursor, IDC_UPARROW }, @@ -506,20 +547,9 @@ HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c) { Qt::PointingHandCursor, IDC_HAND } }; - const Qt::CursorShape cursorShape = c.shape(); switch (cursorShape) { - case Qt::BitmapCursor: { - const QPixmap pixmap = c.pixmap(); - if (!pixmap.isNull()) - return QWindowsCursor::createPixmapCursor(pixmap, c.hotSpot()); - const QImage bbits = c.bitmap()->toImage().convertToFormat(QImage::Format_Mono); - const QImage mbits = c.mask()->toImage().convertToFormat(QImage::Format_Mono); - const bool invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1)); - const bool invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1)); - return createBitmapCursor(bbits, mbits, c.hotSpot(), invb, invm); - } case Qt::BlankCursor: { - QImage blank = QImage(systemCursorSize(), QImage::Format_Mono); + QImage blank = QImage(systemCursorSize(screen), QImage::Format_Mono); blank.fill(0); // ignore color table return createBitmapCursor(blank, blank); } @@ -530,7 +560,7 @@ HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c) case Qt::DragCopyCursor: case Qt::DragMoveCursor: case Qt::DragLinkCursor: - return createSystemCursor(customCursor(cursorShape)); + return QWindowsCursor::createPixmapCursor(customCursor(cursorShape, screen)); default: break; } @@ -555,44 +585,52 @@ HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c) \brief Return cached standard cursor resources or create new ones. */ -QWindowsWindowCursor QWindowsCursor::standardWindowCursor(Qt::CursorShape shape) +CursorHandlePtr QWindowsCursor::standardWindowCursor(Qt::CursorShape shape) { - const QWindowsCursorCacheKey key(shape); - CursorCache::iterator it = m_cursorCache.find(key); - if (it == m_cursorCache.end()) - it = m_cursorCache.insert(key, QWindowsWindowCursor(QCursor(shape))); - return it.value(); + StandardCursorCache::Iterator it = m_standardCursorCache.find(shape); + if (it == m_standardCursorCache.end()) { + if (const HCURSOR hc = QWindowsCursor::createCursorFromShape(shape, m_screen)) + it = m_standardCursorCache.insert(shape, CursorHandlePtr(new CursorHandle(hc))); + } + return it != m_standardCursorCache.end() ? it.value() : CursorHandlePtr(new CursorHandle); } /*! \brief Return cached pixmap cursor or create new one. */ -QWindowsWindowCursor QWindowsCursor::pixmapWindowCursor(const QCursor &c) +CursorHandlePtr QWindowsCursor::pixmapWindowCursor(const QCursor &c) { - const QWindowsCursorCacheKey cacheKey(c); - CursorCache::iterator it = m_cursorCache.find(cacheKey); - if (it == m_cursorCache.end()) { - if (m_cursorCache.size() > 50) { + const QWindowsPixmapCursorCacheKey cacheKey(c); + PixmapCursorCache::iterator it = m_pixmapCursorCache.find(cacheKey); + if (it == m_pixmapCursorCache.end()) { + if (m_pixmapCursorCache.size() > 50) { // Prevent the cursor cache from growing indefinitely hitting GDI resource // limits if new pixmap cursors are created repetitively by purging out // all-noncurrent pixmap cursors (QTBUG-43515) const HCURSOR currentCursor = GetCursor(); - for (it = m_cursorCache.begin(); it != m_cursorCache.end() ; ) { - if (it.key().bitmapCacheKey && it.value().handle() != currentCursor) - it = m_cursorCache.erase(it); + for (it = m_pixmapCursorCache.begin(); it != m_pixmapCursorCache.end() ; ) { + if (it.value()->handle() != currentCursor) + it = m_pixmapCursorCache.erase(it); else ++it; } } - it = m_cursorCache.insert(cacheKey, QWindowsWindowCursor(c)); + const qreal scaleFactor = QHighDpiScaling::factor(m_screen); + const QPixmap pixmap = c.pixmap(); + const HCURSOR hc = pixmap.isNull() + ? createBitmapCursor(c, scaleFactor) + : QWindowsCursor::createPixmapCursor(pixmap, c.hotSpot(), scaleFactor); + it = m_pixmapCursorCache.insert(cacheKey, CursorHandlePtr(new CursorHandle(hc))); } return it.value(); } -QWindowsCursor::QWindowsCursor() +QWindowsCursor::QWindowsCursor(const QPlatformScreen *screen) + : m_screen(screen) { - initResources(); + static const bool dummy = initResources(); + Q_UNUSED(dummy) } /*! @@ -607,13 +645,13 @@ void QWindowsCursor::changeCursor(QCursor *cursorIn, QWindow *window) if (!window) return; if (!cursorIn) { - QWindowsWindow::baseWindowOf(window)->setCursor(QWindowsWindowCursor()); + QWindowsWindow::baseWindowOf(window)->setCursor(CursorHandlePtr(new CursorHandle)); return; } - const QWindowsWindowCursor wcursor = + const CursorHandlePtr wcursor = cursorIn->shape() == Qt::BitmapCursor ? pixmapWindowCursor(*cursorIn) : standardWindowCursor(cursorIn->shape()); - if (wcursor.handle()) { + if (wcursor->handle()) { QWindowsWindow::baseWindowOf(window)->setCursor(wcursor); } else { qWarning("%s: Unable to obtain system cursor for %d", @@ -646,13 +684,100 @@ QWindowsCursor::CursorState QWindowsCursor::cursorState() QPoint QWindowsCursor::pos() const { - return mousePosition() / QWindowsScaling::factor(); + return mousePosition(); } void QWindowsCursor::setPos(const QPoint &pos) { - const QPoint posDp = pos * QWindowsScaling::factor(); - SetCursorPos(posDp.x() , posDp.y()); + SetCursorPos(pos.x() , pos.y()); +} + +QPixmap QWindowsCursor::dragDefaultCursor(Qt::DropAction action) const +{ + switch (action) { + case Qt::CopyAction: + if (m_copyDragCursor.isNull()) + m_copyDragCursor = QWindowsCursor::customCursor(Qt::DragCopyCursor, m_screen).pixmap; + return m_copyDragCursor; + case Qt::TargetMoveAction: + case Qt::MoveAction: + if (m_moveDragCursor.isNull()) + m_moveDragCursor = QWindowsCursor::customCursor(Qt::DragMoveCursor, m_screen).pixmap; + return m_moveDragCursor; + case Qt::LinkAction: + if (m_linkDragCursor.isNull()) + m_linkDragCursor = QWindowsCursor::customCursor(Qt::DragLinkCursor, m_screen).pixmap; + return m_linkDragCursor; + default: + break; + } + + static const char * const ignoreDragCursorXpmC[] = { + "24 30 3 1", + ". c None", + "a c #000000", + "X c #FFFFFF", + "aa......................", + "aXa.....................", + "aXXa....................", + "aXXXa...................", + "aXXXXa..................", + "aXXXXXa.................", + "aXXXXXXa................", + "aXXXXXXXa...............", + "aXXXXXXXXa..............", + "aXXXXXXXXXa.............", + "aXXXXXXaaaa.............", + "aXXXaXXa................", + "aXXaaXXa................", + "aXa..aXXa...............", + "aa...aXXa...............", + "a.....aXXa..............", + "......aXXa.....XXXX.....", + ".......aXXa..XXaaaaXX...", + ".......aXXa.XaaaaaaaaX..", + "........aa.XaaaXXXXaaaX.", + "...........XaaaaX..XaaX.", + "..........XaaXaaaX..XaaX", + "..........XaaXXaaaX.XaaX", + "..........XaaX.XaaaXXaaX", + "..........XaaX..XaaaXaaX", + "...........XaaX..XaaaaX.", + "...........XaaaXXXXaaaX.", + "............XaaaaaaaaX..", + ".............XXaaaaXX...", + "...............XXXX....."}; + + if (m_ignoreDragCursor.isNull()) { +#if !defined (Q_OS_WINCE) + HCURSOR cursor = LoadCursor(NULL, IDC_NO); + ICONINFO iconInfo = {0, 0, 0, 0, 0}; + GetIconInfo(cursor, &iconInfo); + BITMAP bmColor = {0, 0, 0, 0, 0, 0, 0}; + + if (iconInfo.hbmColor + && GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bmColor) + && bmColor.bmWidth == bmColor.bmWidthBytes / 4) { + const int colorBitsLength = bmColor.bmHeight * bmColor.bmWidthBytes; + uchar *colorBits = new uchar[colorBitsLength]; + GetBitmapBits(iconInfo.hbmColor, colorBitsLength, colorBits); + const QImage colorImage(colorBits, bmColor.bmWidth, bmColor.bmHeight, + bmColor.bmWidthBytes, QImage::Format_ARGB32); + + m_ignoreDragCursor = QPixmap::fromImage(colorImage); + delete [] colorBits; + } else { + m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC); + } + + DeleteObject(iconInfo.hbmMask); + DeleteObject(iconInfo.hbmColor); + DestroyCursor(cursor); +#else // !Q_OS_WINCE + m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC); +#endif // !Q_OS_WINCE + } + return m_ignoreDragCursor; } /*! @@ -660,78 +785,11 @@ void QWindowsCursor::setPos(const QPoint &pos) \brief Per-Window cursor. Contains a QCursor and manages its associated system cursor handle resource. - Based on QSharedDataPointer, so that it can be passed around and - used as a property of QWindowsBaseWindow. - \internal \ingroup qt-lighthouse-win \sa QWindowsCursor */ -class QWindowsWindowCursorData : public QSharedData -{ -public: - QWindowsWindowCursorData() : m_cursor(Qt::ArrowCursor), m_handle(0) {} - explicit QWindowsWindowCursorData(const QCursor &c); - ~QWindowsWindowCursorData(); - - const QCursor m_cursor; - const HCURSOR m_handle; -}; - -QWindowsWindowCursorData::QWindowsWindowCursorData(const QCursor &c) : - m_cursor(c), - m_handle(QWindowsCursor::createSystemCursor(c)) -{ -} - -QWindowsWindowCursorData::~QWindowsWindowCursorData() -{ - if (m_handle) - DestroyCursor(m_handle); -} - -QWindowsWindowCursor::QWindowsWindowCursor() : - m_data(new QWindowsWindowCursorData) -{ -} - -QWindowsWindowCursor::QWindowsWindowCursor(const QCursor &c) : - m_data(new QWindowsWindowCursorData(c)) -{ -} - -QWindowsWindowCursor::~QWindowsWindowCursor() -{ -} - -QWindowsWindowCursor::QWindowsWindowCursor(const QWindowsWindowCursor &rhs) : - m_data(rhs.m_data) -{ -} - -QWindowsWindowCursor & QWindowsWindowCursor::operator =(const QWindowsWindowCursor &rhs) -{ - if (this != &rhs) - m_data.operator =(rhs.m_data); - return *this; -} - -bool QWindowsWindowCursor::isNull() const -{ - return m_data->m_handle == 0; -} - -QCursor QWindowsWindowCursor::cursor() const -{ - return m_data->m_cursor; -} - -HCURSOR QWindowsWindowCursor::handle() const -{ - return m_data->m_handle; -} - QT_END_NAMESPACE #endif // !QT_NO_CURSOR diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h index f1763ddd7d..e93f779f94 100644 --- a/src/plugins/platforms/windows/qwindowscursor.h +++ b/src/plugins/platforms/windows/qwindowscursor.h @@ -37,51 +37,49 @@ #include "qtwindows_additional.h" #include <qpa/qplatformcursor.h> -#include <QtCore/QSharedDataPointer> +#include <QtCore/QSharedPointer> #include <QtCore/QHash> QT_BEGIN_NAMESPACE -class QWindowsWindowCursorData; - -struct QWindowsCursorCacheKey +struct QWindowsPixmapCursorCacheKey { - explicit QWindowsCursorCacheKey(const QCursor &c); - explicit QWindowsCursorCacheKey(Qt::CursorShape s) : shape(s), bitmapCacheKey(0), maskCacheKey(0) {} - QWindowsCursorCacheKey() : shape(Qt::CustomCursor), bitmapCacheKey(0), maskCacheKey(0) {} + explicit QWindowsPixmapCursorCacheKey(const QCursor &c); - Qt::CursorShape shape; qint64 bitmapCacheKey; qint64 maskCacheKey; }; -inline bool operator==(const QWindowsCursorCacheKey &k1, const QWindowsCursorCacheKey &k2) +inline bool operator==(const QWindowsPixmapCursorCacheKey &k1, const QWindowsPixmapCursorCacheKey &k2) { - return k1.shape == k2.shape && k1.bitmapCacheKey == k2.bitmapCacheKey && k1.maskCacheKey == k2.maskCacheKey; + return k1.bitmapCacheKey == k2.bitmapCacheKey && k1.maskCacheKey == k2.maskCacheKey; } -inline uint qHash(const QWindowsCursorCacheKey &k, uint seed) Q_DECL_NOTHROW +inline uint qHash(const QWindowsPixmapCursorCacheKey &k, uint seed) Q_DECL_NOTHROW { - return (uint(k.shape) + uint(k.bitmapCacheKey) + uint(k.maskCacheKey)) ^ seed; + return (uint(k.bitmapCacheKey) + uint(k.maskCacheKey)) ^ seed; } -class QWindowsWindowCursor +class CursorHandle { + Q_DISABLE_COPY(CursorHandle) public: - QWindowsWindowCursor(); - explicit QWindowsWindowCursor(const QCursor &c); - ~QWindowsWindowCursor(); - QWindowsWindowCursor(const QWindowsWindowCursor &c); - QWindowsWindowCursor &operator=(const QWindowsWindowCursor &c); + explicit CursorHandle(HCURSOR hcursor = Q_NULLPTR) : m_hcursor(hcursor) {} + ~CursorHandle() + { + if (m_hcursor) + DestroyCursor(m_hcursor); + } - bool isNull() const; - QCursor cursor() const; - HCURSOR handle() const; + bool isNull() const { return !m_hcursor; } + HCURSOR handle() const { return m_hcursor; } private: - QSharedDataPointer<QWindowsWindowCursorData> m_data; + const HCURSOR m_hcursor; }; +typedef QSharedPointer<CursorHandle> CursorHandlePtr; + class QWindowsCursor : public QPlatformCursor { public: @@ -91,25 +89,44 @@ public: CursorSuppressed // Cursor suppressed by touch interaction (Windows 8). }; - QWindowsCursor(); + struct PixmapCursor { + explicit PixmapCursor(const QPixmap &pix = QPixmap(), const QPoint &h = QPoint()) : pixmap(pix), hotSpot(h) {} + + QPixmap pixmap; + QPoint hotSpot; + }; + + explicit QWindowsCursor(const QPlatformScreen *screen); void changeCursor(QCursor * widgetCursor, QWindow * widget) Q_DECL_OVERRIDE; QPoint pos() const Q_DECL_OVERRIDE; void setPos(const QPoint &pos) Q_DECL_OVERRIDE; - static HCURSOR createPixmapCursor(const QPixmap &pixmap, const QPoint &hotSpot); - static HCURSOR createSystemCursor(const QCursor &c); - static QCursor customCursor(Qt::CursorShape cursorShape); + static HCURSOR createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor = 1); + static HCURSOR createPixmapCursor(const PixmapCursor &pc, qreal scaleFactor = 1) { return createPixmapCursor(pc.pixmap, pc.hotSpot, scaleFactor); } + static PixmapCursor customCursor(Qt::CursorShape cursorShape, const QPlatformScreen *screen = Q_NULLPTR); + + static HCURSOR createCursorFromShape(Qt::CursorShape cursorShape, const QPlatformScreen *screen = Q_NULLPTR); static QPoint mousePosition(); static CursorState cursorState(); - QWindowsWindowCursor standardWindowCursor(Qt::CursorShape s = Qt::ArrowCursor); - QWindowsWindowCursor pixmapWindowCursor(const QCursor &c); + CursorHandlePtr standardWindowCursor(Qt::CursorShape s = Qt::ArrowCursor); + CursorHandlePtr pixmapWindowCursor(const QCursor &c); + + QPixmap dragDefaultCursor(Qt::DropAction action) const; private: - typedef QHash<QWindowsCursorCacheKey, QWindowsWindowCursor> CursorCache; + typedef QHash<Qt::CursorShape, CursorHandlePtr> StandardCursorCache; + typedef QHash<QWindowsPixmapCursorCacheKey, CursorHandlePtr> PixmapCursorCache; + + const QPlatformScreen *const m_screen; + StandardCursorCache m_standardCursorCache; + PixmapCursorCache m_pixmapCursorCache; - CursorCache m_cursorCache; + mutable QPixmap m_copyDragCursor; + mutable QPixmap m_moveDragCursor; + mutable QPixmap m_linkDragCursor; + mutable QPixmap m_ignoreDragCursor; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index da0ba27e3a..9211fd1320 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -360,6 +360,7 @@ public: QT_BEGIN_NAMESPACE +#ifndef QT_NO_DEBUG_STREAM /* Output UID (IID, CLSID) as C++ constants. * The constants are contained in the Windows SDK libs, but not for MinGW. */ static inline QString guidToString(const GUID &g) @@ -385,6 +386,7 @@ inline QDebug operator<<(QDebug d, const GUID &g) d << guidToString(g); return d; } +#endif // !QT_NO_DEBUG_STREAM // Return an allocated wchar_t array from a QString, reserve more memory if desired. static wchar_t *qStringToWCharArray(const QString &s, size_t reserveSize = 0) @@ -874,12 +876,12 @@ public: inline static QWindowsNativeFileDialogBase *create(QFileDialogOptions::AcceptMode am, const QWindowsFileDialogSharedData &data); - virtual void setWindowTitle(const QString &title); + void setWindowTitle(const QString &title) Q_DECL_OVERRIDE; inline void setMode(QFileDialogOptions::FileMode mode, QFileDialogOptions::AcceptMode acceptMode, QFileDialogOptions::FileDialogOptions options); inline void setDirectory(const QUrl &directory); inline void updateDirectory() { setDirectory(m_data.directory()); } inline QString directory() const; - virtual void doExec(HWND owner = 0); + void doExec(HWND owner = 0) Q_DECL_OVERRIDE; virtual void setNameFilters(const QStringList &f); inline void selectNameFilter(const QString &filter); inline void updateSelectedNameFilter() { selectNameFilter(m_data.selectedNameFilter()); } @@ -908,7 +910,7 @@ signals: void filterSelected(const QString & filter); public slots: - virtual void close(); + void close() Q_DECL_OVERRIDE; protected: explicit QWindowsNativeFileDialogBase(const QWindowsFileDialogSharedData &data); @@ -1458,9 +1460,9 @@ class QWindowsNativeSaveFileDialog : public QWindowsNativeFileDialogBase public: explicit QWindowsNativeSaveFileDialog(const QWindowsFileDialogSharedData &data) : QWindowsNativeFileDialogBase(data) {} - virtual void setNameFilters(const QStringList &f); - virtual QList<QUrl> selectedFiles() const; - virtual QList<QUrl> dialogResult() const; + void setNameFilters(const QStringList &f) Q_DECL_OVERRIDE; + QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE; + QList<QUrl> dialogResult() const Q_DECL_OVERRIDE; }; // Return the first suffix from the name filter "Foo files (*.foo;*.bar)" -> "foo". @@ -1529,8 +1531,8 @@ class QWindowsNativeOpenFileDialog : public QWindowsNativeFileDialogBase public: explicit QWindowsNativeOpenFileDialog(const QWindowsFileDialogSharedData &data) : QWindowsNativeFileDialogBase(data) {} - virtual QList<QUrl> selectedFiles() const; - virtual QList<QUrl> dialogResult() const; + QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE; + QList<QUrl> dialogResult() const Q_DECL_OVERRIDE; private: inline IFileOpenDialog *openFileDialog() const @@ -1614,7 +1616,7 @@ public: virtual QString selectedNameFilter() const Q_DECL_OVERRIDE; private: - virtual QWindowsNativeDialogBase *createNativeDialog(); + QWindowsNativeDialogBase *createNativeDialog() Q_DECL_OVERRIDE; inline QWindowsNativeFileDialogBase *nativeFileDialog() const { return static_cast<QWindowsNativeFileDialogBase *>(nativeDialog()); } @@ -1742,14 +1744,13 @@ public: static QWindowsXpNativeFileDialog *create(const OptionsPtr &options, const QWindowsFileDialogSharedData &data); - virtual void setWindowTitle(const QString &t) { m_title = t; } - virtual void doExec(HWND owner = 0); - virtual QPlatformDialogHelper::DialogCode result() const { return m_result; } + void setWindowTitle(const QString &t) Q_DECL_OVERRIDE { m_title = t; } + void doExec(HWND owner = 0) Q_DECL_OVERRIDE; int existingDirCallback(HWND hwnd, UINT uMsg, LPARAM lParam); public slots: - virtual void close() {} + void close() Q_DECL_OVERRIDE {} private: typedef BOOL (APIENTRY *PtrGetOpenFileNameW)(LPOPENFILENAMEW); @@ -1985,19 +1986,19 @@ class QWindowsXpFileDialogHelper : public QWindowsDialogHelperBase<QPlatformFile { public: QWindowsXpFileDialogHelper() {} - virtual bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const { return false; } - virtual bool defaultNameFilterDisables() const + bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const Q_DECL_OVERRIDE { return false; } + bool defaultNameFilterDisables() const Q_DECL_OVERRIDE { return true; } - virtual void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE; - virtual QUrl directory() const Q_DECL_OVERRIDE; - virtual void selectFile(const QUrl &url) Q_DECL_OVERRIDE; - virtual QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE; - virtual void setFilter() Q_DECL_OVERRIDE {} - virtual void selectNameFilter(const QString &) Q_DECL_OVERRIDE; - virtual QString selectedNameFilter() const Q_DECL_OVERRIDE; + void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE; + QUrl directory() const Q_DECL_OVERRIDE; + void selectFile(const QUrl &url) Q_DECL_OVERRIDE; + QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE; + void setFilter() Q_DECL_OVERRIDE {} + void selectNameFilter(const QString &) Q_DECL_OVERRIDE; + QString selectedNameFilter() const Q_DECL_OVERRIDE; private: - virtual QWindowsNativeDialogBase *createNativeDialog(); + QWindowsNativeDialogBase *createNativeDialog() Q_DECL_OVERRIDE; inline QWindowsXpNativeFileDialog *nativeFileDialog() const { return static_cast<QWindowsXpNativeFileDialog *>(nativeDialog()); } @@ -2071,14 +2072,13 @@ public: explicit QWindowsNativeColorDialog(const SharedPointerColor &color); - virtual void setWindowTitle(const QString &) {} - virtual QPlatformDialogHelper::DialogCode result() const { return m_code; } + void setWindowTitle(const QString &) Q_DECL_OVERRIDE {} public slots: - virtual void close() {} + void close() Q_DECL_OVERRIDE {} private: - virtual void doExec(HWND owner = 0); + void doExec(HWND owner = 0) Q_DECL_OVERRIDE; COLORREF m_customColors[CustomColorCount]; QPlatformDialogHelper::DialogCode m_code; diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index 03438e3ee2..16079576a2 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -33,7 +33,7 @@ #include "qwindowsdrag.h" #include "qwindowscontext.h" -#include "qwindowsscaling.h" +#include "qwindowsscreen.h" #ifndef QT_NO_CLIPBOARD # include "qwindowsclipboard.h" #endif @@ -43,7 +43,6 @@ #include "qwindowswindow.h" #include "qwindowsmousehandler.h" #include "qwindowscursor.h" -#include "qwindowsscaling.h" #include <QtGui/QMouseEvent> #include <QtGui/QPixmap> @@ -52,6 +51,7 @@ #include <QtGui/QGuiApplication> #include <qpa/qwindowsysteminterface_p.h> #include <QtGui/private/qguiapplication_p.h> +#include <QtGui/private/qhighdpiscaling_p.h> #include <QtCore/QDebug> #include <QtCore/QBuffer> @@ -78,7 +78,7 @@ public: void setPixmap(const QPixmap &p); protected: - void paintEvent(QPaintEvent *) + void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE { QPainter painter(this); painter.drawPixmap(0, 0, m_pixmap); @@ -218,23 +218,14 @@ public: STDMETHOD(GiveFeedback)(DWORD dwEffect); private: - class DragCursorHandle { - Q_DISABLE_COPY(DragCursorHandle) - public: - DragCursorHandle(HCURSOR c) : cursor(c) {} - ~DragCursorHandle() { DestroyCursor(cursor); } - const HCURSOR cursor; - }; - typedef QSharedPointer<DragCursorHandle> DragCursorHandlePtr; - struct CursorEntry { CursorEntry() : cacheKey(0) {} - CursorEntry(const QPixmap &p, qint64 cK, const DragCursorHandlePtr &c, const QPoint &h) : + CursorEntry(const QPixmap &p, qint64 cK, const CursorHandlePtr &c, const QPoint &h) : pixmap(p), cacheKey(cK), cursor(c), hotSpot(h) {} QPixmap pixmap; qint64 cacheKey; // Cache key of cursor - DragCursorHandlePtr cursor; + CursorHandlePtr cursor; QPoint hotSpot; }; @@ -249,7 +240,7 @@ private: QWindowsDragCursorWindow *m_touchDragWindow; ULONG m_refs; -#ifndef QT_NO_DEBUG_OUTPUT +#ifndef QT_NO_DEBUG_STREAM friend QDebug operator<<(QDebug, const QWindowsOleDropSource::CursorEntry &); #endif }; @@ -271,14 +262,14 @@ QWindowsOleDropSource::~QWindowsOleDropSource() qCDebug(lcQpaMime) << __FUNCTION__; } -#ifndef QT_NO_DEBUG_OUTPUT +#ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const QWindowsOleDropSource::CursorEntry &e) { d << "CursorEntry:" << e.pixmap.size() << '#' << e.cacheKey - << "HCURSOR" << e.cursor->cursor << "hotspot:" << e.hotSpot; + << "HCURSOR" << e.cursor->handle() << "hotspot:" << e.hotSpot; return d; } -#endif // !QT_NO_DEBUG_OUTPUT +#endif // !QT_NO_DEBUG_STREAM /*! \brief Blend custom pixmap with cursors. @@ -289,24 +280,37 @@ void QWindowsOleDropSource::createCursors() const QDrag *drag = m_drag->currentDrag(); const QPixmap pixmap = drag->pixmap(); const bool hasPixmap = !pixmap.isNull(); - const int scaleFactor = QWindowsScaling::factor(); - const QSize pixmapSizeDp = pixmap.size() * scaleFactor; + + // Find screen for drag. Could be obtained from QDrag::source(), but that might be a QWidget. + + qreal scaleFactor = 1; + QPlatformCursor *platformCursor = Q_NULLPTR; + if (const QPlatformScreen *platformScreen = QWindowsContext::instance()->screenManager().screenAtDp(QWindowsCursor::mousePosition())) { + scaleFactor = QHighDpiScaling::factor(platformScreen); + platformCursor = platformScreen->cursor(); + } + if (!platformCursor && QGuiApplication::primaryScreen()) + platformCursor = QGuiApplication::primaryScreen()->handle()->cursor(); + const bool scalePixmap = hasPixmap && m_mode != TouchDrag // Touch drag: pixmap is shown in a separate QWindow, which will be scaled. && (scaleFactor != 1 && scaleFactor != qRound(pixmap.devicePixelRatio())); - const QPixmap drawPixmap = scalePixmap - ? pixmap.scaled(pixmapSizeDp, Qt::KeepAspectRatio, Qt::SmoothTransformation) : pixmap; - + const QPixmap scaledPixmap = scalePixmap + ? pixmap.scaled((QSizeF(pixmap.size()) * scaleFactor).toSize(), + Qt::KeepAspectRatio, Qt::SmoothTransformation) + : pixmap; Qt::DropAction actions[] = { Qt::MoveAction, Qt::CopyAction, Qt::LinkAction, Qt::IgnoreAction }; int actionCount = int(sizeof(actions) / sizeof(actions[0])); if (!hasPixmap) --actionCount; // No Qt::IgnoreAction unless pixmap - const QPoint hotSpot = drag->hotSpot() * scaleFactor; + const QPoint hotSpot = scalePixmap + ? (QPointF(drag->hotSpot()) * scaleFactor).toPoint() + : drag->hotSpot(); for (int cnum = 0; cnum < actionCount; ++cnum) { const Qt::DropAction action = actions[cnum]; QPixmap cursorPixmap = drag->dragCursor(action); - if (cursorPixmap.isNull()) - cursorPixmap = m_drag->defaultCursor(action); + if (cursorPixmap.isNull() && platformCursor) + cursorPixmap = static_cast<QWindowsCursor *>(platformCursor)->dragDefaultCursor(action); const qint64 cacheKey = cursorPixmap.cacheKey(); const ActionCursorMapIt it = m_cursors.find(action); if (it != m_cursors.end() && it.value().cacheKey == cacheKey) @@ -321,21 +325,21 @@ void QWindowsOleDropSource::createCursors() if (hasPixmap) { const int x1 = qMin(-hotSpot.x(), 0); - const int x2 = qMax(pixmapSizeDp.width() - hotSpot.x(), cursorPixmap.width()); + const int x2 = qMax(scaledPixmap.width() - hotSpot.x(), cursorPixmap.width()); const int y1 = qMin(-hotSpot.y(), 0); - const int y2 = qMax(pixmapSizeDp.height() - hotSpot.y(), cursorPixmap.height()); + const int y2 = qMax(scaledPixmap.height() - hotSpot.y(), cursorPixmap.height()); QPixmap newCursor(x2 - x1 + 1, y2 - y1 + 1); newCursor.fill(Qt::transparent); QPainter p(&newCursor); const QPoint pmDest = QPoint(qMax(0, -hotSpot.x()), qMax(0, -hotSpot.y())); - p.drawPixmap(pmDest, drawPixmap); + p.drawPixmap(pmDest, scaledPixmap); p.drawPixmap(qMax(0, hotSpot.x()),qMax(0, hotSpot.y()), cursorPixmap); newPixmap = newCursor; newHotSpot = QPoint(qMax(0, hotSpot.x()), qMax(0, hotSpot.y())); } if (const HCURSOR sysCursor = QWindowsCursor::createPixmapCursor(newPixmap, newHotSpot)) { - const CursorEntry entry(newPixmap, cacheKey, DragCursorHandlePtr(new DragCursorHandle(sysCursor)), newHotSpot); + const CursorEntry entry(newPixmap, cacheKey, CursorHandlePtr(new CursorHandle(sysCursor)), newHotSpot); if (it == m_cursors.end()) m_cursors.insert(action, entry); else @@ -448,13 +452,13 @@ QWindowsOleDropSource::GiveFeedback(DWORD dwEffect) const CursorEntry &e = it.value(); switch (m_mode) { case MouseDrag: - SetCursor(e.cursor->cursor); + SetCursor(e.cursor->handle()); break; case TouchDrag: if (!m_touchDragWindow) m_touchDragWindow = new QWindowsDragCursorWindow; m_touchDragWindow->setPixmap(e.pixmap); - m_touchDragWindow->setFramePosition((QWindowsCursor::mousePosition() - e.hotSpot) / QWindowsScaling::factor()); + m_touchDragWindow->setFramePosition(QWindowsCursor::mousePosition() - e.hotSpot); if (!m_touchDragWindow->isVisible()) m_touchDragWindow->show(); break; @@ -530,9 +534,7 @@ void QWindowsOleDropTarget::handleDrag(QWindow *window, DWORD grfKeyState, QGuiApplicationPrivate::mouse_buttons = QWindowsMouseHandler::keyStateToMouseButtons(grfKeyState); const QPlatformDragQtResponse response = - QWindowSystemInterface::handleDrag(window, windowsDrag->dropData(), - m_lastPoint / QWindowsScaling::factor(), - actions); + QWindowSystemInterface::handleDrag(window, windowsDrag->dropData(), m_lastPoint, actions); m_answerRect = response.answerRect(); const Qt::DropAction action = response.acceptedAction(); @@ -625,9 +627,8 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState, const QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(m_window, windowsDrag->dropData(), - m_lastPoint / QWindowsScaling::factor(), + m_lastPoint, translateToQDragDropActions(*pdwEffect)); - if (response.isAccepted()) { const Qt::DropAction action = response.acceptedAction(); if (action == Qt::MoveAction || action == Qt::TargetMoveAction) { @@ -706,94 +707,6 @@ IDropTargetHelper* QWindowsDrag::dropHelper() { return m_cachedDropTargetHelper; } -QPixmap QWindowsDrag::defaultCursor(Qt::DropAction action) const -{ - switch (action) { - case Qt::CopyAction: - if (m_copyDragCursor.isNull()) - m_copyDragCursor = QWindowsCursor::customCursor(Qt::DragCopyCursor).pixmap(); - return m_copyDragCursor; - case Qt::TargetMoveAction: - case Qt::MoveAction: - if (m_moveDragCursor.isNull()) - m_moveDragCursor = QWindowsCursor::customCursor(Qt::DragMoveCursor).pixmap(); - return m_moveDragCursor; - case Qt::LinkAction: - if (m_linkDragCursor.isNull()) - m_linkDragCursor = QWindowsCursor::customCursor(Qt::DragLinkCursor).pixmap(); - return m_linkDragCursor; - default: - break; - } - - static const char * const ignoreDragCursorXpmC[] = { - "24 30 3 1", - ". c None", - "a c #000000", - "X c #FFFFFF", - "aa......................", - "aXa.....................", - "aXXa....................", - "aXXXa...................", - "aXXXXa..................", - "aXXXXXa.................", - "aXXXXXXa................", - "aXXXXXXXa...............", - "aXXXXXXXXa..............", - "aXXXXXXXXXa.............", - "aXXXXXXaaaa.............", - "aXXXaXXa................", - "aXXaaXXa................", - "aXa..aXXa...............", - "aa...aXXa...............", - "a.....aXXa..............", - "......aXXa.....XXXX.....", - ".......aXXa..XXaaaaXX...", - ".......aXXa.XaaaaaaaaX..", - "........aa.XaaaXXXXaaaX.", - "...........XaaaaX..XaaX.", - "..........XaaXaaaX..XaaX", - "..........XaaXXaaaX.XaaX", - "..........XaaX.XaaaXXaaX", - "..........XaaX..XaaaXaaX", - "...........XaaX..XaaaaX.", - "...........XaaaXXXXaaaX.", - "............XaaaaaaaaX..", - ".............XXaaaaXX...", - "...............XXXX....."}; - - if (m_ignoreDragCursor.isNull()) { -#if !defined (Q_OS_WINCE) - HCURSOR cursor = LoadCursor(NULL, IDC_NO); - ICONINFO iconInfo = {0, 0, 0, 0, 0}; - GetIconInfo(cursor, &iconInfo); - BITMAP bmColor = {0, 0, 0, 0, 0, 0, 0}; - - if (iconInfo.hbmColor - && GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bmColor) - && bmColor.bmWidth == bmColor.bmWidthBytes / 4) { - const int colorBitsLength = bmColor.bmHeight * bmColor.bmWidthBytes; - uchar *colorBits = new uchar[colorBitsLength]; - GetBitmapBits(iconInfo.hbmColor, colorBitsLength, colorBits); - const QImage colorImage(colorBits, bmColor.bmWidth, bmColor.bmHeight, - bmColor.bmWidthBytes, QImage::Format_ARGB32); - - m_ignoreDragCursor = QPixmap::fromImage(colorImage); - delete [] colorBits; - } else { - m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC); - } - - DeleteObject(iconInfo.hbmMask); - DeleteObject(iconInfo.hbmColor); - DestroyCursor(cursor); -#else // !Q_OS_WINCE - m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC); -#endif // !Q_OS_WINCE - } - return m_ignoreDragCursor; -} - Qt::DropAction QWindowsDrag::drag(QDrag *drag) { // TODO: Accessibility handling? diff --git a/src/plugins/platforms/windows/qwindowsdrag.h b/src/plugins/platforms/windows/qwindowsdrag.h index 9a5e0b17f2..890ad6c142 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.h +++ b/src/plugins/platforms/windows/qwindowsdrag.h @@ -42,6 +42,9 @@ struct IDropTargetHelper; QT_BEGIN_NAMESPACE + +class QPlatformScreen; + class QWindowsDropMimeData : public QWindowsInternalMimeData { public: QWindowsDropMimeData() {} @@ -95,18 +98,11 @@ public: IDropTargetHelper* dropHelper(); - QPixmap defaultCursor(Qt::DropAction action) const; - private: QWindowsDropMimeData m_dropData; IDataObject *m_dropDataObject; IDropTargetHelper* m_cachedDropTargetHelper; - - mutable QPixmap m_copyDragCursor; - mutable QPixmap m_moveDragCursor; - mutable QPixmap m_linkDragCursor; - mutable QPixmap m_ignoreDragCursor; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index f2547d5cdd..65a9763be6 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -39,7 +39,7 @@ #include <QtGui/QOpenGLContext> #if defined(QT_OPENGL_ES_2_ANGLE) || defined(QT_OPENGL_DYNAMIC) -# include <QtANGLE/EGL/eglext.h> +# include <EGL/eglext.h> #endif QT_BEGIN_NAMESPACE @@ -118,11 +118,11 @@ void *QWindowsLibEGL::resolve(const char *name) bool QWindowsLibEGL::init() { -#ifdef QT_DEBUG - const char dllName[] = "libEGLd.dll"; -#else - const char dllName[] = "libEGL.dll"; + const char dllName[] = QT_STRINGIFY(LIBEGL_NAME) +#if defined(QT_DEBUG) && !defined(Q_OS_WINCE) + "d" #endif + ""; qCDebug(lcQpaGl) << "Qt: Using EGL from" << dllName; @@ -178,11 +178,12 @@ void *QWindowsLibGLESv2::resolve(const char *name) bool QWindowsLibGLESv2::init() { -#ifdef QT_DEBUG - const char dllName[] = "libGLESv2d.dll"; -#else - const char dllName[] = "libGLESv2.dll"; + + const char dllName[] = QT_STRINGIFY(LIBGLESV2_NAME) +#if defined(QT_DEBUG) && !defined(Q_OS_WINCE) + "d" #endif + ""; qCDebug(lcQpaGl) << "Qt: Using OpenGL ES 2.0 from" << dllName; #if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC) @@ -350,16 +351,16 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester: { const HDC dc = QWindowsContext::instance()->displayContext(); if (!dc){ - qWarning("%s: No Display", Q_FUNC_INFO); + qWarning("%s: No Display", __FUNCTION__); return 0; } if (!libEGL.init()) { - qWarning("%s: Failed to load and resolve libEGL functions", Q_FUNC_INFO); + qWarning("%s: Failed to load and resolve libEGL functions", __FUNCTION__); return 0; } if (!libGLESv2.init()) { - qWarning("%s: Failed to load and resolve libGLESv2 functions", Q_FUNC_INFO); + qWarning("%s: Failed to load and resolve libGLESv2 functions", __FUNCTION__); return 0; } @@ -396,15 +397,15 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester: if (display == EGL_NO_DISPLAY) display = libEGL.eglGetDisplay((EGLNativeDisplayType)dc); if (!display) { - qWarning("%s: Could not obtain EGL display", Q_FUNC_INFO); + qWarning("%s: Could not obtain EGL display", __FUNCTION__); return 0; } if (!major && !libEGL.eglInitialize(display, &major, &minor)) { int err = libEGL.eglGetError(); - qWarning("%s: Could not initialize EGL display: error 0x%x\n", Q_FUNC_INFO, err); + 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", Q_FUNC_INFO); + qWarning("%s: When using ANGLE, check if d3dcompiler_4x.dll is available", __FUNCTION__); return 0; } @@ -430,7 +431,7 @@ void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *na (EGLNativeWindowType) nativeWindow, 0); if (surface == EGL_NO_SURFACE) { *err = libEGL.eglGetError(); - qWarning("%s: Could not create the EGL window surface: 0x%x\n", Q_FUNC_INFO, *err); + qWarning("%s: Could not create the EGL window surface: 0x%x", __FUNCTION__, *err); } return surface; @@ -533,7 +534,12 @@ QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext, } if (m_eglContext == EGL_NO_CONTEXT) { - qWarning("QWindowsEGLContext: eglError: %x, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this); + int err = QWindowsEGLStaticContext::libEGL.eglGetError(); + qWarning("QWindowsEGLContext: Failed to create context, eglError: %x, this: %p", err, this); + // ANGLE gives bad alloc when it fails to reset a previously lost D3D device. + // A common cause for this is disabling the graphics adapter used by the app. + if (err == EGL_BAD_ALLOC) + qWarning("QWindowsEGLContext: Graphics device lost. (Did the adapter get disabled?)"); return; } @@ -594,6 +600,12 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface) if (err == EGL_CONTEXT_LOST) { m_eglContext = EGL_NO_CONTEXT; qCDebug(lcQpaGl) << "Got EGL context lost in createWindowSurface() for context" << this; + } else if (err == EGL_BAD_ACCESS) { + // With ANGLE this means no (D3D) device and can happen when disabling/changing graphics adapters. + qCDebug(lcQpaGl) << "Bad access (missing device?) in createWindowSurface() for context" << this; + // Simulate context loss as the context is useless. + QWindowsEGLStaticContext::libEGL.eglDestroyContext(m_eglDisplay, m_eglContext); + m_eglContext = EGL_NO_CONTEXT; } return false; } @@ -623,7 +635,7 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface) // Drop the surface. Will recreate on the next makeCurrent. window->invalidateSurface(); } else { - qWarning("QWindowsEGLContext::makeCurrent: eglError: %x, this: %p \n", err, this); + qWarning("%s: Failed to make surface current. eglError: %x, this: %p", __FUNCTION__, err, this); } } @@ -635,7 +647,8 @@ void QWindowsEGLContext::doneCurrent() QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api); bool ok = QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (!ok) - qWarning("QWindowsEGLContext::doneCurrent: eglError: %d, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this); + qWarning("%s: Failed to make no context/surface current. eglError: %d, this: %p", __FUNCTION__, + QWindowsEGLStaticContext::libEGL.eglGetError(), this); } void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface) @@ -653,8 +666,15 @@ void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface) } bool ok = QWindowsEGLStaticContext::libEGL.eglSwapBuffers(m_eglDisplay, eglSurface); - if (!ok) - qWarning("QWindowsEGLContext::swapBuffers: eglError: %d, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this); + if (!ok) { + err = QWindowsEGLStaticContext::libEGL.eglGetError(); + if (err == EGL_CONTEXT_LOST) { + m_eglContext = EGL_NO_CONTEXT; + qCDebug(lcQpaGl) << "Got EGL context lost in eglSwapBuffers()"; + } else { + qWarning("%s: Failed to swap buffers. eglError: %d, this: %p", __FUNCTION__, err, this); + } + } } QFunctionPointer QWindowsEGLContext::getProcAddress(const QByteArray &procName) diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index 3b27964b0e..8a2fbe1f6d 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -40,11 +40,13 @@ #include <QtGui/QFont> #include <QtGui/QGuiApplication> +#include <QtGui/private/qhighdpiscaling_p.h> #include <QtCore/qmath.h> #include <QtCore/QDebug> #include <QtCore/QtEndian> #include <QtCore/QThreadStorage> +#include <QtCore/private/qsystemlibrary_p.h> #include <wchar.h> @@ -59,6 +61,38 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_DIRECTWRITE +// ### fixme: Consider direct linking of dwrite.dll once Windows Vista pre SP2 is dropped (QTBUG-49711) + +typedef HRESULT (WINAPI *DWriteCreateFactoryType)(DWRITE_FACTORY_TYPE, const IID &, IUnknown **); + +static inline DWriteCreateFactoryType resolveDWriteCreateFactory() +{ + if (QSysInfo::windowsVersion() < QSysInfo::WV_VISTA) + return Q_NULLPTR; + QSystemLibrary library(QStringLiteral("dwrite")); + QFunctionPointer result = library.resolve("DWriteCreateFactory"); + if (Q_UNLIKELY(!result)) { + qWarning("Unable to load dwrite.dll"); + return Q_NULLPTR; + } + return reinterpret_cast<DWriteCreateFactoryType>(result); +} + +static IDWriteFactory *createDirectWriteFactory() +{ + static const DWriteCreateFactoryType dWriteCreateFactory = resolveDWriteCreateFactory(); + if (!dWriteCreateFactory) + return Q_NULLPTR; + IUnknown *result = Q_NULLPTR; + if (FAILED(dWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &result))) { + qErrnoWarning("DWriteCreateFactory failed"); + return Q_NULLPTR; + } + return reinterpret_cast<IDWriteFactory *>(result); +} +#endif // !QT_NO_DIRECTWRITE + // Helper classes for creating font engines directly from font data namespace { @@ -465,14 +499,9 @@ namespace { class CustomFontFileLoader { public: - CustomFontFileLoader() : m_directWriteFactory(0), m_directWriteFontFileLoader(0) + CustomFontFileLoader() : m_directWriteFactory(createDirectWriteFactory()), m_directWriteFontFileLoader(0) { - HRESULT hres = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, - __uuidof(IDWriteFactory), - reinterpret_cast<IUnknown **>(&m_directWriteFactory)); - if (FAILED(hres)) { - qErrnoWarning(hres, "%s: DWriteCreateFactory failed.", __FUNCTION__); - } else { + if (m_directWriteFactory) { m_directWriteFontFileLoader = new DirectWriteFontFileLoader(); m_directWriteFactory->RegisterFontFileLoader(m_directWriteFontFileLoader); } @@ -570,15 +599,9 @@ qreal QWindowsFontDatabase::fontSmoothingGamma() static inline bool initDirectWrite(QWindowsFontEngineData *d) { if (!d->directWriteFactory) { - const HRESULT hr = DWriteCreateFactory( - DWRITE_FACTORY_TYPE_SHARED, - __uuidof(IDWriteFactory), - reinterpret_cast<IUnknown **>(&d->directWriteFactory) - ); - if (FAILED(hr)) { - qErrnoWarning("%s: DWriteCreateFactory failed", __FUNCTION__); + d->directWriteFactory = createDirectWriteFactory(); + if (!d->directWriteFactory) return false; - } } if (!d->directWriteGdiInterop) { const HRESULT hr = d->directWriteFactory->GetGdiInterop(&d->directWriteGdiInterop); @@ -606,6 +629,7 @@ static inline bool initDirectWrite(QWindowsFontEngineData *d) \ingroup qt-lighthouse-win */ +#ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const QFontDef &def) { QDebugStateSaver saver(d); @@ -617,6 +641,7 @@ QDebug operator<<(QDebug d, const QFontDef &def) << def.hintingPreference; return d; } +#endif // !QT_NO_DEBUG_STREAM static inline QFontDatabase::WritingSystem writingSystemFromCharSet(uchar charSet) { @@ -1098,8 +1123,11 @@ QFontEngine *QWindowsFontDatabase::fontEngine(const QByteArray &fontData, qreal QFontEngine *fontEngine = 0; #if !defined(QT_NO_DIRECTWRITE) - if (hintingPreference == QFont::PreferDefaultHinting - || hintingPreference == QFont::PreferFullHinting) + bool useDirectWrite = (hintingPreference == QFont::PreferNoHinting) + || (hintingPreference == QFont::PreferVerticalHinting) + || (QHighDpiScaling::isActive() && hintingPreference == QFont::PreferDefaultHinting); + + if (!useDirectWrite) #endif { GUID guid; @@ -1211,11 +1239,13 @@ QT_WARNING_POP fontFile->Release(); - fontEngine = new QWindowsFontEngineDirectWrite(directWriteFontFace, pixelSize, + fontEngine = new QWindowsFontEngineDirectWrite(directWriteFontFace, + pixelSize, fontEngineData); // Get font family from font data fontEngine->fontDef.family = font.familyName(); + fontEngine->fontDef.hintingPreference = hintingPreference; directWriteFontFace->Release(); } @@ -1702,7 +1732,8 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, #if !defined(QT_NO_DIRECTWRITE) bool useDirectWrite = (request.hintingPreference == QFont::PreferNoHinting) - || (request.hintingPreference == QFont::PreferVerticalHinting); + || (request.hintingPreference == QFont::PreferVerticalHinting) + || (QHighDpiScaling::isActive() && request.hintingPreference == QFont::PreferDefaultHinting); if (useDirectWrite && initDirectWrite(data.data())) { const QString fam = QString::fromWCharArray(lf.lfFaceName); const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(fam); diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.h b/src/plugins/platforms/windows/qwindowsfontdatabase.h index efb5421996..10b6315aab 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.h +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.h @@ -118,6 +118,10 @@ private: QMap<QString, UniqueFontData> m_uniqueFontData; }; +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug, const QFontDef &def); +#endif + QT_END_NAMESPACE #endif // QWINDOWSFONTDATABASE_H diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp index 795554698c..684c44acf2 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp @@ -194,7 +194,14 @@ typedef struct { quint16 stringOffset; } NAME_RECORD; -static QString fontNameFromTTFile(const QString &filename) +typedef struct { + quint32 tag; + quint16 majorVersion; + quint16 minorVersion; + quint32 numFonts; +} TTC_TABLE_HEADER; + +static QString fontNameFromTTFile(const QString &filename, int startPos = 0) { QFile f(filename); QString retVal; @@ -202,6 +209,7 @@ static QString fontNameFromTTFile(const QString &filename) qint64 bytesToRead; if (f.open(QIODevice::ReadOnly)) { + f.seek(startPos); OFFSET_TABLE ttOffsetTable; bytesToRead = sizeof(OFFSET_TABLE); bytesRead = f.read((char*)&ttOffsetTable, bytesToRead); @@ -282,6 +290,37 @@ static QString fontNameFromTTFile(const QString &filename) return retVal; } +static QStringList fontNamesFromTTCFile(const QString &filename) +{ + QFile f(filename); + QStringList retVal; + qint64 bytesRead; + qint64 bytesToRead; + + if (f.open(QIODevice::ReadOnly)) { + TTC_TABLE_HEADER ttcTableHeader; + bytesToRead = sizeof(TTC_TABLE_HEADER); + bytesRead = f.read((char*)&ttcTableHeader, bytesToRead); + if (bytesToRead != bytesRead) + return retVal; + ttcTableHeader.majorVersion = qFromBigEndian(ttcTableHeader.majorVersion); + ttcTableHeader.minorVersion = qFromBigEndian(ttcTableHeader.minorVersion); + ttcTableHeader.numFonts = qFromBigEndian(ttcTableHeader.numFonts); + + if (ttcTableHeader.majorVersion < 1 || ttcTableHeader.majorVersion > 2) + return retVal; + QVarLengthArray<quint32> offsetTable(ttcTableHeader.numFonts); + bytesToRead = sizeof(quint32) * ttcTableHeader.numFonts; + bytesRead = f.read((char*)offsetTable.data(), bytesToRead); + if (bytesToRead != bytesRead) + return retVal; + f.close(); + for (int i = 0; i < (int)ttcTableHeader.numFonts; ++i) + retVal << fontNameFromTTFile(filename, qFromBigEndian(offsetTable[i])); + } + return retVal; +} + static inline QString fontSettingsOrganization() { return QStringLiteral("Qt-Project"); } static inline QString fontSettingsApplication() { return QStringLiteral("Qtbase"); } static inline QString fontSettingsGroup() { return QStringLiteral("CEFontCache"); } @@ -308,20 +347,28 @@ static QString findFontFile(const QString &faceName) //empty the cache first, as it seems that it is dirty settings.remove(QString()); - QDirIterator it(QStringLiteral("/Windows"), QStringList(QStringLiteral("*.ttf")), QDir::Files | QDir::Hidden | QDir::System); - + QDirIterator it(QStringLiteral("/Windows"), QStringList() << QStringLiteral("*.ttf") << QStringLiteral("*.ttc"), QDir::Files | QDir::Hidden | QDir::System); + const QLatin1Char lowerF('f'); + const QLatin1Char upperF('F'); while (it.hasNext()) { const QString fontFile = it.next(); - const QString fontName = fontNameFromTTFile(fontFile); - if (fontName.isEmpty()) - continue; - fontCache.insert(fontName, fontFile); - settings.setValue(fontName, fontFile); - - if (localizedName(fontName)) { - QString englishFontName = getEnglishName(fontName); - fontCache.insert(englishFontName, fontFile); - settings.setValue(englishFontName, fontFile); + QStringList fontNames; + const QChar c = fontFile[fontFile.size() - 1]; + if (c == lowerF || c == upperF) + fontNames << fontNameFromTTFile(fontFile); + else + fontNames << fontNamesFromTTCFile(fontFile); + foreach (const QString fontName, fontNames) { + if (fontName.isEmpty()) + continue; + fontCache.insert(fontName, fontFile); + settings.setValue(fontName, fontFile); + + if (localizedName(fontName)) { + QString englishFontName = getEnglishName(fontName); + fontCache.insert(englishFontName, fontFile); + settings.setValue(englishFontName, fontFile); + } } } settings.endGroup(); @@ -355,7 +402,7 @@ static bool addFontToDatabase(const QString &faceName, const QFont::Weight weight = QPlatformFontDatabase::weightFromInteger(tm->tmWeight); const QFont::Stretch stretch = QFont::Unstretched; -#ifndef QT_NO_DEBUG_OUTPUT +#ifndef QT_NO_DEBUG_STREAM if (QWindowsContext::verbose > 2) { QString message; QTextStream str(&message); @@ -677,7 +724,7 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QF result.append(QWindowsFontDatabase::extraTryFontsForFamily(family)); - result.append(QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script)); + result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script)); qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint << script << result; diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h index ad5c005ffa..f65dc38801 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h @@ -43,12 +43,15 @@ QT_BEGIN_NAMESPACE class QWindowsFontDatabaseFT : public QBasicFontDatabase { public: - void populateFontDatabase(); + void populateFontDatabase() Q_DECL_OVERRIDE; void populateFamily(const QString &familyName) Q_DECL_OVERRIDE; - QFontEngine *fontEngine(const QFontDef &fontDef, void *handle); - QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference); + QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE; + QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, + QFont::HintingPreference hintingPreference) Q_DECL_OVERRIDE; - QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const; + QStringList fallbacksForFamily(const QString &family, QFont::Style style, + QFont::StyleHint styleHint, + QChar::Script script) const Q_DECL_OVERRIDE; QString fontDir() const Q_DECL_OVERRIDE; QFont defaultFont() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp index 3685197430..30417f7cee 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.cpp +++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp @@ -1357,6 +1357,12 @@ QFontEngine *QWindowsMultiFontEngine::loadEngine(int at) QWindowsFontEngineDirectWrite *fedw = new QWindowsFontEngineDirectWrite(directWriteFontFace, fontEngine->fontDef.pixelSize, data); + if (fontEngine->fontDef.weight > QFont::Normal) + fedw->fontDef.weight = fontEngine->fontDef.weight; + if (fontEngine->fontDef.style > QFont::StyleNormal) + fedw->fontDef.style = fontEngine->fontDef.style; + fedw->fontDef.family = fam; + fedw->fontDef.hintingPreference = fontEngine->fontDef.hintingPreference; return fedw; } else { qErrnoWarning("%s: CreateFontFace failed", __FUNCTION__); @@ -1368,7 +1374,14 @@ QFontEngine *QWindowsMultiFontEngine::loadEngine(int at) // Get here if original font is not DirectWrite or DirectWrite creation failed for some // reason - return new QWindowsFontEngine(fam, lf, data); + QFontEngine *fe = new QWindowsFontEngine(fam, lf, data); + if (fontEngine->fontDef.weight > QFont::Normal) + fe->fontDef.weight = fontEngine->fontDef.weight; + if (fontEngine->fontDef.style > QFont::StyleNormal) + fe->fontDef.style = fontEngine->fontDef.style; + fe->fontDef.family = fam; + fe->fontDef.hintingPreference = fontEngine->fontDef.hintingPreference; + return fe; } bool QWindowsFontEngine::supportsTransformation(const QTransform &transform) const diff --git a/src/plugins/platforms/windows/qwindowsfontengine.h b/src/plugins/platforms/windows/qwindowsfontengine.h index 409b44264e..5317368455 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.h +++ b/src/plugins/platforms/windows/qwindowsfontengine.h @@ -84,7 +84,7 @@ public: void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE; virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, - QPainterPath *path, QTextItem::RenderFlags flags); + QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE; HGDIOBJ selectDesignFont() const; diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index 75449e22ed..a50ee60975 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -50,6 +50,7 @@ #include <QtCore/QtEndian> #include <QtCore/QVarLengthArray> #include <private/qstringiterator_p.h> +#include <QtCore/private/qsystemlibrary_p.h> #include <dwrite.h> #include <d2d1.h> @@ -196,8 +197,8 @@ namespace { */ QWindowsFontEngineDirectWrite::QWindowsFontEngineDirectWrite(IDWriteFontFace *directWriteFontFace, - qreal pixelSize, - const QSharedPointer<QWindowsFontEngineData> &d) + qreal pixelSize, + const QSharedPointer<QWindowsFontEngineData> &d) : QFontEngine(DirectWrite) , m_fontEngineData(d) , m_directWriteFontFace(directWriteFontFace) @@ -485,9 +486,9 @@ qreal QWindowsFontEngineDirectWrite::maxCharWidth() const return 0; } -QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) +QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) { - QImage im = imageForGlyph(glyph, subPixelPosition, 0, QTransform()); + QImage im = alphaRGBMapForGlyph(glyph, subPixelPosition, t); QImage alphaMap(im.width(), im.height(), QImage::Format_Alpha8); @@ -504,6 +505,11 @@ QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed sub return alphaMap; } +QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) +{ + return alphaMapForGlyph(glyph, subPixelPosition, QTransform()); +} + bool QWindowsFontEngineDirectWrite::supportsSubPixelPositions() const { return true; @@ -547,12 +553,17 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, transform.m21 = xform.m21(); transform.m22 = xform.m22(); + DWRITE_RENDERING_MODE renderMode = + fontDef.hintingPreference == QFont::PreferNoHinting + ? DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC + : DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL; + IDWriteGlyphRunAnalysis *glyphAnalysis = NULL; HRESULT hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis( &glyphRun, 1.0f, &transform, - DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC, + renderMode, DWRITE_MEASURING_MODE_NATURAL, 0.0, 0.0, &glyphAnalysis @@ -626,7 +637,8 @@ QImage QWindowsFontEngineDirectWrite::alphaRGBMapForGlyph(glyph_t t, QFontEngine *QWindowsFontEngineDirectWrite::cloneWithSize(qreal pixelSize) const { QFontEngine *fontEngine = new QWindowsFontEngineDirectWrite(m_directWriteFontFace, - pixelSize, m_fontEngineData); + pixelSize, + m_fontEngineData); fontEngine->fontDef = fontDef; fontEngine->fontDef.pixelSize = pixelSize; @@ -634,6 +646,16 @@ QFontEngine *QWindowsFontEngineDirectWrite::cloneWithSize(qreal pixelSize) const return fontEngine; } +// Dynamically resolve GetUserDefaultLocaleName, which is available from Windows +// Vista onwards. ### fixme 5.7: Consider reverting to direct linking. +typedef int (WINAPI *GetUserDefaultLocaleNamePtr)(LPWSTR, int); + +static inline GetUserDefaultLocaleNamePtr resolveGetUserDefaultLocaleName() +{ + QSystemLibrary library(QStringLiteral("kernel32")); + return (GetUserDefaultLocaleNamePtr)library.resolve("GetUserDefaultLocaleName"); +} + void QWindowsFontEngineDirectWrite::initFontInfo(const QFontDef &request, int dpi, IDWriteFont *font) { @@ -652,7 +674,9 @@ void QWindowsFontEngineDirectWrite::initFontInfo(const QFontDef &request, BOOL exists = false; wchar_t localeName[LOCALE_NAME_MAX_LENGTH]; - int defaultLocaleSuccess = GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH); + static const GetUserDefaultLocaleNamePtr getUserDefaultLocaleName = resolveGetUserDefaultLocaleName(); + const int defaultLocaleSuccess = getUserDefaultLocaleName + ? getUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH) : 0; if (defaultLocaleSuccess) hr = familyNames->FindLocaleName(localeName, &index, &exists); @@ -703,9 +727,9 @@ QString QWindowsFontEngineDirectWrite::fontNameSubstitute(const QString &familyN glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph, QFixed pos, const QTransform &matrix, GlyphFormat format) { Q_UNUSED(pos); - int margin = 0; - if (format == QFontEngine::Format_A32 || format == QFontEngine::Format_ARGB) - margin = glyphMargin(QFontEngine::Format_A32); + Q_UNUSED(format); + + int margin = glyphMargin(QFontEngine::Format_A32); glyph_metrics_t gm = QFontEngine::boundingBox(glyph, matrix); gm.width += margin * 2; gm.height += margin * 2; diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h index da772469e9..07e040ed33 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h @@ -61,34 +61,37 @@ public: void initFontInfo(const QFontDef &request, int dpi, IDWriteFont *font); - QFixed lineThickness() const; - QFixed underlinePosition() const; - bool getSfntTableData(uint tag, uchar *buffer, uint *length) const; - QFixed emSquareSize() const; + QFixed lineThickness() const Q_DECL_OVERRIDE; + QFixed underlinePosition() const Q_DECL_OVERRIDE; + bool getSfntTableData(uint tag, uchar *buffer, uint *length) const Q_DECL_OVERRIDE; + QFixed emSquareSize() const Q_DECL_OVERRIDE; glyph_t glyphIndex(uint ucs4) const Q_DECL_OVERRIDE; - bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const; - void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const; + bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, + ShaperFlags flags) const Q_DECL_OVERRIDE; + void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const Q_DECL_OVERRIDE; void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, - QPainterPath *path, QTextItem::RenderFlags flags); + QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE; - glyph_metrics_t boundingBox(const QGlyphLayout &glyphs); - glyph_metrics_t boundingBox(glyph_t g); - glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed, const QTransform &matrix, GlyphFormat); + glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) Q_DECL_OVERRIDE; + glyph_metrics_t boundingBox(glyph_t g) Q_DECL_OVERRIDE; + glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed, + const QTransform &matrix, GlyphFormat) Q_DECL_OVERRIDE; - QFixed ascent() const; - QFixed descent() const; - QFixed leading() const; - QFixed xHeight() const; - qreal maxCharWidth() const; + QFixed ascent() const Q_DECL_OVERRIDE; + QFixed descent() const Q_DECL_OVERRIDE; + QFixed leading() const Q_DECL_OVERRIDE; + QFixed xHeight() const Q_DECL_OVERRIDE; + qreal maxCharWidth() const Q_DECL_OVERRIDE; - bool supportsSubPixelPositions() const; + bool supportsSubPixelPositions() const Q_DECL_OVERRIDE; - QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition); - QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform); + QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) Q_DECL_OVERRIDE; + QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE; + QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform) Q_DECL_OVERRIDE; - QFontEngine *cloneWithSize(qreal pixelSize) const; + QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE; const QSharedPointer<QWindowsFontEngineData> &fontEngineData() const { return m_fontEngineData; } diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index a7c14ed2ac..8d33e2f0db 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -284,6 +284,7 @@ static inline void initPixelFormatDescriptor(PIXELFORMATDESCRIPTOR *d) d->nVersion = 1; } +#ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const PIXELFORMATDESCRIPTOR &pd) { QDebugStateSaver saver(d); @@ -326,6 +327,32 @@ QDebug operator<<(QDebug d, const PIXELFORMATDESCRIPTOR &pd) return d; } +QDebug operator<<(QDebug d, const QOpenGLStaticContext &s) +{ + QDebugStateSaver saver(d); + d.nospace(); + d << "OpenGL: " << s.vendor << ',' << s.renderer << " default " + << s.defaultFormat; + if (s.extensions & QOpenGLStaticContext::SampleBuffers) + d << ",SampleBuffers"; + if (s.hasExtensions()) + d << ", Extension-API present"; + d << "\nExtensions: " << (s.extensionNames.count(' ') + 1); + if (QWindowsContext::verbose > 1) + d << s.extensionNames; + return d; +} + +QDebug operator<<(QDebug d, const QWindowsOpenGLContextFormat &f) +{ + QDebugStateSaver saver(d); + d.nospace(); + d << "ContextFormat: v" << (f.version >> 8) << '.' << (f.version & 0xFF) + << " profile: " << f.profile << " options: " << f.options; + return d; +} +#endif // !QT_NO_DEBUG_STREAM + // Check whether an obtained PIXELFORMATDESCRIPTOR matches the request. static inline bool isAcceptableFormat(const QWindowsOpenGLAdditionalFormat &additional, @@ -436,7 +463,7 @@ static int choosePixelFormat(HDC hdc, const QSurfaceFormat &format, PIXELFORMATDESCRIPTOR *obtainedPfd) { if (QOpenGLStaticContext::opengl32.moduleIsNotOpengl32()) { - qWarning("%s: Attempted to use GDI functions with a non-opengl32.dll library", Q_FUNC_INFO); + qWarning("Attempted to use GDI functions with a non-opengl32.dll library"); return 0; } @@ -856,16 +883,11 @@ QWindowsOpenGLContextFormat QWindowsOpenGLContextFormat::current() { QWindowsOpenGLContextFormat result; const QByteArray version = QOpenGLStaticContext::getGlString(GL_VERSION); - const int majorDot = version.indexOf('.'); - if (majorDot != -1) { - int minorDot = version.indexOf('.', majorDot + 1); - if (minorDot == -1) - minorDot = version.size(); - result.version = (version.mid(0, majorDot).toInt() << 8) - + version.mid(majorDot + 1, minorDot - majorDot - 1).toInt(); - } else { + int major, minor; + if (QPlatformOpenGLContext::parseOpenGLVersion(version, major, minor)) + result.version = (major << 8) + minor; + else result.version = 0x0200; - } result.profile = QSurfaceFormat::NoProfile; if (result.version < 0x0300) { result.options |= QSurfaceFormat::DeprecatedFunctions; @@ -905,15 +927,6 @@ void QWindowsOpenGLContextFormat::apply(QSurfaceFormat *format) const format->setOption(QSurfaceFormat::DeprecatedFunctions); } -QDebug operator<<(QDebug d, const QWindowsOpenGLContextFormat &f) -{ - QDebugStateSaver saver(d); - d.nospace(); - d << "ContextFormat: v" << (f.version >> 8) << '.' << (f.version & 0xFF) - << " profile: " << f.profile << " options: " << f.options; - return d; -} - /*! \class QOpenGLTemporaryContext \brief A temporary context that can be instantiated on the stack. @@ -1005,7 +1018,7 @@ QByteArray QOpenGLStaticContext::getGlString(unsigned int which) QOpenGLStaticContext *QOpenGLStaticContext::create(bool softwareRendering) { if (!opengl32.init(softwareRendering)) { - qWarning("%s: Failed to load and resolve WGL/OpenGL functions", Q_FUNC_INFO); + qWarning("Failed to load and resolve WGL/OpenGL functions"); return 0; } @@ -1018,22 +1031,6 @@ QOpenGLStaticContext *QOpenGLStaticContext::create(bool softwareRendering) return result; } -QDebug operator<<(QDebug d, const QOpenGLStaticContext &s) -{ - QDebugStateSaver saver(d); - d.nospace(); - d << "OpenGL: " << s.vendor << ',' << s.renderer << " default " - << s.defaultFormat; - if (s.extensions & QOpenGLStaticContext::SampleBuffers) - d << ",SampleBuffers"; - if (s.hasExtensions()) - d << ", Extension-API present"; - d << "\nExtensions: " << (s.extensionNames.count(' ') + 1); - if (QWindowsContext::verbose > 1) - d << s.extensionNames; - return d; -} - /*! \class QWindowsGLContext \brief Open GL context. diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h index 516fa0707e..ba617f13ce 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.h +++ b/src/plugins/platforms/windows/qwindowsglcontext.h @@ -85,7 +85,11 @@ struct QWindowsOpenGLContextFormat QSurfaceFormat::FormatOptions options; }; +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const PIXELFORMATDESCRIPTOR &); QDebug operator<<(QDebug d, const QWindowsOpenGLContextFormat &); +QDebug operator<<(QDebug d, const QOpenGLStaticContext &s); +#endif struct QWindowsOpengl32DLL { @@ -224,8 +228,6 @@ public: static QWindowsOpengl32DLL opengl32; }; -QDebug operator<<(QDebug d, const QOpenGLStaticContext &); - class QWindowsGLContext : public QWindowsOpenGLContext { public: diff --git a/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp b/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp deleted file mode 100644 index 0bfa0239aa..0000000000 --- a/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch> -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwindowsguieventdispatcher.h" -#include "qwindowscontext.h" - -#include <qpa/qwindowsysteminterface.h> - -#include <QtCore/QCoreApplication> -#include <QtCore/QStack> -#include <QtCore/QDebug> - -#include <windowsx.h> - -QT_BEGIN_NAMESPACE - -/*! - \class QWindowsGuiEventDispatcher - \brief Event dispatcher for Windows - - Maintains a global stack storing the current event dispatcher and - its processing flags for access from the Windows procedure - qWindowsWndProc. Handling the Lighthouse gui events should be done - from within the qWindowsWndProc to ensure correct processing of messages. - - \internal - \ingroup qt-lighthouse-win -*/ - -QWindowsGuiEventDispatcher::QWindowsGuiEventDispatcher(QObject *parent) : - QEventDispatcherWin32(parent), m_flags(0) -{ - setObjectName(QStringLiteral("QWindowsGuiEventDispatcher")); - createInternalHwnd(); // QTBUG-40881: Do not delay registering timers, etc. for QtMfc. -} - -bool QWindowsGuiEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) -{ - const QEventLoop::ProcessEventsFlags oldFlags = m_flags; - m_flags = flags; - if (QWindowsContext::verbose > 2 && lcQpaEvents().isDebugEnabled()) - qCDebug(lcQpaEvents) << '>' << __FUNCTION__ << objectName() << flags; - const bool rc = QEventDispatcherWin32::processEvents(flags); - if (QWindowsContext::verbose > 2 && lcQpaEvents().isDebugEnabled()) - qCDebug(lcQpaEvents) << '<' << __FUNCTION__ << "returns" << rc; - m_flags = oldFlags; - return rc; -} - -void QWindowsGuiEventDispatcher::sendPostedEvents() -{ - QEventDispatcherWin32::sendPostedEvents(); - QWindowSystemInterface::sendWindowSystemEvents(m_flags); -} - -// Helpers for printing debug output for WM_* messages. -struct MessageDebugEntry -{ - UINT message; - const char *description; - bool interesting; -}; - -static const MessageDebugEntry -messageDebugEntries[] = { - {WM_CREATE, "WM_CREATE", true}, - {WM_PAINT, "WM_PAINT", true}, - {WM_CLOSE, "WM_CLOSE", true}, - {WM_DESTROY, "WM_DESTROY", true}, - {WM_MOVE, "WM_MOVE", true}, - {WM_SIZE, "WM_SIZE", true}, - {WM_MOUSEACTIVATE,"WM_MOUSEACTIVATE", true}, - {WM_CHILDACTIVATE, "WM_CHILDACTIVATE", true}, - {WM_PARENTNOTIFY, "WM_PARENTNOTIFY", true}, - {WM_ENTERIDLE, "WM_ENTERIDLE", false}, - {WM_GETICON, "WM_GETICON", false}, - {WM_KEYDOWN, "WM_KEYDOWN", true}, - {WM_SYSKEYDOWN, "WM_SYSKEYDOWN", true}, - {WM_SYSCOMMAND, "WM_SYSCOMMAND", true}, - {WM_KEYUP, "WM_KEYUP", true}, - {WM_SYSKEYUP, "WM_SYSKEYUP", true}, -#if defined(WM_APPCOMMAND) - {WM_APPCOMMAND, "WM_APPCOMMAND", true}, -#endif - {WM_IME_CHAR, "WM_IMECHAR", true}, - {WM_IME_KEYDOWN, "WM_IMECHAR", true}, - {WM_CANCELMODE, "WM_CANCELMODE", true}, - {WM_CHAR, "WM_CHAR", true}, - {WM_DEADCHAR, "WM_DEADCHAR", true}, - {WM_ACTIVATE, "WM_ACTIVATE", true}, - {WM_GETMINMAXINFO, "WM_GETMINMAXINFO", true}, - {WM_SETFOCUS, "WM_SETFOCUS", true}, - {WM_KILLFOCUS, "WM_KILLFOCUS", true}, - {WM_ENABLE, "WM_ENABLE", true}, - {WM_SHOWWINDOW, "WM_SHOWWINDOW", true}, - {WM_WINDOWPOSCHANGING, "WM_WINDOWPOSCHANGING", true}, - {WM_WINDOWPOSCHANGED, "WM_WINDOWPOSCHANGED", true}, - {WM_SETCURSOR, "WM_SETCURSOR", false}, - {WM_GETFONT, "WM_GETFONT", true}, - {WM_NCMOUSEMOVE, "WM_NCMOUSEMOVE", true}, - {WM_LBUTTONDOWN, "WM_LBUTTONDOWN", true}, - {WM_LBUTTONUP, "WM_LBUTTONUP", true}, - {WM_LBUTTONDBLCLK, "WM_LBUTTONDBLCLK", true}, - {WM_RBUTTONDOWN, "WM_RBUTTONDOWN", true}, - {WM_RBUTTONUP, "WM_RBUTTONUP", true}, - {WM_RBUTTONDBLCLK, "WM_RBUTTONDBLCLK", true}, - {WM_MBUTTONDOWN, "WM_MBUTTONDOWN", true}, - {WM_MBUTTONUP, "WM_MBUTTONUP", true}, - {WM_MBUTTONDBLCLK, "WM_MBUTTONDBLCLK", true}, - {WM_MOUSEWHEEL, "WM_MOUSEWHEEL", true}, - {WM_XBUTTONDOWN, "WM_XBUTTONDOWN", true}, - {WM_XBUTTONUP, "WM_XBUTTONUP", true}, - {WM_XBUTTONDBLCLK, "WM_XBUTTONDBLCLK", true}, - {WM_MOUSEHWHEEL, "WM_MOUSEHWHEEL", true}, - {WM_NCCREATE, "WM_NCCREATE", true}, - {WM_NCCALCSIZE, "WM_NCCALCSIZE", true}, - {WM_NCACTIVATE, "WM_NCACTIVATE", true}, - {WM_NCMOUSELEAVE, "WM_NCMOUSELEAVE", true}, - {WM_NCLBUTTONDOWN, "WM_NCLBUTTONDOWN", true}, - {WM_NCLBUTTONUP, "WM_NCLBUTTONUP", true}, - {WM_ACTIVATEAPP, "WM_ACTIVATEAPP", true}, - {WM_NCPAINT, "WM_NCPAINT", true}, - {WM_ERASEBKGND, "WM_ERASEBKGND", true}, - {WM_MOUSEMOVE, "WM_MOUSEMOVE", true}, - {WM_MOUSELEAVE, "WM_MOUSELEAVE", true}, - {WM_NCHITTEST, "WM_NCHITTEST", false}, - {WM_IME_SETCONTEXT, "WM_IME_SETCONTEXT", true}, - {WM_INPUTLANGCHANGE, "WM_INPUTLANGCHANGE", true}, - {WM_IME_NOTIFY, "WM_IME_NOTIFY", true}, -#if defined(WM_DWMNCRENDERINGCHANGED) - {WM_DWMNCRENDERINGCHANGED, "WM_DWMNCRENDERINGCHANGED", true}, -#endif - {WM_IME_SETCONTEXT, "WM_IME_SETCONTEXT", true}, - {WM_IME_NOTIFY, "WM_IME_NOTIFY", true}, - {WM_TOUCH, "WM_TOUCH", true}, - {WM_CHANGECBCHAIN, "WM_CHANGECBCHAIN", true}, - {WM_DRAWCLIPBOARD, "WM_DRAWCLIPBOARD", true}, - {WM_RENDERFORMAT, "WM_RENDERFORMAT", true}, - {WM_RENDERALLFORMATS, "WM_RENDERALLFORMATS", true}, - {WM_DESTROYCLIPBOARD, "WM_DESTROYCLIPBOARD", true}, - {WM_CAPTURECHANGED, "WM_CAPTURECHANGED", true}, - {WM_IME_STARTCOMPOSITION, "WM_IME_STARTCOMPOSITION", true}, - {WM_IME_COMPOSITION, "WM_IME_COMPOSITION", true}, - {WM_IME_ENDCOMPOSITION, "WM_IME_ENDCOMPOSITION", true}, - {WM_IME_NOTIFY, "WM_IME_NOTIFY", true}, - {WM_IME_REQUEST, "WM_IME_REQUEST", true}, -#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) - {WM_QUERYENDSESSION, "WM_QUERYENDSESSION", true}, - {WM_ENDSESSION, "WM_ENDSESSION", true}, -#endif - {WM_DISPLAYCHANGE, "WM_DISPLAYCHANGE", true}, - {WM_THEMECHANGED, "WM_THEMECHANGED", true} -}; - -static inline const MessageDebugEntry *messageDebugEntry(UINT msg) -{ - for (size_t i = 0; i < sizeof(messageDebugEntries)/sizeof(MessageDebugEntry); i++) - if (messageDebugEntries[i].message == msg) - return messageDebugEntries + i; - return 0; -} - -const char *QWindowsGuiEventDispatcher::windowsMessageName(UINT msg) -{ - if (const MessageDebugEntry *e = messageDebugEntry(msg)) - return e->description; - return "Unknown"; -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsguieventdispatcher.h b/src/plugins/platforms/windows/qwindowsguieventdispatcher.h deleted file mode 100644 index 3389139461..0000000000 --- a/src/plugins/platforms/windows/qwindowsguieventdispatcher.h +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWINDOWSGUIEVENTDISPATCHER_H -#define QWINDOWSGUIEVENTDISPATCHER_H - -#include "qtwindows_additional.h" - -#include <QtCore/private/qeventdispatcher_win_p.h> - -QT_BEGIN_NAMESPACE - -class QWindowsGuiEventDispatcher : public QEventDispatcherWin32 -{ - Q_OBJECT -public: - explicit QWindowsGuiEventDispatcher(QObject *parent = 0); - - static const char *windowsMessageName(UINT msg); - - bool QT_ENSURE_STACK_ALIGNED_FOR_SSE processEvents(QEventLoop::ProcessEventsFlags flags) Q_DECL_OVERRIDE; - void sendPostedEvents() Q_DECL_OVERRIDE; - -private: - QEventLoop::ProcessEventsFlags m_flags; -}; - -QT_END_NAMESPACE - -#endif // QWINDOWSGUIEVENTDISPATCHER_H diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index 68e38dc4a6..56b5561756 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -36,7 +36,6 @@ #include "qwindowswindow.h" #include "qwindowsintegration.h" #include "qwindowsmousehandler.h" -#include "qwindowsscaling.h" #include <QtCore/QDebug> #include <QtCore/QObject> @@ -85,6 +84,18 @@ static inline void imeNotifyCancelComposition(HWND hwnd) ImmReleaseContext(hwnd, himc); } +static inline LCID languageIdFromLocaleId(LCID localeId) +{ + return localeId & 0xFFFF; +} + +static inline LCID currentInputLanguageId() +{ + return languageIdFromLocaleId(reinterpret_cast<quintptr>(GetKeyboardLayout(0))); +} + +Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id); // from qlocale_win.cpp + /*! \class QWindowsInputContext \brief Windows Input context implementation @@ -154,7 +165,9 @@ QWindowsInputContext::CompositionContext::CompositionContext() : QWindowsInputContext::QWindowsInputContext() : m_WM_MSIME_MOUSE(RegisterWindowMessage(L"MSIMEMouseOperation")), - m_endCompositionRecursionGuard(false) + m_endCompositionRecursionGuard(false), + m_languageId(currentInputLanguageId()), + m_locale(qt_localeFromLCID(m_languageId)) { connect(QGuiApplication::inputMethod(), &QInputMethod::cursorRectangleChanged, this, &QWindowsInputContext::cursorRectChanged); @@ -220,21 +233,24 @@ void QWindowsInputContext::updateEnabled() const bool accepted = inputMethodAccepted(); if (QWindowsContext::verbose > 1) qCDebug(lcQpaInputMethods) << __FUNCTION__ << window << "accepted=" << accepted; - if (accepted) { - // Re-enable IME by associating default context saved on first disabling. - if (platformWindow->testFlag(QWindowsWindow::InputMethodDisabled)) { - ImmAssociateContext(platformWindow->handle(), QWindowsInputContext::m_defaultContext); - platformWindow->clearFlag(QWindowsWindow::InputMethodDisabled); - } - } else { - // Disable IME by associating 0 context. Store context first time. - if (!platformWindow->testFlag(QWindowsWindow::InputMethodDisabled)) { - const HIMC oldImC = ImmAssociateContext(platformWindow->handle(), 0); - platformWindow->setFlag(QWindowsWindow::InputMethodDisabled); - if (!QWindowsInputContext::m_defaultContext && oldImC) - QWindowsInputContext::m_defaultContext = oldImC; - } - } + QWindowsInputContext::setWindowsImeEnabled(platformWindow, accepted); + } +} + +void QWindowsInputContext::setWindowsImeEnabled(QWindowsWindow *platformWindow, bool enabled) +{ + if (!platformWindow || platformWindow->testFlag(QWindowsWindow::InputMethodDisabled) == !enabled) + return; + if (enabled) { + // Re-enable Windows IME by associating default context saved on first disabling. + ImmAssociateContext(platformWindow->handle(), QWindowsInputContext::m_defaultContext); + platformWindow->clearFlag(QWindowsWindow::InputMethodDisabled); + } else { + // Disable Windows IME by associating 0 context. Store context first time. + const HIMC oldImC = ImmAssociateContext(platformWindow->handle(), 0); + platformWindow->setFlag(QWindowsWindow::InputMethodDisabled); + if (!QWindowsInputContext::m_defaultContext && oldImC) + QWindowsInputContext::m_defaultContext = oldImC; } } @@ -254,10 +270,9 @@ void QWindowsInputContext::cursorRectChanged() if (!m_compositionContext.hwnd) return; const QInputMethod *inputMethod = QGuiApplication::inputMethod(); - const QRect cursorRectangleDip = inputMethod->cursorRectangle().toRect(); - if (!cursorRectangleDip.isValid()) + const QRect cursorRectangle = inputMethod->cursorRectangle().toRect(); + if (!cursorRectangle.isValid()) return; - const QRect cursorRectangle = QWindowsScaling::mapToNative(cursorRectangleDip); qCDebug(lcQpaInputMethods) << __FUNCTION__<< cursorRectangle; @@ -308,11 +323,6 @@ void QWindowsInputContext::invokeAction(QInputMethod::Action action, int cursorP ImmReleaseContext(m_compositionContext.hwnd, himc); } -QWindowsInputContext *QWindowsInputContext::instance() -{ - return static_cast<QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext()); -} - static inline QString getCompositionString(HIMC himc, DWORD dwIndex) { enum { bufferSize = 256 }; @@ -375,7 +385,7 @@ bool QWindowsInputContext::startComposition(HWND hwnd) QWindow *window = QGuiApplication::focusWindow(); if (!window) return false; - qCDebug(lcQpaInputMethods) << __FUNCTION__ << fo << window; + qCDebug(lcQpaInputMethods) << __FUNCTION__ << fo << window << "language=" << m_languageId; if (!fo || QWindowsWindow::handleOf(window) != hwnd) return false; initContext(hwnd, fo); @@ -474,7 +484,8 @@ bool QWindowsInputContext::composition(HWND hwnd, LPARAM lParamIn) if (lParam & GCS_RESULTSTR) { // A fixed result, return the converted string event->setCommitString(getCompositionString(himc, GCS_RESULTSTR)); - endContextComposition(); + if (!(lParam & GCS_DELTASTART)) + endContextComposition(); } const bool result = QCoreApplication::sendEvent(m_compositionContext.focusObject, event.data()); qCDebug(lcQpaInputMethods) << '<' << __FUNCTION__ << "sending markup=" @@ -559,6 +570,21 @@ bool QWindowsInputContext::handleIME_Request(WPARAM wParam, return false; } +void QWindowsInputContext::handleInputLanguageChanged(WPARAM wparam, LPARAM lparam) +{ + const LCID newLanguageId = languageIdFromLocaleId(lparam); + if (newLanguageId == m_languageId) + return; + const LCID oldLanguageId = m_languageId; + m_languageId = newLanguageId; + m_locale = qt_localeFromLCID(m_languageId); + emitLocaleChanged(); + + qCDebug(lcQpaInputMethods) << __FUNCTION__ << hex << showbase + << oldLanguageId << "->" << newLanguageId << "Character set:" + << DWORD(wparam) << dec << noshowbase << m_locale; +} + /*! \brief Determines the string for reconversion with selection. diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.h b/src/plugins/platforms/windows/qwindowsinputcontext.h index 110986c20c..636d481e70 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.h +++ b/src/plugins/platforms/windows/qwindowsinputcontext.h @@ -36,12 +36,14 @@ #include "qtwindows_additional.h" +#include <QtCore/QLocale> #include <QtCore/QPointer> #include <qpa/qplatforminputcontext.h> QT_BEGIN_NAMESPACE class QInputMethodEvent; +class QWindowsWindow; class QWindowsInputContext : public QPlatformInputContext { @@ -62,14 +64,16 @@ public: explicit QWindowsInputContext(); ~QWindowsInputContext(); + static void setWindowsImeEnabled(QWindowsWindow *platformWindow, bool enabled); + bool hasCapability(Capability capability) const Q_DECL_OVERRIDE; + QLocale locale() const Q_DECL_OVERRIDE { return m_locale; } + void reset() Q_DECL_OVERRIDE; void update(Qt::InputMethodQueries) Q_DECL_OVERRIDE; void invokeAction(QInputMethod::Action, int cursorPosition) Q_DECL_OVERRIDE; void setFocusObject(QObject *object) Q_DECL_OVERRIDE; - static QWindowsInputContext *instance(); - bool startComposition(HWND hwnd); bool composition(HWND hwnd, LPARAM lParam); bool endComposition(HWND hwnd); @@ -78,6 +82,7 @@ public: int reconvertString(RECONVERTSTRING *reconv); bool handleIME_Request(WPARAM wparam, LPARAM lparam, LRESULT *result); + void handleInputLanguageChanged(WPARAM wparam, LPARAM lparam); private slots: void cursorRectChanged(); @@ -93,6 +98,8 @@ private: static HIMC m_defaultContext; CompositionContext m_compositionContext; bool m_endCompositionRecursionGuard; + LCID m_languageId; + QLocale m_locale; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 089c3cd0fe..bd2014b8f2 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -33,7 +33,6 @@ ****************************************************************************/ #include "qwindowsintegration.h" -#include "qwindowsscaling.h" #include "qwindowswindow.h" #include "qwindowscontext.h" #include "qwindowsopenglcontext.h" @@ -45,7 +44,6 @@ # include "qwindowsfontdatabase_ft.h" #endif #include "qwindowsfontdatabase.h" -#include "qwindowsguieventdispatcher.h" #ifndef QT_NO_CLIPBOARD # include "qwindowsclipboard.h" # ifndef QT_NO_DRAGANDDROP @@ -64,9 +62,11 @@ # include "qwindowssessionmanager.h" #endif #include <QtGui/private/qguiapplication_p.h> +#include <QtGui/private/qhighdpiscaling_p.h> #include <QtGui/qpa/qplatforminputcontextfactory_p.h> -#include <QtCore/private/qeventdispatcher_win_p.h> +#include <QtPlatformSupport/private/qwindowsguieventdispatcher_p.h> + #include <QtCore/QDebug> #include <QtCore/QVariant> @@ -223,12 +223,9 @@ QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList ¶mL m_context.setProcessDpiAwareness(dpiAwareness); dpiAwarenessSet = true; } - // Determine suitable scale factor, don't mix Windows and Qt scaling - if (dpiAwareness != QtWindows::ProcessDpiUnaware) - QWindowsScaling::setFactor(QWindowsScaling::determineUiScaleFactor()); qCDebug(lcQpaWindows) - << __FUNCTION__ << "DpiAwareness=" << dpiAwareness <<",Scaling=" - << QWindowsScaling::factor(); + << __FUNCTION__ << "DpiAwareness=" << dpiAwareness + << "effective process DPI awareness=" << QWindowsContext::processDpiAwareness(); m_context.initTouch(m_options); } @@ -258,10 +255,9 @@ QWindowsIntegration::~QWindowsIntegration() void QWindowsIntegration::initialize() { - if (QPlatformInputContext *pluginContext = QPlatformInputContextFactory::create()) - d->m_inputContext.reset(pluginContext); - else - d->m_inputContext.reset(new QWindowsInputContext); + QString icStr = QPlatformInputContextFactory::requested(); + icStr.isNull() ? d->m_inputContext.reset(new QWindowsInputContext) + : d->m_inputContext.reset(QPlatformInputContextFactory::create(icStr)); } bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) const @@ -287,17 +283,19 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co return true; case AllGLFunctionsQueryable: return true; + case SwitchableWidgetComposition: + return true; default: return QPlatformIntegration::hasCapability(cap); } return false; } -QWindowsWindowData QWindowsIntegration::createWindowData(QWindow *window) const +QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) const { QWindowsWindowData requested; requested.flags = window->flags(); - requested.geometry = QWindowsScaling::mapToNative(window->geometry()); + requested.geometry = QHighDpi::toNativePixels(window->geometry(), window); // Apply custom margins (see QWindowsWindow::setCustomMargins())). const QVariant customMarginsV = window->property("_q_windowsCustomMargins"); if (customMarginsV.isValid()) @@ -312,22 +310,30 @@ QWindowsWindowData QWindowsIntegration::createWindowData(QWindow *window) const << "\n Obtained : " << obtained.geometry << " margins=" << obtained.frame << " handle=" << obtained.hwnd << ' ' << obtained.flags << '\n'; - if (obtained.hwnd) { - if (requested.flags != obtained.flags) - window->setFlags(obtained.flags); - // Trigger geometry change signals of QWindow. - if ((obtained.flags & Qt::Desktop) != Qt::Desktop && requested.geometry != obtained.geometry) - QWindowSystemInterface::handleGeometryChange(window, QWindowsScaling::mapFromNative(obtained.geometry)); + if (Q_UNLIKELY(!obtained.hwnd)) + return Q_NULLPTR; + + QWindowsWindow *result = createPlatformWindowHelper(window, obtained); + Q_ASSERT(result); + + if (requested.flags != obtained.flags) + window->setFlags(obtained.flags); + // Trigger geometry/screen change signals of QWindow. + if ((obtained.flags & Qt::Desktop) != Qt::Desktop) { + if (requested.geometry != obtained.geometry) + QWindowSystemInterface::handleGeometryChange(window, obtained.geometry); + QPlatformScreen *screen = result->screenForGeometry(obtained.geometry); + if (screen && result->screen() != screen) + QWindowSystemInterface::handleWindowScreenChanged(window, screen->screen()); } - return obtained; + return result; } -QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) const +// Overridden to return a QWindowsDirect2DWindow in Direct2D plugin. +QWindowsWindow *QWindowsIntegration::createPlatformWindowHelper(QWindow *window, const QWindowsWindowData &data) const { - QWindowsWindowData data = createWindowData(window); - return data.hwnd ? new QWindowsWindow(window, data) - : Q_NULLPTR; + return new QWindowsWindow(window, data); } #ifndef QT_NO_OPENGL @@ -335,11 +341,18 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::doCreate() { #if defined(QT_OPENGL_DYNAMIC) + const QWindowsOpenGLTester::Renderers supportedRenderers = QWindowsOpenGLTester::supportedRenderers(); + QWindowsOpenGLTester::Renderer requestedRenderer = QWindowsOpenGLTester::requestedRenderer(); switch (requestedRenderer) { case QWindowsOpenGLTester::DesktopGl: - if (QWindowsStaticOpenGLContext *glCtx = QOpenGLStaticContext::create()) + if (QWindowsStaticOpenGLContext *glCtx = QOpenGLStaticContext::create()) { + if ((supportedRenderers & QWindowsOpenGLTester::DisableRotationFlag) + && !QWindowsScreen::setOrientationPreference(Qt::LandscapeOrientation)) { + qCWarning(lcQpaGl, "Unable to disable rotation."); + } return glCtx; + } qCWarning(lcQpaGl, "System OpenGL failed. Falling back to Software OpenGL."); return QOpenGLStaticContext::create(true); // If ANGLE is requested, use it, don't try anything else. @@ -360,10 +373,14 @@ QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::doCreate() break; } - const QWindowsOpenGLTester::Renderers supportedRenderers = QWindowsOpenGLTester::supportedRenderers(); if (supportedRenderers & QWindowsOpenGLTester::DesktopGl) { - if (QWindowsStaticOpenGLContext *glCtx = QOpenGLStaticContext::create()) + if (QWindowsStaticOpenGLContext *glCtx = QOpenGLStaticContext::create()) { + if ((supportedRenderers & QWindowsOpenGLTester::DisableRotationFlag) + && !QWindowsScreen::setOrientationPreference(Qt::LandscapeOrientation)) { + qCWarning(lcQpaGl, "Unable to disable rotation."); + } return glCtx; + } } if (QWindowsOpenGLTester::Renderers glesRenderers = supportedRenderers & QWindowsOpenGLTester::GlesMask) { if (QWindowsEGLStaticContext *eglCtx = QWindowsEGLStaticContext::create(glesRenderers)) diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h index fa5192ba03..da20d9261a 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.h +++ b/src/plugins/platforms/windows/qwindowsintegration.h @@ -60,13 +60,12 @@ public: explicit QWindowsIntegration(const QStringList ¶mList); virtual ~QWindowsIntegration(); - bool hasCapability(QPlatformIntegration::Capability cap) const; + bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; - QWindowsWindowData createWindowData(QWindow *window) const; - QPlatformWindow *createPlatformWindow(QWindow *window) const; + QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE; #ifndef QT_NO_OPENGL QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE; - QOpenGLContext::OpenGLModuleType openGLModuleType(); + QOpenGLContext::OpenGLModuleType openGLModuleType() Q_DECL_OVERRIDE; static QWindowsStaticOpenGLContext *staticOpenGLContext(); #endif QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE; @@ -84,7 +83,7 @@ public: QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE; QStringList themeNames() const Q_DECL_OVERRIDE; QPlatformTheme *createPlatformTheme(const QString &name) const Q_DECL_OVERRIDE; - QPlatformServices *services() const; + QPlatformServices *services() const Q_DECL_OVERRIDE; QVariant styleHint(StyleHint hint) const Q_DECL_OVERRIDE; Qt::KeyboardModifiers queryKeyboardModifiers() const Q_DECL_OVERRIDE; @@ -101,6 +100,9 @@ public: QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const Q_DECL_OVERRIDE; #endif +protected: + virtual QWindowsWindow *createPlatformWindowHelper(QWindow *window, const QWindowsWindowData &) const; + private: QScopedPointer<QWindowsIntegrationPrivate> d; diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index d47c7df9e0..c5dff60114 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -33,15 +33,16 @@ #include "qwindowskeymapper.h" #include "qwindowscontext.h" +#include "qwindowsintegration.h" #include "qwindowswindow.h" -#include "qwindowsguieventdispatcher.h" -#include "qwindowsscaling.h" #include "qwindowsinputcontext.h" #include <QtGui/QWindow> #include <qpa/qwindowsysteminterface.h> #include <private/qguiapplication_p.h> +#include <private/qhighdpiscaling_p.h> #include <QtGui/QKeyEvent> +#include <QtPlatformSupport/private/qwindowsguieventdispatcher_p.h> #if defined(WM_APPCOMMAND) # ifndef FAPPCOMMAND_MOUSE @@ -85,10 +86,15 @@ QT_BEGIN_NAMESPACE The code originates from \c qkeymapper_win.cpp. */ +static void clearKeyRecorderOnApplicationInActive(Qt::ApplicationState state); + QWindowsKeyMapper::QWindowsKeyMapper() : m_useRTLExtensions(false), m_keyGrabber(0) { memset(keyLayout, 0, sizeof(keyLayout)); + QGuiApplication *app = static_cast<QGuiApplication *>(QGuiApplication::instance()); + QObject::connect(app, &QGuiApplication::applicationStateChanged, + app, clearKeyRecorderOnApplicationInActive); } QWindowsKeyMapper::~QWindowsKeyMapper() @@ -143,6 +149,12 @@ struct KeyRecorder }; static KeyRecorder key_recorder; +static void clearKeyRecorderOnApplicationInActive(Qt::ApplicationState state) +{ + if (state == Qt::ApplicationInactive) + key_recorder.clearKeys(); +} + KeyRecord *KeyRecorder::findKey(int code, bool remove) { KeyRecord *result = 0; @@ -792,10 +804,12 @@ static void showSystemMenu(QWindow* w) #undef enabled #undef disabled #endif // !Q_OS_WINCE - const QPoint topLeft = topLevel->geometry().topLeft() * QWindowsScaling::factor(); + const QPoint pos = QHighDpi::toNativePixels(topLevel->geometry().topLeft(), topLevel); const int ret = TrackPopupMenuEx(menu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD, - topLeft.x(), topLeft.y(), topLevelHwnd, 0); + pos.x(), pos.y(), + topLevelHwnd, + 0); if (ret) qWindowsWndProc(topLevelHwnd, WM_SYSCOMMAND, ret, 0); } @@ -1072,7 +1086,9 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms // results, if we map this virtual key-code directly (for eg '?' US layouts). So try // to find the correct key using the current message parameters & keyboard state. if (uch.isNull() && msgType == WM_IME_KEYDOWN) { - if (!QWindowsInputContext::instance()->isComposing()) + const QWindowsInputContext *windowsInputContext = + qobject_cast<const QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext()); + if (!(windowsInputContext && windowsInputContext->isComposing())) vk_key = ImmGetVirtualKey((HWND)window->winId()); BYTE keyState[256]; wchar_t newKey[3] = {0}; diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp index 622352e987..171ace5c20 100644 --- a/src/plugins/platforms/windows/qwindowsmime.cpp +++ b/src/plugins/platforms/windows/qwindowsmime.cpp @@ -299,8 +299,6 @@ static bool qt_read_dibv5(QDataStream &s, QImage &image) return true; } -//#define QMIME_DEBUG - // helpers for using global memory static int getCf(const FORMATETC &formatetc) @@ -380,6 +378,73 @@ static bool canGetData(int cf, IDataObject * pDataObj) return true; } +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const FORMATETC &tc) +{ + QDebugStateSaver saver(d); + d.nospace(); + d << "FORMATETC(cfFormat=" << tc.cfFormat << ' '; + switch (tc.cfFormat) { + case CF_TEXT: + d << "CF_TEXT"; + break; + case CF_BITMAP: + d << "CF_BITMAP"; + break; + case CF_TIFF: + d << "CF_TIFF"; + break; + case CF_OEMTEXT: + d << "CF_OEMTEXT"; + break; + case CF_DIB: + d << "CF_DIB"; + break; + case CF_DIBV5: + d << "CF_DIBV5"; + break; + case CF_UNICODETEXT: + d << "CF_UNICODETEXT"; + break; +#ifndef Q_OS_WINCE + case CF_ENHMETAFILE: + d << "CF_ENHMETAFILE"; + break; +#endif // !Q_OS_WINCE + default: + d << QWindowsMimeConverter::clipboardFormatName(tc.cfFormat); + break; + } + d << ", dwAspect=" << tc.dwAspect << ", lindex=" << tc.lindex + << ", tymed=" << tc.tymed << ", ptd=" << tc.ptd << ')'; + return d; +} + +QDebug operator<<(QDebug d, IDataObject *dataObj) +{ + QDebugStateSaver saver(d); + d.nospace(); + d.noquote(); + d << "IDataObject("; + if (dataObj) { // Output formats contained in IDataObject. + IEnumFORMATETC *enumFormatEtc; + if (SUCCEEDED(dataObj->EnumFormatEtc(DATADIR_GET, &enumFormatEtc)) && enumFormatEtc) { + FORMATETC formatEtc[1]; + ULONG fetched; + if (SUCCEEDED(enumFormatEtc->Reset())) { + while (SUCCEEDED(enumFormatEtc->Next(1, formatEtc, &fetched)) && fetched) + d << formatEtc[0] << ','; + enumFormatEtc->Release(); + } + } + } else { + d << '0'; + } + d << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM + /*! \class QWindowsMime \brief The QWindowsMime class maps open-standard MIME to Window Clipboard formats. @@ -832,14 +897,14 @@ public: QWindowsMimeHtml(); // for converting from Qt - bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const; - bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const; - QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const; + bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const Q_DECL_OVERRIDE; + bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const Q_DECL_OVERRIDE; + QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const Q_DECL_OVERRIDE; // for converting to Qt - bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const; - QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const; - QString mimeForFormat(const FORMATETC &formatetc) const; + bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const Q_DECL_OVERRIDE; + QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const Q_DECL_OVERRIDE; + QString mimeForFormat(const FORMATETC &formatetc) const Q_DECL_OVERRIDE; private: int CF_HTML; @@ -894,11 +959,7 @@ QVariant QWindowsMimeHtml::convertToMime(const QString &mime, IDataObject *pData QVariant result; if (canConvertToMime(mime, pDataObj)) { QByteArray html = getData(CF_HTML, pDataObj); -#ifdef QMIME_DEBUG - qDebug("QWindowsMimeHtml::convertToMime"); - qDebug("raw :"); - qDebug(html); -#endif + qCDebug(lcQpaMime) << __FUNCTION__ << "raw:" << html; int start = html.indexOf("StartHTML:"); int end = html.indexOf("EndHTML:"); @@ -968,14 +1029,14 @@ class QWindowsMimeImage : public QWindowsMime public: QWindowsMimeImage(); // for converting from Qt - bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const; - bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const; - QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const; + bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const Q_DECL_OVERRIDE; + bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const Q_DECL_OVERRIDE; + QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const Q_DECL_OVERRIDE; // for converting to Qt - bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const; - QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const; - QString mimeForFormat(const FORMATETC &formatetc) const; + bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const Q_DECL_OVERRIDE; + QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const Q_DECL_OVERRIDE; + QString mimeForFormat(const FORMATETC &formatetc) const Q_DECL_OVERRIDE; private: bool hasOriginalDIBV5(IDataObject *pDataObj) const; UINT CF_PNG; @@ -996,6 +1057,8 @@ QVector<FORMATETC> QWindowsMimeImage::formatsForMime(const QString &mimeType, co formatetcs += setCf(CF_DIBV5); formatetcs += setCf(CF_DIB); } + if (!formatetcs.isEmpty()) + qCDebug(lcQpaMime) << __FUNCTION__ << mimeType << formatetcs; return formatetcs; } @@ -1120,14 +1183,14 @@ public: QBuiltInMimes(); // for converting from Qt - bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const; - bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const; - QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const; + bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const Q_DECL_OVERRIDE; + bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const Q_DECL_OVERRIDE; + QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const Q_DECL_OVERRIDE; // for converting to Qt - bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const; - QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const; - QString mimeForFormat(const FORMATETC &formatetc) const; + bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const Q_DECL_OVERRIDE; + QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const Q_DECL_OVERRIDE; + QString mimeForFormat(const FORMATETC &formatetc) const Q_DECL_OVERRIDE; private: QMap<int, QString> outFormats; @@ -1216,9 +1279,7 @@ QVariant QBuiltInMimes::convertToMime(const QString &mimeType, IDataObject *pDat if (canConvertToMime(mimeType, pDataObj)) { QByteArray data = getData(inFormats.key(mimeType), pDataObj); if (!data.isEmpty()) { -#ifdef QMIME_DEBUG - qDebug("QBuiltInMimes::convertToMime()"); -#endif + qCDebug(lcQpaMime) << __FUNCTION__; if (mimeType == QLatin1String("text/html") && preferredType == QVariant::String) { // text/html is in wide chars on windows (compatible with Mozilla) val = QString::fromWCharArray((const wchar_t *)data.data()); @@ -1242,14 +1303,14 @@ public: QLastResortMimes(); // for converting from Qt - bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const; - bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const; - QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const; + bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const Q_DECL_OVERRIDE; + bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const Q_DECL_OVERRIDE; + QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const Q_DECL_OVERRIDE; // for converting to Qt - bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const; - QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const; - QString mimeForFormat(const FORMATETC &formatetc) const; + bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const Q_DECL_OVERRIDE; + QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const Q_DECL_OVERRIDE; + QString mimeForFormat(const FORMATETC &formatetc) const Q_DECL_OVERRIDE; private: QMap<int, QString> formats; @@ -1326,6 +1387,8 @@ QVector<FORMATETC> QLastResortMimes::formatsForMime(const QString &mimeType, con that->formats.insert(cf, mimeType); formatetcs += setCf(cf); } + if (!formatetcs.isEmpty()) + qCDebug(lcQpaMime) << __FUNCTION__ << mimeType << formatetcs; return formatetcs; } static const char x_qt_windows_mime[] = "application/x-qt-windows-mime;value=\""; @@ -1400,11 +1463,8 @@ QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const if (!format.isEmpty()) return format; - wchar_t buffer[256]; - int len = GetClipboardFormatName(getCf(formatetc), buffer, 256); - - if (len) { - QString clipFormat = QString::fromWCharArray(buffer, len); + const QString clipFormat = QWindowsMimeConverter::clipboardFormatName(getCf(formatetc)); + if (!clipFormat.isEmpty()) { #ifndef QT_NO_DRAGANDDROP if (QInternalMimeData::canReadData(clipFormat)) format = clipFormat; @@ -1470,15 +1530,12 @@ QStringList QWindowsMimeConverter::allMimesForFormats(IDataObject *pDataObj) con if (hr == NOERROR) { FORMATETC fmtetc; while (S_OK == fmtenum->Next(1, &fmtetc, 0)) { -#if defined(QMIME_DEBUG) - wchar_t buf[256] = {0}; - GetClipboardFormatName(fmtetc.cfFormat, buf, 255); - qDebug("CF = %d : %s", fmtetc.cfFormat, qPrintable(QString::fromWCharArray(buf))); -#endif for (int i= m_mimes.size() - 1; i >= 0; --i) { QString format = m_mimes.at(i)->mimeForFormat(fmtetc); if (!format.isEmpty() && !formats.contains(format)) { formats += format; + if (QWindowsContext::verbose > 1 && lcQpaMime().isDebugEnabled()) + qCDebug(lcQpaMime) << __FUNCTION__ << fmtetc << format; } } // as documented in MSDN to avoid possible memleak @@ -1494,6 +1551,7 @@ QStringList QWindowsMimeConverter::allMimesForFormats(IDataObject *pDataObj) con QWindowsMime * QWindowsMimeConverter::converterFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const { ensureInitialized(); + qCDebug(lcQpaMime) << __FUNCTION__ << formatetc; for (int i = m_mimes.size()-1; i >= 0; --i) { if (m_mimes.at(i)->canConvertFromMime(formatetc, mimeData)) return m_mimes.at(i); @@ -1521,13 +1579,24 @@ QVector<FORMATETC> QWindowsMimeConverter::allFormatsForMime(const QMimeData *mim void QWindowsMimeConverter::ensureInitialized() const { if (m_mimes.isEmpty()) { - m_mimes << new QWindowsMimeImage << new QLastResortMimes + m_mimes +#ifndef QT_NO_IMAGEFORMAT_BMP + << new QWindowsMimeImage +#endif //QT_NO_IMAGEFORMAT_BMP + << new QLastResortMimes << new QWindowsMimeText << new QWindowsMimeURI << new QWindowsMimeHtml << new QBuiltInMimes; m_internalMimeCount = m_mimes.size(); } } +QString QWindowsMimeConverter::clipboardFormatName(int cf) +{ + wchar_t buf[256] = {0}; + return GetClipboardFormatName(cf, buf, 255) + ? QString::fromWCharArray(buf) : QString(); +} + QVariant QWindowsMimeConverter::convertToMime(const QStringList &mimeTypes, IDataObject *pDataObj, QVariant::Type preferredType, diff --git a/src/plugins/platforms/windows/qwindowsmime.h b/src/plugins/platforms/windows/qwindowsmime.h index 952410e14b..1ec0dccdf8 100644 --- a/src/plugins/platforms/windows/qwindowsmime.h +++ b/src/plugins/platforms/windows/qwindowsmime.h @@ -42,6 +42,7 @@ QT_BEGIN_NAMESPACE +class QDebug; class QMimeData; class QWindowsMime @@ -83,6 +84,8 @@ public: void registerMime(QWindowsMime *mime); void unregisterMime(QWindowsMime *mime) { m_mimes.removeOne(mime); } + static QString clipboardFormatName(int cf); + private: void ensureInitialized() const; @@ -90,6 +93,11 @@ private: mutable int m_internalMimeCount; }; +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug, const FORMATETC &); +QDebug operator<<(QDebug d, IDataObject *); +#endif + QT_END_NAMESPACE #endif // QWINDOWSMIME_H diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index e83354157b..e26010b5c4 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -218,10 +218,8 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, const QPoint globalPosition = winEventPosition; const QPoint clientPosition = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPosition); const Qt::MouseButtons buttons = QWindowsMouseHandler::queryMouseButtons(); - QWindowSystemInterface::handleFrameStrutMouseEvent(window, - clientPosition / QWindowsScaling::factor(), - globalPosition / QWindowsScaling::factor(), - buttons, + QWindowSystemInterface::handleFrameStrutMouseEvent(window, clientPosition, + globalPosition, buttons, QWindowsKeyMapper::queryKeyboardModifiers(), source); return false; // Allow further event processing (dragging of windows). @@ -286,7 +284,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, // ChildWindowFromPointEx() may not find the Qt window (failing with ERROR_ACCESS_DENIED) if (!currentWindowUnderMouse) { const QRect clientRect(QPoint(0, 0), window->size()); - if (clientRect.contains(winEventPosition / QWindowsScaling::factor())) + if (clientRect.contains(winEventPosition)) currentWindowUnderMouse = window; } @@ -373,14 +371,14 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, m_windowUnderMouse = currentWindowUnderMouse; } - QWindowSystemInterface::handleMouseEvent(window, - winEventPosition / QWindowsScaling::factor(), - globalPosition / QWindowsScaling::factor(), - buttons, + QWindowSystemInterface::handleMouseEvent(window, winEventPosition, globalPosition, buttons, QWindowsKeyMapper::queryKeyboardModifiers(), source); m_previousCaptureWindow = hasCapture ? window : 0; - return true; + // 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(); } static bool isValidWheelReceiver(QWindow *candidate) @@ -411,11 +409,9 @@ static void redirectWheelEvent(QWindow *window, const QPoint &globalPos, int del } if (handleEvent) { - const QPoint posDip = QWindowsGeometryHint::mapFromGlobal(receiver, globalPos) / QWindowsScaling::factor(); QWindowSystemInterface::handleWheelEvent(receiver, - posDip, globalPos / QWindowsScaling::factor(), - delta / QWindowsScaling::factor(), - orientation, mods); + QWindowsGeometryHint::mapFromGlobal(receiver, globalPos), + globalPos, delta, orientation, mods); } } @@ -492,7 +488,12 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, return true; } - const QRect screenGeometry = window->screen()->geometry(); + const QScreen *screen = window->screen(); + if (!screen) + screen = QGuiApplication::primaryScreen(); + if (!screen) + return true; + const QRect screenGeometry = screen->geometry(); const int winTouchPointCount = msg.wParam; QScopedArrayPointer<TOUCHINPUT> winTouchInputs(new TOUCHINPUT[winTouchPointCount]); @@ -503,7 +504,6 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, Qt::TouchPointStates allStates = 0; QWindowsContext::user32dll.getTouchInputInfo((HANDLE) msg.lParam, msg.wParam, winTouchInputs.data(), sizeof(TOUCHINPUT)); - const qreal screenPosFactor = 0.01 / qreal(QWindowsScaling::factor()); for (int i = 0; i < winTouchPointCount; ++i) { const TOUCHINPUT &winTouchInput = winTouchInputs[i]; int id = m_touchInputIDToTouchPointID.value(winTouchInput.dwID, -1); @@ -517,9 +517,9 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, if (m_lastTouchPositions.contains(id)) touchPoint.normalPosition = m_lastTouchPositions.value(id); - const QPointF screenPos = QPointF(winTouchInput.x, winTouchInput.y) * screenPosFactor; + const QPointF screenPos = QPointF(winTouchInput.x, winTouchInput.y) / qreal(100.); if (winTouchInput.dwMask & TOUCHINPUTMASKF_CONTACTAREA) - touchPoint.area.setSize(QSizeF(winTouchInput.cxContact, winTouchInput.cyContact) * screenPosFactor); + touchPoint.area.setSize(QSizeF(winTouchInput.cxContact, winTouchInput.cyContact) / qreal(100.)); touchPoint.area.moveCenter(screenPos); QPointF normalPosition = QPointF(screenPos.x() / screenGeometry.width(), screenPos.y() / screenGeometry.height()); @@ -583,7 +583,12 @@ bool QWindowsMouseHandler::translateGestureEvent(QWindow *window, HWND hwnd, if (gi.dwID != GID_DIRECTMANIPULATION) return true; static QPoint lastTouchPos; - const QRect screenGeometry = window->screen()->geometry(); + const QScreen *screen = window->screen(); + if (!screen) + screen = QGuiApplication::primaryScreen(); + if (!screen) + return true; + const QRect screenGeometry = screen->geometry(); QWindowSystemInterface::TouchPoint touchPoint; static QWindowSystemInterface::TouchPoint touchPoint2; touchPoint.id = 0;//gi.dwInstanceID; diff --git a/src/plugins/platforms/windows/qwindowsnativeimage.h b/src/plugins/platforms/windows/qwindowsnativeimage.h index 6f9ce93ef0..80a1de1ea5 100644 --- a/src/plugins/platforms/windows/qwindowsnativeimage.h +++ b/src/plugins/platforms/windows/qwindowsnativeimage.h @@ -57,8 +57,6 @@ public: HDC hdc() const { return m_hdc; } - void setDevicePixelRatio(qreal scaleFactor) { m_image.setDevicePixelRatio(scaleFactor); } - static QImage::Format systemFormat(); private: diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp index db8b2ec094..659ef79c18 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp @@ -234,6 +234,8 @@ QFunctionPointer QWindowsNativeInterface::platformFunction(const QByteArray &fun { if (function == QWindowsWindowFunctions::setTouchWindowTouchTypeIdentifier()) return QFunctionPointer(QWindowsWindow::setTouchWindowTouchTypeStatic); + else if (function == QWindowsWindowFunctions::setHasBorderInFullScreenIdentifier()) + return QFunctionPointer(QWindowsWindow::setHasBorderInFullScreenStatic); return Q_NULLPTR; } diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp index 6f5a521af8..e480c1ebcf 100644 --- a/src/plugins/platforms/windows/qwindowsole.cpp +++ b/src/plugins/platforms/windows/qwindowsole.cpp @@ -132,12 +132,6 @@ QWindowsOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) { HRESULT hr = ResultFromScode(DATA_E_FORMATETC); - if (QWindowsContext::verbose > 1 && lcQpaMime().isDebugEnabled()) { - wchar_t buf[256] = {0}; - GetClipboardFormatName(pformatetc->cfFormat, buf, 255); - qCDebug(lcQpaMime) <<__FUNCTION__ << "CF = " << pformatetc->cfFormat << QString::fromWCharArray(buf); - } - if (data) { const QWindowsMimeConverter &mc = QWindowsContext::instance()->mimeConverter(); if (QWindowsMime *converter = mc.converterFromMime(*pformatetc, data)) @@ -145,11 +139,8 @@ QWindowsOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) hr = ResultFromScode(S_OK); } - if (QWindowsContext::verbose > 1) { - wchar_t buf[256] = {0}; - GetClipboardFormatName(pformatetc->cfFormat, buf, 255); - qCDebug(lcQpaMime) <<__FUNCTION__ << "CF = " << pformatetc->cfFormat << " returns 0x" << int(hr) << dec; - } + if (QWindowsContext::verbose > 1 && lcQpaMime().isDebugEnabled()) + qCDebug(lcQpaMime) <<__FUNCTION__ << *pformatetc << "returns" << hex << showbase << quint64(hr); return hr; } @@ -211,7 +202,7 @@ STDMETHODIMP QWindowsOleDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc) { if (QWindowsContext::verbose > 1) - qCDebug(lcQpaMime) << __FUNCTION__; + qCDebug(lcQpaMime) << __FUNCTION__ << "dwDirection=" << dwDirection; if (!data) return ResultFromScode(DATA_E_FORMATETC); @@ -274,7 +265,7 @@ QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector<FORMATETC> &fmtetcs) m_dwRefs(1), m_nIndex(0), m_isNull(false) { if (QWindowsContext::verbose > 1) - qCDebug(lcQpaMime) << __FUNCTION__; + qCDebug(lcQpaMime) << __FUNCTION__ << fmtetcs; m_lpfmtetcs.reserve(fmtetcs.count()); for (int idx = 0; idx < fmtetcs.count(); ++idx) { LPFORMATETC destetc = new FORMATETC(); diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp index 9ebd946ce4..fcbe488f93 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.cpp +++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp @@ -98,6 +98,7 @@ GpuDescription GpuDescription::detect() #endif } +#ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const GpuDescription &gd) { QDebugStateSaver s(d); @@ -109,6 +110,7 @@ QDebug operator<<(QDebug d, const GpuDescription &gd) << ", version=" << gd.driverVersion << ", " << gd.description << ')'; return d; } +#endif // !QT_NO_DEBUG_STREAM // Return printable string formatted like the output of the dxdiag tool. QString GpuDescription::toString() const @@ -224,7 +226,7 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(c #elif defined(Q_OS_WINCE) return QWindowsOpenGLTester::Gles; #else - QOpenGLConfig::Gpu qgpu = QOpenGLConfig::Gpu::fromDevice(gpu.vendorId, gpu.deviceId, gpu.driverVersion); + QOpenGLConfig::Gpu qgpu = QOpenGLConfig::Gpu::fromDevice(gpu.vendorId, gpu.deviceId, gpu.driverVersion, gpu.description); SupportedRenderersCache *srCache = supportedRenderersCache(); SupportedRenderersCache::const_iterator it = srCache->find(qgpu); if (it != srCache->cend()) @@ -250,23 +252,26 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(c qCDebug(lcQpaGl) << "GPU features:" << features; if (features.contains(QStringLiteral("disable_desktopgl"))) { // Qt-specific - qCWarning(lcQpaGl) << "Disabling Desktop GL: " << gpu; + qCDebug(lcQpaGl) << "Disabling Desktop GL: " << gpu; result &= ~QWindowsOpenGLTester::DesktopGl; } if (features.contains(QStringLiteral("disable_angle"))) { // Qt-specific keyword - qCWarning(lcQpaGl) << "Disabling ANGLE: " << gpu; + qCDebug(lcQpaGl) << "Disabling ANGLE: " << gpu; result &= ~QWindowsOpenGLTester::GlesMask; } else { if (features.contains(QStringLiteral("disable_d3d11"))) { // standard keyword - qCWarning(lcQpaGl) << "Disabling D3D11: " << gpu; + qCDebug(lcQpaGl) << "Disabling D3D11: " << gpu; result &= ~QWindowsOpenGLTester::AngleRendererD3d11; } if (features.contains(QStringLiteral("disable_d3d9"))) { // Qt-specific - qCWarning(lcQpaGl) << "Disabling D3D9: " << gpu; + qCDebug(lcQpaGl) << "Disabling D3D9: " << gpu; result &= ~QWindowsOpenGLTester::AngleRendererD3d9; } } - + if (features.contains(QStringLiteral("disable_rotation"))) { + qCDebug(lcQpaGl) << "Disabling rotation: " << gpu; + result |= DisableRotationFlag; + } srCache->insert(qgpu, result); return result; #endif // !Q_OS_WINCE && !QT_NO_OPENGL diff --git a/src/plugins/platforms/windows/qwindowsopengltester.h b/src/plugins/platforms/windows/qwindowsopengltester.h index 748885542d..0fad3d960e 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.h +++ b/src/plugins/platforms/windows/qwindowsopengltester.h @@ -36,7 +36,7 @@ #include <QtCore/QByteArray> #include <QtCore/QFlags> -#include <private/qversionnumber_p.h> +#include <QtCore/qversionnumber.h> QT_BEGIN_NAMESPACE @@ -60,7 +60,9 @@ struct GpuDescription QByteArray description; }; +#ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const GpuDescription &gd); +#endif class QWindowsOpenGLTester { @@ -74,7 +76,9 @@ public: AngleBackendMask = AngleRendererD3d11 | AngleRendererD3d9 | AngleRendererD3d11Warp, Gles = 0x0010, // ANGLE/unspecified or Generic GLES for Windows CE. GlesMask = Gles | AngleBackendMask, - SoftwareRasterizer = 0x0020 + SoftwareRasterizer = 0x0020, + RendererMask = 0x00FF, + DisableRotationFlag = 0x0100 }; Q_DECLARE_FLAGS(Renderers, Renderer) diff --git a/src/plugins/platforms/windows/qwindowsscaling.cpp b/src/plugins/platforms/windows/qwindowsscaling.cpp deleted file mode 100644 index 6ab7f254fd..0000000000 --- a/src/plugins/platforms/windows/qwindowsscaling.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwindowsscaling.h" -#include "qwindowsscreen.h" - -#include <QtCore/QDebug> -#include <QtCore/QCoreApplication> - -QT_BEGIN_NAMESPACE - -/*! - \class QWindowsScaling - \brief Windows scaling utilities - - \internal - \ingroup qt-lighthouse-win -*/ - -int QWindowsScaling::m_factor = 1; - -static const char devicePixelRatioEnvVar[] = "QT_DEVICE_PIXEL_RATIO"; - -// Suggest a scale factor by checking monitor sizes. -int QWindowsScaling::determineUiScaleFactor() -{ - if (!qEnvironmentVariableIsSet(devicePixelRatioEnvVar)) - return 1; - const QByteArray envDevicePixelRatioEnv = qgetenv(devicePixelRatioEnvVar); - // Auto: Suggest a scale factor by checking monitor resolution. - if (envDevicePixelRatioEnv == "auto") { - const int maxResolution = QWindowsScreen::maxMonitorHorizResolution(); - return maxResolution > 180 ? maxResolution / 96 : 1; - } - // Get factor from environment - bool ok = false; - const int envFactor = envDevicePixelRatioEnv.toInt(&ok); - return ok && envFactor > 0 ? envFactor : 1; -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsscaling.h b/src/plugins/platforms/windows/qwindowsscaling.h deleted file mode 100644 index 39e554bbe2..0000000000 --- a/src/plugins/platforms/windows/qwindowsscaling.h +++ /dev/null @@ -1,106 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWINDOWSSCALING_H -#define QWINDOWSSCALING_H - -#include <QtGui/QRegion> -#include <QtCore/QVector> -#include <QtCore/QRect> - -QT_BEGIN_NAMESPACE - -enum -#if defined(Q_COMPILER_CLASS_ENUM) || defined(Q_CC_MSVC) - : int -#endif -{ QWINDOWSIZE_MAX = 16777215 }; - -class QWindowsScaling { -public: - static bool isActive() { return m_factor > 1; } - static int factor() { return m_factor; } - static void setFactor(int factor) { m_factor = factor; } - static int determineUiScaleFactor(); - - // Scaling helpers for size constraints. - static int mapToNativeConstrained(int qt) - { return m_factor != 1 && qt > 0 && qt < QWINDOWSIZE_MAX ? qt * m_factor : qt; } - - static int mapFromNativeConstrained(int dp) - { return m_factor != 1 && dp > 0 && dp < QWINDOWSIZE_MAX ? dp / m_factor : dp; } - - static QSize mapToNativeConstrained(const QSize &qt) - { return QSize(mapToNativeConstrained(qt.width()), mapToNativeConstrained(qt.height())); } - - static QRect mapToNative(const QRect &qRect) - { - return QRect(qRect.x() * m_factor, qRect.y() * m_factor, qRect.width() * m_factor, qRect.height() * m_factor); - } - - static QRect mapFromNative(const QRect &dp) - { - return isActive() ? - QRect(dp.x() / m_factor, dp.y() / m_factor, (dp.width() + 1) / m_factor, (dp.height() + 1) / m_factor) : - dp; - } - - static QRegion mapToNative(const QRegion ®ionQt) - { - if (!QWindowsScaling::isActive() || regionQt.isEmpty()) - return regionQt; - - QRegion result; - foreach (const QRect &rectQt, regionQt.rects()) - result += QWindowsScaling::mapToNative(rectQt); - return result; - } - - static QRegion mapFromNative(const QRegion ®ionDp) - { - if (!QWindowsScaling::isActive() || regionDp.isEmpty()) - return regionDp; - - QRegion result; - foreach (const QRect &rectDp, regionDp.rects()) - result += QWindowsScaling::mapFromNative(rectDp); - return result; - } - -private: - static int m_factor; -}; - -QT_END_NAMESPACE - -#endif // QWINDOWSSCALING_H diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index 7756c77001..02696c87cd 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -43,6 +43,7 @@ #include <QtGui/QPixmap> #include <QtGui/QGuiApplication> #include <qpa/qwindowsysteminterface.h> +#include <private/qhighdpiscaling_p.h> #include <QtGui/QScreen> #include <QtCore/QDebug> @@ -171,6 +172,7 @@ static inline WindowsScreenDataList monitorData() return result; } +#ifndef QT_NO_DEBUG_STREAM static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d) { QDebugStateSaver saver(dbg); @@ -191,16 +193,7 @@ static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d) dbg << " lock screen"; return dbg; } - -// Return the cursor to be shared by all screens (virtual desktop). -static inline QSharedPointer<QPlatformCursor> sharedCursor() -{ -#ifndef QT_NO_CURSOR - if (const QScreen *primaryScreen = QGuiApplication::primaryScreen()) - return static_cast<const QWindowsScreen *>(primaryScreen->handle())->cursorPtr(); -#endif - return QSharedPointer<QPlatformCursor>(new QWindowsCursor); -} +#endif // !QT_NO_DEBUG_STREAM /*! \class QWindowsScreen @@ -213,41 +206,19 @@ static inline QSharedPointer<QPlatformCursor> sharedCursor() QWindowsScreen::QWindowsScreen(const QWindowsScreenData &data) : m_data(data) #ifndef QT_NO_CURSOR - ,m_cursor(sharedCursor()) + , m_cursor(new QWindowsCursor(this)) #endif { } -BOOL QT_WIN_CALLBACK monitorResolutionEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM p) -{ - QWindowsScreenData data; - if (monitorData(hMonitor, &data)) { - int *maxHorizResolution = reinterpret_cast<int *>(p); - const int horizResolution = qRound(data.dpi.first); - if (horizResolution > *maxHorizResolution) - *maxHorizResolution = horizResolution; - } - return TRUE; -} - -int QWindowsScreen::maxMonitorHorizResolution() -{ - int result = 0; - EnumDisplayMonitors(0, 0, monitorResolutionEnumCallback, (LPARAM)&result); - return result; -} - Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0); -QPixmap QWindowsScreen::grabWindow(WId window, int qX, int qY, int qWidth, int qHeight) const +QPixmap QWindowsScreen::grabWindow(WId window, int x, int y, int width, int height) const { RECT r; HWND hwnd = window ? (HWND)window : GetDesktopWindow(); GetClientRect(hwnd, &r); - const int x = qX * QWindowsScaling::factor(); - const int y = qY * QWindowsScaling::factor(); - int width = qWidth * QWindowsScaling::factor(); - int height = qHeight * QWindowsScaling::factor(); + if (width < 0) width = r.right - r.left; if (height < 0) height = r.bottom - r.top; @@ -271,10 +242,6 @@ QPixmap QWindowsScreen::grabWindow(WId window, int qX, int qY, int qWidth, int q DeleteObject(bitmap); ReleaseDC(0, display_dc); - if (QWindowsScaling::isActive()) { - const qreal factor = 1.0 / qreal(QWindowsScaling::factor()); - return pixmap.transformed(QTransform::fromScale(factor, factor)); - } return pixmap; } @@ -285,7 +252,7 @@ QPixmap QWindowsScreen::grabWindow(WId window, int qX, int qY, int qWidth, int q QWindow *QWindowsScreen::topLevelAt(const QPoint &point) const { QWindow *result = 0; - if (QWindow *child = QWindowsScreen::windowAt(point * QWindowsScaling::factor(), CWP_SKIPINVISIBLE)) + if (QWindow *child = QWindowsScreen::windowAt(point, CWP_SKIPINVISIBLE)) result = QWindowsWindow::topLevelOf(child); qCDebug(lcQpaWindows) <<__FUNCTION__ << point << result; return result; @@ -301,16 +268,13 @@ QWindow *QWindowsScreen::windowAt(const QPoint &screenPoint, unsigned flags) return result; } -QWindowsScreen *QWindowsScreen::screenOf(const QWindow *w) +qreal QWindowsScreen::pixelDensity() const { - if (w) - if (const QScreen *s = w->screen()) - if (QPlatformScreen *pscr = s->handle()) - return static_cast<QWindowsScreen *>(pscr); - if (const QScreen *ps = QGuiApplication::primaryScreen()) - if (QPlatformScreen *ppscr = ps->handle()) - return static_cast<QWindowsScreen *>(ppscr); - return 0; + // QTBUG-49195: Use logical DPI instead of physical DPI to calculate + // the pixel density since it is reflects the Windows UI scaling. + // High DPI auto scaling should be disabled when the user chooses + // small fonts on a High DPI monitor, resulting in lower logical DPI. + return qRound(logicalDpi().first / 96); } /*! @@ -361,6 +325,74 @@ void QWindowsScreen::handleChanges(const QWindowsScreenData &newData) } } +enum OrientationPreference // matching Win32 API ORIENTATION_PREFERENCE +#if defined(Q_COMPILER_CLASS_ENUM) || defined(Q_CC_MSVC) + : DWORD +#endif +{ + orientationPreferenceNone = 0, + orientationPreferenceLandscape = 0x1, + orientationPreferencePortrait = 0x2, + orientationPreferenceLandscapeFlipped = 0x4, + orientationPreferencePortraitFlipped = 0x8 +}; + +bool QWindowsScreen::setOrientationPreference(Qt::ScreenOrientation o) +{ + bool result = false; +#ifndef Q_OS_WINCE + if (QWindowsContext::user32dll.setDisplayAutoRotationPreferences) { + DWORD orientationPreference = 0; + switch (o) { + case Qt::PrimaryOrientation: + orientationPreference = orientationPreferenceNone; + break; + case Qt::PortraitOrientation: + orientationPreference = orientationPreferencePortrait; + break; + case Qt::LandscapeOrientation: + orientationPreference = orientationPreferenceLandscape; + break; + case Qt::InvertedPortraitOrientation: + orientationPreference = orientationPreferencePortraitFlipped; + break; + case Qt::InvertedLandscapeOrientation: + orientationPreference = orientationPreferenceLandscapeFlipped; + break; + } + result = QWindowsContext::user32dll.setDisplayAutoRotationPreferences(orientationPreference); + } +#endif // !Q_OS_WINCE + return result; +} + +Qt::ScreenOrientation QWindowsScreen::orientationPreference() +{ + Qt::ScreenOrientation result = Qt::PrimaryOrientation; +#ifndef Q_OS_WINCE + if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences) { + DWORD orientationPreference = 0; + if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences(&orientationPreference)) { + switch (orientationPreference) { + case orientationPreferenceLandscape: + result = Qt::LandscapeOrientation; + break; + case orientationPreferencePortrait: + result = Qt::PortraitOrientation; + break; + case orientationPreferenceLandscapeFlipped: + result = Qt::InvertedLandscapeOrientation; + break; + case orientationPreferencePortraitFlipped: + result = Qt::InvertedPortraitOrientation; + break; + } + } + } +#endif // !Q_OS_WINCE + return result; +} + /*! \brief Queries ClearType settings to check the pixel layout */ @@ -542,7 +574,7 @@ void QWindowsScreenManager::clearScreens() const QWindowsScreen *QWindowsScreenManager::screenAtDp(const QPoint &p) const { foreach (QWindowsScreen *scr, m_screens) { - if (scr->geometryDp().contains(p)) + if (scr->geometry().contains(p)) return scr; } return Q_NULLPTR; diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h index 7352c45777..b46bd88ec6 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.h +++ b/src/plugins/platforms/windows/qwindowsscreen.h @@ -34,7 +34,6 @@ #ifndef QWINDOWSSCREEN_H #define QWINDOWSSCREEN_H -#include "qwindowsscaling.h" #include "qtwindowsglobal.h" #ifdef Q_OS_WINCE # include "qplatformfunctions_wince.h" @@ -43,7 +42,7 @@ #include <QtCore/QList> #include <QtCore/QVector> #include <QtCore/QPair> -#include <QtCore/QSharedPointer> +#include <QtCore/QScopedPointer> #include <qpa/qplatformscreen.h> QT_BEGIN_NAMESPACE @@ -75,23 +74,19 @@ class QWindowsScreen : public QPlatformScreen { public: #ifndef QT_NO_CURSOR - typedef QSharedPointer<QPlatformCursor> CursorPtr; + typedef QScopedPointer<QPlatformCursor> CursorPtr; #endif explicit QWindowsScreen(const QWindowsScreenData &data); - static QWindowsScreen *screenOf(const QWindow *w = 0); - - QRect geometryDp() const { return m_data.geometry; } - QRect geometry() const Q_DECL_OVERRIDE { return QWindowsScaling::mapFromNative(geometryDp()); } - QRect availableGeometryDp() const { return m_data.availableGeometry; } - QRect availableGeometry() const Q_DECL_OVERRIDE { return QWindowsScaling::mapFromNative(availableGeometryDp()); } + QRect geometry() const Q_DECL_OVERRIDE { return m_data.geometry; } + QRect availableGeometry() const Q_DECL_OVERRIDE { return m_data.availableGeometry; } int depth() const Q_DECL_OVERRIDE { return m_data.depth; } QImage::Format format() const Q_DECL_OVERRIDE { return m_data.format; } QSizeF physicalSize() const Q_DECL_OVERRIDE { return m_data.physicalSizeMM; } - QDpi logicalDpi() const Q_DECL_OVERRIDE - { return QDpi(m_data.dpi.first / QWindowsScaling::factor(), m_data.dpi.second / QWindowsScaling::factor()); } - qreal devicePixelRatio() const Q_DECL_OVERRIDE { return QWindowsScaling::factor(); } + QDpi logicalDpi() const Q_DECL_OVERRIDE { return m_data.dpi; } + qreal pixelDensity() const Q_DECL_OVERRIDE; + qreal devicePixelRatio() const Q_DECL_OVERRIDE { return 1.0; } qreal refreshRate() const Q_DECL_OVERRIDE { return m_data.refreshRateHz; } QString name() const Q_DECL_OVERRIDE { return m_data.name; } Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE { return m_data.orientation; } @@ -102,6 +97,9 @@ public: QPixmap grabWindow(WId window, int qX, int qY, int qWidth, int qHeight) const Q_DECL_OVERRIDE; QPlatformScreen::SubpixelAntialiasingType subpixelAntialiasingTypeHint() const Q_DECL_OVERRIDE; + static Qt::ScreenOrientation orientationPreference(); + static bool setOrientationPreference(Qt::ScreenOrientation o); + inline void handleChanges(const QWindowsScreenData &newData); #ifndef QT_NO_CURSOR @@ -112,7 +110,6 @@ public: #endif // !QT_NO_CURSOR const QWindowsScreenData &data() const { return m_data; } - static int maxMonitorHorizResolution(); private: QWindowsScreenData m_data; diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp index 7b871be015..b27811df9e 100644 --- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp +++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp @@ -32,7 +32,6 @@ ****************************************************************************/ #include "qwindowstabletsupport.h" -#include "qwindowsscaling.h" #ifndef QT_NO_TABLETEVENT @@ -55,7 +54,7 @@ #include <QtCore/private/qsystemlibrary_p.h> // Note: The definition of the PACKET structure in pktdef.h depends on this define. -#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION | PK_CURSOR | PK_Z) +#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION | PK_CURSOR | PK_Z | PK_TIME) #include <pktdef.h> QT_BEGIN_NAMESPACE @@ -303,8 +302,11 @@ static inline QTabletEvent::PointerType pointerType(unsigned currentCursor) return QTabletEvent::UnknownPointer; } +#ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const QWindowsTabletDeviceData &t) { + QDebugStateSaver saver(d); + d.nospace(); d << "TabletDevice id:" << t.uniqueId << " pressure: " << t.minPressure << ".." << t.maxPressure << " tan pressure: " << t.minTanPressure << ".." << t.maxTanPressure << " area:" << t.minX << t.minY <<t.minZ @@ -312,6 +314,7 @@ QDebug operator<<(QDebug d, const QWindowsTabletDeviceData &t) << " pointer " << t.currentPointerType; return d; } +#endif // !QT_NO_DEBUG_STREAM QWindowsTabletDeviceData QWindowsTabletSupport::tabletInit(const quint64 uniqueId, const UINT cursorType) const { @@ -343,17 +346,18 @@ QWindowsTabletDeviceData QWindowsTabletSupport::tabletInit(const quint64 uniqueI bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, LPARAM lParam) { + PACKET proximityBuffer[1]; // we are only interested in the first packet in this case + const int totalPacks = QWindowsTabletSupport::m_winTab32DLL.wTPacketsGet(m_context, 1, proximityBuffer); + if (!totalPacks) + return false; if (!LOWORD(lParam)) { qCDebug(lcQpaTablet) << "leave proximity for device #" << m_currentDevice; - QWindowSystemInterface::handleTabletLeaveProximityEvent(m_devices.at(m_currentDevice).currentDevice, + QWindowSystemInterface::handleTabletLeaveProximityEvent(proximityBuffer[0].pkTime, + m_devices.at(m_currentDevice).currentDevice, m_devices.at(m_currentDevice).currentPointerType, m_devices.at(m_currentDevice).uniqueId); return true; } - PACKET proximityBuffer[1]; // we are only interested in the first packet in this case - const int totalPacks = QWindowsTabletSupport::m_winTab32DLL.wTPacketsGet(m_context, 1, proximityBuffer); - if (!totalPacks) - return false; const UINT currentCursor = proximityBuffer[0].pkCursor; UINT physicalCursorId; QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_CURSORS + currentCursor, CSR_PHYSID, &physicalCursorId); @@ -371,7 +375,8 @@ bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, L m_devices[m_currentDevice].currentPointerType = pointerType(currentCursor); qCDebug(lcQpaTablet) << "enter proximity for device #" << m_currentDevice << m_devices.at(m_currentDevice); - QWindowSystemInterface::handleTabletEnterProximityEvent(m_devices.at(m_currentDevice).currentDevice, + QWindowSystemInterface::handleTabletEnterProximityEvent(proximityBuffer[0].pkTime, + m_devices.at(m_currentDevice).currentDevice, m_devices.at(m_currentDevice).currentPointerType, m_devices.at(m_currentDevice).uniqueId); return true; @@ -399,8 +404,7 @@ bool QWindowsTabletSupport::translateTabletPacketEvent() // in which case we snap the position to the mouse position. // It seems there is no way to find out the mode programmatically, the LOGCONTEXT orgX/Y/Ext // area is always the virtual desktop. - const QRect virtualDesktopArea - = QWindowsScaling::mapToNative(QGuiApplication::primaryScreen()->virtualGeometry()); + const QRect virtualDesktopArea = QGuiApplication::primaryScreen()->virtualGeometry(); qCDebug(lcQpaTablet) << __FUNCTION__ << "processing " << packetCount << "target:" << QGuiApplicationPrivate::tabletPressTarget; @@ -420,7 +424,7 @@ bool QWindowsTabletSupport::translateTabletPacketEvent() QPoint globalPos = globalPosF.toPoint(); // Get Mouse Position and compare to tablet info - QPoint mouseLocation = QWindowsCursor::mousePosition(); + const QPoint mouseLocation = QWindowsCursor::mousePosition(); // Positions should be almost the same if we are in absolute // mode. If they are not, use the mouse location. @@ -475,9 +479,7 @@ bool QWindowsTabletSupport::translateTabletPacketEvent() << tiltY << "tanP:" << tangentialPressure << "rotation:" << rotation; } - const QPointF localPosDip = QPointF(localPos / QWindowsScaling::factor()); - const QPointF globalPosDip = globalPosF / qreal(QWindowsScaling::factor()); - QWindowSystemInterface::handleTabletEvent(target, localPosDip, globalPosDip, + QWindowSystemInterface::handleTabletEvent(target, packet.pkTime, QPointF(localPos), globalPosF, currentDevice, currentPointer, static_cast<Qt::MouseButtons>(packet.pkButtons), pressureNew, tiltX, tiltY, diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.h b/src/plugins/platforms/windows/qwindowstabletsupport.h index 718ae98572..a6d2771206 100644 --- a/src/plugins/platforms/windows/qwindowstabletsupport.h +++ b/src/plugins/platforms/windows/qwindowstabletsupport.h @@ -97,7 +97,9 @@ struct QWindowsTabletDeviceData int currentPointerType; }; +#ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const QWindowsTabletDeviceData &t); +#endif class QWindowsTabletSupport { diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index d3f67e9eaa..cc367ff801 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -43,7 +43,6 @@ #include "qwindowsintegration.h" #include "qt_windows.h" #include "qwindowsfontdatabase.h" -#include "qwindowsscaling.h" #ifdef Q_OS_WINCE # include "qplatformfunctions_wince.h" # include "winuser.h" @@ -68,6 +67,7 @@ #include <QtGui/QPainter> #include <QtGui/QPixmapCache> #include <qpa/qwindowsysteminterface.h> +#include <private/qhighdpiscaling_p.h> #include <private/qsystemlibrary_p.h> #include <algorithm> @@ -131,7 +131,7 @@ static inline bool booleanSystemParametersInfo(UINT what, bool defaultValue) return defaultValue; } -static inline bool dWordSystemParametersInfo(UINT what, DWORD defaultValue) +static inline DWORD dWordSystemParametersInfo(UINT what, DWORD defaultValue) { DWORD result; if (SystemParametersInfo(what, 0, &result, 0)) @@ -393,6 +393,8 @@ QVariant QWindowsTheme::themeHint(ThemeHint hint) const return QVariant(booleanSystemParametersInfo(SPI_GETSNAPTODEFBUTTON, false)); case ContextMenuOnMouseRelease: return QVariant(true); + case WheelScrollLines: + return QVariant(int(dWordSystemParametersInfo(SPI_GETWHEELSCROLLLINES, 3))); default: break; } @@ -495,7 +497,8 @@ static QPixmap loadIconFromShell32(int resourceId, QSizeF size) QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const { - const int scaleFactor = QWindowsScaling::factor(); + const QScreen *primaryScreen = QGuiApplication::primaryScreen(); + const int scaleFactor = primaryScreen ? qRound(QHighDpiScaling::factor(primaryScreen)) : 1; const QSizeF pixmapSize = size * scaleFactor; int resourceId = -1; LPCTSTR iconName = 0; @@ -632,7 +635,7 @@ public: static FakePointer *create(T thing) { - return reinterpret_cast<FakePointer *>(thing); + return reinterpret_cast<FakePointer *>(qintptr(thing)); } T operator * () const @@ -720,6 +723,7 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s iconSize|SHGFI_SYSICONINDEX; #endif // Q_OS_WINCE unsigned long val = 0; +#if !defined(QT_NO_WINCE_SHELLSDK) if (cacheableDirIcon && useDefaultFolderIcon) { flags |= SHGFI_USEFILEATTRIBUTES; val = SHGetFileInfo(L"dummy", @@ -729,6 +733,7 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s val = SHGetFileInfo(reinterpret_cast<const wchar_t *>(filePath.utf16()), 0, &info, sizeof(SHFILEINFO), flags); } +#endif // !QT_NO_WINCE_SHELLSDK // Even if GetFileInfo returns a valid result, hIcon can be empty in some cases if (val && info.hIcon) { diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h index b2f8e13b64..fc004b68c8 100644 --- a/src/plugins/platforms/windows/qwindowstheme.h +++ b/src/plugins/platforms/windows/qwindowstheme.h @@ -51,9 +51,9 @@ public: bool usePlatformNativeDialog(DialogType type) const Q_DECL_OVERRIDE; QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const Q_DECL_OVERRIDE; QVariant themeHint(ThemeHint) const Q_DECL_OVERRIDE; - virtual const QPalette *palette(Palette type = SystemPalette) const + const QPalette *palette(Palette type = SystemPalette) const Q_DECL_OVERRIDE { return m_palettes[type]; } - virtual const QFont *font(Font type = SystemFont) const + const QFont *font(Font type = SystemFont) const Q_DECL_OVERRIDE { return m_fonts[type]; } QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 288f73cb8f..cac8ec5ecc 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -36,7 +36,6 @@ #include "qwindowscontext.h" #include "qwindowsdrag.h" #include "qwindowsscreen.h" -#include "qwindowsscaling.h" #include "qwindowsintegration.h" #include "qwindowsopenglcontext.h" #ifdef QT_NO_CURSOR @@ -49,8 +48,9 @@ #include <QtGui/QRegion> #include <QtGui/QOpenGLContext> #include <private/qsystemlibrary_p.h> -#include <private/qwindow_p.h> +#include <private/qwindow_p.h> // QWINDOWSIZE_MAX #include <private/qguiapplication_p.h> +#include <private/qhighdpiscaling_p.h> #include <qpa/qwindowsysteminterface.h> #include <QtCore/QDebug> @@ -106,20 +106,6 @@ static QByteArray debugWinExStyle(DWORD exStyle) return rc; } -#ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO -QDebug operator<<(QDebug d, const MINMAXINFO &i) -{ - QDebugStateSaver saver(d); - d.nospace(); - d << "MINMAXINFO maxSize=" << i.ptMaxSize.x << ',' - << i.ptMaxSize.y << " maxpos=" << i.ptMaxPosition.x - << ',' << i.ptMaxPosition.y << " mintrack=" - << i.ptMinTrackSize.x << ',' << i.ptMinTrackSize.y - << " maxtrack=" << i.ptMaxTrackSize.x << ',' << i.ptMaxTrackSize.y; - return d; -} -#endif // !Q_OS_WINCE - static inline QSize qSizeOfRect(const RECT &rect) { return QSize(rect.right -rect.left, rect.bottom - rect.top); @@ -138,6 +124,7 @@ static inline RECT RECTfromQRect(const QRect &rect) return result; } +#ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const RECT &r) { QDebugStateSaver saver(d); @@ -147,7 +134,13 @@ QDebug operator<<(QDebug d, const RECT &r) return d; } -#ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_NCCALCSIZE +QDebug operator<<(QDebug d, const POINT &p) +{ + d << p.x << ',' << p.y; + return d; +} + +# ifndef Q_OS_WINCE QDebug operator<<(QDebug d, const NCCALCSIZE_PARAMS &p) { QDebugStateSaver saver(d); @@ -156,7 +149,30 @@ QDebug operator<<(QDebug d, const NCCALCSIZE_PARAMS &p) << ' ' << qrectFromRECT(p.rgrc[1]) << ' ' << qrectFromRECT(p.rgrc[2]); return d; } -#endif // !Q_OS_WINCE + +QDebug operator<<(QDebug d, const MINMAXINFO &i) +{ + QDebugStateSaver saver(d); + d.nospace(); + d << "MINMAXINFO maxSize=" << i.ptMaxSize.x << ',' + << i.ptMaxSize.y << " maxpos=" << i.ptMaxPosition.x + << ',' << i.ptMaxPosition.y << " mintrack=" + << i.ptMinTrackSize.x << ',' << i.ptMinTrackSize.y + << " maxtrack=" << i.ptMaxTrackSize.x << ',' << i.ptMaxTrackSize.y; + return d; +} + +QDebug operator<<(QDebug d, const WINDOWPLACEMENT &wp) +{ + QDebugStateSaver saver(d); + d.nospace(); + d << "WINDOWPLACEMENT(flags=0x" << hex << wp.flags << dec << ", showCmd=" + << wp.showCmd << ", ptMinPosition=" << wp.ptMinPosition << ", ptMaxPosition=" << wp.ptMaxPosition + << ", rcNormalPosition=" << wp.rcNormalPosition; + return d; +} +# endif // !Q_OS_WINCE +#endif // !QT_NO_DEBUG_STREAM // QTBUG-43872, for windows that do not have WS_EX_TOOLWINDOW set, WINDOWPLACEMENT // is in workspace/available area coordinates. @@ -169,7 +185,7 @@ static QPoint windowPlacementOffset(HWND hwnd, const QPoint &point) const QWindowsScreen *screen = screenManager.screens().size() == 1 ? screenManager.screens().first() : screenManager.screenAtDp(point); if (screen) - return screen->availableGeometryDp().topLeft() - screen->geometryDp().topLeft(); + return screen->availableGeometry().topLeft() - screen->geometry().topLeft(); #else Q_UNUSED(hwnd) Q_UNUSED(point) @@ -608,9 +624,7 @@ QWindowsWindowData const QString windowClassName = QWindowsContext::instance()->registerWindowClass(w); - const QRect geometryDip = QWindowsScaling::mapFromNative(data.geometry); - QRect fixedGeometryDip = QPlatformWindow::initialGeometry(w, geometryDip, defaultWindowWidth, defaultWindowHeight); - const QRect rect = fixedGeometryDip != geometryDip ? QWindowsScaling::mapToNative(fixedGeometryDip) : data.geometry; + const QRect rect = QPlatformWindow::initialGeometry(w, data.geometry, defaultWindowWidth, defaultWindowHeight); if (title.isEmpty() && (result.flags & Qt::WindowTitleHint)) title = topLevel ? qAppName() : w->objectName(); @@ -706,6 +720,20 @@ void WindowCreationData::initialize(const QWindow *w, HWND hwnd, bool frameChang } } + +// Scaling helpers for size constraints. +static QSize toNativeSizeConstrained(QSize dip, const QWindow *w) +{ + if (QHighDpiScaling::isActive()) { + const qreal factor = QHighDpiScaling::factor(w); + if (dip.width() > 0 && dip.width() < QWINDOWSIZE_MAX) + dip.rwidth() *= factor; + if (dip.height() > 0 && dip.height() < QWINDOWSIZE_MAX) + dip.rheight() *= factor; + } + return dip; +} + /*! \class QWindowsGeometryHint \brief Stores geometry constraints and provides utility functions. @@ -718,8 +746,8 @@ void WindowCreationData::initialize(const QWindow *w, HWND hwnd, bool frameChang */ QWindowsGeometryHint::QWindowsGeometryHint(const QWindow *w, const QMargins &cm) : - minimumSize(QWindowsScaling::mapToNativeConstrained(w->minimumSize())), - maximumSize(QWindowsScaling::mapToNativeConstrained(w->maximumSize())), + minimumSize(toNativeSizeConstrained(w->minimumSize(), w)), + maximumSize(toNativeSizeConstrained(w->maximumSize(), w)), customMargins(cm) { } @@ -900,6 +928,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) m_hdc(0), m_windowState(Qt::WindowNoState), m_opacity(1.0), + m_cursor(new CursorHandle), m_dropTarget(0), m_savedStyle(0), m_format(aWindow->requestedFormat()), @@ -953,8 +982,7 @@ void QWindowsWindow::fireExpose(const QRegion ®ion, bool force) clearFlag(Exposed); else setFlag(Exposed); - QWindowSystemInterface::handleExposeEvent(window(), - QWindowsScaling::mapFromNative(region)); + QWindowSystemInterface::handleExposeEvent(window(), region); } static inline QWindow *findTransientChild(const QWindow *parent) @@ -1005,7 +1033,17 @@ void QWindowsWindow::destroyWindow() void QWindowsWindow::updateDropSite(bool topLevel) { bool enabled = false; - if (topLevel) { + bool parentIsEmbedded = false; + + if (!topLevel) { + // if the parent window is a foreign window wrapped via QWindow::fromWinId, we need to enable the drop site + // on the first child window + const QWindow *parent = window()->parent(); + if (parent && (parent->type() == Qt::ForeignWindow)) + parentIsEmbedded = true; + } + + if (topLevel || parentIsEmbedded) { switch (window()->type()) { case Qt::Window: case Qt::Dialog: @@ -1051,7 +1089,7 @@ QWindow *QWindowsWindow::topLevelOf(QWindow *w) if (const QPlatformWindow *handle = w->handle()) { const QWindowsWindow *ww = static_cast<const QWindowsWindow *>(handle); - if (ww->isEmbedded(0)) { + if (ww->isEmbedded()) { HWND parentHWND = GetAncestor(ww->handle(), GA_PARENT); const HWND desktopHwnd = GetDesktopWindow(); const QWindowsContext *ctx = QWindowsContext::instance(); @@ -1129,12 +1167,12 @@ bool QWindowsWindow::isEmbedded(const QPlatformWindow *parentWindow) const } if (!m_data.embedded && parent()) - return parent()->isEmbedded(0); + return parent()->isEmbedded(); return m_data.embedded; } -QPoint QWindowsWindow::mapToGlobalDp(const QPoint &pos) const +QPoint QWindowsWindow::mapToGlobal(const QPoint &pos) const { if (m_data.hwnd) return QWindowsGeometryHint::mapToGlobal(m_data.hwnd, pos); @@ -1142,7 +1180,7 @@ QPoint QWindowsWindow::mapToGlobalDp(const QPoint &pos) const return pos; } -QPoint QWindowsWindow::mapFromGlobalDp(const QPoint &pos) const +QPoint QWindowsWindow::mapFromGlobal(const QPoint &pos) const { if (m_data.hwnd) return QWindowsGeometryHint::mapFromGlobal(m_data.hwnd, pos); @@ -1323,22 +1361,22 @@ static QRect normalFrameGeometry(HWND hwnd) return QRect(); } -QRect QWindowsWindow::normalGeometryDp() const +QRect QWindowsWindow::normalGeometry() const { // Check for fake 'fullscreen' mode. const bool fakeFullScreen = m_savedFrameGeometry.isValid() && window()->windowState() == Qt::WindowFullScreen; const QRect frame = fakeFullScreen ? m_savedFrameGeometry : normalFrameGeometry(m_data.hwnd); - const QMargins margins = fakeFullScreen ? QWindowsGeometryHint::frame(m_savedStyle, 0) : frameMarginsDp(); + const QMargins margins = fakeFullScreen ? QWindowsGeometryHint::frame(m_savedStyle, 0) : frameMargins(); return frame.isValid() ? frame.marginsRemoved(margins) : frame; } -void QWindowsWindow::setGeometryDp(const QRect &rectIn) +void QWindowsWindow::setGeometry(const QRect &rectIn) { QRect rect = rectIn; // This means it is a call from QWindow::setFramePosition() and // the coordinates include the frame (size is still the contents rectangle). if (QWindowsGeometryHint::positionIncludesFrame(window())) { - const QMargins margins = frameMarginsDp(); + const QMargins margins = frameMargins(); rect.moveTopLeft(rect.topLeft() + QPoint(margins.left(), margins.top())); } if (m_windowState == Qt::WindowMinimized) @@ -1407,9 +1445,8 @@ void QWindowsWindow::handleGeometryChange() return; const QRect previousGeometry = m_data.geometry; m_data.geometry = geometry_sys(); - const QRect geometryDip = QWindowsScaling::mapFromNative(m_data.geometry); - QPlatformWindow::setGeometry(geometryDip); - QWindowSystemInterface::handleGeometryChange(window(), geometryDip); + QPlatformWindow::setGeometry(m_data.geometry); + QWindowSystemInterface::handleGeometryChange(window(), m_data.geometry); // QTBUG-32121: OpenGL/normal windows (with exception of ANGLE) do not receive // expose events when shrinking, synthesize. if (!testFlag(OpenGL_ES2) && isExposed() @@ -1417,7 +1454,7 @@ void QWindowsWindow::handleGeometryChange() fireExpose(QRect(QPoint(0, 0), m_data.geometry.size()), true); } if (previousGeometry.topLeft() != m_data.geometry.topLeft()) { - QPlatformScreen *newScreen = screenForGeometry(geometryDip); + QPlatformScreen *newScreen = screenForGeometry(m_data.geometry); if (newScreen != screen()) QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); } @@ -1429,7 +1466,7 @@ void QWindowsWindow::handleGeometryChange() void QWindowsWindow::setGeometry_sys(const QRect &rect) const { - const QMargins margins = frameMarginsDp(); + const QMargins margins = frameMargins(); const QRect frameGeometry = rect + margins; qCDebug(lcQpaWindows) << '>' << __FUNCTION__ << window() @@ -1468,7 +1505,7 @@ QRect QWindowsWindow::frameGeometry_sys() const QRect QWindowsWindow::geometry_sys() const { - return frameGeometry_sys().marginsRemoved(frameMarginsDp()); + return frameGeometry_sys().marginsRemoved(frameMargins()); } /*! @@ -1540,7 +1577,7 @@ void QWindowsWindow::setWindowFlags(Qt::WindowFlags flags) { qCDebug(lcQpaWindows) << '>' << __FUNCTION__ << this << window() << "\n from: " << m_data.flags << "\n to: " << flags; - const QRect oldGeometry = geometryDp(); + const QRect oldGeometry = geometry(); if (m_data.flags != flags) { m_data.flags = flags; if (m_data.hwnd) { @@ -1626,8 +1663,13 @@ void QWindowsWindow::setWindowState(Qt::WindowState state) bool QWindowsWindow::isFullScreen_sys() const { - return window()->isTopLevel() - && geometry_sys() == QWindowsScaling::mapToNative(window()->screen()->geometry()); + const QWindow *w = window(); + if (!w->isTopLevel()) + return false; + const QScreen *screen = w->screen(); + if (!screen) + screen = QGuiApplication::primaryScreen(); + return screen && geometry_sys() == QHighDpi::toNativePixels(screen->geometry(), w); } /*! @@ -1678,7 +1720,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState) if (!m_savedStyle) { m_savedStyle = style(); #ifndef Q_OS_WINCE - if (oldState == Qt::WindowMinimized) { + if (oldState == Qt::WindowMinimized || oldState == Qt::WindowMaximized) { const QRect nf = normalFrameGeometry(m_data.hwnd); if (nf.isValid()) m_savedFrameGeometry = nf; @@ -1693,19 +1735,22 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState) newStyle |= WS_SYSMENU; if (visible) newStyle |= WS_VISIBLE; + if (testFlag(HasBorderInFullScreen)) + newStyle |= WS_BORDER; setStyle(newStyle); // Use geometry of QWindow::screen() within creation or the virtual screen the // window is in (QTBUG-31166, QTBUG-30724). const QScreen *screen = window()->screen(); - const QRect rDip = screen->geometry(); - const QRect r = QWindowsScaling::mapToNative(rDip); + if (!screen) + screen = QGuiApplication::primaryScreen(); + const QRect r = screen ? QHighDpi::toNativePixels(screen->geometry(), window()) : m_savedFrameGeometry; const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE; const bool wasSync = testFlag(SynchronousGeometryChangeEvent); setFlag(SynchronousGeometryChangeEvent); SetWindowPos(m_data.hwnd, HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf); if (!wasSync) clearFlag(SynchronousGeometryChangeEvent); - QWindowSystemInterface::handleGeometryChange(window(), rDip); + QWindowSystemInterface::handleGeometryChange(window(), r); QWindowSystemInterface::flushWindowSystemEvents(); } else if (newState != Qt::WindowMinimized) { // Restore saved state. @@ -1726,7 +1771,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState) // preserve maximized state if (visible) { setFlag(WithinMaximize); - ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE); + ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNA); clearFlag(WithinMaximize); } m_savedStyle = 0; @@ -1746,7 +1791,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState) if ((oldState == Qt::WindowMinimized) != (newState == Qt::WindowMinimized)) { if (visible) ShowWindow(m_data.hwnd, (newState == Qt::WindowMinimized) ? SW_MINIMIZE : - (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE); + (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNORMAL); } qCDebug(lcQpaWindows) << '<' << __FUNCTION__ << this << window() << newState; } @@ -1804,7 +1849,7 @@ void QWindowsWindow::propagateSizeHints() qCDebug(lcQpaWindows) << __FUNCTION__ << this << window(); } -bool QWindowsWindow::handleGeometryChangingMessage(MSG *message, const QWindow *qWindow, const QMargins &marginsDp) +bool QWindowsWindow::handleGeometryChangingMessage(MSG *message, const QWindow *qWindow, const QMargins &margins) { #ifndef Q_OS_WINCE if (!qWindow->isTopLevel()) // Implement hasHeightForWidth(). @@ -1812,26 +1857,19 @@ bool QWindowsWindow::handleGeometryChangingMessage(MSG *message, const QWindow * WINDOWPOS *windowPos = reinterpret_cast<WINDOWPOS *>(message->lParam); if ((windowPos->flags & (SWP_NOCOPYBITS | SWP_NOSIZE))) return false; - const QRect suggestedFrameGeometryDp(windowPos->x, windowPos->y, - windowPos->cx, windowPos->cy); - const qreal factor = QWindowsScaling::factor(); - const QRect suggestedGeometryDp = suggestedFrameGeometryDp - marginsDp; - const QRectF suggestedGeometry = QRectF(QPointF(suggestedGeometryDp.topLeft()) / factor, - QSizeF(suggestedGeometryDp.size()) / factor); - const QRectF correctedGeometryF = - qt_window_private(const_cast<QWindow *>(qWindow))->closestAcceptableGeometry(suggestedGeometry); + const QRect suggestedFrameGeometry(windowPos->x, windowPos->y, + windowPos->cx, windowPos->cy); + const QRect suggestedGeometry = suggestedFrameGeometry - margins; + const QRectF correctedGeometryF = QPlatformWindow::closestAcceptableGeometry(qWindow, suggestedGeometry); if (!correctedGeometryF.isValid()) return false; - const QRect correctedFrameGeometryDp - = QRectF(correctedGeometryF.topLeft() * factor, - correctedGeometryF.size() * factor).toRect() - + marginsDp; - if (correctedFrameGeometryDp == suggestedFrameGeometryDp) + const QRect correctedFrameGeometry = correctedGeometryF.toRect() + margins; + if (correctedFrameGeometry == suggestedFrameGeometry) return false; - windowPos->x = correctedFrameGeometryDp.left(); - windowPos->y = correctedFrameGeometryDp.top(); - windowPos->cx = correctedFrameGeometryDp.width(); - windowPos->cy = correctedFrameGeometryDp.height(); + windowPos->x = correctedFrameGeometry.left(); + windowPos->y = correctedFrameGeometry.top(); + windowPos->cx = correctedFrameGeometry.width(); + windowPos->cy = correctedFrameGeometry.height(); return true; #else // !Q_OS_WINCE Q_UNUSED(message) @@ -1841,11 +1879,11 @@ bool QWindowsWindow::handleGeometryChangingMessage(MSG *message, const QWindow * bool QWindowsWindow::handleGeometryChanging(MSG *message) const { - const QMargins marginsDp = window()->isTopLevel() ? frameMarginsDp() : QMargins(); - return QWindowsWindow::handleGeometryChangingMessage(message, window(), marginsDp); + const QMargins margins = window()->isTopLevel() ? frameMargins() : QMargins(); + return QWindowsWindow::handleGeometryChangingMessage(message, window(), margins); } -QMargins QWindowsWindow::frameMarginsDp() const +QMargins QWindowsWindow::frameMargins() const { // Frames are invalidated by style changes (window state, flags). // As they are also required for geometry calculations in resize @@ -1892,17 +1930,17 @@ static inline void addRectToWinRegion(const QRect &rect, HRGN *winRegion) } } -static HRGN qRegionToWinRegion(const QRegion ®ionDip) +static HRGN qRegionToWinRegion(const QRegion ®ion) { - const QVector<QRect> rects = regionDip.rects(); + const QVector<QRect> rects = region.rects(); if (rects.isEmpty()) return NULL; const int rectCount = rects.size(); if (rectCount == 1) - return createRectRegion(QWindowsScaling::mapToNative(regionDip.boundingRect())); - HRGN hRegion = createRectRegion(QWindowsScaling::mapToNative(rects.front())); + return createRectRegion(region.boundingRect()); + HRGN hRegion = createRectRegion(rects.front()); for (int i = 1; i < rectCount; ++i) - addRectToWinRegion(QWindowsScaling::mapToNative(rects.at(i)), &hRegion); + addRectToWinRegion(rects.at(i), &hRegion); return hRegion; } @@ -1916,7 +1954,7 @@ void QWindowsWindow::setMask(const QRegion ®ion) // Mask is in client area coordinates, so offset it in case we have a frame if (window()->isTopLevel()) { - const QMargins margins = frameMarginsDp(); + const QMargins margins = frameMargins(); OffsetRgn(winRegion, margins.left(), margins.top()); } @@ -2053,23 +2091,23 @@ bool QWindowsWindow::handleNonClientHitTest(const QPoint &globalPos, LRESULT *re || (m_data.flags & Qt::FramelessWindowHint)) { return false; } - const QSize minimumSize = QWindowsScaling::mapToNativeConstrained(w->minimumSize()); + const QSize minimumSize = w->minimumSize(); if (minimumSize.isEmpty()) return false; - const QSize maximumSize = QWindowsScaling::mapToNativeConstrained(w->maximumSize()); + const QSize maximumSize = w->maximumSize(); const bool fixedWidth = minimumSize.width() == maximumSize.width(); const bool fixedHeight = minimumSize.height() == maximumSize.height(); if (!fixedWidth && !fixedHeight) return false; - const QPoint localPos = mapFromGlobalDp(globalPos); - const QSize size = w->size() * QWindowsScaling::factor(); + const QPoint localPos = w->mapFromGlobal(QHighDpi::fromNativePixels(globalPos, w)); + const QSize size = w->size(); if (fixedHeight) { if (localPos.y() >= size.height()) { *result = HTBORDER; // Unspecified border, no resize cursor. return true; } if (localPos.y() < 0) { - const QMargins margins = frameMarginsDp(); + const QMargins margins = frameMargins(); const int topResizeBarPos = margins.left() - margins.top(); if (localPos.y() < topResizeBarPos) { *result = HTCAPTION; // Extend caption over top resize bar, let's user move the window. @@ -2088,13 +2126,13 @@ bool QWindowsWindow::handleNonClientHitTest(const QPoint &globalPos, LRESULT *re #ifndef QT_NO_CURSOR // Return the default cursor (Arrow) from QWindowsCursor's cache. -static inline QWindowsWindowCursor defaultCursor(const QWindow *w) +static inline CursorHandlePtr defaultCursor(const QWindow *w) { if (QScreen *screen = w->screen()) if (const QPlatformScreen *platformScreen = screen->handle()) if (QPlatformCursor *cursor = platformScreen->cursor()) return static_cast<QWindowsCursor *>(cursor)->standardWindowCursor(Qt::ArrowCursor); - return QWindowsWindowCursor(Qt::ArrowCursor); + return CursorHandlePtr(new CursorHandle(QWindowsCursor::createCursorFromShape(Qt::ArrowCursor))); } // Check whether to apply a new cursor. Either the window in question is @@ -2108,7 +2146,7 @@ static inline bool applyNewCursor(const QWindow *w) for (const QWindow *p = underMouse; p ; p = p->parent()) { if (p == w) return true; - if (!QWindowsWindow::baseWindowOf(p)->cursor().isNull()) + if (!QWindowsWindow::baseWindowOf(p)->cursor()->isNull()) return false; } return false; @@ -2124,25 +2162,25 @@ static inline bool applyNewCursor(const QWindow *w) void QWindowsWindow::applyCursor() { #ifndef QT_NO_CURSOR - if (m_cursor.isNull()) { // Recurse up to parent with non-null cursor. Set default for toplevel. + if (m_cursor->isNull()) { // Recurse up to parent with non-null cursor. Set default for toplevel. if (const QWindow *p = window()->parent()) { QWindowsWindow::baseWindowOf(p)->applyCursor(); } else { - SetCursor(defaultCursor(window()).handle()); + SetCursor(defaultCursor(window())->handle()); } } else { - SetCursor(m_cursor.handle()); + SetCursor(m_cursor->handle()); } #endif } -void QWindowsWindow::setCursor(const QWindowsWindowCursor &c) +void QWindowsWindow::setCursor(const CursorHandlePtr &c) { #ifndef QT_NO_CURSOR - if (c.handle() != m_cursor.handle()) { + if (c->handle() != m_cursor->handle()) { const bool apply = applyNewCursor(window()); qCDebug(lcQpaWindows) << window() << __FUNCTION__ - << c.cursor().shape() << " doApply=" << apply; + << c->handle() << " doApply=" << apply; m_cursor = c; if (apply) applyCursor(); @@ -2245,10 +2283,6 @@ void QWindowsWindow::setWindowIcon(const QIcon &icon) The property can be set using QPlatformNativeInterface::setWindowProperty() or, before platform window creation, by setting a dynamic property on the QWindow (see QWindowsIntegration::createPlatformWindow()). - - Note: The function uses (unscaled) device pixels since the QWizard also - uses AdjustWindowRect() and using device independent pixels would introduce - rounding errors. */ void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins) @@ -2339,4 +2373,19 @@ void QWindowsWindow::aboutToMakeCurrent() #endif } +void QWindowsWindow::setHasBorderInFullScreenStatic(QWindow *window, bool border) +{ + if (!window->handle()) + return; + static_cast<QWindowsWindow *>(window->handle())->setHasBorderInFullScreen(border); +} + +void QWindowsWindow::setHasBorderInFullScreen(bool border) +{ + if (border) + setFlag(HasBorderInFullScreen); + else + clearFlag(HasBorderInFullScreen); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index fff90b4b11..6fffa1e6e9 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -38,7 +38,6 @@ #ifdef Q_OS_WINCE # include "qplatformfunctions_wince.h" #endif -#include "qwindowsscaling.h" #include "qwindowscursor.h" #include <qpa/qplatformwindow.h> @@ -138,35 +137,28 @@ public: WithinMaximize = 0x40000, MaximizeToFullScreen = 0x80000, InputMethodDisabled = 0x100000, - Compositing = 0x200000 + Compositing = 0x200000, + HasBorderInFullScreen = 0x400000 }; QWindowsWindow(QWindow *window, const QWindowsWindowData &data); ~QWindowsWindow(); + using QPlatformWindow::screenForGeometry; + QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_format; } - void setGeometryDp(const QRect &rectIn); - void setGeometry(const QRect &rect) Q_DECL_OVERRIDE - { setGeometryDp(QWindowsScaling::mapToNative(rect)); } - QRect geometryDp() const { return m_data.geometry; } - QRect geometry() const Q_DECL_OVERRIDE - { return QWindowsScaling::mapFromNative(geometryDp()); } - QRect normalGeometryDp() const; - QRect normalGeometry() const Q_DECL_OVERRIDE - { return QWindowsScaling::mapFromNative(normalGeometryDp()); } - qreal devicePixelRatio() const Q_DECL_OVERRIDE - { return qreal(QWindowsScaling::factor()); } + void setGeometry(const QRect &rect) Q_DECL_OVERRIDE; + QRect geometry() const Q_DECL_OVERRIDE { return m_data.geometry; } + QRect normalGeometry() const Q_DECL_OVERRIDE; + void setVisible(bool visible) Q_DECL_OVERRIDE; bool isVisible() const; bool isExposed() const Q_DECL_OVERRIDE { return testFlag(Exposed); } bool isActive() const Q_DECL_OVERRIDE; - bool isEmbedded(const QPlatformWindow *parentWindow) const Q_DECL_OVERRIDE; - QPoint mapToGlobalDp(const QPoint &pos) const; - QPoint mapToGlobal(const QPoint &pos) const Q_DECL_OVERRIDE - { return mapToGlobalDp(pos * QWindowsScaling::factor()) / QWindowsScaling::factor(); } - QPoint mapFromGlobalDp(const QPoint &pos) const; - QPoint mapFromGlobal(const QPoint &pos) const Q_DECL_OVERRIDE - { return mapFromGlobalDp(pos * QWindowsScaling::factor()) / QWindowsScaling::factor(); } + bool isEmbedded(const QPlatformWindow *parentWindow = 0) const Q_DECL_OVERRIDE; + QPoint mapToGlobal(const QPoint &pos) const Q_DECL_OVERRIDE; + QPoint mapFromGlobal(const QPoint &pos) const Q_DECL_OVERRIDE; + void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE; void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE; @@ -179,13 +171,12 @@ public: void raise() Q_DECL_OVERRIDE; void lower() Q_DECL_OVERRIDE; - void windowEvent(QEvent *event); + void windowEvent(QEvent *event) Q_DECL_OVERRIDE; void propagateSizeHints() Q_DECL_OVERRIDE; static bool handleGeometryChangingMessage(MSG *message, const QWindow *qWindow, const QMargins &marginsDp); bool handleGeometryChanging(MSG *message) const; - QMargins frameMarginsDp() const; - QMargins frameMargins() const Q_DECL_OVERRIDE { return frameMarginsDp() / QWindowsScaling::factor(); } + QMargins frameMargins() const Q_DECL_OVERRIDE; void setOpacity(qreal level) Q_DECL_OVERRIDE; void setMask(const QRegion ®ion) Q_DECL_OVERRIDE; @@ -196,10 +187,10 @@ public: bool setMouseGrabEnabled(bool grab) Q_DECL_OVERRIDE; inline bool hasMouseCapture() const { return GetCapture() == m_data.hwnd; } - bool startSystemResize(const QPoint &, Qt::Corner corner) Q_DECL_OVERRIDE; + bool startSystemResize(const QPoint &pos, Qt::Corner corner) Q_DECL_OVERRIDE; - void setFrameStrutEventsEnabled(bool enabled); - bool frameStrutEventsEnabled() const { return testFlag(FrameStrutEventsEnabled); } + void setFrameStrutEventsEnabled(bool enabled) Q_DECL_OVERRIDE; + bool frameStrutEventsEnabled() const Q_DECL_OVERRIDE { return testFlag(FrameStrutEventsEnabled); } QMargins customMargins() const { return m_data.customMargins; } void setCustomMargins(const QMargins &m); @@ -235,9 +226,9 @@ public: #endif // !Q_OS_WINCE #ifndef QT_NO_CURSOR - QWindowsWindowCursor cursor() const { return m_cursor; } + CursorHandlePtr cursor() const { return m_cursor; } #endif - void setCursor(const QWindowsWindowCursor &c); + void setCursor(const CursorHandlePtr &c); void applyCursor(); inline bool testFlag(unsigned f) const { return (m_flags & f) != 0; } @@ -246,22 +237,23 @@ public: void setEnabled(bool enabled); bool isEnabled() const; - void setWindowIcon(const QIcon &icon); + void setWindowIcon(const QIcon &icon) Q_DECL_OVERRIDE; void *surface(void *nativeConfig, int *err); void invalidateSurface() Q_DECL_OVERRIDE; void aboutToMakeCurrent(); #ifndef Q_OS_WINCE - void setAlertState(bool enabled); - bool isAlertState() const { return testFlag(AlertState); } + void setAlertState(bool enabled) Q_DECL_OVERRIDE; + bool isAlertState() const Q_DECL_OVERRIDE { return testFlag(AlertState); } void alertWindow(int durationMs = 0); void stopAlertWindow(); #endif static void setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes); void registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes = QWindowsWindowFunctions::NormalTouch); - + static void setHasBorderInFullScreenStatic(QWindow *window, bool border); + void setHasBorderInFullScreen(bool border); private: inline void show_sys() const; inline void hide_sys() const; @@ -288,7 +280,7 @@ private: Qt::WindowState m_windowState; qreal m_opacity; #ifndef QT_NO_CURSOR - QWindowsWindowCursor m_cursor; + CursorHandlePtr m_cursor; #endif QWindowsOleDropTarget *m_dropTarget; unsigned m_savedStyle; @@ -302,12 +294,15 @@ private: void *m_surface; }; -// Debug +#ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const RECT &r); -#ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO/WM_NCCALCSIZE +QDebug operator<<(QDebug d, const POINT &); +# ifndef Q_OS_WINCE QDebug operator<<(QDebug d, const MINMAXINFO &i); QDebug operator<<(QDebug d, const NCCALCSIZE_PARAMS &p); -#endif +QDebug operator<<(QDebug d, const WINDOWPLACEMENT &); +# endif // !Q_OS_WINCE +#endif // !QT_NO_DEBUG_STREAM // ---------- QWindowsGeometryHint inline functions. QPoint QWindowsGeometryHint::mapToGlobal(HWND hwnd, const QPoint &qp) diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri index de901aaeb1..67af5c03ef 100644 --- a/src/plugins/platforms/windows/windows.pri +++ b/src/plugins/platforms/windows/windows.pri @@ -13,7 +13,6 @@ wince: DEFINES *= QT_LIBINFIX=L"\"\\\"$${QT_LIBINFIX}\\\"\"" DEFINES *= QT_NO_CAST_FROM_ASCII contains(QT_CONFIG, directwrite) { - LIBS *= -ldwrite SOURCES += $$PWD/qwindowsfontenginedirectwrite.cpp HEADERS += $$PWD/qwindowsfontenginedirectwrite.h } else { @@ -29,7 +28,6 @@ SOURCES += \ $$PWD/qwindowsfontengine.cpp \ $$PWD/qwindowsfontdatabase.cpp \ $$PWD/qwindowsmousehandler.cpp \ - $$PWD/qwindowsguieventdispatcher.cpp \ $$PWD/qwindowsole.cpp \ $$PWD/qwindowsmime.cpp \ $$PWD/qwindowsinternalmimedata.cpp \ @@ -40,7 +38,6 @@ SOURCES += \ $$PWD/qwindowsservices.cpp \ $$PWD/qwindowsnativeimage.cpp \ $$PWD/qwindowsnativeinterface.cpp \ - $$PWD/qwindowsscaling.cpp \ $$PWD/qwindowsopengltester.cpp HEADERS += \ @@ -52,7 +49,6 @@ HEADERS += \ $$PWD/qwindowsfontengine.h \ $$PWD/qwindowsfontdatabase.h \ $$PWD/qwindowsmousehandler.h \ - $$PWD/qwindowsguieventdispatcher.h \ $$PWD/qtwindowsglobal.h \ $$PWD/qtwindows_additional.h \ $$PWD/qwindowsole.h \ @@ -67,7 +63,6 @@ HEADERS += \ $$PWD/qplatformfunctions_wince.h \ $$PWD/qwindowsnativeimage.h \ $$PWD/qwindowsnativeinterface.h \ - $$PWD/qwindowsscaling.h \ $$PWD/qwindowsopengltester.h INCLUDEPATH += $$PWD @@ -136,3 +131,6 @@ contains(QT_CONFIG, freetype) { } contains(QT_CONFIG, accessibility):include($$PWD/accessible/accessible.pri) + +DEFINES *= LIBEGL_NAME=$${LIBEGL_NAME} +DEFINES *= LIBGLESV2_NAME=$${LIBGLESV2_NAME} |