From 8d7e23ea0b6d0e198e445e3cd4285a34d4e7dc96 Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Wed, 21 May 2014 13:25:26 +0300 Subject: Direct2D QPA: Cache QVectorPaths if drawn more than once Hooking into the caching mechanism gets us a measurable performance boost for paths that are drawn repeatedly, around 10% on my machine when drawing aliased arcs. Change-Id: I32f4ed7daa8a51b5c5a9c6d5414ab5d4ef759f70 Reviewed-by: Risto Avila Reviewed-by: Friedemann Kleint --- .../direct2d/qwindowsdirect2dpaintengine.cpp | 49 +++++++++++++++++++--- 1 file changed, 43 insertions(+), 6 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp index a838950c9e..f376f7707f 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp @@ -256,8 +256,30 @@ static ComPtr painterPathToID2D1PathGeometry(const QPainterP return writer.geometry(); } -static ComPtr vectorPathToID2D1PathGeometry(const QVectorPath &path, bool alias) +struct D2DVectorPathCache { + ComPtr aliased; + ComPtr antiAliased; + + static void cleanup_func(QPaintEngineEx *engine, void *data) { + Q_UNUSED(engine); + D2DVectorPathCache *e = static_cast(data); + delete e; + } +}; + +static ComPtr vectorPathToID2D1PathGeometry(const QVectorPath &path, bool alias, QPaintEngineEx* engine) { + QVectorPath::CacheEntry *cacheEntry = path.isCacheable() ? path.lookupCacheData(engine) + : Q_NULLPTR; + + if (cacheEntry) { + D2DVectorPathCache *e = static_cast(cacheEntry->data); + if (alias && e->aliased) + return e->aliased; + else if (!alias && e->antiAliased) + return e->antiAliased; + } + Direct2DPathGeometryWriter writer; if (!writer.begin()) return NULL; @@ -321,7 +343,22 @@ static ComPtr vectorPathToID2D1PathGeometry(const QVectorPat writer.lineTo(QPointF(points[0], points[1])); writer.close(); - return writer.geometry(); + ComPtr geometry = writer.geometry(); + + if (path.isCacheable()) { + if (!cacheEntry) + cacheEntry = path.addCacheData(engine, new D2DVectorPathCache, D2DVectorPathCache::cleanup_func); + + D2DVectorPathCache *e = static_cast(cacheEntry->data); + if (alias) + e->aliased = geometry; + else + e->antiAliased = geometry; + } else { + path.makeCacheable(); + } + + return geometry; } class QWindowsDirect2DPaintEnginePrivate : public QPaintEngineExPrivate @@ -426,7 +463,7 @@ public: dc()->PushAxisAlignedClip(rect, antialiasMode()); pushedClips.push(AxisAlignedClip); } else { - ComPtr geometry = vectorPathToID2D1PathGeometry(path, antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED); + ComPtr geometry = vectorPathToID2D1PathGeometry(path, antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED, q); if (!geometry) { qWarning("%s: Could not convert vector path to painter path!", __FUNCTION__); return; @@ -938,7 +975,7 @@ void QWindowsDirect2DPaintEngine::draw(const QVectorPath &path) { Q_D(QWindowsDirect2DPaintEngine); - ComPtr geometry = vectorPathToID2D1PathGeometry(path, d->antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED); + ComPtr geometry = vectorPathToID2D1PathGeometry(path, d->antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED, this); if (!geometry) { qWarning("%s: Could not convert path to d2d geometry", __FUNCTION__); return; @@ -978,7 +1015,7 @@ void QWindowsDirect2DPaintEngine::fill(const QVectorPath &path, const QBrush &br if (!d->brush.brush) return; - ComPtr geometry = vectorPathToID2D1PathGeometry(path, d->antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED); + ComPtr geometry = vectorPathToID2D1PathGeometry(path, d->antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED, this); if (!geometry) { qWarning("%s: Could not convert path to d2d geometry", __FUNCTION__); return; @@ -1016,7 +1053,7 @@ void QWindowsDirect2DPaintEngine::stroke(const QVectorPath &path, const QPen &pe if (!d->pen.brush) return; - ComPtr geometry = vectorPathToID2D1PathGeometry(path, d->antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED); + ComPtr geometry = vectorPathToID2D1PathGeometry(path, d->antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED, this); if (!geometry) { qWarning("%s: Could not convert path to d2d geometry", __FUNCTION__); return; -- cgit v1.2.3 From bcab05cb4f35d8bfab3755a4358e6af1adc801f5 Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Wed, 21 May 2014 14:02:42 +0300 Subject: Direct2D QPA: Get rid of QPainterPath conversion function This function was used only in one place and duplicated a lot of logic with the very similar QVectorPath conversion function. Just use QVectorPath everywhere instead. Change-Id: I3a4821f0452634c309ca0730047ea6ef7a7591ca Reviewed-by: Risto Avila Reviewed-by: Friedemann Kleint --- .../direct2d/qwindowsdirect2dpaintengine.cpp | 49 ++-------------------- 1 file changed, 3 insertions(+), 46 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp index f376f7707f..18844a2ce5 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp @@ -211,51 +211,6 @@ private: bool m_roundCoordinates; }; -static ComPtr painterPathToID2D1PathGeometry(const QPainterPath &path, bool alias) -{ - Direct2DPathGeometryWriter writer; - if (!writer.begin()) - return NULL; - - writer.setWindingFillEnabled(path.fillRule() == Qt::WindingFill); - writer.setAliasingEnabled(alias); - - for (int i = 0; i < path.elementCount(); i++) { - const QPainterPath::Element element = path.elementAt(i); - - switch (element.type) { - case QPainterPath::MoveToElement: - writer.moveTo(element); - break; - - case QPainterPath::LineToElement: - writer.lineTo(element); - break; - - case QPainterPath::CurveToElement: - { - const QPainterPath::Element data1 = path.elementAt(++i); - const QPainterPath::Element data2 = path.elementAt(++i); - - Q_ASSERT(i < path.elementCount()); - - Q_ASSERT(data1.type == QPainterPath::CurveToDataElement); - Q_ASSERT(data2.type == QPainterPath::CurveToDataElement); - - writer.curveTo(element, data1, data2); - } - break; - - case QPainterPath::CurveToDataElement: - qWarning("%s: Unhandled Curve Data Element", __FUNCTION__); - break; - } - } - - writer.close(); - return writer.geometry(); -} - struct D2DVectorPathCache { ComPtr aliased; ComPtr antiAliased; @@ -908,7 +863,9 @@ bool QWindowsDirect2DPaintEngine::begin(QPaintDevice * pdev) QPainterPath p; p.addRegion(systemClip()); - ComPtr geometry = painterPathToID2D1PathGeometry(p, d->antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED); + ComPtr geometry = vectorPathToID2D1PathGeometry(qtVectorPathForPath(p), + d->antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED, + this); if (!geometry) return false; -- cgit v1.2.3 From 26a2fb744866414748ed35a36322460b06911394 Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Wed, 21 May 2014 14:11:14 +0300 Subject: Direct2D QPA: Move QVectorPath conversion function into private class The function already needs information from the engine for conversion, moving it into the private class makes it possible to get this info directly in the method and makes calling the method nicer. Change-Id: I47fa9a4531d0d0605aa587fba90fbfdf036f0998 Reviewed-by: Risto Avila Reviewed-by: Friedemann Kleint --- .../direct2d/qwindowsdirect2dpaintengine.cpp | 204 +++++++++++---------- 1 file changed, 103 insertions(+), 101 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp index 18844a2ce5..3b598b365d 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp @@ -222,100 +222,6 @@ struct D2DVectorPathCache { } }; -static ComPtr vectorPathToID2D1PathGeometry(const QVectorPath &path, bool alias, QPaintEngineEx* engine) -{ - QVectorPath::CacheEntry *cacheEntry = path.isCacheable() ? path.lookupCacheData(engine) - : Q_NULLPTR; - - if (cacheEntry) { - D2DVectorPathCache *e = static_cast(cacheEntry->data); - if (alias && e->aliased) - return e->aliased; - else if (!alias && e->antiAliased) - return e->antiAliased; - } - - Direct2DPathGeometryWriter writer; - if (!writer.begin()) - return NULL; - - writer.setWindingFillEnabled(path.hasWindingFill()); - writer.setAliasingEnabled(alias); - - const QPainterPath::ElementType *types = path.elements(); - const int count = path.elementCount(); - const qreal *points = path.points(); - - Q_ASSERT(points); - - if (types) { - qreal x, y; - - for (int i = 0; i < count; i++) { - x = points[i * 2]; - y = points[i * 2 + 1]; - - switch (types[i]) { - case QPainterPath::MoveToElement: - writer.moveTo(QPointF(x, y)); - break; - - case QPainterPath::LineToElement: - writer.lineTo(QPointF(x, y)); - break; - - case QPainterPath::CurveToElement: - { - Q_ASSERT((i + 2) < count); - Q_ASSERT(types[i+1] == QPainterPath::CurveToDataElement); - Q_ASSERT(types[i+2] == QPainterPath::CurveToDataElement); - - i++; - const qreal x2 = points[i * 2]; - const qreal y2 = points[i * 2 + 1]; - - i++; - const qreal x3 = points[i * 2]; - const qreal y3 = points[i * 2 + 1]; - - writer.curveTo(QPointF(x, y), QPointF(x2, y2), QPointF(x3, y3)); - } - break; - - case QPainterPath::CurveToDataElement: - qWarning("%s: Unhandled Curve Data Element", __FUNCTION__); - break; - } - } - } else { - writer.moveTo(QPointF(points[0], points[1])); - for (int i = 1; i < count; i++) - writer.lineTo(QPointF(points[i * 2], points[i * 2 + 1])); - } - - if (writer.isInFigure()) - if (path.hasImplicitClose()) - writer.lineTo(QPointF(points[0], points[1])); - - writer.close(); - ComPtr geometry = writer.geometry(); - - if (path.isCacheable()) { - if (!cacheEntry) - cacheEntry = path.addCacheData(engine, new D2DVectorPathCache, D2DVectorPathCache::cleanup_func); - - D2DVectorPathCache *e = static_cast(cacheEntry->data); - if (alias) - e->aliased = geometry; - else - e->antiAliased = geometry; - } else { - path.makeCacheable(); - } - - return geometry; -} - class QWindowsDirect2DPaintEnginePrivate : public QPaintEngineExPrivate { Q_DECLARE_PUBLIC(QWindowsDirect2DPaintEngine) @@ -418,7 +324,7 @@ public: dc()->PushAxisAlignedClip(rect, antialiasMode()); pushedClips.push(AxisAlignedClip); } else { - ComPtr geometry = vectorPathToID2D1PathGeometry(path, antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED, q); + ComPtr geometry = vectorPathToID2D1PathGeometry(path); if (!geometry) { qWarning("%s: Could not convert vector path to painter path!", __FUNCTION__); return; @@ -827,6 +733,104 @@ public: return result; } + ComPtr vectorPathToID2D1PathGeometry(const QVectorPath &path) + { + Q_Q(QWindowsDirect2DPaintEngine); + + const bool alias = !q->antiAliasingEnabled(); + + QVectorPath::CacheEntry *cacheEntry = path.isCacheable() ? path.lookupCacheData(q) + : Q_NULLPTR; + + if (cacheEntry) { + D2DVectorPathCache *e = static_cast(cacheEntry->data); + if (alias && e->aliased) + return e->aliased; + else if (!alias && e->antiAliased) + return e->antiAliased; + } + + Direct2DPathGeometryWriter writer; + if (!writer.begin()) + return NULL; + + writer.setWindingFillEnabled(path.hasWindingFill()); + writer.setAliasingEnabled(alias); + + const QPainterPath::ElementType *types = path.elements(); + const int count = path.elementCount(); + const qreal *points = path.points(); + + Q_ASSERT(points); + + if (types) { + qreal x, y; + + for (int i = 0; i < count; i++) { + x = points[i * 2]; + y = points[i * 2 + 1]; + + switch (types[i]) { + case QPainterPath::MoveToElement: + writer.moveTo(QPointF(x, y)); + break; + + case QPainterPath::LineToElement: + writer.lineTo(QPointF(x, y)); + break; + + case QPainterPath::CurveToElement: + { + Q_ASSERT((i + 2) < count); + Q_ASSERT(types[i+1] == QPainterPath::CurveToDataElement); + Q_ASSERT(types[i+2] == QPainterPath::CurveToDataElement); + + i++; + const qreal x2 = points[i * 2]; + const qreal y2 = points[i * 2 + 1]; + + i++; + const qreal x3 = points[i * 2]; + const qreal y3 = points[i * 2 + 1]; + + writer.curveTo(QPointF(x, y), QPointF(x2, y2), QPointF(x3, y3)); + } + break; + + case QPainterPath::CurveToDataElement: + qWarning("%s: Unhandled Curve Data Element", __FUNCTION__); + break; + } + } + } else { + writer.moveTo(QPointF(points[0], points[1])); + for (int i = 1; i < count; i++) + writer.lineTo(QPointF(points[i * 2], points[i * 2 + 1])); + } + + if (writer.isInFigure()) + if (path.hasImplicitClose()) + writer.lineTo(QPointF(points[0], points[1])); + + writer.close(); + ComPtr geometry = writer.geometry(); + + if (path.isCacheable()) { + if (!cacheEntry) + cacheEntry = path.addCacheData(q, new D2DVectorPathCache, D2DVectorPathCache::cleanup_func); + + D2DVectorPathCache *e = static_cast(cacheEntry->data); + if (alias) + e->aliased = geometry; + else + e->antiAliased = geometry; + } else { + path.makeCacheable(); + } + + return geometry; + } + void updateHints() { dc()->SetAntialiasMode(antialiasMode()); @@ -863,9 +867,7 @@ bool QWindowsDirect2DPaintEngine::begin(QPaintDevice * pdev) QPainterPath p; p.addRegion(systemClip()); - ComPtr geometry = vectorPathToID2D1PathGeometry(qtVectorPathForPath(p), - d->antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED, - this); + ComPtr geometry = d->vectorPathToID2D1PathGeometry(qtVectorPathForPath(p)); if (!geometry) return false; @@ -932,7 +934,7 @@ void QWindowsDirect2DPaintEngine::draw(const QVectorPath &path) { Q_D(QWindowsDirect2DPaintEngine); - ComPtr geometry = vectorPathToID2D1PathGeometry(path, d->antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED, this); + ComPtr geometry = d->vectorPathToID2D1PathGeometry(path); if (!geometry) { qWarning("%s: Could not convert path to d2d geometry", __FUNCTION__); return; @@ -972,7 +974,7 @@ void QWindowsDirect2DPaintEngine::fill(const QVectorPath &path, const QBrush &br if (!d->brush.brush) return; - ComPtr geometry = vectorPathToID2D1PathGeometry(path, d->antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED, this); + ComPtr geometry = d->vectorPathToID2D1PathGeometry(path); if (!geometry) { qWarning("%s: Could not convert path to d2d geometry", __FUNCTION__); return; @@ -1010,7 +1012,7 @@ void QWindowsDirect2DPaintEngine::stroke(const QVectorPath &path, const QPen &pe if (!d->pen.brush) return; - ComPtr geometry = vectorPathToID2D1PathGeometry(path, d->antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED, this); + ComPtr geometry = d->vectorPathToID2D1PathGeometry(path); if (!geometry) { qWarning("%s: Could not convert path to d2d geometry", __FUNCTION__); return; -- cgit v1.2.3 From 4c9eb38390b35ee3ec0dc966e0b5036cac5ac76b Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Fri, 16 May 2014 10:22:47 +0300 Subject: Support Windows Phone 8.1 in WinRT QPA - Unsupported code paths for WP8.0 are avoided, and new APIs are used where appropriate (virtual keyboard) - DirectWrite fonts are loaded on WP8.1 - Platform dialogs are used on WP8.1 Change-Id: I721006ac943ad4e248f0f1590ce247a03e40fbc0 Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtfontdatabase.cpp | 10 ++-- src/plugins/platforms/winrt/qwinrtfontdatabase.h | 6 +-- src/plugins/platforms/winrt/qwinrtinputcontext.cpp | 53 +++++++++++++++++++++- .../platforms/winrt/qwinrtplatformtheme.cpp | 10 ++-- src/plugins/platforms/winrt/winrt.pro | 8 ++-- 5 files changed, 69 insertions(+), 18 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp index 70bb9469db..7de223bbed 100644 --- a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp +++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp @@ -44,13 +44,13 @@ #include #include -#ifndef Q_OS_WINPHONE +#ifdef QT_WINRT_USE_DWRITE #include #include #include #include using namespace Microsoft::WRL; -#endif // !Q_OS_WINPHONE +#endif // QT_WINRT_USE_DWRITE QT_BEGIN_NAMESPACE @@ -62,7 +62,7 @@ QString QWinRTFontDatabase::fontDir() const const QString applicationDirPath = QCoreApplication::applicationDirPath(); fontDirectory = applicationDirPath + QLatin1String("/fonts"); if (!QFile::exists(fontDirectory)) { -#ifndef Q_OS_WINPHONE +#ifdef QT_WINRT_USE_DWRITE if (m_fontFamilies.isEmpty()) #endif qWarning("No fonts directory found in application package."); @@ -72,7 +72,7 @@ QString QWinRTFontDatabase::fontDir() const return fontDirectory; } -#ifndef Q_OS_WINPHONE +#ifdef QT_WINRT_USE_DWRITE QWinRTFontDatabase::~QWinRTFontDatabase() { @@ -398,6 +398,6 @@ void QWinRTFontDatabase::releaseHandle(void *handle) QBasicFontDatabase::releaseHandle(handle); } -#endif // !Q_OS_WINPHONE +#endif // QT_WINRT_USE_DWRITE QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.h b/src/plugins/platforms/winrt/qwinrtfontdatabase.h index b318a95502..19bf6fa9cf 100644 --- a/src/plugins/platforms/winrt/qwinrtfontdatabase.h +++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.h @@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE -#ifndef Q_OS_WINPHONE +#ifdef QT_WINRT_USE_DWRITE struct IDWriteFontFile; struct IDWriteFontFamily; @@ -61,7 +61,7 @@ class QWinRTFontDatabase : public QBasicFontDatabase { public: QString fontDir() const; -#ifndef Q_OS_WINPHONE +#ifdef QT_WINRT_USE_DWRITE ~QWinRTFontDatabase(); QFont defaultFont() const Q_DECL_OVERRIDE; void populateFontDatabase() Q_DECL_OVERRIDE; @@ -71,7 +71,7 @@ public: private: QHash m_fonts; QHash m_fontFamilies; -#endif // !Q_OS_WINPHONE +#endif // QT_WINRT_USE_DWRITE }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp index bc15f1e448..8e1728dc04 100644 --- a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp +++ b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp @@ -52,7 +52,7 @@ using namespace ABI::Windows::Foundation; using namespace ABI::Windows::UI::ViewManagement; using namespace ABI::Windows::UI::Core; -#ifdef Q_OS_WINPHONE +#if defined(Q_OS_WINPHONE) && _MSC_VER==1700 #include using namespace ABI::Windows::Phone::UI::Core; #endif @@ -148,22 +148,73 @@ void QWinRTInputContext::setKeyboardRect(const QRectF rect) #ifdef Q_OS_WINPHONE +#if _MSC_VER>1700 // Windows Phone 8.1+ +static HRESULT getInputPane(ComPtr *inputPane2) +{ + ComPtr factory; + HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_InputPane).Get(), + &factory); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get input pane factory."); + return hr; + } + + ComPtr inputPane; + hr = factory->GetForCurrentView(&inputPane); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get input pane."); + return hr; + } + + hr = inputPane.As(inputPane2); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get extended input pane."); + return hr; + } + return hr; +} +#endif // _MSC_VER>1700 + void QWinRTInputContext::showInputPanel() { +#if _MSC_VER<=1700 // Windows Phone 8.0 ICoreWindowKeyboardInput *input; if (SUCCEEDED(m_window->QueryInterface(IID_PPV_ARGS(&input)))) { input->put_IsKeyboardInputEnabled(true); input->Release(); } +#else // _MSC_VER<=1700 + ComPtr inputPane; + HRESULT hr = getInputPane(&inputPane); + if (FAILED(hr)) + return; + + boolean success; + hr = inputPane->TryShow(&success); + if (FAILED(hr)) + qErrnoWarning(hr, "Failed to show input panel."); +#endif // _MSC_VER>1700 } void QWinRTInputContext::hideInputPanel() { +#if _MSC_VER<=1700 // Windows Phone 8.0 ICoreWindowKeyboardInput *input; if (SUCCEEDED(m_window->QueryInterface(IID_PPV_ARGS(&input)))) { input->put_IsKeyboardInputEnabled(false); input->Release(); } +#else // _MSC_VER<=1700 + ComPtr inputPane; + HRESULT hr = getInputPane(&inputPane); + if (FAILED(hr)) + return; + + boolean success; + hr = inputPane->TryHide(&success); + if (FAILED(hr)) + qErrnoWarning(hr, "Failed to hide input panel."); +#endif // _MSC_VER>1700 } #else // Q_OS_WINPHONE diff --git a/src/plugins/platforms/winrt/qwinrtplatformtheme.cpp b/src/plugins/platforms/winrt/qwinrtplatformtheme.cpp index 2c8d33da84..e8f853e4b1 100644 --- a/src/plugins/platforms/winrt/qwinrtplatformtheme.cpp +++ b/src/plugins/platforms/winrt/qwinrtplatformtheme.cpp @@ -50,25 +50,25 @@ QWinRTPlatformTheme::QWinRTPlatformTheme() bool QWinRTPlatformTheme::usePlatformNativeDialog(QPlatformTheme::DialogType type) const { -#ifndef Q_OS_WINPHONE +#if !(defined(Q_OS_WINPHONE) && _MSC_VER<=1700) if (type == QPlatformTheme::MessageDialog) return true; -#endif // Q_OS_WINPHONE +#endif // !(Q_OS_WINPHONE && _MSC_VER<=1700) return false; } QPlatformDialogHelper *QWinRTPlatformTheme::createPlatformDialogHelper(QPlatformTheme::DialogType type) const { -#ifndef Q_OS_WINPHONE +#if !(defined(Q_OS_WINPHONE) && _MSC_VER<=1700) switch (type) { case QPlatformTheme::MessageDialog: return new QWinRTPlatformMessageDialogHelper(); default: return QPlatformTheme::createPlatformDialogHelper(type); } -#else +#else // !(Q_OS_WINPHONE && _MSC_VER<=1700) return QPlatformTheme::createPlatformDialogHelper(type); -#endif // Q_OS_WINPHONE +#endif // Q_OS_WINPHONE && _MSC_VER<=1700 } QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro index 0122bf9475..349cdf11c9 100644 --- a/src/plugins/platforms/winrt/winrt.pro +++ b/src/plugins/platforms/winrt/winrt.pro @@ -3,8 +3,7 @@ CONFIG -= precompile_header # For Windows Phone 8 we have to deploy fonts together with the application as DirectWrite # is not supported here. -# TODO: Add a condition/remove this block if Windows Phone 8.1 supports DirectWrite -winphone { +winphone:equals(WINSDK_VER, 8.0): { fonts.path = $$[QT_INSTALL_LIBS]/fonts fonts.files = $$QT_SOURCE_TREE/lib/fonts/DejaVu*.ttf INSTALLS += fonts @@ -21,9 +20,10 @@ DEFINES *= QT_NO_CAST_FROM_ASCII __WRL_NO_DEFAULT_LIB__ GL_GLEXT_PROTOTYPES LIBS += $$QMAKE_LIBS_CORE -!winphone { +!if(winphone:equals(WINSDK_VER, 8.0)) { LIBS += -ldwrite INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/freetype/include + DEFINES += QT_WINRT_USE_DWRITE } SOURCES = \ @@ -70,7 +70,7 @@ fxc_blitvs.variable_out = HEADERS fxc_blitvs.CONFIG += target_predeps QMAKE_EXTRA_COMPILERS += fxc_blitps fxc_blitvs -winphone { +winphone:equals(WINSDK_VER, 8.0): { SOURCES -= qwinrtplatformmessagedialoghelper.cpp HEADERS -= qwinrtplatformmessagedialoghelper.h } -- cgit v1.2.3 From eea02ff10da0ff6bba665df560c5404477b9f550 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Thu, 22 May 2014 08:54:14 +0300 Subject: WinRT: Support High-DPI Previously, the backing store and default framebuffer were created with the logical screen resolution (in device-independent pixels), not the the physical screen resolution. This lead to blurry text on high-DPI devices. This change fixes this by creating those at full size, and setting the device pixel ratio appropriately. Windows are still reported in device-independent pixels, but text and images are now rendered sharply for Qt Quick applications. As QPainter does not support non-integer scaling, the backing store is still drawn in DIPs and scaled by OpenGL. Task-number: QTBUG-38464 Change-Id: I7377d4c734126825d670b8ebb65fd0dd1ef705f2 Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtbackingstore.cpp | 22 +-- src/plugins/platforms/winrt/qwinrtbackingstore.h | 3 +- src/plugins/platforms/winrt/qwinrtscreen.cpp | 155 +++++++++++++++++---- src/plugins/platforms/winrt/qwinrtscreen.h | 22 ++- src/plugins/platforms/winrt/qwinrtwindow.cpp | 5 + src/plugins/platforms/winrt/qwinrtwindow.h | 2 + 6 files changed, 171 insertions(+), 38 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp index 9b623048af..b8418eef6a 100644 --- a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp +++ b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp @@ -284,7 +284,7 @@ QWinRTBackingStore::~QWinRTBackingStore() QPaintDevice *QWinRTBackingStore::paintDevice() { - return m_paintDevice.data(); + return &m_paintDevice; } void QWinRTBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) @@ -293,8 +293,6 @@ void QWinRTBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo if (m_size.isEmpty()) return; - const QImage *image = static_cast(m_paintDevice.data()); - m_context->makeCurrent(window); // Blitting the entire image width trades zero image copy/relayout for a larger texture upload. @@ -307,7 +305,7 @@ void QWinRTBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo glBindTexture(GL_TEXTURE_2D, m_texture); QRect bounds = region.boundingRect(); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, bounds.y(), m_size.width(), bounds.height(), - GL_BGRA_EXT, GL_UNSIGNED_BYTE, image->scanLine(bounds.y())); + GL_BGRA_EXT, GL_UNSIGNED_BYTE, m_paintDevice.constScanLine(bounds.y())); // TODO: Implement GL_EXT_unpack_subimage in ANGLE for more minimal uploads //glPixelStorei(GL_UNPACK_ROW_LENGTH, image->bytesPerLine()); //glTexSubImage2D(GL_TEXTURE_2D, 0, bounds.x(), bounds.y(), bounds.width(), bounds.height(), @@ -325,7 +323,8 @@ void QWinRTBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, quadCoords); // Render - glViewport(0, 0, m_size.width(), m_size.height()); + const QSize blitSize = m_size * window->devicePixelRatio(); + glViewport(0, 0, blitSize.width(), blitSize.height()); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); // Unbind @@ -338,8 +337,8 @@ void QWinRTBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo // fast blit - TODO: perform the blit inside swap buffers instead glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, m_fbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, 0); - glBlitFramebufferANGLE(0, 0, m_size.width(), m_size.height(), // TODO: blit only the changed rectangle - 0, 0, m_size.width(), m_size.height(), + glBlitFramebufferANGLE(0, 0, blitSize.width(), blitSize.height(), // TODO: blit only the changed rectangle + 0, 0, blitSize.width(), blitSize.height(), GL_COLOR_BUFFER_BIT, GL_NEAREST); m_context->swapBuffers(window); @@ -359,21 +358,22 @@ void QWinRTBackingStore::resize(const QSize &size, const QRegion &staticContents if (m_size.isEmpty()) return; - m_paintDevice.reset(new QImage(m_size, QImage::Format_ARGB32_Premultiplied)); + m_paintDevice = QImage(m_size, QImage::Format_ARGB32_Premultiplied); m_context->makeCurrent(window()); // Input texture glBindTexture(GL_TEXTURE_2D, m_texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, m_size.width(), m_size.height(), 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_2D, 0); // Render buffer glBindRenderbuffer(GL_RENDERBUFFER, m_rbo); - glRenderbufferStorage(GL_RENDERBUFFER, GL_BGRA8_EXT, m_size.width(), m_size.height()); + const QSize blitSize = m_size * window()->devicePixelRatio(); + glRenderbufferStorage(GL_RENDERBUFFER, GL_BGRA8_EXT, blitSize.width(), blitSize.height()); glBindRenderbuffer(GL_RENDERBUFFER, 0); m_context->doneCurrent(); } diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.h b/src/plugins/platforms/winrt/qwinrtbackingstore.h index 726f7c838f..f00fa85a26 100644 --- a/src/plugins/platforms/winrt/qwinrtbackingstore.h +++ b/src/plugins/platforms/winrt/qwinrtbackingstore.h @@ -60,18 +60,19 @@ public: void endPaint(); void flush(QWindow *window, const QRegion ®ion, const QPoint &offset); void resize(const QSize &size, const QRegion &staticContents); + QImage toImage() const Q_DECL_OVERRIDE { return m_paintDevice; } private: bool initialize(); bool m_initialized; QSize m_size; - QScopedPointer m_paintDevice; QScopedPointer m_context; quint32 m_shaderProgram; quint32 m_fbo; quint32 m_rbo; quint32 m_texture; QWinRTScreen *m_screen; + QImage m_paintDevice; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index e2ff7197aa..3fe856558f 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -93,6 +93,11 @@ typedef ITypedEventHandler PointerHandler; typedef ITypedEventHandler SizeChangedHandler; typedef ITypedEventHandler VisibilityChangedHandler; typedef ITypedEventHandler AutomationProviderRequestedHandler; +#if _MSC_VER <=1700 +typedef IDisplayPropertiesEventHandler DisplayInformationHandler; +#else +typedef ITypedEventHandler DisplayInformationHandler; +#endif #ifdef Q_OS_WINPHONE typedef IEventHandler BackPressedHandler; #endif @@ -424,12 +429,13 @@ QWinRTScreen::QWinRTScreen(ICoreWindow *window) , m_inputContext(Make(m_coreWindow).Detach()) #endif , m_cursor(new QWinRTCursor(window)) + , m_devicePixelRatio(1.0) , m_orientation(Qt::PrimaryOrientation) , m_touchDevice(Q_NULLPTR) { Rect rect; window->get_Bounds(&rect); - m_geometry = QRect(0, 0, rect.Width, rect.Height); + m_geometry = QRectF(0, 0, rect.Width, rect.Height); m_surfaceFormat.setAlphaBufferSize(0); m_surfaceFormat.setRedBufferSize(8); @@ -478,26 +484,63 @@ QWinRTScreen::QWinRTScreen(ICoreWindow *window) m_coreWindow->add_AutomationProviderRequested(Callback(this, &QWinRTScreen::onAutomationProviderRequested).Get(), &m_tokens[QEvent::InputMethodQuery]); // Orientation handling - if (SUCCEEDED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), - &m_displayProperties))) { - // Set native orientation - DisplayOrientations displayOrientation; - m_displayProperties->get_NativeOrientation(&displayOrientation); - m_nativeOrientation = static_cast(static_cast(qtOrientationsFromNative(displayOrientation))); - - // Set initial orientation - onOrientationChanged(0); - setOrientationUpdateMask(m_nativeOrientation); - - m_displayProperties->add_OrientationChanged(Callback(this, &QWinRTScreen::onOrientationChanged).Get(), - &m_tokens[QEvent::OrientationChange]); +#if _MSC_VER<=1700 + HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), + &m_displayInformation); +#else + HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Display_DisplayInformation).Get(), + &m_displayInformationFactory); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get display information factory."); + return; } -#ifndef Q_OS_WINPHONE - GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_ApplicationView).Get(), - &m_applicationView); + hr = m_displayInformationFactory->GetForCurrentView(&m_displayInformation); #endif + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get display information for the current view."); + return; + } + + // Set native orientation + DisplayOrientations displayOrientation; + hr = m_displayInformation->get_NativeOrientation(&displayOrientation); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get native orientation."); + return; + } + + m_nativeOrientation = static_cast(static_cast(qtOrientationsFromNative(displayOrientation))); + + hr = m_displayInformation->add_OrientationChanged(Callback(this, &QWinRTScreen::onOrientationChanged).Get(), + &m_tokens[QEvent::OrientationChange]); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to add orientation change callback."); + return; + } + +#if _MSC_VER<=1700 + hr = m_displayInformation->add_LogicalDpiChanged(Callback(this, &QWinRTScreen::onDpiChanged).Get(), + &m_tokens[QEvent::Type(QEvent::User + 1)]); +#else + hr = m_displayInformation->add_DpiChanged(Callback(this, &QWinRTScreen::onDpiChanged).Get(), + &m_tokens[QEvent::Type(QEvent::User + 1)]); +#endif + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to add logical dpi change callback."); + return; + } + + // Set initial orientation & pixel density +#if _MSC_VER<=1700 + onOrientationChanged(Q_NULLPTR); + onDpiChanged(Q_NULLPTR); +#else + onOrientationChanged(Q_NULLPTR, Q_NULLPTR); + onDpiChanged(Q_NULLPTR, Q_NULLPTR); +#endif + setOrientationUpdateMask(m_nativeOrientation); if (SUCCEEDED(RoGetActivationFactory(Wrappers::HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(), IID_PPV_ARGS(&m_application)))) { @@ -508,7 +551,7 @@ QWinRTScreen::QWinRTScreen(ICoreWindow *window) QRect QWinRTScreen::geometry() const { - return m_geometry; + return m_geometry.toRect(); } int QWinRTScreen::depth() const @@ -526,6 +569,21 @@ QSurfaceFormat QWinRTScreen::surfaceFormat() const return m_surfaceFormat; } +QSizeF QWinRTScreen::physicalSize() const +{ + return m_geometry.size() / m_dpi * qreal(25.4); +} + +QDpi QWinRTScreen::logicalDpi() const +{ + return QDpi(m_dpi, m_dpi); +} + +qreal QWinRTScreen::devicePixelRatio() const +{ + return m_devicePixelRatio; +} + QWinRTInputContext *QWinRTScreen::inputContext() const { return m_inputContext; @@ -572,7 +630,11 @@ Qt::ScreenOrientation QWinRTScreen::orientation() const void QWinRTScreen::setOrientationUpdateMask(Qt::ScreenOrientations mask) { - m_displayProperties->put_AutoRotationPreferences(nativeOrientationsFromQt(mask)); +#if _MSC_VER<=1700 + m_displayInformation->put_AutoRotationPreferences(nativeOrientationsFromQt(mask)); +#else + m_displayInformationFactory->put_AutoRotationPreferences(nativeOrientationsFromQt(mask)); +#endif } ICoreWindow *QWinRTScreen::coreWindow() const @@ -637,7 +699,7 @@ void QWinRTScreen::handleExpose() if (m_visibleWindows.isEmpty()) return; QList::const_iterator it = m_visibleWindows.constBegin(); - QWindowSystemInterface::handleExposeEvent(*it, m_geometry); + QWindowSystemInterface::handleExposeEvent(*it, m_geometry.toRect()); while (++it != m_visibleWindows.constEnd()) QWindowSystemInterface::handleExposeEvent(*it, QRegion()); QWindowSystemInterface::flushWindowSystemEvents(); @@ -914,9 +976,9 @@ HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *window, IWindowSizeChangedEvent // Regardless of state, all top-level windows are viewport-sized - this might change if // a more advanced compositor is written. - m_geometry.setSize(QSize(size.Width, size.Height)); - QWindowSystemInterface::handleScreenGeometryChange(screen(), m_geometry); - QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), m_geometry); + m_geometry.setSize(QSizeF(size.Width, size.Height)); + QWindowSystemInterface::handleScreenGeometryChange(screen(), m_geometry.toRect()); + QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), m_geometry.toRect()); QPlatformScreen::resizeMaximizedWindows(); handleExpose(); @@ -981,10 +1043,14 @@ HRESULT QWinRTScreen::onVisibilityChanged(ICoreWindow *window, IVisibilityChange return S_OK; } +#if _MSC_VER<=1700 HRESULT QWinRTScreen::onOrientationChanged(IInspectable *) +#else +HRESULT QWinRTScreen::onOrientationChanged(IDisplayInformation *, IInspectable *) +#endif { DisplayOrientations displayOrientation; - m_displayProperties->get_CurrentOrientation(&displayOrientation); + m_displayInformation->get_CurrentOrientation(&displayOrientation); Qt::ScreenOrientation newOrientation = static_cast(static_cast(qtOrientationsFromNative(displayOrientation))); if (m_orientation != newOrientation) { m_orientation = newOrientation; @@ -994,6 +1060,47 @@ HRESULT QWinRTScreen::onOrientationChanged(IInspectable *) return S_OK; } +#if _MSC_VER<=1700 +HRESULT QWinRTScreen::onDpiChanged(IInspectable *) +#else +HRESULT QWinRTScreen::onDpiChanged(IDisplayInformation *, IInspectable *) +#endif +{ +#if defined(Q_OS_WINPHONE) && _MSC_VER>=1800 // WP 8.1 + ComPtr displayInformation; + HRESULT hr = m_displayInformation->QueryInterface(IID_IDisplayInformation2, &displayInformation); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to cast display information."); + return S_OK; + } + hr = displayInformation->get_RawPixelsPerViewPixel(&m_devicePixelRatio); +#else + ResolutionScale resolutionScale; + HRESULT hr = m_displayInformation->get_ResolutionScale(&resolutionScale); +#endif + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get display resolution scale."); + return S_OK; + } +#if !(defined(Q_OS_WINPHONE) && _MSC_VER>=1800) // !WP8.1 + m_devicePixelRatio = qreal(resolutionScale) / 100; +#endif + + // Correct the scale factor for integer window size + m_devicePixelRatio = m_devicePixelRatio * ((m_geometry.width()/qRound(m_geometry.width()) + + m_geometry.height()/qRound(m_geometry.height())) / 2.0); + + FLOAT dpi; + hr = m_displayInformation->get_LogicalDpi(&dpi); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get logical DPI."); + return S_OK; + } + m_dpi = dpi; + + return S_OK; +} + #ifdef Q_OS_WINPHONE HRESULT QWinRTScreen::onBackButtonPressed(IInspectable *, IBackPressedEventArgs *args) { diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h index 753d89541c..d39683a960 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.h +++ b/src/plugins/platforms/winrt/qwinrtscreen.h @@ -78,6 +78,8 @@ namespace ABI { namespace Graphics { namespace Display { struct IDisplayPropertiesStatics; + struct IDisplayInformationStatics; + struct IDisplayInformation; } } #ifdef Q_OS_WINPHONE @@ -109,6 +111,9 @@ public: int depth() const; QImage::Format format() const; QSurfaceFormat surfaceFormat() const; + QSizeF physicalSize() const Q_DECL_OVERRIDE; + QDpi logicalDpi() const Q_DECL_OVERRIDE; + qreal devicePixelRatio() const Q_DECL_OVERRIDE; QWinRTInputContext *inputContext() const; QPlatformCursor *cursor() const; Qt::KeyboardModifiers keyboardModifiers() const; @@ -150,7 +155,13 @@ private: HRESULT onVisibilityChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IVisibilityChangedEventArgs *args); HRESULT onAutomationProviderRequested(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IAutomationProviderRequestedEventArgs *args); +#if _MSC_VER<=1700 HRESULT onOrientationChanged(IInspectable *); + HRESULT onDpiChanged(IInspectable *); +#else + HRESULT onOrientationChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *); + HRESULT onDpiChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *); +#endif #ifdef Q_OS_WINPHONE HRESULT onBackButtonPressed(IInspectable *, ABI::Windows::Phone::UI::Input::IBackPressedEventArgs *args); @@ -160,9 +171,10 @@ private: ABI::Windows::UI::ViewManagement::IApplicationViewStatics *m_applicationView; ABI::Windows::ApplicationModel::Core::ICoreApplication *m_application; - QRect m_geometry; + QRectF m_geometry; QImage::Format m_format; QSurfaceFormat m_surfaceFormat; + qreal m_dpi; int m_depth; QWinRTInputContext *m_inputContext; QWinRTCursor *m_cursor; @@ -171,7 +183,13 @@ private: EGLDisplay m_eglDisplay; EGLSurface m_eglSurface; - ABI::Windows::Graphics::Display::IDisplayPropertiesStatics *m_displayProperties; +#if _MSC_VER<=1700 + ABI::Windows::Graphics::Display::IDisplayPropertiesStatics *m_displayInformation; +#else + ABI::Windows::Graphics::Display::IDisplayInformationStatics *m_displayInformationFactory; + ABI::Windows::Graphics::Display::IDisplayInformation *m_displayInformation; +#endif + qreal m_devicePixelRatio; Qt::ScreenOrientation m_nativeOrientation; Qt::ScreenOrientation m_orientation; diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp index 88b753b463..80ee6bd761 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.cpp +++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp @@ -116,4 +116,9 @@ void QWinRTWindow::lower() m_screen->lower(window()); } +qreal QWinRTWindow::devicePixelRatio() const +{ + return screen()->devicePixelRatio(); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtwindow.h b/src/plugins/platforms/winrt/qwinrtwindow.h index 1f19b4f2d5..121f430686 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.h +++ b/src/plugins/platforms/winrt/qwinrtwindow.h @@ -63,6 +63,8 @@ public: void raise(); void lower(); + qreal devicePixelRatio() const Q_DECL_OVERRIDE; + private: QWinRTScreen *m_screen; }; -- cgit v1.2.3 From 0057507184bc87fc26be95298d8d734a47e73251 Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Fri, 23 May 2014 08:01:43 +0300 Subject: Direct2D QPA: Add missing break statement Change-Id: Ib40daa1ba56cce423b29ac8f1ab50e4638980728 Reviewed-by: Risto Avila Reviewed-by: Friedemann Kleint --- src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp index 3b598b365d..e3adcde964 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp @@ -469,6 +469,7 @@ public: break; case Qt::RoundCap: props.startCap = props.endCap = props.dashCap = D2D1_CAP_STYLE_ROUND; + break; case Qt::FlatCap: default: props.startCap = props.endCap = props.dashCap = D2D1_CAP_STYLE_FLAT; -- cgit v1.2.3 From c6b877917241257d159bd3b9070c4be09231f40b Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Thu, 22 May 2014 10:12:39 +0300 Subject: Direct2D QPA: Fix HighRes painting It turns out that supporting HighRes painting with Direct2D is quite simple. Two things are necessary. First, we set the unit mode to D2D1_UNIT_MODE_PIXELS on all our device contexts, which tells Direct2D that we specify everything in pixels. Direct2D will internally do the required conversions. Second, we scale font sizes according to DPI. Previously rendering errors resulted when a highres mode was used, this fixes those errors. Task-number: QTBUG-39105 Change-Id: Ibb4dbea4746687228249e2c36d48c4bd6c5c7bf9 Reviewed-by: Risto Avila Reviewed-by: Friedemann Kleint --- .../direct2d/qwindowsdirect2ddevicecontext.cpp | 1 + .../direct2d/qwindowsdirect2dpaintengine.cpp | 20 +++++++++----------- 2 files changed, 10 insertions(+), 11 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.cpp index fb47851a06..f2400cf8fc 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.cpp @@ -64,6 +64,7 @@ public: } Q_ASSERT(deviceContext); + deviceContext->SetUnitMode(D2D1_UNIT_MODE_PIXELS); } void begin() diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp index e3adcde964..a1c405067c 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp @@ -1465,29 +1465,27 @@ void QWindowsDirect2DPaintEngine::drawTextItem(const QPointF &p, const QTextItem rtl); } -// Points (1/72 inches) to Microsoft's Device Independent Pixels (1/96 inches) -inline static Q_DECL_CONSTEXPR FLOAT pointSizeToDIP(qreal pointSize) +inline static FLOAT pointSizeToDIP(qreal pointSize, FLOAT dpiY) { - return pointSize + (pointSize / qreal(3.0)); + return (pointSize + (pointSize / qreal(3.0))) * (dpiY / 96.0f); } -inline static FLOAT pixelSizeToDIP(int pixelSize) +inline static FLOAT pixelSizeToDIP(int pixelSize, FLOAT dpiY) { - FLOAT dpiX, dpiY; - factory()->GetDesktopDpi(&dpiX, &dpiY); - - return FLOAT(pixelSize) / (dpiY / 96.0f); + return FLOAT(pixelSize) * 96.0f / dpiY; } inline static FLOAT fontSizeInDIP(const QFont &font) { - // Direct2d wants the font size in DIPs (Device Independent Pixels), each of which is 1/96 inches. + FLOAT dpiX, dpiY; + QWindowsDirect2DContext::instance()->d2dFactory()->GetDesktopDpi(&dpiX, &dpiY); + if (font.pixelSize() == -1) { // font size was set as points - return pointSizeToDIP(font.pointSizeF()); + return pointSizeToDIP(font.pointSizeF(), dpiY); } else { // font size was set as pixels - return pixelSizeToDIP(font.pixelSize()); + return pixelSizeToDIP(font.pixelSize(), dpiY); } } -- cgit v1.2.3 From 05e8b54d23e3d906d5f29113a73d88d3482c8f64 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Thu, 22 May 2014 17:08:45 +0300 Subject: WinRT: fix default font when DirectWrite is disabled Instead of loading the default font "Helvetica", which is likely not part of the package, load the first font found. Change-Id: I225979986883a26c3fec72858cf32c3d1e45d902 Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtfontdatabase.cpp | 9 ++++++++- src/plugins/platforms/winrt/qwinrtfontdatabase.h | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp index 7de223bbed..f4e1fbe533 100644 --- a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp +++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp @@ -398,6 +398,13 @@ void QWinRTFontDatabase::releaseHandle(void *handle) QBasicFontDatabase::releaseHandle(handle); } -#endif // QT_WINRT_USE_DWRITE +#else // QT_WINRT_USE_DWRITE + +QFont QWinRTFontDatabase::defaultFont() const +{ + return QFont(QFontDatabase().families().value(0)); +} + +#endif // !QT_WINRT_USE_DWRITE QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.h b/src/plugins/platforms/winrt/qwinrtfontdatabase.h index 19bf6fa9cf..eabcc83afd 100644 --- a/src/plugins/platforms/winrt/qwinrtfontdatabase.h +++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.h @@ -61,9 +61,9 @@ class QWinRTFontDatabase : public QBasicFontDatabase { public: QString fontDir() const; + QFont defaultFont() const Q_DECL_OVERRIDE; #ifdef QT_WINRT_USE_DWRITE ~QWinRTFontDatabase(); - QFont defaultFont() const Q_DECL_OVERRIDE; void populateFontDatabase() Q_DECL_OVERRIDE; void populateFamily(const QString &familyName) Q_DECL_OVERRIDE; QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE; -- cgit v1.2.3 From 28f32afd3fed07c7772b76faf731bb104810d934 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Fri, 23 May 2014 10:51:19 +0200 Subject: iOS: Be more careful when hiding the keyboard upon enter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A typical pattern in an application is to listen for "enter" in a line edit and transfer focus to the next edit in the focus chain. This would currently not work on iOS since we would force the keyboard down after delivering the KeyPress/release events, effectively overriding any focus handling done by the app. This patch will hide the keyboard _before_ sending the events, so that we don't override focus handling done by the app. By also hiding the keyboard using QInputMethod, the hiding will also be delayed a bit (in QIOSInputContext) to catch subsequent hide/show calls. Change-Id: Ic19511d494a55d1bda963ed9bc7185d63b51bc03 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/quiview_textinput.mm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/ios/quiview_textinput.mm b/src/plugins/platforms/ios/quiview_textinput.mm index 79e3897013..03006b3f99 100644 --- a/src/plugins/platforms/ios/quiview_textinput.mm +++ b/src/plugins/platforms/ios/quiview_textinput.mm @@ -495,14 +495,14 @@ Q_GLOBAL_STATIC(StaticVariables, staticVariables); return; if ([text isEqualToString:@"\n"]) { + if (self.returnKeyType == UIReturnKeyDone) + qApp->inputMethod()->hide(); + QKeyEvent press(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier); QKeyEvent release(QEvent::KeyRelease, Qt::Key_Return, Qt::NoModifier); [self sendEventToFocusObject:press]; [self sendEventToFocusObject:release]; - if (self.returnKeyType == UIReturnKeyDone) - [self resignFirstResponder]; - return; } -- cgit v1.2.3 From 57d0ed8f1e0b2e98102bd3718abd449d5dd7aa1d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 19 May 2014 11:28:06 +0200 Subject: Remove unused variable in qwindowsmousehandler.cpp. Change-Id: Iacfeec396c2eeef973b62bf78c698aa206b01c41 Reviewed-by: Andy Shaw --- src/plugins/platforms/windows/qwindowsmousehandler.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 5c9add4baa..cc0597b72d 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -354,7 +354,6 @@ static bool isValidWheelReceiver(QWindow *candidate) bool QWindowsMouseHandler::translateMouseWheelEvent(QWindow *window, HWND, MSG msg, LRESULT *) { - const Qt::MouseButtons buttons = keyStateToMouseButtons((int)msg.wParam); const Qt::KeyboardModifiers mods = keyStateToModifiers((int)msg.wParam); int delta; -- cgit v1.2.3 From 9a2dbcab7e820c63aac55ba08dc120a56986efac Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 13 May 2014 14:08:05 +0200 Subject: QPrinter/Windows: Fix handling of native paper source ids. On Windows, it is possible to pass native Windows paper source ids >= DMBIN_USER to QPrinter::setPaperSource() and they are listed by supportedPaperSources(). Task-number: QTBUG-38897 Task-number: QTBUG-38888 Change-Id: I8f1264e80ce5bdddd3873602200b24eabee00502 Reviewed-by: Lars Knoll Reviewed-by: Andy Shaw --- src/plugins/printsupport/windows/qwindowsprintdevice.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/plugins') diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp index 1b55937ec7..2c75ab7016 100644 --- a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp +++ b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp @@ -78,6 +78,7 @@ static QPrint::InputSlot paperBinToInputSlot(int windowsId, const QString &name) } slot.key = inputSlotMap[i].key; slot.id = inputSlotMap[i].id; + slot.windowsId = windowsId; return slot; } -- cgit v1.2.3 From 92c6bfa0b238614db328bdc7a57cd0390adc95a5 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Wed, 14 May 2014 18:43:50 +0200 Subject: Fix loss of precision warnings Found by http://www.viva64.com/en/b/0251 Change-Id: I2a0c3dba74fef07c3119c9e57b343a8253ee7daa Reviewed-by: Friedemann Kleint Reviewed-by: Laszlo Agocs --- src/plugins/platforms/windows/qwindowstabletsupport.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp index 484ed9cb05..2a1e5c58b9 100644 --- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp +++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp @@ -458,8 +458,8 @@ bool QWindowsTabletSupport::translateTabletPacketEvent() // Z = sin(altitude) // X Tilt = arctan(X / Z) // Y Tilt = arctan(Y / Z) - const double radAzim = (packet.pkOrientation.orAzimuth / 10) * (M_PI / 180); - const double tanAlt = tan((abs(packet.pkOrientation.orAltitude / 10)) * (M_PI / 180)); + const double radAzim = (packet.pkOrientation.orAzimuth / 10.0) * (M_PI / 180); + const double tanAlt = tan((abs(packet.pkOrientation.orAltitude / 10.0)) * (M_PI / 180)); const double degX = atan(sin(radAzim) / tanAlt); const double degY = atan(cos(radAzim) / tanAlt); -- cgit v1.2.3 From 5d48eb8bbc43b37235c29c2caf1e5fafec864b49 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Mon, 19 May 2014 19:58:35 +0200 Subject: Cocoa: Make sure modal windows get correct geometry on show MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit beginModalSessionForWindow will center the window and ignore the set geometry. So to workaround this it checks the new value against the old one and moves it back if need be. Change-Id: I38bc74c04138992f2e0570fca666414025aeeba8 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index e0ce9f9648..b625f233ce 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -622,7 +622,8 @@ NSModalSession QCocoaEventDispatcherPrivate::currentModalSession() if (!info.session) { QCocoaAutoReleasePool pool; - NSWindow *nswindow = static_cast(info.window->handle())->nativeWindow(); + QCocoaWindow *cocoaWindow = static_cast(info.window->handle()); + NSWindow *nswindow = cocoaWindow->nativeWindow(); if (!nswindow) continue; @@ -630,7 +631,10 @@ NSModalSession QCocoaEventDispatcherPrivate::currentModalSession() QBoolBlocker block1(blockSendPostedEvents, true); info.nswindow = nswindow; [(NSWindow*) info.nswindow retain]; + QRect rect = cocoaWindow->geometry(); info.session = [NSApp beginModalSessionForWindow:nswindow]; + if (rect != cocoaWindow->geometry()) + cocoaWindow->setGeometry(rect); } currentModalSessionCached = info.session; cleanupModalSessionsNeeded = false; -- cgit v1.2.3 From 8701c20f0dcae0d6647675dbd2181610543b7926 Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Fri, 23 May 2014 14:53:03 +0300 Subject: Direct2D QPA: Match raster engine line output For whatever reason direct2d and the raster engine disagree by one pixel about the positioning of positively sloping aliased lines. To get the same output, we shift such lines by one pixel. Change-Id: I4b20319770c02e3fdd212b3535ccae3c27ca9f2f Reviewed-by: Risto Avila Reviewed-by: Friedemann Kleint --- .../direct2d/qwindowsdirect2dpaintengine.cpp | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp index a1c405067c..4c39560cbe 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp @@ -1160,6 +1160,25 @@ void QWindowsDirect2DPaintEngine::drawRects(const QRectF *rects, int rectCount) } } +static bool isLinePositivelySloped(const QPointF &p1, const QPointF &p2) +{ + if (p2.x() > p1.x()) + return p2.y() < p1.y(); + + if (p1.x() > p2.x()) + return p1.y() < p2.y(); + + return false; +} + +static void adjustLine(QPointF *p1, QPointF *p2) +{ + if (isLinePositivelySloped(*p1, *p2)) { + p1->ry() -= qreal(1.0); + p2->ry() -= qreal(1.0); + } +} + void QWindowsDirect2DPaintEngine::drawLines(const QLine *lines, int lineCount) { Q_D(QWindowsDirect2DPaintEngine); @@ -1181,6 +1200,10 @@ void QWindowsDirect2DPaintEngine::drawLines(const QLine *lines, int lineCount) continue; } + // Match raster engine output + if (!antiAliasingEnabled()) + adjustLine(&p1, &p2); + adjustForAliasing(&p1); adjustForAliasing(&p2); @@ -1213,6 +1236,10 @@ void QWindowsDirect2DPaintEngine::drawLines(const QLineF *lines, int lineCount) continue; } + // Match raster engine output + if (!antiAliasingEnabled()) + adjustLine(&p1, &p2); + adjustForAliasing(&p1); adjustForAliasing(&p2); -- cgit v1.2.3 From 7ba0eb5a0daae59c495bbf250fa37a2627950e94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 21 May 2014 11:30:54 +0200 Subject: Cocoa: Prevent crash on QWindow delete. Clear the QCocoaWindow pointer stored on the QNSWindowHelper when detaching from the platform window. This makes sure callbacks from cocoa does not try access deleted Qt window objects. Task-number: QTBUG-39141 Change-Id: I4672eae92940dcbd59a2848e56f94b50a828bbf6 Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoawindow.mm | 1 + 1 file changed, 1 insertion(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 651fedb26e..13e8dde012 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -182,6 +182,7 @@ static bool isMouseEvent(NSEvent *ev) - (void)detachFromPlatformWindow { + _platformWindow = 0; [self.window.delegate release]; self.window.delegate = nil; } -- cgit v1.2.3 From 1ac0f953ba70ceda76e90918ab4ae7ebe2339969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 21 May 2014 11:36:54 +0200 Subject: Cocoa: Remove the NSWindow -> QCococaWindow hash. Cast the NSWindow to a QNSWindow instead. Now there is no way we can fail to maintain the hash properly. Change-Id: I5fd03b6fad964a61fadb3460b7063fd43ff25c79 Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoaintegration.h | 3 --- src/plugins/platforms/cocoa/qcocoaintegration.mm | 17 +++++------------ src/plugins/platforms/cocoa/qcocoawindow.mm | 5 ----- 3 files changed, 5 insertions(+), 20 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index 9c4f86d893..07b73c1a7a 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -139,8 +139,6 @@ public: void setToolbar(QWindow *window, NSToolbar *toolbar); NSToolbar *toolbar(QWindow *window) const; void clearToolbars(); - void setWindow(NSWindow* nsWindow, QCocoaWindow *window); - QCocoaWindow *window(NSWindow *window); private: static QCocoaIntegration *mInstance; @@ -159,7 +157,6 @@ private: QScopedPointer mKeyboardMapper; QHash mToolbars; - QHash mWindows; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index c4398622e8..19753ccc89 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -159,9 +159,12 @@ qreal QCocoaScreen::devicePixelRatio() const QWindow *QCocoaScreen::topLevelAt(const QPoint &point) const { // Get a z-ordered list of windows. Iterate through it until - // we find a window which contains the point. + // we find a (Qt) window which contains the point. for (NSWindow *nsWindow in [NSApp orderedWindows]) { - QCocoaWindow *cocoaWindow = QCocoaIntegration::instance()->window(nsWindow); + if (![nsWindow isKindOfClass:[QNSWindow class]]) + continue; + QNSWindow *qnsWindow = static_cast(nsWindow); + QCocoaWindow *cocoaWindow = qnsWindow.helper.platformWindow; if (!cocoaWindow) continue; QWindow *window = cocoaWindow->window(); @@ -518,16 +521,6 @@ NSToolbar *QCocoaIntegration::toolbar(QWindow *window) const return mToolbars.value(window); } -void QCocoaIntegration::setWindow(NSWindow* nsWindow, QCocoaWindow *window) -{ - mWindows.insert(nsWindow, window); -} - -QCocoaWindow *QCocoaIntegration::window(NSWindow *window) -{ - return mWindows.value(window); -} - void QCocoaIntegration::clearToolbars() { QHash::const_iterator it = mToolbars.constBegin(); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 13e8dde012..0f51d0664c 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -262,8 +262,6 @@ static bool isMouseEvent(NSEvent *ev) { [self close]; - QCocoaIntegration::instance()->setWindow(self, 0); - if (self.helper.grabbingMouse) { self.helper.releaseOnMouseUp = YES; } else { @@ -330,7 +328,6 @@ static bool isMouseEvent(NSEvent *ev) { [self.helper detachFromPlatformWindow]; [self close]; - QCocoaIntegration::instance()->setWindow(self, 0); [self release]; } @@ -1414,8 +1411,6 @@ QCocoaNSWindow * QCocoaWindow::createNSWindow() applyContentBorderThickness(createdWindow); - QCocoaIntegration::instance()->setWindow(createdWindow, this); - return createdWindow; } -- cgit v1.2.3 From b214c177ea799baa33fe7ef7cf6446407928a38b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Thu, 22 May 2014 09:38:34 +0200 Subject: Make QT_MAC_OPENGL_SURFACE_ORDER=-1 work better Mark the window as not opaque and give it a transparent background when layering OpenGL below the window. Change-Id: I2188842249c592f17619f7a2c3ef1fd30958987e Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoawindow.mm | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 0f51d0664c..7ab7486ce9 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -999,9 +999,14 @@ bool QCocoaWindow::isExposed() const bool QCocoaWindow::isOpaque() const { + // OpenGL surfaces can be ordered either above(default) or below the NSWindow. + // When ordering below the window must be tranclucent. + static GLint openglSourfaceOrder = qt_mac_resolveOption(1, "QT_MAC_OPENGL_SURFACE_ORDER"); + bool translucent = (window()->format().alphaBufferSize() > 0 || window()->opacity() < 1 - || (m_qtView && [m_qtView hasMask])); + || (m_qtView && [m_qtView hasMask])) + || (surface()->supportsOpenGL() && openglSourfaceOrder == -1); return !translucent; } @@ -1402,7 +1407,13 @@ QCocoaNSWindow * QCocoaWindow::createNSWindow() NSInteger level = windowLevel(flags); [createdWindow setLevel:level]; - if (window()->format().alphaBufferSize() > 0) { + // OpenGL surfaces can be ordered either above(default) or below the NSWindow. + // When ordering below the window must be tranclucent and have a clear background color. + static GLint openglSourfaceOrder = qt_mac_resolveOption(1, "QT_MAC_OPENGL_SURFACE_ORDER"); + + bool isTranslucent = window()->format().alphaBufferSize() > 0 + || (surface()->supportsOpenGL() && openglSourfaceOrder == -1); + if (isTranslucent) { [createdWindow setBackgroundColor:[NSColor clearColor]]; [createdWindow setOpaque:NO]; } -- cgit v1.2.3 From 262d2cba12e9b164f9699951b37def21e1ed1652 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Mon, 26 May 2014 09:24:18 +0200 Subject: WinRT: Fix compile warnings Change-Id: If223dd73b9558a0f5144be38f19a61316f8c807b Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtcursor.cpp | 2 ++ src/plugins/platforms/winrt/qwinrtplatformtheme.cpp | 2 ++ src/plugins/platforms/winrt/qwinrtscreen.cpp | 2 ++ 3 files changed, 6 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/winrt/qwinrtcursor.cpp b/src/plugins/platforms/winrt/qwinrtcursor.cpp index 8241560cef..f09454ebc3 100644 --- a/src/plugins/platforms/winrt/qwinrtcursor.cpp +++ b/src/plugins/platforms/winrt/qwinrtcursor.cpp @@ -135,6 +135,8 @@ void QWinRTCursor::changeCursor(QCursor *windowCursor, QWindow *) ICoreCursor *cursor; if (SUCCEEDED(m_cursorFactory->CreateCursor(type, 0, &cursor))) m_window->put_PointerCursor(cursor); +#else // Q_OS_WINPHONE + Q_UNUSED(windowCursor) #endif // Q_OS_WINPHONE } #endif // QT_NO_CURSOR diff --git a/src/plugins/platforms/winrt/qwinrtplatformtheme.cpp b/src/plugins/platforms/winrt/qwinrtplatformtheme.cpp index e8f853e4b1..d4034ec571 100644 --- a/src/plugins/platforms/winrt/qwinrtplatformtheme.cpp +++ b/src/plugins/platforms/winrt/qwinrtplatformtheme.cpp @@ -53,6 +53,8 @@ bool QWinRTPlatformTheme::usePlatformNativeDialog(QPlatformTheme::DialogType typ #if !(defined(Q_OS_WINPHONE) && _MSC_VER<=1700) if (type == QPlatformTheme::MessageDialog) return true; +#else + Q_UNUSED(type) #endif // !(Q_OS_WINPHONE && _MSC_VER<=1700) return false; } diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 3fe856558f..f948cf9924 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -960,6 +960,8 @@ HRESULT QWinRTScreen::onAutomationProviderRequested(ICoreWindow *, IAutomationPr { #ifndef Q_OS_WINPHONE args->put_AutomationProvider(m_inputContext); +#else + Q_UNUSED(args) #endif return S_OK; } -- cgit v1.2.3 From b732e56969940a9c3bbb1b4e09d671005e4a1006 Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Fri, 23 May 2014 14:39:53 +0200 Subject: Android: Report current selection to the input method Task-number: QTBUG-39196 Change-Id: Ib798f1de83ccbe3830a746b6ddd435a0934c34cd Reviewed-by: J-P Nurmi Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../platforms/android/qandroidinputcontext.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index c2e5f83639..5d47d2fda4 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -472,12 +472,24 @@ void QAndroidInputContext::updateCursorPosition() if (m_composingText.isEmpty() != (m_composingTextStart == -1)) qWarning() << "Input method out of sync" << m_composingText << m_composingTextStart; - - // Qt's idea of the cursor position is the start of the preedit area, so we have to maintain our own preedit cursor pos int realCursorPosition = cursorPos; + int realAnchorPosition = cursorPos; + + int cpos = query->value(Qt::ImCursorPosition).toInt(); + int anchor = query->value(Qt::ImAnchorPosition).toInt(); + if (cpos != anchor) { + if (!m_composingText.isEmpty()) { + qWarning("Selecting text while preediting may give unpredictable results."); + finishComposingText(); + } + int blockPos = getBlockPosition(query); + realCursorPosition = blockPos + cpos; + realAnchorPosition = blockPos + anchor; + } + // Qt's idea of the cursor position is the start of the preedit area, so we maintain our own preedit cursor pos if (!m_composingText.isEmpty()) - realCursorPosition = m_composingCursor; - QtAndroidInput::updateSelection(realCursorPosition, realCursorPosition, //empty selection + realCursorPosition = realAnchorPosition = m_composingCursor; + QtAndroidInput::updateSelection(realCursorPosition, realAnchorPosition, m_composingTextStart, m_composingTextStart + composeLength); // pre-edit text } } -- cgit v1.2.3 From 8917179b47cf2ead645aaacfb680d261308cd866 Mon Sep 17 00:00:00 2001 From: Dyami Caliri Date: Sat, 24 May 2014 10:18:48 -0700 Subject: plugin/bearer remove static QDBusConnection::systemBus() initialization The static initialization of QDBusConnection::systemBus() can occur before the creation of QCoreApplication. This causes a warning from QDBusConnection and may cause the application to crash on exit. Since QDBusConnection::systemBus() is just an accessor, there is no real advantage to storing a static reference to it. Task-number: QTBUG-39248 Change-Id: I4401810c7c2ffd21a30f9ffd41b3a46e7e09214c Reviewed-by: Thiago Macieira Reviewed-by: Alex Blasche --- .../networkmanager/qnetworkmanagerservice.cpp | 35 ++++++++++++---------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp index 776d69403a..c28f7ef664 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp @@ -58,8 +58,6 @@ QT_BEGIN_NAMESPACE -static QDBusConnection dbusConnection = QDBusConnection::systemBus(); - class QNetworkManagerInterfacePrivate { public: @@ -74,7 +72,7 @@ QNetworkManagerInterface::QNetworkManagerInterface(QObject *parent) d->connectionInterface = new QDBusInterface(QLatin1String(NM_DBUS_SERVICE), QLatin1String(NM_DBUS_PATH), QLatin1String(NM_DBUS_INTERFACE), - dbusConnection); + QDBusConnection::systemBus()); if (!d->connectionInterface->isValid()) { d->valid = false; return; @@ -103,6 +101,9 @@ bool QNetworkManagerInterface::setConnections() { if(!isValid() ) return false; + + QDBusConnection dbusConnection = QDBusConnection::systemBus(); + bool allOk = false; if (!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), QLatin1String(NM_DBUS_PATH), @@ -198,7 +199,7 @@ QNetworkManagerInterfaceAccessPoint::QNetworkManagerInterfaceAccessPoint(const Q d->connectionInterface = new QDBusInterface(QLatin1String(NM_DBUS_SERVICE), d->path, QLatin1String(NM_DBUS_INTERFACE_ACCESS_POINT), - dbusConnection); + QDBusConnection::systemBus()); if (!d->connectionInterface->isValid()) { d->valid = false; return; @@ -229,7 +230,7 @@ bool QNetworkManagerInterfaceAccessPoint::setConnections() connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(QString,QMap)), this,SIGNAL(propertiesChanged(QString,QMap))); - if(dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), + if (QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), d->path, QLatin1String(NM_DBUS_INTERFACE_ACCESS_POINT), QLatin1String("PropertiesChanged"), @@ -306,7 +307,7 @@ QNetworkManagerInterfaceDevice::QNetworkManagerInterfaceDevice(const QString &de d->connectionInterface = new QDBusInterface(QLatin1String(NM_DBUS_SERVICE), d->path, QLatin1String(NM_DBUS_INTERFACE_DEVICE), - dbusConnection); + QDBusConnection::systemBus()); if (!d->connectionInterface->isValid()) { d->valid = false; return; @@ -335,7 +336,7 @@ bool QNetworkManagerInterfaceDevice::setConnections() nmDBusHelper = new QNmDBusHelper(this); connect(nmDBusHelper,SIGNAL(pathForStateChanged(QString,quint32)), this, SIGNAL(stateChanged(QString,quint32))); - if(dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), + if (QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), d->path, QLatin1String(NM_DBUS_INTERFACE_DEVICE), QLatin1String("StateChanged"), @@ -397,7 +398,7 @@ QNetworkManagerInterfaceDeviceWired::QNetworkManagerInterfaceDeviceWired(const Q d->connectionInterface = new QDBusInterface(QLatin1String(NM_DBUS_SERVICE), d->path, QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRED), - dbusConnection, parent); + QDBusConnection::systemBus(), parent); if (!d->connectionInterface->isValid()) { d->valid = false; return; @@ -428,7 +429,7 @@ bool QNetworkManagerInterfaceDeviceWired::setConnections() nmDBusHelper = new QNmDBusHelper(this); connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(QString,QMap)), this,SIGNAL(propertiesChanged(QString,QMap))); - if(dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), + if (QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), d->path, QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRED), QLatin1String("PropertiesChanged"), @@ -474,7 +475,7 @@ QNetworkManagerInterfaceDeviceWireless::QNetworkManagerInterfaceDeviceWireless(c d->connectionInterface = new QDBusInterface(QLatin1String(NM_DBUS_SERVICE), d->path, QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS), - dbusConnection, parent); + QDBusConnection::systemBus(), parent); if (!d->connectionInterface->isValid()) { d->valid = false; return; @@ -498,6 +499,7 @@ bool QNetworkManagerInterfaceDeviceWireless::setConnections() if(!isValid() ) return false; + QDBusConnection dbusConnection = QDBusConnection::systemBus(); bool allOk = false; delete nmDBusHelper; nmDBusHelper = new QNmDBusHelper(this); @@ -591,7 +593,7 @@ QNetworkManagerSettings::QNetworkManagerSettings(const QString &settingsService, d->connectionInterface = new QDBusInterface(settingsService, QLatin1String(NM_DBUS_PATH_SETTINGS), QLatin1String(NM_DBUS_IFACE_SETTINGS), - dbusConnection); + QDBusConnection::systemBus()); if (!d->connectionInterface->isValid()) { d->valid = false; return; @@ -614,7 +616,7 @@ bool QNetworkManagerSettings::setConnections() { bool allOk = false; - if (!dbusConnection.connect(d->path, QLatin1String(NM_DBUS_PATH_SETTINGS), + if (!QDBusConnection::systemBus().connect(d->path, QLatin1String(NM_DBUS_PATH_SETTINGS), QLatin1String(NM_DBUS_IFACE_SETTINGS), QLatin1String("NewConnection"), this, SIGNAL(newConnection(QDBusObjectPath)))) { allOk = true; @@ -655,7 +657,7 @@ QNetworkManagerSettingsConnection::QNetworkManagerSettingsConnection(const QStri d->connectionInterface = new QDBusInterface(settingsService, d->path, QLatin1String(NM_DBUS_IFACE_SETTINGS_CONNECTION), - dbusConnection, parent); + QDBusConnection::systemBus(), parent); if (!d->connectionInterface->isValid()) { d->valid = false; return; @@ -681,6 +683,7 @@ bool QNetworkManagerSettingsConnection::setConnections() if(!isValid() ) return false; + QDBusConnection dbusConnection = QDBusConnection::systemBus(); bool allOk = false; if(!dbusConnection.connect(d->service, d->path, QLatin1String(NM_DBUS_IFACE_SETTINGS_CONNECTION), QLatin1String("Updated"), @@ -808,7 +811,7 @@ QNetworkManagerConnectionActive::QNetworkManagerConnectionActive( const QString d->connectionInterface = new QDBusInterface(QLatin1String(NM_DBUS_SERVICE), d->path, QLatin1String(NM_DBUS_INTERFACE_ACTIVE_CONNECTION), - dbusConnection, parent); + QDBusConnection::systemBus(), parent); if (!d->connectionInterface->isValid()) { d->valid = false; return; @@ -837,7 +840,7 @@ bool QNetworkManagerConnectionActive::setConnections() nmDBusHelper = new QNmDBusHelper(this); connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(QString,QMap)), this,SIGNAL(propertiesChanged(QString,QMap))); - if(dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), + if (QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), d->path, QLatin1String(NM_DBUS_INTERFACE_ACTIVE_CONNECTION), QLatin1String("PropertiesChanged"), @@ -902,7 +905,7 @@ QNetworkManagerIp4Config::QNetworkManagerIp4Config( const QString &deviceObjectP d->connectionInterface = new QDBusInterface(QLatin1String(NM_DBUS_SERVICE), d->path, QLatin1String(NM_DBUS_INTERFACE_IP4_CONFIG), - dbusConnection, parent); + QDBusConnection::systemBus(), parent); if (!d->connectionInterface->isValid()) { d->valid = false; return; -- cgit v1.2.3 From 8746a6a3e2a21f952badd6301565783f07f61c03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Tue, 20 May 2014 13:01:50 +0200 Subject: Improve the implementation of the _NET_WM_SYNC_REQUEST protocol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change improves the synced resizes of xcb windows and adds support for synced resizes of glx windows. The QXcbWindow keeps a better track on whether the window manager expects a sync and can be in one of three states: * no sync required * sync required, but configure notify event not yet received * sync required and configured By tracking this in the QXcbWindow itself the backing store can make use of this information and doesn't need an own heuristic to decide whether a sync is needed. Also this allows to add support for synced resizes of windows with an OpenGLSurface. This is accomplished by checking the sync state after swapping buffers. As the OpenGL context may be bound to a background thread the sync is done using a QueuedConnection to ensure that the sync happens in the thread which created the xcb window. So far this is only added for GLX. This significantly improves the resize experience of QQuickWindow and also the initial mapping with a composited window manager in case the compositor uses the sync protocol to determine whether the window is ready to get painted on screen. Change-Id: Ied0261873043d785dec652d2821fc3638292fa36 Reviewed-by: Uli Schlachter Reviewed-by: Jørgen Lind --- src/plugins/platforms/xcb/qglxintegration.cpp | 9 +++++++++ src/plugins/platforms/xcb/qxcbbackingstore.cpp | 16 ++++------------ src/plugins/platforms/xcb/qxcbbackingstore.h | 1 - src/plugins/platforms/xcb/qxcbconnection.cpp | 5 +++++ src/plugins/platforms/xcb/qxcbconnection.h | 3 +++ src/plugins/platforms/xcb/qxcbintegration.cpp | 1 + src/plugins/platforms/xcb/qxcbwindow.cpp | 25 +++++++++++++++++++++++-- src/plugins/platforms/xcb/qxcbwindow.h | 15 ++++++++++++++- 8 files changed, 59 insertions(+), 16 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp index f78d3bcc4e..9a56455940 100644 --- a/src/plugins/platforms/xcb/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/qglxintegration.cpp @@ -390,6 +390,15 @@ void QGLXContext::swapBuffers(QPlatformSurface *surface) else glxDrawable = static_cast(surface)->xcb_window(); glXSwapBuffers(DISPLAY_FROM_XCB(m_screen), glxDrawable); + + if (surface->surface()->surfaceClass() == QSurface::Window) { + QXcbWindow *platformWindow = static_cast(surface); + // OpenGL context might be bound to a non-gui thread + // use QueuedConnection to sync the window from the platformWindow's thread + // as QXcbWindow is no QObject, a wrapper slot in QXcbConnection is used. + if (platformWindow->needsSync()) + QMetaObject::invokeMethod(m_screen->connection(), "syncWindow", Qt::QueuedConnection, Q_ARG(QXcbWindow*, platformWindow)); + } } void (*QGLXContext::getProcAddress(const QByteArray &procName)) () diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 57d6bc580b..ada5b0eedf 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -261,7 +261,6 @@ void QXcbShmImage::preparePaint(const QRegion ®ion) QXcbBackingStore::QXcbBackingStore(QWindow *window) : QPlatformBackingStore(window) , m_image(0) - , m_syncingResize(false) { QXcbScreen *screen = static_cast(window->screen()->handle()); setConnection(screen->connection()); @@ -330,13 +329,10 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoin Q_XCB_NOOP(connection()); - if (m_syncingResize) { - connection()->sync(); - m_syncingResize = false; + if (platformWindow->needsSync()) platformWindow->updateSyncRequestCounter(); - } else { + else xcb_flush(xcb_connection()); - } } #ifndef QT_NO_OPENGL @@ -347,10 +343,8 @@ void QXcbBackingStore::composeAndFlush(QWindow *window, const QRegion ®ion, c Q_XCB_NOOP(connection()); - if (m_syncingResize) { - QXcbWindow *platformWindow = static_cast(window->handle()); - connection()->sync(); - m_syncingResize = false; + QXcbWindow *platformWindow = static_cast(window->handle()); + if (platformWindow->needsSync()) { platformWindow->updateSyncRequestCounter(); } else { xcb_flush(xcb_connection()); @@ -376,8 +370,6 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &) delete m_image; m_image = new QXcbShmImage(screen, size, win->depth(), win->imageFormat()); Q_XCB_NOOP(connection()); - - m_syncingResize = true; } extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset); diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.h b/src/plugins/platforms/xcb/qxcbbackingstore.h index 19a5ac62d0..af3c004c2d 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.h +++ b/src/plugins/platforms/xcb/qxcbbackingstore.h @@ -72,7 +72,6 @@ public: private: QXcbShmImage *m_image; - bool m_syncingResize; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index f5f6c712c5..1b72bb0da1 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1833,6 +1833,11 @@ QXcbSystemTrayTracker *QXcbConnection::systemTrayTracker() return m_systemTrayTracker; } +void QXcbConnection::syncWindow(QXcbWindow *window) +{ + window->updateSyncRequestCounter(); +} + QXcbConnectionGrabber::QXcbConnectionGrabber(QXcbConnection *connection) :m_connection(connection) { diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 6e511356c4..f96541318c 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -464,6 +464,9 @@ public: void handleEnterEvent(const xcb_enter_notify_event_t *); #endif +public slots: + void syncWindow(QXcbWindow *window); + private slots: void processXcbEvents(); diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 0bab341914..ddb164bf07 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -127,6 +127,7 @@ QXcbIntegration::QXcbIntegration(const QStringList ¶meters, int &argc, char : m_services(new QGenericUnixServices) , m_instanceName(0) { + qRegisterMetaType(); #ifdef XCB_USE_XLIB XInitThreads(); #endif diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 3645b6469a..a46fe437d8 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -200,6 +200,7 @@ QXcbWindow::QXcbWindow(QWindow *window) , m_eglSurface(0) #endif , m_lastWindowStateEvent(-1) + , m_syncState(NoSyncNeeded) { m_screen = static_cast(window->screen()->handle()); @@ -367,7 +368,12 @@ void QXcbWindow::create() properties[propertyCount++] = atom(QXcbAtom::WM_TAKE_FOCUS); properties[propertyCount++] = atom(QXcbAtom::_NET_WM_PING); - m_usingSyncProtocol = m_screen->syncRequestSupported() && window()->surfaceType() != QSurface::OpenGLSurface; + m_usingSyncProtocol = m_screen->syncRequestSupported(); +#if !defined(XCB_USE_GLX) + // synced resize only implemented on GLX + if (window()->supportsOpenGL()) + m_usingSyncProtocol = false; +#endif if (m_usingSyncProtocol) properties[propertyCount++] = atom(QXcbAtom::_NET_WM_SYNC_REQUEST); @@ -1596,6 +1602,8 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even connection()->setTime(event->data.data32[1]); m_syncValue.lo = event->data.data32[2]; m_syncValue.hi = event->data.data32[3]; + if (m_usingSyncProtocol) + m_syncState = SyncReceived; #ifndef QT_NO_WHATSTHIS } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_CONTEXT_HELP)) { QWindowSystemInterface::handleEnterWhatsThisEvent(); @@ -1669,6 +1677,9 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size())); } + if (m_usingSyncProtocol && m_syncState == SyncReceived) + m_syncState = SyncAndConfigureReceived; + m_dirtyFrameMargins = true; } @@ -1945,12 +1956,17 @@ void QXcbWindow::handleFocusOutEvent(const xcb_focus_out_event_t *) void QXcbWindow::updateSyncRequestCounter() { + if (m_syncState != SyncAndConfigureReceived) { + // window manager does not expect a sync event yet. + return; + } if (m_usingSyncProtocol && (m_syncValue.lo != 0 || m_syncValue.hi != 0)) { Q_XCB_CALL(xcb_sync_set_counter(xcb_connection(), m_syncCounter, m_syncValue)); - connection()->sync(); + xcb_flush(xcb_connection()); m_syncValue.lo = 0; m_syncValue.hi = 0; + m_syncState = NoSyncNeeded; } } @@ -2173,4 +2189,9 @@ void QXcbWindow::setAlertState(bool enabled) } } +bool QXcbWindow::needsSync() const +{ + return m_syncState == SyncAndConfigureReceived; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 12d17023fb..b924ee27e5 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -144,13 +144,17 @@ public: void handleMouseEvent(xcb_timestamp_t time, const QPoint &local, const QPoint &global, Qt::KeyboardModifiers modifiers); - void updateSyncRequestCounter(); void updateNetWmUserTime(xcb_timestamp_t timestamp); #if defined(XCB_USE_EGL) QXcbEGLSurface *eglSurface() const; #endif + bool needsSync() const; + +public Q_SLOTS: + void updateSyncRequestCounter(); + private: void changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two = 0); NetWmStates netWmStates(); @@ -217,8 +221,17 @@ private: xcb_visualid_t m_visualId; int m_lastWindowStateEvent; + + enum SyncState { + NoSyncNeeded, + SyncReceived, + SyncAndConfigureReceived + }; + SyncState m_syncState; }; QT_END_NAMESPACE +Q_DECLARE_METATYPE(QXcbWindow*) + #endif -- cgit v1.2.3 From 626e0f204e846040e8e3a67bfc088f09b5091e7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 14 May 2014 11:30:35 +0200 Subject: Revert "Cocoa: Post event to "show()" a modal window" This reverts commit a9cbddf4739f3cfabd38367b5f872fe2c1a3814c. The reverted commit is an incorrect bug-fix for a regression introduced by adding a call to [NSApp abortModal] in change d9875f7b. Change-Id: If23463ebdfe2ff64c68739dbece73a13773683c9 Reviewed-by: Gabriel de Dietrich --- .../platforms/cocoa/qcocoaeventdispatcher.h | 3 +-- .../platforms/cocoa/qcocoaeventdispatcher.mm | 25 ++++++++++------------ 2 files changed, 12 insertions(+), 16 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h index de6c6585e9..0274ed8201 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h @@ -134,8 +134,6 @@ public: void interrupt(); void flush(); - bool event(QEvent *); - friend void qt_mac_maybeCancelWaitForMoreEventsForwarder(QAbstractEventDispatcher *eventDispatcher); }; @@ -165,6 +163,7 @@ public: // The following variables help organizing modal sessions: QStack cocoaModalSessionStack; bool currentExecIsNSAppRun; + bool modalSessionOnNSAppRun; bool nsAppRunCalledByQt; bool cleanupModalSessionsNeeded; uint processEventsCalled; diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index b625f233ce..98becf0728 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -738,25 +738,13 @@ void QCocoaEventDispatcherPrivate::beginModalSession(QWindow *window) updateChildrenWorksWhenModal(); currentModalSessionCached = 0; if (currentExecIsNSAppRun) { - QEvent *e = new QEvent(QEvent::User); - qApp->postEvent(q, e, Qt::HighEventPriority); + modalSessionOnNSAppRun = true; + q->wakeUp(); } else { q->interrupt(); } } -bool QCocoaEventDispatcher::event(QEvent *e) -{ - Q_D(QCocoaEventDispatcher); - - if (e->type() == QEvent::User) { - d->q_func()->processEvents(QEventLoop::DialogExec | QEventLoop::EventLoopExec | QEventLoop::WaitForMoreEvents); - return true; - } - - return QObject::event(e); -} - void QCocoaEventDispatcherPrivate::endModalSession(QWindow *window) { Q_Q(QCocoaEventDispatcher); @@ -793,6 +781,7 @@ QCocoaEventDispatcherPrivate::QCocoaEventDispatcherPrivate() runLoopTimerRef(0), blockSendPostedEvents(false), currentExecIsNSAppRun(false), + modalSessionOnNSAppRun(false), nsAppRunCalledByQt(false), cleanupModalSessionsNeeded(false), processEventsCalled(0), @@ -923,6 +912,14 @@ void QCocoaEventDispatcherPrivate::postedEventsSourceCallback(void *info) // processEvents() was called "manually," ignore this source for now d->maybeCancelWaitForMoreEvents(); return; + } else if (d->modalSessionOnNSAppRun) { + // We're about to spawn the 1st modal session on top of the main runloop. + // Instead of calling processPostedEvents(), which would need us stop + // NSApp, we just re-enter processEvents(). This is equivalent to calling + // QDialog::exec() except that it's done in a non-blocking way. + d->modalSessionOnNSAppRun = false; + d->q_func()->processEvents(QEventLoop::DialogExec | QEventLoop::EventLoopExec | QEventLoop::WaitForMoreEvents); + return; } d->processPostedEvents(); d->maybeCancelWaitForMoreEvents(); -- cgit v1.2.3 From 385ba9e7e3604fa181e89ae7242a6b1a36544c94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 14 May 2014 11:30:46 +0200 Subject: Revert "Cocoa: Don't stop NSApp when showing a modal dialog" This reverts commit ff3dcc49c4a1912189091e35e87cb61af2f62d47. The reverted commit is an incorrect bug-fix for a regression introduced by adding a call to [NSApp abortModal] in change d9875f7b. Change-Id: I1307d1790ada740e0552d62267b6009cbccd6c4c Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoaeventdispatcher.h | 1 - src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm | 16 +--------------- 2 files changed, 1 insertion(+), 16 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h index 0274ed8201..33d7dcbcf4 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h @@ -163,7 +163,6 @@ public: // The following variables help organizing modal sessions: QStack cocoaModalSessionStack; bool currentExecIsNSAppRun; - bool modalSessionOnNSAppRun; bool nsAppRunCalledByQt; bool cleanupModalSessionsNeeded; uint processEventsCalled; diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index 98becf0728..97b8771354 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -725,6 +725,7 @@ void QCocoaEventDispatcherPrivate::beginModalSession(QWindow *window) // setting currentModalSessionCached to zero, so that interrupt() calls // [NSApp abortModal] if another modal session is currently running Q_Q(QCocoaEventDispatcher); + q->interrupt(); // Add a new, empty (null), NSModalSession to the stack. // It will become active the next time QEventDispatcher::processEvents is called. @@ -737,12 +738,6 @@ void QCocoaEventDispatcherPrivate::beginModalSession(QWindow *window) cocoaModalSessionStack.push(info); updateChildrenWorksWhenModal(); currentModalSessionCached = 0; - if (currentExecIsNSAppRun) { - modalSessionOnNSAppRun = true; - q->wakeUp(); - } else { - q->interrupt(); - } } void QCocoaEventDispatcherPrivate::endModalSession(QWindow *window) @@ -781,7 +776,6 @@ QCocoaEventDispatcherPrivate::QCocoaEventDispatcherPrivate() runLoopTimerRef(0), blockSendPostedEvents(false), currentExecIsNSAppRun(false), - modalSessionOnNSAppRun(false), nsAppRunCalledByQt(false), cleanupModalSessionsNeeded(false), processEventsCalled(0), @@ -912,14 +906,6 @@ void QCocoaEventDispatcherPrivate::postedEventsSourceCallback(void *info) // processEvents() was called "manually," ignore this source for now d->maybeCancelWaitForMoreEvents(); return; - } else if (d->modalSessionOnNSAppRun) { - // We're about to spawn the 1st modal session on top of the main runloop. - // Instead of calling processPostedEvents(), which would need us stop - // NSApp, we just re-enter processEvents(). This is equivalent to calling - // QDialog::exec() except that it's done in a non-blocking way. - d->modalSessionOnNSAppRun = false; - d->q_func()->processEvents(QEventLoop::DialogExec | QEventLoop::EventLoopExec | QEventLoop::WaitForMoreEvents); - return; } d->processPostedEvents(); d->maybeCancelWaitForMoreEvents(); -- cgit v1.2.3 From 11fdc4f6c06922b474a311d7afb8a393686ddf13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 14 May 2014 11:32:54 +0200 Subject: Partially revert "Cocoa: support modal windows" This reverts parts of commit d9875f7bff6d52a52a1d0bf4002044a5304cf6bf, in particular the code for "2. Make interrupt() use [NSApp abortModal]" abortModal is not the right way to end a modal session, and introduced bad side effects, as reported in QTBUG-34677. Restore this part of the event dispatcher to the Qt 4 state. Change-Id: Iacc2d4a0757807c87c4320c93ed4db186622945c Reviewed-by: Gabriel de Dietrich --- .../platforms/cocoa/qcocoaeventdispatcher.mm | 36 ++++++++-------------- 1 file changed, 12 insertions(+), 24 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index 97b8771354..96a8fa1ad4 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -721,9 +721,7 @@ void QCocoaEventDispatcherPrivate::beginModalSession(QWindow *window) { // We need to start spinning the modal session. Usually this is done with // QDialog::exec() for Qt Widgets based applications, but for others that - // just call show(), we need to interrupt(). We call this here, before - // setting currentModalSessionCached to zero, so that interrupt() calls - // [NSApp abortModal] if another modal session is currently running + // just call show(), we need to interrupt(). Q_Q(QCocoaEventDispatcher); q->interrupt(); @@ -759,10 +757,7 @@ void QCocoaEventDispatcherPrivate::endModalSession(QWindow *window) info.window = 0; if (i + endedSessions == stackSize-1) { // The top sessions ended. Interrupt the event dispatcher to - // start spinning the correct session immediately. Like in - // beginModalSession(), we call interrupt() before clearing - // currentModalSessionCached to make sure we stop any currently - // running modal session with [NSApp abortModal] + // start spinning the correct session immediately. q->interrupt(); currentModalSessionCached = 0; cleanupModalSessionsNeeded = true; @@ -935,23 +930,16 @@ void QCocoaEventDispatcher::interrupt() { Q_D(QCocoaEventDispatcher); d->interrupt = true; - if (d->currentModalSessionCached) { - // If a modal session is active, abort it so that we can clean it up - // later. We can't use [NSApp stopModal] here, because we do not know - // where the interrupt() came from. - [NSApp abortModal]; - } else { - wakeUp(); - - // We do nothing more here than setting d->interrupt = true, and - // poke the event loop if it is sleeping. Actually stopping - // NSApp, or the current modal session, is done inside the send - // posted events callback. We do this to ensure that all current pending - // cocoa events gets delivered before we stop. Otherwise, if we now stop - // the last event loop recursion, cocoa will just drop pending posted - // events on the floor before we get a chance to reestablish a new session. - d->cancelWaitForMoreEvents(); - } + wakeUp(); + + // We do nothing more here than setting d->interrupt = true, and + // poke the event loop if it is sleeping. Actually stopping + // NSApp, or the current modal session, is done inside the send + // posted events callback. We do this to ensure that all current pending + // cocoa events gets delivered before we stop. Otherwise, if we now stop + // the last event loop recursion, cocoa will just drop pending posted + // events on the floor before we get a chance to reestablish a new session. + d->cancelWaitForMoreEvents(); } void QCocoaEventDispatcher::flush() -- cgit v1.2.3 From 530607d8ba0dac8d91d20ec0e62d3129cb21e225 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Thu, 15 May 2014 13:29:25 +0200 Subject: Cocoa: Fix modal session cleanup. Call [NSApp endModalSession] at the correct time. Calling cleanupModalSessions() from processPostedEvents() resulted in endModalSession being called from within [NSApp runModalSession] - ending and cleaning up the the modal session while Cocoa is still using it. Move the cleanupModalSessions() call to to after runModalSession returns. Task-number: QTBUG-37699 Change-Id: I5868def36f6869667b0bbe33733286e3e49488eb Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index 96a8fa1ad4..9aaf08adcf 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -415,6 +415,11 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) // 'session' as well. As a result, we need to restart all internal sessions: d->temporarilyStopAllModalSessions(); } + + // Clean up the modal session list, call endModalSession. + if (d->cleanupModalSessionsNeeded) + d->cleanupModalSessions(); + } else { d->nsAppRunCalledByQt = true; QBoolBlocker execGuard(d->currentExecIsNSAppRun, true); @@ -441,6 +446,11 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) // 'session' as well. As a result, we need to restart all internal sessions: d->temporarilyStopAllModalSessions(); } + + // Clean up the modal session list, call endModalSession. + if (d->cleanupModalSessionsNeeded) + d->cleanupModalSessions(); + retVal = true; } else do { // Dispatch all non-user events (but que non-user events up for later). In @@ -860,9 +870,6 @@ void QCocoaEventDispatcherPrivate::processPostedEvents() return; } - if (cleanupModalSessionsNeeded) - cleanupModalSessions(); - if (interrupt) { if (currentExecIsNSAppRun) { // The event dispatcher has been interrupted. But since -- cgit v1.2.3 From 909b0de5d16f2af3b3d6a3ca4c7e53b84836ad37 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 15 May 2014 13:32:27 +0200 Subject: Windows: Fix another crash when creating QRawFont from invalid data The sanity check added in d16508a285a5423ae9a5034e969801bce74ffb98 didn't actually catch the case where the invalid data is large enough to contain the offset table and table directory. Added sanity checks to all the code that accesses the font data now, so this should fix crashes with partial data as well as invalid data. Task-number: QTBUG-37190 Change-Id: Ie43f10d8cf0b09007783b9b1c4d91bfed8c6b0f0 Reviewed-by: Konstantin Ritt --- .../platforms/windows/qwindowsfontdatabase.cpp | 36 ++++++++++++++++------ 1 file changed, 27 insertions(+), 9 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index 6d9f01da4e..696dc06cee 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -164,15 +164,18 @@ namespace { { Q_ASSERT(tagName.size() == 4); quint32 tagId = *(reinterpret_cast(tagName.constData())); - - if (m_fontData.size() < sizeof(OffsetSubTable) + sizeof(TableDirectory)) + if (Q_UNLIKELY(m_fontData.size() < sizeof(OffsetSubTable))) return 0; OffsetSubTable *offsetSubTable = reinterpret_cast(m_fontData.data()); TableDirectory *tableDirectory = reinterpret_cast(offsetSubTable + 1); + quint16 tableCount = qFromBigEndian(offsetSubTable->numTables); + if (Q_UNLIKELY(quint32(m_fontData.size()) < sizeof(OffsetSubTable) + sizeof(TableDirectory) * tableCount)) + return 0; + TableDirectory *nameTableDirectoryEntry = 0; - for (int i = 0; i < qFromBigEndian(offsetSubTable->numTables); ++i, ++tableDirectory) { + for (int i = 0; i < tableCount; ++i, ++tableDirectory) { if (tableDirectory->identifier == tagId) { nameTableDirectoryEntry = tableDirectory; break; @@ -190,19 +193,34 @@ namespace { nameTableDirectoryEntry = tableDirectoryEntry("name"); if (nameTableDirectoryEntry != 0) { - NameTable *nameTable = reinterpret_cast( - m_fontData.data() + qFromBigEndian(nameTableDirectoryEntry->offset)); + quint32 offset = qFromBigEndian(nameTableDirectoryEntry->offset); + if (Q_UNLIKELY(quint32(m_fontData.size()) < offset + sizeof(NameTable))) + return QString(); + + NameTable *nameTable = reinterpret_cast(m_fontData.data() + offset); NameRecord *nameRecord = reinterpret_cast(nameTable + 1); - for (int i = 0; i < qFromBigEndian(nameTable->count); ++i, ++nameRecord) { + + quint16 nameTableCount = qFromBigEndian(nameTable->count); + if (Q_UNLIKELY(quint32(m_fontData.size()) < offset + sizeof(NameRecord) * nameTableCount)) + return QString(); + + for (int i = 0; i < nameTableCount; ++i, ++nameRecord) { if (qFromBigEndian(nameRecord->nameID) == 1 && qFromBigEndian(nameRecord->platformID) == 3 // Windows && qFromBigEndian(nameRecord->languageID) == 0x0409) { // US English + quint16 stringOffset = qFromBigEndian(nameTable->stringOffset); + quint16 nameOffset = qFromBigEndian(nameRecord->offset); + quint16 nameLength = qFromBigEndian(nameRecord->length); + + if (Q_UNLIKELY(quint32(m_fontData.size()) < offset + stringOffset + nameOffset + nameLength)) + return QString(); + const void *ptr = reinterpret_cast(nameTable) - + qFromBigEndian(nameTable->stringOffset) - + qFromBigEndian(nameRecord->offset); + + stringOffset + + nameOffset; const quint16 *s = reinterpret_cast(ptr); - const quint16 *e = s + qFromBigEndian(nameRecord->length) / sizeof(quint16); + const quint16 *e = s + nameLength / sizeof(quint16); while (s != e) name += QChar( qFromBigEndian(*s++)); break; -- cgit v1.2.3 From bfc0b27b4b2cba117a5f1e00e2ec8ac13d2af586 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Fri, 30 May 2014 10:37:41 +0200 Subject: Do not resolve the java functions for each call Instead do it only once (in registerNatives). This is seems to be the preferred way of doing it in other parts of the platform plugin. Change-Id: I361a7862bb5a24b4024c7c6a30ecb14fc515d4ff Reviewed-by: Frederik Gladhorn --- .../platforms/android/androidjniaccessibility.cpp | 62 ++++++++++++++-------- 1 file changed, 41 insertions(+), 21 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp index fa7e259460..d9f5cec27a 100644 --- a/src/plugins/platforms/android/androidjniaccessibility.cpp +++ b/src/plugins/platforms/android/androidjniaccessibility.cpp @@ -56,6 +56,18 @@ static const char m_methodErrorMsg[] = "Can't find method \"%s%s\""; namespace QtAndroidAccessibility { + static jmethodID m_addActionMethodID = 0; + static jmethodID m_setCheckableMethodID = 0; + static jmethodID m_setCheckedMethodID = 0; + static jmethodID m_setClickableMethodID = 0; + static jmethodID m_setContentDescriptionMethodID = 0; + static jmethodID m_setEnabledMethodID = 0; + static jmethodID m_setFocusableMethodID = 0; + static jmethodID m_setFocusedMethodID = 0; + static jmethodID m_setTextSelectionMethodID = 0; + static jmethodID m_setVisibleToUserMethodID = 0; + + static void setActive(JNIEnv */*env*/, jobject /*thiz*/, jboolean active) { QAndroidPlatformIntegration *platformIntegration = QtAndroid::androidPlatformIntegration(); @@ -164,17 +176,6 @@ if (!clazz) { \ //__android_log_print(ANDROID_LOG_FATAL, m_qtTag, m_methodErrorMsg, METHOD_NAME, METHOD_SIGNATURE); -#define CALL_METHOD(OBJECT, METHOD_NAME, METHOD_SIGNATURE, ...) \ -{ \ - jclass clazz = env->GetObjectClass(OBJECT); \ - jmethodID method = env->GetMethodID(clazz, METHOD_NAME, METHOD_SIGNATURE); \ - if (!method) { \ - __android_log_print(ANDROID_LOG_WARN, m_qtTag, m_methodErrorMsg, METHOD_NAME, METHOD_SIGNATURE); \ - return false; \ - } \ - env->CallVoidMethod(OBJECT, method, __VA_ARGS__); \ -} - static jstring descriptionForAccessibleObject(JNIEnv *env, jobject /*thiz*/, jint objectId) { @@ -210,30 +211,30 @@ if (!clazz) { \ int startSelection; int endSelection; textIface->selection(0, &startSelection, &endSelection); - CALL_METHOD(node, "setTextSelection", "(II)V", startSelection, endSelection) + env->CallVoidMethod(node, m_setTextSelectionMethodID, startSelection, endSelection); } } - CALL_METHOD(node, "setEnabled", "(Z)V", !state.disabled) - CALL_METHOD(node, "setFocusable", "(Z)V", (bool)state.focusable) - CALL_METHOD(node, "setFocused", "(Z)V", (bool)state.focused) - CALL_METHOD(node, "setCheckable", "(Z)V", (bool)state.checkable) - CALL_METHOD(node, "setChecked", "(Z)V", (bool)state.checked) - CALL_METHOD(node, "setVisibleToUser", "(Z)V", !state.invisible) + env->CallVoidMethod(node, m_setEnabledMethodID, !state.disabled); + env->CallVoidMethod(node, m_setCheckedMethodID, (bool)state.checked); + env->CallVoidMethod(node, m_setFocusableMethodID, (bool)state.focusable); + env->CallVoidMethod(node, m_setFocusedMethodID, (bool)state.focused); + env->CallVoidMethod(node, m_setCheckableMethodID, (bool)state.checkable); + env->CallVoidMethod(node, m_setVisibleToUserMethodID, !state.invisible); if (iface->actionInterface()) { QStringList actions = iface->actionInterface()->actionNames(); bool clickable = actions.contains(QAccessibleActionInterface::pressAction()); bool toggle = actions.contains(QAccessibleActionInterface::toggleAction()); if (clickable || toggle) { - CALL_METHOD(node, "setClickable", "(Z)V", (bool)clickable) - CALL_METHOD(node, "addAction", "(I)V", 16) // ACTION_CLICK defined in AccessibilityNodeInfo + env->CallVoidMethod(node, m_setClickableMethodID, (bool)clickable); + env->CallVoidMethod(node, m_addActionMethodID, (int)16); // ACTION_CLICK defined in AccessibilityNodeInfo } } jstring jdesc = env->NewString((jchar*) desc.constData(), (jsize) desc.size()); //CALL_METHOD(node, "setText", "(Ljava/lang/CharSequence;)V", jdesc) - CALL_METHOD(node, "setContentDescription", "(Ljava/lang/CharSequence;)V", jdesc) + env->CallVoidMethod(node, m_setContentDescriptionMethodID, jdesc); return true; } @@ -249,6 +250,13 @@ if (!clazz) { \ {"clickAction", "(I)Z", (void*)clickAction}, }; +#define GET_AND_CHECK_STATIC_METHOD(VAR, CLASS, METHOD_NAME, METHOD_SIGNATURE) \ + VAR = env->GetMethodID(CLASS, METHOD_NAME, METHOD_SIGNATURE); \ + if (!VAR) { \ + __android_log_print(ANDROID_LOG_FATAL, QtAndroid::qtTagText(), QtAndroid::methodErrorMsgFmt(), METHOD_NAME, METHOD_SIGNATURE); \ + return false; \ + } + bool registerNatives(JNIEnv *env) { jclass clazz; @@ -260,6 +268,18 @@ if (!clazz) { \ return false; } + jclass nodeInfoClass = env->FindClass("android/view/accessibility/AccessibilityNodeInfo"); + GET_AND_CHECK_STATIC_METHOD(m_addActionMethodID, nodeInfoClass, "addAction", "(I)V"); + GET_AND_CHECK_STATIC_METHOD(m_setCheckableMethodID, nodeInfoClass, "setCheckable", "(Z)V"); + GET_AND_CHECK_STATIC_METHOD(m_setCheckedMethodID, nodeInfoClass, "setChecked", "(Z)V"); + GET_AND_CHECK_STATIC_METHOD(m_setClickableMethodID, nodeInfoClass, "setClickable", "(Z)V"); + GET_AND_CHECK_STATIC_METHOD(m_setContentDescriptionMethodID, nodeInfoClass, "setContentDescription", "(Ljava/lang/CharSequence;)V"); + GET_AND_CHECK_STATIC_METHOD(m_setEnabledMethodID, nodeInfoClass, "setEnabled", "(Z)V"); + GET_AND_CHECK_STATIC_METHOD(m_setFocusableMethodID, nodeInfoClass, "setFocusable", "(Z)V"); + GET_AND_CHECK_STATIC_METHOD(m_setFocusedMethodID, nodeInfoClass, "setFocused", "(Z)V"); + GET_AND_CHECK_STATIC_METHOD(m_setTextSelectionMethodID, nodeInfoClass, "setTextSelection", "(II)V"); + GET_AND_CHECK_STATIC_METHOD(m_setVisibleToUserMethodID, nodeInfoClass, "setVisibleToUser", "(Z)V"); + return true; } } -- cgit v1.2.3 From 6bd8c3742e111301481d3658a7c0a970bb10d66b Mon Sep 17 00:00:00 2001 From: Rafael Roquetto Date: Mon, 26 May 2014 18:26:45 -0300 Subject: QNX: Fix clearing transparent buffer Testing whether alphaBufferSize() != 0 does not work, because when no alpha channel is present, alphaBufferSize() can return '-1', which will cause non-transparent windows to be wrongly cleared and an artifact will appear. Change-Id: Id9e985f105c0bb302cc6f53960a5dbae2acdb921 Reviewed-by: Frank Osterfeld Reviewed-by: Wolfgang Bremer Reviewed-by: Sergio Ahumada --- src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp b/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp index 3109388fb2..e0ecb5c798 100644 --- a/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp +++ b/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp @@ -170,7 +170,7 @@ void QQnxRasterBackingStore::beginPaint(const QRegion ®ion) platformWindow()->adjustBufferSize(); - if (window()->requestedFormat().alphaBufferSize() != 0) { + if (window()->requestedFormat().alphaBufferSize() > 0) { foreach (const QRect &r, region.rects()) { // Clear transparent regions const int bg[] = { -- cgit v1.2.3 From 69e2d3b3e96bb1fa553acb5cd867267d1596c314 Mon Sep 17 00:00:00 2001 From: Rafael Roquetto Date: Thu, 29 May 2014 19:20:17 -0300 Subject: QNX: Fix compilation when OpenGL is not available Change-Id: I67a1d095fc3efd58e9520c9cb3fad13e04a4d64f Reviewed-by: Frank Osterfeld Reviewed-by: Bernd Weimer --- src/plugins/platforms/qnx/qqnxnativeinterface.cpp | 8 ++++++++ src/plugins/platforms/qnx/qqnxnativeinterface.h | 3 +++ 2 files changed, 11 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/qnx/qqnxnativeinterface.cpp b/src/plugins/platforms/qnx/qqnxnativeinterface.cpp index a245a0c43a..05504f8bf4 100644 --- a/src/plugins/platforms/qnx/qqnxnativeinterface.cpp +++ b/src/plugins/platforms/qnx/qqnxnativeinterface.cpp @@ -41,7 +41,10 @@ #include "qqnxnativeinterface.h" +#if !defined(QT_NO_OPENGL) #include "qqnxglcontext.h" +#endif + #include "qqnxscreen.h" #include "qqnxwindow.h" #if defined(QQNX_IMF) @@ -50,7 +53,10 @@ #include "qqnxintegration.h" +#if !defined(QT_NO_OPENGL) #include +#endif + #include #include @@ -95,6 +101,7 @@ void *QQnxNativeInterface::nativeResourceForIntegration(const QByteArray &resour return 0; } +#if !defined(QT_NO_OPENGL) void *QQnxNativeInterface::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) { if (resource == "eglcontext" && context) @@ -102,6 +109,7 @@ void *QQnxNativeInterface::nativeResourceForContext(const QByteArray &resource, return 0; } +#endif void QQnxNativeInterface::setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value) { diff --git a/src/plugins/platforms/qnx/qqnxnativeinterface.h b/src/plugins/platforms/qnx/qqnxnativeinterface.h index 83900791f6..41e6105f84 100644 --- a/src/plugins/platforms/qnx/qqnxnativeinterface.h +++ b/src/plugins/platforms/qnx/qqnxnativeinterface.h @@ -56,7 +56,10 @@ public: void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen); void *nativeResourceForIntegration(const QByteArray &resource); +#if !defined(QT_NO_OPENGL) void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context); +#endif + void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value); NativeResourceForIntegrationFunction nativeResourceFunctionForIntegration(const QByteArray &resource); -- cgit v1.2.3 From 6b9a9a01e289381ea915ac43595c6c5da0db73b4 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Fri, 23 May 2014 17:16:54 +0200 Subject: remove HSTRING instances HSTRING needs to be released or handles will be leaked. Instead use HString which takes care of resource management on its own. Task-Number: QTBUG-38115 Change-Id: I2c767776c1f22f45acd8dd77b693f30d63d894b9 Reviewed-by: Andrew Knight Reviewed-by: Oliver Wolff --- .../platforms/winrt/qwinrtplatformmessagedialoghelper.cpp | 7 ++++--- src/plugins/platforms/winrt/qwinrtservices.cpp | 15 +++++++++------ 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/winrt/qwinrtplatformmessagedialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtplatformmessagedialoghelper.cpp index e70d06860c..c2f884055d 100644 --- a/src/plugins/platforms/winrt/qwinrtplatformmessagedialoghelper.cpp +++ b/src/plugins/platforms/winrt/qwinrtplatformmessagedialoghelper.cpp @@ -171,10 +171,11 @@ void QWinRTPlatformMessageDialogHelper::hide() HRESULT QWinRTPlatformMessageDialogHelper::onInvoked(ABI::Windows::UI::Popups::IUICommand *command) { - HSTRING hLabel; + HString hLabel; UINT32 labelLength; - command->get_Label(&hLabel); - QString label = QString::fromWCharArray(::WindowsGetStringRawBuffer(hLabel, &labelLength)); + command->get_Label(hLabel.GetAddressOf()); + PCWSTR rawString = hLabel.GetRawBuffer(&labelLength); + QString label = QString::fromWCharArray(rawString, labelLength); int buttonId = -1; for (int i = QPlatformDialogHelper::FirstButton; i < QPlatformDialogHelper::LastButton; i<<=1) { if ( options()->standardButtons() & i ) { diff --git a/src/plugins/platforms/winrt/qwinrtservices.cpp b/src/plugins/platforms/winrt/qwinrtservices.cpp index 73c090351b..b0f9247d36 100644 --- a/src/plugins/platforms/winrt/qwinrtservices.cpp +++ b/src/plugins/platforms/winrt/qwinrtservices.cpp @@ -81,9 +81,11 @@ bool QWinRTServices::openUrl(const QUrl &url) return QPlatformServices::openUrl(url); IUriRuntimeClass *uri; - QString urlString = url.toString(); HSTRING uriString; HSTRING_HEADER header; - WindowsCreateStringReference((const wchar_t*)urlString.utf16(), urlString.length(), &header, &uriString); - m_uriFactory->CreateUri(uriString, &uri); + QString urlString = url.toString(); + // ### TODO: Replace with HStringReference when WP8.0 support is removed + HString uriString; + uriString.Set((const wchar_t*)urlString.utf16(), urlString.length()); + m_uriFactory->CreateUri(uriString.Get(), &uri); if (!uri) return false; @@ -107,10 +109,11 @@ bool QWinRTServices::openDocument(const QUrl &url) return QPlatformServices::openDocument(url); const QString pathString = QDir::toNativeSeparators(url.toLocalFile()); - HSTRING_HEADER header; HSTRING path; - WindowsCreateStringReference((const wchar_t*)pathString.utf16(), pathString.length(), &header, &path); + // ### TODO: Replace with HStringReference when WP8.0 support is removed + HString path; + path.Set((const wchar_t*)pathString.utf16(), pathString.length()); IAsyncOperation *fileOp; - m_fileFactory->GetFileFromPathAsync(path, &fileOp); + m_fileFactory->GetFileFromPathAsync(path.Get(), &fileOp); if (!fileOp) return false; -- cgit v1.2.3 From 365cd4adeb7c8719d438ff2438c1db5726c90c54 Mon Sep 17 00:00:00 2001 From: Rafael Roquetto Date: Mon, 2 Jun 2014 17:12:37 -0300 Subject: QNX: fix race condition when clearing transparent buffer Block flush until all bits have been flushed. This prevents Qt from trying to draw over the buffer while it is still being cleared. Change-Id: I49b90a7653ec3768411a1a94837bb31fec4d44e8 Reviewed-by: Frank Osterfeld Reviewed-by: Andreas Holzammer Reviewed-by: Bernd Weimer --- src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp b/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp index e0ecb5c798..7ae042cb50 100644 --- a/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp +++ b/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp @@ -185,8 +185,8 @@ void QQnxRasterBackingStore::beginPaint(const QRegion ®ion) platformWindow()->renderBuffer().nativeBuffer(), bg), "failed to clear transparent regions"); } - Q_SCREEN_CHECKERROR(screen_flush_blits(platformWindow()->screen()->nativeContext(), 0), - "failed to flush blits"); + Q_SCREEN_CHECKERROR(screen_flush_blits(platformWindow()->screen()->nativeContext(), + SCREEN_WAIT_IDLE), "failed to flush blits"); } } -- cgit v1.2.3 From 9e02f9cf085386f44045e5991a39c05acb660b5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Thu, 15 May 2014 23:14:58 +0200 Subject: Cocoa: Make QMacNativeWidget event processing work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't interrupt the Qt event loop if the Qt event loop isn't running (meaning processEvents has not/ will not be called). This can happen in the QMacNativeWidget or plugin case where the native code calls [NSApp run] and QApplication::exec() is never called. In Qt 4 this was not necessary since UI event processing was more direct: QCocoaView would call QCoreApplication::sendMouseEvent/sendSpontaneousEvent directly on mouse events. Task-number: QTBUG-36225 Change-Id: I2894cbbca66a902652c9f8bc916e94ad8ce0e18e Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index 9aaf08adcf..45c0714b6b 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -870,7 +870,7 @@ void QCocoaEventDispatcherPrivate::processPostedEvents() return; } - if (interrupt) { + if (processEventsCalled > 0 && interrupt) { if (currentExecIsNSAppRun) { // The event dispatcher has been interrupted. But since // [NSApplication run] is running the event loop, we -- cgit v1.2.3 From 70e4428b6f1c6a4bad112203f67ee7d22107616c Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 3 Jun 2014 14:20:20 +0200 Subject: Cocoa: Adapt to Xcode 6 clang version sudden pickiness MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Yes, that means OS X Yosemite fix. Change-Id: I236f7af7b803de24ff0895e04c9a9253b5cfdb3b Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm | 2 +- src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm | 2 +- src/plugins/platforms/cocoa/qcocoamenuloader.mm | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index dd3b9f53db..078dc67cad 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -380,7 +380,7 @@ - (BOOL)accessibilityIsAttributeSettable:(NSString *)attribute { QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); if (!iface) - return nil; + return NO; if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { return iface->state().focusable ? YES : NO; diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm index f8411845dc..548c6a23f0 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm @@ -124,7 +124,7 @@ static void cleanupCocoaApplicationDelegate() [dockMenu release]; [qtMenuLoader release]; if (reflectionDelegate) { - [NSApp setDelegate:reflectionDelegate]; + [[NSApplication sharedApplication] setDelegate:reflectionDelegate]; [reflectionDelegate release]; } [[NSNotificationCenter defaultCenter] removeObserver:self]; diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.mm b/src/plugins/platforms/cocoa/qcocoamenuloader.mm index 60bc3b5a55..9340e945fb 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuloader.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuloader.mm @@ -174,7 +174,7 @@ QT_END_NAMESPACE - (void)removeActionsFromAppMenu { for (NSMenuItem *item in [appMenu itemArray]) - [item setTag:nil]; + [item setTag:0]; } - (void)dealloc -- cgit v1.2.3 From ac7bf97f51837eecc5e5570d5d62996746f378ed Mon Sep 17 00:00:00 2001 From: Dyami Caliri Date: Thu, 22 May 2014 15:19:46 -0700 Subject: Cocoa: clear queued user input events when window is destroyed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QCocoaEventDispatcher stores user input events in a queue in certain cases. If the target of those events is destroyed, the events are later sent to the stale window, causing a crash. Task-number: QTBUG-39211 Change-Id: Ie55d2df5697c742bcb644ebf8c5028015a0b8148 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaeventdispatcher.h | 2 ++ src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm | 15 +++++++++++++++ src/plugins/platforms/cocoa/qcocoawindow.mm | 10 +++++++++- 3 files changed, 26 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h index 33d7dcbcf4..dc0b8fcc18 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h @@ -178,6 +178,8 @@ public: void maybeCancelWaitForMoreEvents(); void ensureNSAppInitialized(); + void removeQueuedUserInputEvents(int nsWinNumber); + QCFSocketNotifier cfSocketNotifier; QList queuedUserInputEvents; // NSEvent * CFRunLoopSourceRef postedEventsSource; diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index 45c0714b6b..e7f8992c6d 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -892,6 +892,21 @@ void QCocoaEventDispatcherPrivate::processPostedEvents() } } +void QCocoaEventDispatcherPrivate::removeQueuedUserInputEvents(int nsWinNumber) +{ + if (nsWinNumber) { + int eventIndex = queuedUserInputEvents.size(); + + while (--eventIndex >= 0) { + NSEvent * nsevent = static_cast(queuedUserInputEvents.at(eventIndex)); + if ([nsevent windowNumber] == nsWinNumber) { + queuedUserInputEvents.removeAt(eventIndex); + [nsevent release]; + } + } + } +} + void QCocoaEventDispatcherPrivate::firstLoopEntry(CFRunLoopObserverRef ref, CFRunLoopActivity activity, void *info) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 7ab7486ce9..c8ca494b33 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -189,7 +189,15 @@ static bool isMouseEvent(NSEvent *ev) - (void)clearWindow { - _window = nil; + if (_window) { + QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast(QGuiApplication::instance()->eventDispatcher()); + if (cocoaEventDispatcher) { + QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = static_cast(QObjectPrivate::get(cocoaEventDispatcher)); + cocoaEventDispatcherPrivate->removeQueuedUserInputEvents([_window windowNumber]); + } + + _window = nil; + } } - (void)dealloc -- cgit v1.2.3 From 90808ead98edbab33a6bcc724d123864842a5ed3 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 22 May 2014 14:10:53 +0200 Subject: Android: Fix flashing on startup/shutdown There were several issues on startup of the application which were caused by the fact that we would get the wrong available screen geometry on startup, set this as the initial surface size and then expose native windows with this size. This would cause first a flicker of white on the early expose and the window contents to jump around as the window was resized to the actual available space on screen. The fix for this is to postpone the first expose until we have actually got a proper screen size from the main layout. We use width,height = 0 as an indicator that the available geometry is not yet known, and we skip posting any expose events before this is set by the layout. In addition, since we removed the surface before we shut down the application, it was by a white rectangle before the shutdown transition happens, and this white rectangle will be animated instead of application contents. To rectify this, we make sure the last surface in the stack remains in the layout until it is either replaced by a different surface or until the application has shut down. This way, the shutdown animation will work on this surface instead. [ChangeLog][Android] Fixed regression where there would be flickering on startup and shutdown of the application. Task-number: QTBUG-38960 Change-Id: Ia1579ca8c522d8beeab066f78070ad49009d0238 Reviewed-by: Paul Olav Tvete --- src/plugins/platforms/android/androidjnimain.cpp | 7 +++++-- .../android/qandroidplatformopenglwindow.cpp | 24 +++++++++++++++++++--- .../platforms/android/qandroidplatformscreen.cpp | 15 ++++++++++++++ .../platforms/android/qandroidplatformwindow.cpp | 4 +++- 4 files changed, 44 insertions(+), 6 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 7ca4db710b..d484a2faff 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -573,8 +573,11 @@ static void updateWindow(JNIEnv */*env*/, jobject /*thiz*/) return; if (QGuiApplication::instance() != 0) { - foreach (QWindow *w, QGuiApplication::topLevelWindows()) - QWindowSystemInterface::handleExposeEvent(w, QRegion(w->geometry())); + foreach (QWindow *w, QGuiApplication::topLevelWindows()) { + QRect availableGeometry = w->screen()->availableGeometry(); + if (w->geometry().width() > 0 && w->geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0) + QWindowSystemInterface::handleExposeEvent(w, QRegion(w->geometry())); + } } QAndroidPlatformScreen *screen = static_cast(m_androidPlatformIntegration->screen()); diff --git a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp index 34db729289..5a028e8a5b 100644 --- a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp +++ b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp @@ -47,7 +47,8 @@ #include #include - +#include +#include #include #include @@ -77,8 +78,20 @@ void QAndroidPlatformOpenGLWindow::setGeometry(const QRect &rect) if (rect == geometry()) return; + QRect oldGeometry = geometry(); + QAndroidPlatformWindow::setGeometry(rect); QtAndroid::setSurfaceGeometry(m_nativeSurfaceId, rect); + + QRect availableGeometry = screen()->availableGeometry(); + if (oldGeometry.width() == 0 + && oldGeometry.height() == 0 + && rect.width() > 0 + && rect.height() > 0 + && availableGeometry.width() > 0 + && availableGeometry.height() > 0) { + QWindowSystemInterface::handleExposeEvent(window(), QRegion(rect)); + } } EGLSurface QAndroidPlatformOpenGLWindow::eglSurface(EGLConfig config) @@ -100,8 +113,11 @@ void QAndroidPlatformOpenGLWindow::checkNativeSurface(EGLConfig config) createEgl(config); + // we've create another surface, the window should be repainted - QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry())); + QRect availableGeometry = screen()->availableGeometry(); + if (geometry().width() > 0 && geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0) + QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry())); } void QAndroidPlatformOpenGLWindow::createEgl(EGLConfig config) @@ -143,7 +159,9 @@ void QAndroidPlatformOpenGLWindow::surfaceChanged(JNIEnv *jniEnv, jobject surfac unlockSurface(); // repaint the window - QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry())); + QRect availableGeometry = screen()->availableGeometry(); + if (geometry().width() > 0 && geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0) + QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry())); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index 678f4e6b5a..11472ce1da 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -55,6 +55,9 @@ #include #include +#include +#include + QT_BEGIN_NAMESPACE #ifdef QANDROIDPLATFORMSCREEN_DEBUG @@ -217,11 +220,23 @@ void QAndroidPlatformScreen::setGeometry(const QRect &rect) if (m_geometry == rect) return; + QRect oldGeometry = m_geometry; + m_geometry = rect; QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry()); QWindowSystemInterface::handleScreenAvailableGeometryChange(QPlatformScreen::screen(), availableGeometry()); resizeMaximizedWindows(); + if (oldGeometry.width() == 0 && oldGeometry.height() == 0 && rect.width() > 0 && rect.height() > 0) { + QList windows = QGuiApplication::allWindows(); + for (int i = 0; i < windows.size(); ++i) { + QWindow *w = windows.at(i); + QRect geometry = w->handle()->geometry(); + if (geometry.width() > 0 && geometry.height() > 0) + QWindowSystemInterface::handleExposeEvent(w, QRegion(geometry)); + } + } + if (m_id != -1) { if (m_nativeSurface) { ANativeWindow_release(m_nativeSurface); diff --git a/src/plugins/platforms/android/qandroidplatformwindow.cpp b/src/plugins/platforms/android/qandroidplatformwindow.cpp index b4231f0283..558525b78c 100644 --- a/src/plugins/platforms/android/qandroidplatformwindow.cpp +++ b/src/plugins/platforms/android/qandroidplatformwindow.cpp @@ -88,7 +88,9 @@ void QAndroidPlatformWindow::setVisible(bool visible) setGeometry(platformScreen()->availableGeometry()); } - QPlatformWindow::setVisible(visible); + QRect availableGeometry = screen()->availableGeometry(); + if (geometry().width() > 0 && geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0) + QPlatformWindow::setVisible(visible); if (visible) platformScreen()->addWindow(this); -- cgit v1.2.3 From 80b6fbc2d9dfc753d6570e971aa4cf4f3420585c Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 21 May 2014 16:30:50 +0200 Subject: Android: Support offscreen surfaces on pbuffers This is pretty much the same thing that eglfs does. Task-number: QTBUG-38960 Change-Id: Ibf310ca8e3a4e31e5310ab3a3d3e851eae31a4ad Reviewed-by: Laszlo Agocs --- .../platforms/android/qandroidplatformintegration.cpp | 14 ++++++++++++++ .../platforms/android/qandroidplatformintegration.h | 1 + .../platforms/android/qandroidplatformopenglcontext.cpp | 5 ++++- .../platforms/android/qandroidplatformopenglwindow.cpp | 9 +++++++++ .../platforms/android/qandroidplatformopenglwindow.h | 2 ++ 5 files changed, 30 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp index 7f0f40be0f..213b1bb7e6 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp @@ -45,11 +45,14 @@ #include #include #include +#include #include +#include #include #include +#include #include "androidjnimain.h" #include "qabstracteventdispatcher.h" @@ -207,6 +210,17 @@ QPlatformOpenGLContext *QAndroidPlatformIntegration::createPlatformOpenGLContext return new QAndroidPlatformOpenGLContext(format, context->shareHandle(), m_eglDisplay); } +QPlatformOffscreenSurface *QAndroidPlatformIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const +{ + QSurfaceFormat format(surface->requestedFormat()); + format.setAlphaBufferSize(8); + format.setRedBufferSize(8); + format.setGreenBufferSize(8); + format.setBlueBufferSize(8); + + return new QEGLPbuffer(m_eglDisplay, format, surface); +} + QPlatformWindow *QAndroidPlatformIntegration::createPlatformWindow(QWindow *window) const { if (window->type() == Qt::ForeignWindow) diff --git a/src/plugins/platforms/android/qandroidplatformintegration.h b/src/plugins/platforms/android/qandroidplatformintegration.h index 4a3fe6c766..f8fa1a91dd 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.h +++ b/src/plugins/platforms/android/qandroidplatformintegration.h @@ -82,6 +82,7 @@ public: QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const; QAbstractEventDispatcher *createEventDispatcher() const; QAndroidPlatformScreen *screen() { return m_primaryScreen; } + QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const; virtual void setDesktopSize(int width, int height); virtual void setDisplayMetrics(int width, int height); diff --git a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp index 152a06c99d..53047585cf 100644 --- a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp +++ b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp @@ -44,6 +44,8 @@ #include "qandroidplatformopenglwindow.h" #include "qandroidplatformintegration.h" +#include + #include #include @@ -98,7 +100,8 @@ EGLSurface QAndroidPlatformOpenGLContext::eglSurfaceForPlatformSurface(QPlatform { if (surface->surface()->surfaceClass() == QSurface::Window) return static_cast(surface)->eglSurface(eglConfig()); - return EGL_NO_SURFACE; + else + return static_cast(surface)->pbuffer(); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp index 5a028e8a5b..f0c4a1de2a 100644 --- a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp +++ b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp @@ -127,6 +127,7 @@ void QAndroidPlatformOpenGLWindow::createEgl(EGLConfig config) m_nativeWindow = ANativeWindow_fromSurface(env, m_androidSurfaceObject.object()); m_androidSurfaceObject = QJNIObjectPrivate(); m_eglSurface = eglCreateWindowSurface(m_eglDisplay, config, m_nativeWindow, NULL); + m_format = q_glFormatFromConfig(m_eglDisplay, config, window()->requestedFormat()); if (m_eglSurface == EGL_NO_SURFACE) { EGLint error = eglGetError(); eglTerminate(m_eglDisplay); @@ -134,6 +135,14 @@ void QAndroidPlatformOpenGLWindow::createEgl(EGLConfig config) } } +QSurfaceFormat QAndroidPlatformOpenGLWindow::format() const +{ + if (m_nativeWindow == 0) + return window()->requestedFormat(); + else + return m_format; +} + void QAndroidPlatformOpenGLWindow::clearEgl() { eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); diff --git a/src/plugins/platforms/android/qandroidplatformopenglwindow.h b/src/plugins/platforms/android/qandroidplatformopenglwindow.h index 7af8b722aa..83df15a524 100644 --- a/src/plugins/platforms/android/qandroidplatformopenglwindow.h +++ b/src/plugins/platforms/android/qandroidplatformopenglwindow.h @@ -60,6 +60,7 @@ public: void setGeometry(const QRect &rect); EGLSurface eglSurface(EGLConfig config); + QSurfaceFormat format() const; void checkNativeSurface(EGLConfig config); @@ -76,6 +77,7 @@ private: int m_nativeSurfaceId = -1; QJNIObjectPrivate m_androidSurfaceObject; QWaitCondition m_surfaceWaitCondition; + QSurfaceFormat m_format; }; QT_END_NAMESPACE -- cgit v1.2.3 From 91b0b2e1a7566dda00ec24e674784e4ccc99fea6 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 4 Jun 2014 12:37:19 +0200 Subject: Android: Repaint affected areas when window moves There are no automatic updates of the window when it moves, since this is not required on most platforms. This broke drag and drop on Android, because drag and drop creates a temporary window containing a pixmap with a snapshot of its content. We need to make sure the old and new location of the window is repainted when it has moved. [ChangeLog][Android] Fixed repaint issues in drag and drop. Task-number: QTBUG-35975 Change-Id: I7b043d728551d9963fb5acec804fb90aec5b50ff Reviewed-by: Paul Olav Tvete --- src/plugins/platforms/android/qandroidplatformrasterwindow.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/android/qandroidplatformrasterwindow.cpp b/src/plugins/platforms/android/qandroidplatformrasterwindow.cpp index eb5a73c4a3..3fb236793b 100644 --- a/src/plugins/platforms/android/qandroidplatformrasterwindow.cpp +++ b/src/plugins/platforms/android/qandroidplatformrasterwindow.cpp @@ -76,6 +76,8 @@ void QAndroidPlatformRasterWindow::setGeometry(const QRect &rect) { m_oldGeometry = geometry(); QAndroidPlatformWindow::setGeometry(rect); + if (rect.topLeft() != m_oldGeometry.topLeft()) + repaint(QRegion(rect)); } QT_END_NAMESPACE -- cgit v1.2.3