diff options
author | Oswald Buddenhagen <oswald.buddenhagen@nokia.com> | 2012-04-10 12:48:01 +0200 |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@nokia.com> | 2012-04-10 15:31:45 +0200 |
commit | 143c4d3e13a430b951f4f4f8c28db14303f80605 (patch) | |
tree | 2b89637b93fc7d81c674106008566010f986d67c /src/plugins/platforms/windows | |
parent | a7ed81b557d593a8ddb43b71bf4bbf3b44ead070 (diff) | |
parent | e5337ad1b1fb02873ce7b5ca8db45f6fd8063352 (diff) |
Merge remote-tracking branch 'origin/master' into api_changes
Conflicts:
configure
src/widgets/styles/qwindowsxpstyle.cpp
tests/auto/gui/kernel/qwindow/qwindow.pro
tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
Change-Id: I624b6d26abce9874c610c04954c1c45bc074bef3
Diffstat (limited to 'src/plugins/platforms/windows')
9 files changed, 248 insertions, 58 deletions
diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index c3d5c543cf..be680e7d48 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -169,7 +169,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryInterface(REFIID id, LPVOI { HRESULT hr = QWindowsMsaaAccessible::QueryInterface(id, iface); if (!SUCCEEDED(hr)) { - if (id == IID_IAccessible2) { + if (id == IID_IServiceProvider) { + *iface = (IServiceProvider*)this; + } else if (id == IID_IAccessible2) { *iface = (IAccessible2*)this; } else if (id == IID_IAccessibleAction) { if (accessible->actionInterface()) diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp index bd928399c8..0672a86dd9 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp @@ -232,9 +232,6 @@ QWindow *QWindowsAccessibility::windowHelper(const QAccessibleInterface *iface) */ IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc) { -#ifdef Q_CC_MINGW - return 0; -#else if (!acc) return 0; #ifdef Q_CC_MINGW @@ -245,7 +242,6 @@ IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc) IAccessible *iacc = 0; wacc->QueryInterface(IID_IAccessible, (void**)&iacc); return iacc; -#endif } /*! diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index e0be731b53..c1c25dd686 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -51,6 +51,7 @@ #include <QtCore/qmath.h> #include <QtCore/QDebug> +#include <QtCore/QtEndian> #include <wchar.h> @@ -68,8 +69,10 @@ QT_BEGIN_NAMESPACE */ QWindowsFontEngineData::QWindowsFontEngineData() + : clearTypeEnabled(false) + , fontSmoothingGamma(QWindowsFontDatabase::fontSmoothingGamma()) #if !defined(QT_NO_DIRECTWRITE) - : directWriteFactory(0) + , directWriteFactory(0) , directWriteGdiInterop(0) #endif { @@ -78,17 +81,6 @@ QWindowsFontEngineData::QWindowsFontEngineData() if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0)) clearTypeEnabled = (result == FE_FONTSMOOTHINGCLEARTYPE); - int winSmooth; - if (SystemParametersInfo(0x200C /* SPI_GETFONTSMOOTHINGCONTRAST */, 0, &winSmooth, 0)) { - fontSmoothingGamma = winSmooth / qreal(1000.0); - } else { - fontSmoothingGamma = 1.0; - } - - // Safeguard ourselves against corrupt registry values... - if (fontSmoothingGamma > 5 || fontSmoothingGamma < 1) - fontSmoothingGamma = qreal(1.4); - const qreal gray_gamma = 2.31; for (int i=0; i<256; ++i) pow_gamma[i] = uint(qRound(qPow(i / qreal(255.), gray_gamma) * 2047)); @@ -110,6 +102,19 @@ QWindowsFontEngineData::~QWindowsFontEngineData() #endif } +qreal QWindowsFontDatabase::fontSmoothingGamma() +{ + int winSmooth; + qreal result = 1; + if (SystemParametersInfo(0x200C /* SPI_GETFONTSMOOTHINGCONTRAST */, 0, &winSmooth, 0)) + result = qreal(winSmooth) / qreal(1000.0); + + // Safeguard ourselves against corrupt registry values... + if (result > 5 || result < 1) + result = qreal(1.4); + return result; +} + #if !defined(QT_NO_DIRECTWRITE) static inline bool initDirectWrite(QWindowsFontEngineData *d) { @@ -614,14 +619,14 @@ static int CALLBACK storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric, void QWindowsFontDatabase::populateFontDatabase() { - if (m_families.isEmpty()) { - QPlatformFontDatabase::populateFontDatabase(); - populate(); // Called multiple times. - // Work around EnumFontFamiliesEx() not listing the system font, see below. - const QString sysFontFamily = QGuiApplication::font().family(); - if (!m_families.contains(sysFontFamily)) - populate(sysFontFamily); - } + m_families.clear(); + removeApplicationFonts(); + QPlatformFontDatabase::populateFontDatabase(); + populate(); // Called multiple times. + // Work around EnumFontFamiliesEx() not listing the system font, see below. + const QString sysFontFamily = QGuiApplication::font().family(); + if (!m_families.contains(sysFontFamily)) + populate(sysFontFamily); } /*! @@ -665,6 +670,7 @@ QWindowsFontDatabase::QWindowsFontDatabase() : QWindowsFontDatabase::~QWindowsFontDatabase() { + removeApplicationFonts(); } QFontEngine * QWindowsFontDatabase::fontEngine(const QFontDef &fontDef, @@ -698,11 +704,160 @@ QStringList QWindowsFontDatabase::fallbacksForFamily(const QString family, const return result; } +static QList<quint32> getTrueTypeFontOffsets(const uchar *fontData) +{ + QList<quint32> offsets; + const quint32 headerTag = *reinterpret_cast<const quint32 *>(fontData); + if (headerTag != MAKE_TAG('t', 't', 'c', 'f')) { + if (headerTag != MAKE_TAG(0, 1, 0, 0) + && headerTag != MAKE_TAG('O', 'T', 'T', 'O') + && headerTag != MAKE_TAG('t', 'r', 'u', 'e') + && headerTag != MAKE_TAG('t', 'y', 'p', '1')) + return offsets; + offsets << 0; + return offsets; + } + const quint32 numFonts = qFromBigEndian<quint32>(fontData + 8); + for (uint i = 0; i < numFonts; ++i) { + offsets << qFromBigEndian<quint32>(fontData + 12 + i * 4); + } + return offsets; +} + +static void getFontTable(const uchar *fileBegin, const uchar *data, quint32 tag, const uchar **table, quint32 *length) +{ + const quint16 numTables = qFromBigEndian<quint16>(data + 4); + for (uint i = 0; i < numTables; ++i) { + const quint32 offset = 12 + 16 * i; + if (*reinterpret_cast<const quint32 *>(data + offset) == tag) { + *table = fileBegin + qFromBigEndian<quint32>(data + offset + 8); + *length = qFromBigEndian<quint32>(data + offset + 12); + return; + } + } + *table = 0; + *length = 0; + return; +} + +static void getFamiliesAndSignatures(const QByteArray &fontData, + QStringList *families, + QVector<FONTSIGNATURE> *signatures) +{ + const uchar *data = reinterpret_cast<const uchar *>(fontData.constData()); + + QList<quint32> offsets = getTrueTypeFontOffsets(data); + if (offsets.isEmpty()) + return; + + for (int i = 0; i < offsets.count(); ++i) { + const uchar *font = data + offsets.at(i); + const uchar *table; + quint32 length; + getFontTable(data, font, MAKE_TAG('n', 'a', 'm', 'e'), &table, &length); + if (!table) + continue; + QString name = getEnglishName(table, length); + if (name.isEmpty()) + continue; + + families->append(name); + + if (signatures) { + FONTSIGNATURE signature; + getFontTable(data, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length); + if (table && length >= 86) { + // Offsets taken from OS/2 table in the TrueType spec + signature.fsUsb[0] = qFromBigEndian<quint32>(table + 42); + signature.fsUsb[1] = qFromBigEndian<quint32>(table + 46); + signature.fsUsb[2] = qFromBigEndian<quint32>(table + 50); + signature.fsUsb[3] = qFromBigEndian<quint32>(table + 54); + + signature.fsCsb[0] = qFromBigEndian<quint32>(table + 78); + signature.fsCsb[1] = qFromBigEndian<quint32>(table + 82); + } else { + memset(&signature, 0, sizeof(signature)); + } + signatures->append(signature); + } + } +} + QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) { - const QStringList result = QPlatformFontDatabase::addApplicationFont(fontData, fileName); - Q_UNIMPLEMENTED(); - return result; + WinApplicationFont font; + font.fileName = fileName; + QVector<FONTSIGNATURE> signatures; + QStringList families; + + if (!fontData.isEmpty()) { + getFamiliesAndSignatures(fontData, &families, &signatures); + if (families.isEmpty()) + return families; + + DWORD dummy = 0; + font.handle = AddFontMemResourceEx((void *)fontData.constData(), fontData.size(), 0, + &dummy); + if (font.handle == 0) + return QStringList(); + + // Memory fonts won't show up in enumeration, so do add them the hard way. + for (int j = 0; j < families.count(); ++j) { + const QString familyName = families.at(j); + HDC hdc = GetDC(0); + LOGFONT lf; + memset(&lf, 0, sizeof(LOGFONT)); + memcpy(lf.lfFaceName, familyName.utf16(), sizeof(wchar_t) * qMin(LF_FACESIZE, familyName.size())); + lf.lfCharSet = DEFAULT_CHARSET; + HFONT hfont = CreateFontIndirect(&lf); + HGDIOBJ oldobj = SelectObject(hdc, hfont); + + TEXTMETRIC textMetrics; + GetTextMetrics(hdc, &textMetrics); + + addFontToDatabase(familyName, QString(), &textMetrics, &signatures.at(j), + TRUETYPE_FONTTYPE); + + SelectObject(hdc, oldobj); + DeleteObject(hfont); + ReleaseDC(0, hdc); + } + } else { + QFile f(fileName); + if (!f.open(QIODevice::ReadOnly)) + return families; + QByteArray data = f.readAll(); + f.close(); + + getFamiliesAndSignatures(data, &families, 0); + if (families.isEmpty()) + return families; + + if (AddFontResourceExW((wchar_t*)fileName.utf16(), FR_PRIVATE, 0) == 0) + return QStringList(); + + font.handle = 0; + + // Fonts based on files are added via populate, as they will show up in font enumeration. + for (int j = 0; j < families.count(); ++j) + populate(families.at(j)); + } + + m_applicationFonts << font; + + return families; +} + +void QWindowsFontDatabase::removeApplicationFonts() +{ + foreach (const WinApplicationFont &font, m_applicationFonts) { + if (font.handle) { + RemoveFontMemResourceEx(font.handle); + } else { + RemoveFontResourceExW((LPCWSTR)font.fileName.utf16(), FR_PRIVATE, 0); + } + } + m_applicationFonts.clear(); } void QWindowsFontDatabase::releaseHandle(void *handle) diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.h b/src/plugins/platforms/windows/qwindowsfontdatabase.h index f8f2a1eb85..2fa615253e 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.h +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.h @@ -96,10 +96,20 @@ public: static HFONT systemFont(); static QFont LOGFONT_to_QFont(const LOGFONT& lf, int verticalDPI = 0); + static qreal fontSmoothingGamma(); + private: void populate(const QString &family = QString()); + void removeApplicationFonts(); QSharedPointer<QWindowsFontEngineData> m_fontEngineData; QSet<QString> m_families; + + struct WinApplicationFont { + HANDLE handle; + QString fileName; + }; + + QList<WinApplicationFont> m_applicationFonts; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp index f90a880cd3..e84f0c7630 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp @@ -195,9 +195,11 @@ static bool addFontToDatabase(QString familyName, const QString &scriptName, const QStringList allKeys = fontRegistry.allKeys(); allFonts.reserve(allKeys.size()); const QString trueType = QStringLiteral("(TrueType)"); + const QRegExp sizeListMatch(QStringLiteral("\\s(\\d+,)+\\d+")); foreach (const QString &key, allKeys) { QString realKey = key; realKey.remove(trueType); + realKey.remove(sizeListMatch); QStringList fonts; const QStringList fontNames = realKey.trimmed().split(QLatin1Char('&')); foreach (const QString &fontName, fontNames) @@ -273,14 +275,13 @@ static int CALLBACK storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric, void QWindowsFontDatabaseFT::populateFontDatabase() { - if (m_families.isEmpty()) { - QPlatformFontDatabase::populateFontDatabase(); - populate(); // Called multiple times. - // Work around EnumFontFamiliesEx() not listing the system font, see below. - const QString sysFontFamily = QGuiApplication::font().family(); - if (!m_families.contains(sysFontFamily)) - populate(sysFontFamily); - } + m_families.clear(); + QPlatformFontDatabase::populateFontDatabase(); + populate(); // Called multiple times. + // Work around EnumFontFamiliesEx() not listing the system font, see below. + const QString sysFontFamily = QGuiApplication::font().family(); + if (!m_families.contains(sysFontFamily)) + populate(sysFontFamily); } /*! @@ -426,14 +427,6 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString family, con << script << result << m_families; return result; } - -QStringList QWindowsFontDatabaseFT::addApplicationFont(const QByteArray &fontData, const QString &fileName) -{ - const QStringList result = QPlatformFontDatabase::addApplicationFont(fontData, fileName); - Q_UNIMPLEMENTED(); - return result; -} - QString QWindowsFontDatabaseFT::fontDir() const { const QString result = QLatin1String(qgetenv("windir")) + QLatin1String("/Fonts");//QPlatformFontDatabase::fontDir(); diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h index 24810c9202..bb55b68251 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h @@ -56,7 +56,6 @@ public: QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference); QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const; - QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName); virtual QString fontDir() const; virtual QFont defaultFont() const; diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index ae5053210e..03a76258f4 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -184,7 +184,7 @@ void QWindowsInputContext::reset() QPlatformInputContext::reset(); if (!m_compositionContext.hwnd) return; - QObject *fo = qApp->inputMethod()->inputItem(); + QObject *fo = qApp->focusObject(); if (QWindowsContext::verboseInputMethods) qDebug() << __FUNCTION__<< fo; if (!fo) @@ -329,11 +329,11 @@ static inline QTextFormat standardFormat(StandardFormat format) bool QWindowsInputContext::startComposition(HWND hwnd) { - const QObject *fo = qApp->inputMethod()->inputItem(); + const QObject *fo = qApp->focusObject(); if (!fo) return false; // This should always match the object. - QWindow *window = qApp->inputMethod()->inputWindow(); + QWindow *window = qApp->focusWindow(); if (!window) return false; if (QWindowsContext::verboseInputMethods) @@ -397,7 +397,7 @@ static inline QList<QInputMethodEvent::Attribute> bool QWindowsInputContext::composition(HWND hwnd, LPARAM lParamIn) { - QObject *fo = qApp->inputMethod()->inputItem(); + QObject *fo = qApp->focusObject(); const int lParam = int(lParamIn); if (QWindowsContext::verboseInputMethods) qDebug() << '>' << __FUNCTION__ << fo << debugComposition(lParam) @@ -459,7 +459,7 @@ bool QWindowsInputContext::endComposition(HWND hwnd) // against that. if (m_endCompositionRecursionGuard || m_compositionContext.hwnd != hwnd) return false; - QObject *fo = qApp->inputMethod()->inputItem(); + QObject *fo = qApp->focusObject(); if (!fo) return false; @@ -537,7 +537,7 @@ bool QWindowsInputContext::handleIME_Request(WPARAM wParam, int QWindowsInputContext::reconvertString(RECONVERTSTRING *reconv) { - QObject *fo = qApp->inputMethod()->inputItem(); + QObject *fo = qApp->focusObject(); if (!fo) return false; diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index ee58a19ca9..47d6a2f11a 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -283,10 +283,11 @@ QPlatformFontDatabase *QWindowsIntegration::fontDatabase() const { if (!d->m_fontDatabase) { #ifndef QT_NO_FREETYPE - if (d->m_nativeInterface.property("fontengine").toString() == QLatin1String("native")) - d->m_fontDatabase = new QWindowsFontDatabase(); - else + 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 d->m_fontDatabase = new QWindowsFontDatabase(); #endif @@ -317,6 +318,8 @@ QVariant QWindowsIntegration::styleHint(QPlatformIntegration::StyleHint hint) co case QPlatformIntegration::KeyboardInputInterval: case QPlatformIntegration::ShowIsFullScreen: break; // Not implemented + case QPlatformIntegration::FontSmoothingGamma: + return QVariant(QWindowsFontDatabase::fontSmoothingGamma()); } return QPlatformIntegration::styleHint(hint); } diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index f3a9d91d00..000311a807 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -68,12 +68,27 @@ static inline QTextStream& operator<<(QTextStream &str, const QColor &c) return str; } +static inline void paletteRoleToString(const QPalette &palette, + const QPalette::ColorRole role, + QTextStream &str) +{ + str << "Role: "; + str.setFieldWidth(2); + str.setPadChar(QLatin1Char('0')); + str << role; + str.setFieldWidth(0); + str << " Active: " << palette.color(QPalette::Active, role) + << " Disabled: " << palette.color(QPalette::Disabled, role) + << " Inactive: " << palette.color(QPalette::Inactive, role) + << '\n'; +} + static inline QString paletteToString(const QPalette &palette) { QString result; QTextStream str(&result); - str << "text=" << palette.color(QPalette::WindowText) - << " background=" << palette.color(QPalette::Window); + for (int r = 0; r < QPalette::NColorRoles; ++r) + paletteRoleToString(palette, static_cast<QPalette::ColorRole>(r), str); return result; } @@ -105,9 +120,26 @@ static inline QColor getSysColor(int index) return qColorToCOLORREF(GetSysColor(index)); } +// from QStyle::standardPalette +static inline QPalette standardPalette() +{ + QColor backgroundColor(0xd4, 0xd0, 0xc8); // win 2000 grey + QColor lightColor(backgroundColor.lighter()); + QColor darkColor(backgroundColor.darker()); + const QBrush darkBrush(darkColor); + QColor midColor(Qt::gray); + QPalette palette(Qt::black, backgroundColor, lightColor, darkColor, + midColor, Qt::black, Qt::white); + palette.setBrush(QPalette::Disabled, QPalette::WindowText, darkBrush); + palette.setBrush(QPalette::Disabled, QPalette::Text, darkBrush); + palette.setBrush(QPalette::Disabled, QPalette::ButtonText, darkBrush); + palette.setBrush(QPalette::Disabled, QPalette::Base, QBrush(backgroundColor)); + return palette; +} + static inline QPalette systemPalette() { - QPalette result; + QPalette result = standardPalette(); result.setColor(QPalette::WindowText, getSysColor(COLOR_WINDOWTEXT)); result.setColor(QPalette::Button, getSysColor(COLOR_BTNFACE)); result.setColor(QPalette::Light, getSysColor(COLOR_BTNHIGHLIGHT)); @@ -183,7 +215,7 @@ static inline QPalette toolTipPalette(const QPalette &systemPalette) static inline QPalette menuPalette(const QPalette &systemPalette) { QPalette result(systemPalette); - const QColor menuColor(getSysColor(COLOR_INFOBK)); + const QColor menuColor(getSysColor(COLOR_MENU)); const QColor menuTextColor(getSysColor(COLOR_MENUTEXT)); const QColor disabled(getSysColor(COLOR_GRAYTEXT)); const bool isFlat = booleanSystemParametersInfo(SPI_GETFLATMENU, false); |