diff options
Diffstat (limited to 'src/plugins/platforms/windows')
14 files changed, 267 insertions, 93 deletions
diff --git a/src/plugins/platforms/windows/accessible/accessible.pri b/src/plugins/platforms/windows/accessible/accessible.pri index 3069c2dda3..1a409cb87e 100644 --- a/src/plugins/platforms/windows/accessible/accessible.pri +++ b/src/plugins/platforms/windows/accessible/accessible.pri @@ -8,7 +8,7 @@ HEADERS += \ $$PWD/qwindowsaccessibility.h \ $$PWD/comutils.h -!*g++: { +!win32-g++*: { SOURCES += $$PWD/iaccessible2.cpp HEADERS += $$PWD/iaccessible2.h include(../../../../3rdparty/iaccessible2/iaccessible2.pri) diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index be680e7d48..ddab3cb0f2 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -114,6 +114,68 @@ HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitVersion(/* [retval][ } +/**************************************************************\ + * AccessibleRelation * + **************************************************************/ +AccessibleRelation::AccessibleRelation(const QList<QAccessibleInterface *> &targets, + QAccessible::Relation relation) + : m_targets(targets), m_relation(relation), m_ref(1) +{ + Q_ASSERT(m_targets.count()); +} + +/* IUnknown */ +HRESULT STDMETHODCALLTYPE AccessibleRelation::QueryInterface(REFIID id, LPVOID *iface) +{ + *iface = 0; + if (id == IID_IUnknown) + *iface = (IUnknown*)this; + + if (*iface) { + AddRef(); + return S_OK; + } + + return E_NOINTERFACE; +} + +ULONG STDMETHODCALLTYPE AccessibleRelation::AddRef() +{ + return ++m_ref; +} + +ULONG STDMETHODCALLTYPE AccessibleRelation::Release() +{ + if (!--m_ref) { + delete this; + return 0; + } + return m_ref; +} + +/* IAccessibleRelation */ +HRESULT STDMETHODCALLTYPE AccessibleRelation::get_relationType( + /* [retval][out] */ BSTR *relationType) +{ + *relationType = relationToBSTR(m_relation); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE AccessibleRelation::get_localizedRelationType( + /* [retval][out] */ BSTR *localizedRelationType) +{ + // Who ever needs this??? + *localizedRelationType = relationToBSTR(m_relation); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE AccessibleRelation::get_nTargets( + /* [retval][out] */ long *nTargets) +{ + // ### always one target + *nTargets = m_targets.count(); + return S_OK; +} /*! \internal @@ -140,7 +202,7 @@ HRESULT STDMETHODCALLTYPE AccessibleRelation::get_target( (see "Special Consideration when using Arrays", in Accessible2.idl) */ HRESULT STDMETHODCALLTYPE AccessibleRelation::get_targets( - /* [in] */ long maxTargets, // Hmmm, ignore ??? + /* [in] */ long maxTargets, /* [length_is][size_is][out] */ IUnknown **targets, /* [retval][out] */ long *nTargets) { @@ -215,6 +277,10 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryInterface(REFIID id, LPVOI return hr; } + +/* Note that IUnknown is inherited from several interfaces. Therefore we must reimplement all its + functions in the concrete class to avoid ambiguity. +*/ ULONG STDMETHODCALLTYPE QWindowsIA2Accessible::AddRef() { return QWindowsMsaaAccessible::AddRef(); diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.h b/src/plugins/platforms/windows/accessible/iaccessible2.h index 9b8a1ad3a6..0f9d3b3c41 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.h +++ b/src/plugins/platforms/windows/accessible/iaccessible2.h @@ -298,83 +298,27 @@ private: /**************************************************************\ - * IAccessibleRelation * + * AccessibleRelation * **************************************************************/ -struct AccessibleRelation : public IAccessibleRelation +class AccessibleRelation : public IAccessibleRelation { +public: AccessibleRelation(const QList<QAccessibleInterface *> &targets, - QAccessible::Relation relation) - : m_targets(targets), m_relation(relation), m_ref(1) - { - Q_ASSERT(m_targets.count()); - } + QAccessible::Relation relation); + virtual ~AccessibleRelation() {} /* IUnknown */ - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface) - { - *iface = 0; - if (id == IID_IUnknown) - *iface = (IUnknown*)this; - - if (*iface) { - AddRef(); - return S_OK; - } - - return E_NOINTERFACE; - } - - ULONG STDMETHODCALLTYPE AddRef() - { - return ++m_ref; - } - - ULONG STDMETHODCALLTYPE Release() - { - if (!--m_ref) { - delete this; - return 0; - } - return m_ref; - } + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); /* IAccessibleRelation */ - HRESULT STDMETHODCALLTYPE get_relationType( - /* [retval][out] */ BSTR *relationType) - { - *relationType = relationToBSTR(m_relation); - return S_OK; - } - - HRESULT STDMETHODCALLTYPE get_localizedRelationType( - /* [retval][out] */ BSTR *localizedRelationType) - { - // Who ever needs this??? - *localizedRelationType = relationToBSTR(m_relation); - return S_OK; - } - - HRESULT STDMETHODCALLTYPE get_nTargets( - /* [retval][out] */ long *nTargets) - { - // ### always one target - *nTargets = m_targets.count(); - return S_OK; - } - + HRESULT STDMETHODCALLTYPE get_relationType(BSTR *relationType); + HRESULT STDMETHODCALLTYPE get_localizedRelationType(BSTR *localizedRelationType); + HRESULT STDMETHODCALLTYPE get_nTargets(long *nTargets); HRESULT STDMETHODCALLTYPE get_target(long targetIndex, IUnknown **target); - - - /*! - \internal - Client allocates and deallocates \a targets array - (see "Special Consideration when using Arrays", in Accessible2.idl) - */ - HRESULT STDMETHODCALLTYPE get_targets( - /* [in] */ long maxTargets, // Hmmm, ignore ??? - /* [length_is][size_is][out] */ IUnknown **targets, - /* [retval][out] */ long *nTargets); + HRESULT STDMETHODCALLTYPE get_targets(long maxTargets, IUnknown **targets, long *nTargets); private: static BSTR relationToBSTR(QAccessible::Relation relation) diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 17420d271d..c5b1dcce9f 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -54,6 +54,7 @@ #include <QtGui/QWindow> #include <QtGui/QWindowSystemInterface> #include <QtGui/QPlatformNativeInterface> +#include <QtGui/QGuiApplication> #include <QtCore/QSet> #include <QtCore/QHash> @@ -276,7 +277,7 @@ QWindowsContext::QWindowsContext() : # pragma warning( disable : 4996 ) #endif m_instance = this; - if (const char *v = getenv("QT_LIGHTHOUSE_WINDOWS_VERBOSE")) { + if (const char *v = getenv("QT_QPA_VERBOSE")) { QWindowsContext::verboseIntegration = componentVerbose(v, "integration"); QWindowsContext::verboseWindows = componentVerbose(v, "windows"); QWindowsContext::verboseEvents = componentVerbose(v, "events"); @@ -791,6 +792,11 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, if (QWindowsTheme *theme = QWindowsTheme::instance()) theme->windowsThemeChanged(platformWindow->window()); return true; + case QtWindows::ActivateWindowEvent: + if (platformWindow->testFlag(QWindowsWindow::BlockedByModal)) + if (const QWindow *modalWindow = QGuiApplication::modalWindow()) + QWindowsWindow::baseWindowOf(modalWindow)->alertWindow(); + break; default: break; } diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index 337ba9ab27..ebcf1172db 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -369,8 +369,6 @@ QPoint QWindowsCursor::mousePosition() { POINT p; GetCursorPos(&p); - if (QWindowsContext::verboseWindows) - qDebug("%s %ld,%ld", __FUNCTION__, p.x, p.y); return QPoint(p.x, p.y); } diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index 9621846284..a6bde74103 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -116,6 +116,7 @@ typedef struct _COMDLG_FILTERSPEC #define FOS_DEFAULTNOMINIMODE 0x20000000 #define FOS_FORCEPREVIEWPANEON 0x40000000 +#if !defined(__MINGW64_VERSION_MAJOR) || (__MINGW64_VERSION_MAJOR < 2) typedef int GETPROPERTYSTOREFLAGS; #define GPS_DEFAULT 0x00000000 #define GPS_HANDLERPROPERTIESONLY 0x00000001 @@ -126,6 +127,7 @@ typedef int GETPROPERTYSTOREFLAGS; #define GPS_DELAYCREATION 0x00000020 #define GPS_BESTEFFORT 0x00000040 #define GPS_MASK_VALID 0x0000007F +#endif typedef int (QT_WIN_CALLBACK* BFFCALLBACK)(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData); // message from browser @@ -288,7 +290,9 @@ DECLARE_INTERFACE_(IFileOpenDialog, IFileDialog) STDMETHOD(GetSelectedItems)(THIS_ IShellItemArray **ppsai) PURE; }; +#if !defined(__MINGW64_VERSION_MAJOR) || (__MINGW64_VERSION_MAJOR < 2) typedef IUnknown IPropertyStore; +#endif typedef IUnknown IFileOperationProgressSink; DECLARE_INTERFACE_(IFileSaveDialog, IFileDialog) diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index c1c25dd686..979b2a028b 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -698,6 +698,32 @@ QStringList QWindowsFontDatabase::fallbacksForFamily(const QString family, const QStringList result = QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script); if (!result.isEmpty()) return result; + + switch (styleHint) { + case QFont::Times: + result << QString::fromLatin1("Times New Roman"); + break; + case QFont::Courier: + result << QString::fromLatin1("Courier New"); + break; + case QFont::Monospace: + result << QString::fromLatin1("Courier New"); + break; + case QFont::Cursive: + result << QString::fromLatin1("Comic Sans MS"); + break; + case QFont::Fantasy: + result << QString::fromLatin1("Impact"); + break; + case QFont::Decorative: + result << QString::fromLatin1("Old English"); + break; + case QFont::Helvetica: + case QFont::System: + default: + result << QString::fromLatin1("Arial"); + } + if (QWindowsContext::verboseFonts) qDebug() << __FUNCTION__ << family << style << styleHint << script << result << m_families.size(); @@ -874,6 +900,11 @@ QString QWindowsFontDatabase::fontDir() const return result; } +bool QWindowsFontDatabase::fontsAlwaysScalable() const +{ + return true; +} + HFONT QWindowsFontDatabase::systemFont() { static const HFONT stock_sysfont = (HFONT)GetStockObject(SYSTEM_FONT); diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.h b/src/plugins/platforms/windows/qwindowsfontdatabase.h index 2fa615253e..3921992775 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.h +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.h @@ -86,6 +86,8 @@ public: virtual QString fontDir() const; virtual QFont defaultFont() const { return systemDefaultFont(); } + virtual bool fontsAlwaysScalable() const; + static QFont systemDefaultFont(); static QFontEngine *createEngine(int script, const QFontDef &request, diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp index e84f0c7630..246b5b3710 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp @@ -422,6 +422,31 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString family, con QStringList result = QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script); if (!result.isEmpty()) return result; + + switch (styleHint) { + case QFont::Times: + result << QString::fromLatin1("Times New Roman"); + break; + case QFont::Courier: + result << QString::fromLatin1("Courier New"); + break; + case QFont::Monospace: + result << QString::fromLatin1("Courier New"); + break; + case QFont::Cursive: + result << QString::fromLatin1("Comic Sans MS"); + break; + case QFont::Fantasy: + result << QString::fromLatin1("Impact"); + break; + case QFont::Decorative: + result << QString::fromLatin1("Old English"); + break; + case QFont::Helvetica: + case QFont::System: + default: + result << QString::fromLatin1("Arial"); + } if (QWindowsContext::verboseFonts) qDebug() << __FUNCTION__ << family << style << styleHint << script << result << m_families; diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp index 007f6d597a..94072622eb 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.cpp +++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp @@ -179,14 +179,14 @@ void QWindowsFontEngine::getCMap() } } - +// ### Qt 5.1: replace with QStringIterator inline unsigned int getChar(const QChar *str, int &i, const int len) { - unsigned int uc = str[i].unicode(); - if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) { + uint uc = str[i].unicode(); + if (QChar::isHighSurrogate(uc) && i < len-1) { uint low = str[i+1].unicode(); - if (low >= 0xdc00 && low < 0xe000) { - uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000; + if (QChar::isLowSurrogate(low)) { + uc = QChar::surrogateToUcs4(uc, low); ++i; } } @@ -402,7 +402,7 @@ void QWindowsFontEngine::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::Shape if (!ttf) { QChar ch[2] = { ushort(glyph), 0 }; int chrLen = 1; - if (glyph > 0xffff) { + if (QChar::requiresSurrogates(glyph)) { ch[0] = QChar::highSurrogate(glyph); ch[1] = QChar::lowSurrogate(glyph); ++chrLen; diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index c8906bd3c9..4dbb2cf65b 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -295,13 +295,14 @@ QFixed QWindowsFontEngineDirectWrite::emSquareSize() const return QFontEngine::emSquareSize(); } +// ### Qt 5.1: replace with QStringIterator inline unsigned int getChar(const QChar *str, int &i, const int len) { - unsigned int uc = str[i].unicode(); - if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) { + uint uc = str[i].unicode(); + if (QChar::isHighSurrogate(uc) && i < len-1) { uint low = str[i+1].unicode(); - if (low >= 0xdc00 && low < 0xe000) { - uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000; + if (QChar::isLowSurrogate(low)) { + uc = QChar::surrogateToUcs4(uc, low); ++i; } } diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 47d6a2f11a..d8d04fc1b6 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -228,8 +228,6 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co QPlatformPixmap *QWindowsIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const { - if (QWindowsContext::verboseIntegration) - qDebug() << __FUNCTION__ << type; return new QRasterPlatformPixmap(type); } @@ -279,17 +277,44 @@ QPlatformOpenGLContext return 0; } +/* Workaround for QTBUG-24205: In 'Auto', pick the FreeType engine for + * QML2 applications. */ + +enum FontDatabaseOption { + FontDatabaseAuto, + FontDatabaseFreeType, + FontDatabaseNative +}; + +static inline FontDatabaseOption fontDatabaseOption(const QObject &nativeInterface) +{ + const QVariant argumentV = nativeInterface.property("fontengine"); + if (argumentV.isValid()) { + const QString argument = argumentV.toString(); + if (argument == QLatin1String("freetype")) + return FontDatabaseFreeType; + if (argument == QLatin1String("native")) + return FontDatabaseNative; + } + return FontDatabaseAuto; +} + QPlatformFontDatabase *QWindowsIntegration::fontDatabase() const { if (!d->m_fontDatabase) { -#ifndef QT_NO_FREETYPE - const QVariant argument = d->m_nativeInterface.property("fontengine"); - if (argument.isValid() && argument.toString() == QLatin1String("freetype")) - d->m_fontDatabase = new QWindowsFontDatabaseFT(); - else - d->m_fontDatabase = new QWindowsFontDatabase(); -#else +#ifdef QT_NO_FREETYPE d->m_fontDatabase = new QWindowsFontDatabase(); +#else + FontDatabaseOption option = fontDatabaseOption(d->m_nativeInterface); + if (option == FontDatabaseAuto) { + option = QCoreApplication::applicationName() == QStringLiteral("QtQmlViewer") ? + FontDatabaseFreeType : FontDatabaseNative; + } + if (option == FontDatabaseFreeType) { + d->m_fontDatabase = new QWindowsFontDatabaseFT; + } else { + d->m_fontDatabase = new QWindowsFontDatabase; + } #endif } return d->m_fontDatabase; diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 6ff854805c..38a44e2b5a 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -704,8 +704,11 @@ void QWindowsWindow::setVisible(bool visible) if (m_data.hwnd) { if (visible) { show_sys(); + QWindowSystemInterface::handleSynchronousExposeEvent(window(), + QRect(QPoint(), geometry().size())); } else { hide_sys(); + QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRegion()); } } } @@ -1191,6 +1194,22 @@ void QWindowsWindow::lower() SetWindowPos(m_data.hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); } +void QWindowsWindow::windowEvent(QEvent *event) +{ + switch (event->type()) { + case QEvent::WindowBlocked: // Blocked by another modal window. + setEnabled(false); + setFlag(BlockedByModal); + break; + case QEvent::WindowUnblocked: + setEnabled(true); + clearFlag(BlockedByModal); + break; + default: + break; + } +} + void QWindowsWindow::propagateSizeHints() { if (QWindowsContext::verboseWindows) @@ -1351,6 +1370,50 @@ QWindowsWindow *QWindowsWindow::childAt(const QPoint &clientPoint, unsigned cwex return 0; } +void QWindowsWindow::alertWindow(int durationMs) +{ + DWORD timeOutMs = GetCaretBlinkTime(); + if (!timeOutMs || timeOutMs == INFINITE) + timeOutMs = 250; + + FLASHWINFO info; + info.cbSize = sizeof(info); + info.hwnd = m_data.hwnd; + info.dwFlags = FLASHW_TRAY; + info.dwTimeout = timeOutMs; + info.uCount = durationMs == 0 ? 10 : durationMs / timeOutMs; + FlashWindowEx(&info); +} + +void QWindowsWindow::stopAlertWindow() +{ + FLASHWINFO info; + info.cbSize = sizeof(info); + info.hwnd = m_data.hwnd; + info.dwFlags = FLASHW_STOP; + info.dwTimeout = 0; + info.uCount = 0; + FlashWindowEx(&info); +} + +bool QWindowsWindow::isEnabled() const +{ + return (style() & WS_DISABLED) == 0; +} + +void QWindowsWindow::setEnabled(bool enabled) +{ + const unsigned oldStyle = style(); + unsigned newStyle = oldStyle; + if (enabled) { + newStyle &= ~WS_DISABLED; + } else { + newStyle |= WS_DISABLED; + } + if (newStyle != oldStyle) + setStyle(newStyle); +} + QByteArray QWindowsWindow::debugWindowFlags(Qt::WindowFlags wf) { const int iwf = int(wf); diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index e3336d1c3a..badc229718 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -100,7 +100,8 @@ public: FrameDirty = 0x4, //! Frame outdated by setStyle, recalculate in next query. OpenGLSurface = 0x10, OpenGLDoubleBuffered = 0x20, - OpenGlPixelFormatInitialized = 0x40 + OpenGlPixelFormatInitialized = 0x40, + BlockedByModal = 0x80 }; struct WindowData @@ -137,6 +138,8 @@ public: virtual void raise(); virtual void lower(); + void windowEvent(QEvent *event); + virtual void propagateSizeHints(); virtual QMargins frameMargins() const; @@ -189,6 +192,12 @@ public: inline void setFlag(unsigned f) const { m_flags |= f; } inline void clearFlag(unsigned f) const { m_flags &= ~f; } + void setEnabled(bool enabled); + bool isEnabled() const; + + void alertWindow(int durationMs = 0); + void stopAlertWindow(); + private: inline void show_sys() const; inline void hide_sys() const; |