diff options
author | Frederik Gladhorn <frederik.gladhorn@theqtcompany.com> | 2015-02-25 11:23:46 +0000 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2015-02-25 11:23:46 +0000 |
commit | 2cac171ddedfecdfc6fa27c5326f9eebfab1822e (patch) | |
tree | ff8e7c162875d7374ddc42224a91533b7e8c8663 /src/plugins | |
parent | 5113fdeb7d50979c6acbe2c9c5b26ad134614873 (diff) | |
parent | 709e40093e6081b18e0d3003e0a088e1a9b6f211 (diff) |
Merge "Merge remote-tracking branch 'origin/5.5' into dev" into refs/staging/dev
Diffstat (limited to 'src/plugins')
19 files changed, 384 insertions, 270 deletions
diff --git a/src/plugins/bearer/android/src/wrappers/androidconnectivitymanager.cpp b/src/plugins/bearer/android/src/wrappers/androidconnectivitymanager.cpp index 8b10c17bb5..da5f042abd 100644 --- a/src/plugins/bearer/android/src/wrappers/androidconnectivitymanager.cpp +++ b/src/plugins/bearer/android/src/wrappers/androidconnectivitymanager.cpp @@ -295,8 +295,7 @@ QList<AndroidNetworkInfo> AndroidConnectivityManager::getAllNetworkInfo() const if (exceptionCheckAndClear(env)) break; - list << AndroidNetworkInfo(lref); - env->DeleteLocalRef(lref); + list << AndroidNetworkInfo(QJNIObjectPrivate::fromLocalRef(lref)); } return list; diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp index d35492564a..843387e679 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp @@ -80,10 +80,10 @@ QNetworkManagerEngine::QNetworkManagerEngine(QObject *parent) this, SLOT(ofonoUnRegistered(QString))); if (QDBusConnection::systemBus().interface()->isServiceRegistered("org.ofono")) - ofonoRegistered(); + QMetaObject::invokeMethod(this, "ofonoRegistered", Qt::QueuedConnection); if (QDBusConnection::systemBus().interface()->isServiceRegistered(NM_DBUS_SERVICE)) - nmRegistered(); + QMetaObject::invokeMethod(this, "nmRegistered", Qt::QueuedConnection); } QNetworkManagerEngine::~QNetworkManagerEngine() diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index 903da2498c..4ece1b5a22 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -438,7 +438,7 @@ static QString strippedText(QString s) - (void)panelSelectionDidChange:(id)sender { Q_UNUSED(sender); - if (mHelper) { + if (mHelper && [mSavePanel isVisible]) { QString selection = QCFString::toQString([[mSavePanel URL] path]); if (selection != mCurrentSelection) { *mCurrentSelection = selection; diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp index aedb8f7b88..36cfff43f5 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp @@ -68,8 +68,6 @@ enum { D2DDebugFillRectTag, D2DDebugDrawRectsTag, D2DDebugDrawRectFsTag, - D2DDebugDrawLinesTag, - D2DDebugDrawLineFsTag, D2DDebugDrawEllipseTag, D2DDebugDrawEllipseFTag, D2DDebugDrawImageTag, @@ -102,22 +100,28 @@ static inline ID2D1Factory1 *factory() return QWindowsDirect2DContext::instance()->d2dFactory(); } -static inline D2D1_MATRIX_3X2_F transformFromLine(const QLineF &line, qreal penWidth) +static inline D2D1_MATRIX_3X2_F transformFromLine(const QLineF &line, qreal penWidth, qreal dashOffset) { const qreal halfWidth = penWidth / 2; const qreal angle = -qDegreesToRadians(line.angle()); - QTransform transform = QTransform::fromTranslate(line.p1().x() + qSin(angle) * halfWidth, - line.p1().y() - qCos(angle) * halfWidth); + const qreal sinA = qSin(angle); + const qreal cosA = qCos(angle); + QTransform transform = QTransform::fromTranslate(line.p1().x() + dashOffset * cosA + sinA * halfWidth, + line.p1().y() + dashOffset * sinA - cosA * halfWidth); transform.rotateRadians(angle); return to_d2d_matrix_3x2_f(transform); } +static void adjustLine(QPointF *p1, QPointF *p2); +static bool isLinePositivelySloped(const QPointF &p1, const QPointF &p2); + class Direct2DPathGeometryWriter { public: Direct2DPathGeometryWriter() : m_inFigure(false) , m_roundCoordinates(false) + , m_adjustPositivelySlopedLines(false) { } @@ -152,6 +156,11 @@ public: m_roundCoordinates = enable; } + void setPositiveSlopeAdjustmentEnabled(bool enable) + { + m_adjustPositivelySlopedLines = enable; + } + bool isInFigure() const { return m_inFigure; @@ -164,11 +173,20 @@ public: m_sink->BeginFigure(adjusted(point), D2D1_FIGURE_BEGIN_FILLED); m_inFigure = true; + m_previousPoint = point; } void lineTo(const QPointF &point) { - m_sink->AddLine(adjusted(point)); + QPointF pt = point; + if (m_adjustPositivelySlopedLines && isLinePositivelySloped(m_previousPoint, point)) { + moveTo(m_previousPoint - QPointF(0, 1)); + pt -= QPointF(0, 1); + } + m_sink->AddLine(adjusted(pt)); + if (pt != point) + moveTo(point); + m_previousPoint = point; } void curveTo(const QPointF &p1, const QPointF &p2, const QPointF &p3) @@ -180,6 +198,7 @@ public: }; m_sink->AddBezier(segment); + m_previousPoint = p3; } void close() @@ -212,6 +231,8 @@ private: bool m_inFigure; bool m_roundCoordinates; + bool m_adjustPositivelySlopedLines; + QPointF m_previousPoint; }; struct D2DVectorPathCache { @@ -257,6 +278,7 @@ public: ComPtr<ID2D1Brush> brush; ComPtr<ID2D1StrokeStyle1> strokeStyle; ComPtr<ID2D1BitmapBrush1> dashBrush; + int dashLength; inline void reset() { emulate = false; @@ -264,6 +286,7 @@ public: brush.Reset(); strokeStyle.Reset(); dashBrush.Reset(); + dashLength = 0; } } pen; @@ -566,6 +589,7 @@ public: D2D1_BITMAP_BRUSH_PROPERTIES1 bitmapBrushProperties = D2D1::BitmapBrushProperties1( D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_CLAMP, D2D1_INTERPOLATION_MODE_LINEAR); hr = dc()->CreateBitmapBrush(bitmap.bitmap(), bitmapBrushProperties, &pen.dashBrush); + pen.dashLength = bitmap.size().width(); } else { hr = factory()->CreateStrokeStyle(props, NULL, 0, &pen.strokeStyle); } @@ -795,6 +819,8 @@ public: writer.setWindingFillEnabled(path.hasWindingFill()); writer.setAliasingEnabled(alias); + writer.setPositiveSlopeAdjustmentEnabled(path.shape() == QVectorPath::LinesHint + || path.shape() == QVectorPath::PolygonHint); const QPainterPath::ElementType *types = path.elements(); const int count = path.elementCount(); @@ -910,6 +936,90 @@ public: DWRITE_MEASURING_MODE_GDI_CLASSIC); } + void stroke(const QVectorPath &path) + { + Q_Q(QWindowsDirect2DPaintEngine); + + // Default path (no optimization) + if (!(path.shape() == QVectorPath::LinesHint || path.shape() == QVectorPath::PolygonHint) + || !pen.dashBrush || q->state()->renderHints.testFlag(QPainter::HighQualityAntialiasing)) { + ComPtr<ID2D1Geometry> geometry = vectorPathToID2D1PathGeometry(path); + if (!geometry) { + qWarning("%s: Could not convert path to d2d geometry", __FUNCTION__); + return; + } + dc()->DrawGeometry(geometry.Get(), pen.brush.Get(), pen.qpen.widthF(), pen.strokeStyle.Get()); + return; + } + + // Optimized dash line drawing + const bool isPolygon = path.shape() == QVectorPath::PolygonHint && path.elementCount() >= 3; + const bool implicitClose = isPolygon && (path.hints() & QVectorPath::ImplicitClose); + const bool skipJoin = !isPolygon // Non-polygons don't require joins + || (pen.qpen.joinStyle() == Qt::MiterJoin && qFuzzyIsNull(pen.qpen.miterLimit())); + const qreal *points = path.points(); + const int lastElement = path.elementCount() - (implicitClose ? 1 : 2); + qreal dashOffset = 0; + QPointF jointStart; + ID2D1Brush *brush = pen.dashBrush ? pen.dashBrush.Get() : pen.brush.Get(); + for (int i = 0; i <= lastElement; ++i) { + QPointF p1(points[i * 2], points[i * 2 + 1]); + QPointF p2 = implicitClose && i == lastElement ? QPointF(points[0], points[1]) + : QPointF(points[i * 2 + 2], points[i * 2 + 3]); + if (!isPolygon) // Advance the count for lines + ++i; + + // Match raster engine output + if (p1 == p2 && pen.qpen.widthF() <= 1.0) { + q->fillRect(QRectF(p1, QSizeF(pen.qpen.widthF(), pen.qpen.widthF())), pen.qpen.brush()); + continue; + } + + if (!q->antiAliasingEnabled()) + adjustLine(&p1, &p2); + + q->adjustForAliasing(&p1); + q->adjustForAliasing(&p2); + + const QLineF line(p1, p2); + const qreal lineLength = line.length(); + if (pen.dashBrush) { + pen.dashBrush->SetTransform(transformFromLine(line, pen.qpen.widthF(), dashOffset)); + dashOffset = pen.dashLength - fmod(lineLength - dashOffset, pen.dashLength); + } + dc()->DrawLine(to_d2d_point_2f(p1), to_d2d_point_2f(p2), + brush, pen.qpen.widthF(), NULL); + + if (skipJoin) + continue; + + // Patch the join with the original brush + const qreal patchSegment = pen.dashBrush ? qBound(0.0, (pen.dashLength - dashOffset) / lineLength, 1.0) + : pen.qpen.widthF(); + if (i > 0) { + Direct2DPathGeometryWriter writer; + writer.begin(); + writer.moveTo(jointStart); + writer.lineTo(p1); + writer.lineTo(line.pointAt(patchSegment)); + writer.close(); + dc()->DrawGeometry(writer.geometry().Get(), pen.brush.Get(), pen.qpen.widthF(), pen.strokeStyle.Get()); + } + // Record the start position of the next joint + jointStart = line.pointAt(1 - patchSegment); + + if (implicitClose && i == lastElement) { // Close the polygon + Direct2DPathGeometryWriter writer; + writer.begin(); + writer.moveTo(jointStart); + writer.lineTo(p2); + writer.lineTo(QLineF(p2, QPointF(points[2], points[3])).pointAt(patchSegment)); + writer.close(); + dc()->DrawGeometry(writer.geometry().Get(), pen.brush.Get(), pen.qpen.widthF(), pen.strokeStyle.Get()); + } + } + } + ComPtr<IDWriteFontFace> fontFaceFromFontEngine(QFontEngine *fe) { const QFontDef fontDef = fe->fontDef; @@ -1055,20 +1165,12 @@ void QWindowsDirect2DPaintEngine::setState(QPainterState *s) void QWindowsDirect2DPaintEngine::draw(const QVectorPath &path) { - Q_D(QWindowsDirect2DPaintEngine); - - ComPtr<ID2D1Geometry> geometry = d->vectorPathToID2D1PathGeometry(path); - if (!geometry) { - qWarning("%s: Could not convert path to d2d geometry", __FUNCTION__); - return; - } - const QBrush &brush = state()->brush; if (qbrush_style(brush) != Qt::NoBrush) { if (emulationRequired(BrushEmulation)) rasterFill(path, brush); else - fill(geometry.Get(), brush); + fill(path, brush); } const QPen &pen = state()->pen; @@ -1076,7 +1178,7 @@ void QWindowsDirect2DPaintEngine::draw(const QVectorPath &path) if (emulationRequired(PenEmulation)) QPaintEngineEx::stroke(path, pen); else - stroke(geometry.Get(), pen); + stroke(path, pen); } } @@ -1106,18 +1208,6 @@ void QWindowsDirect2DPaintEngine::fill(const QVectorPath &path, const QBrush &br d->dc()->FillGeometry(geometry.Get(), d->brush.brush.Get()); } -void QWindowsDirect2DPaintEngine::fill(ID2D1Geometry *geometry, const QBrush &brush) -{ - Q_D(QWindowsDirect2DPaintEngine); - D2D_TAG(D2DDebugFillTag); - - ensureBrush(brush); - if (!d->brush.brush) - return; - - d->dc()->FillGeometry(geometry, d->brush.brush.Get()); -} - void QWindowsDirect2DPaintEngine::stroke(const QVectorPath &path, const QPen &pen) { Q_D(QWindowsDirect2DPaintEngine); @@ -1135,25 +1225,7 @@ void QWindowsDirect2DPaintEngine::stroke(const QVectorPath &path, const QPen &pe if (!d->pen.brush) return; - ComPtr<ID2D1Geometry> geometry = d->vectorPathToID2D1PathGeometry(path); - if (!geometry) { - qWarning("%s: Could not convert path to d2d geometry", __FUNCTION__); - return; - } - - d->dc()->DrawGeometry(geometry.Get(), d->pen.brush.Get(), d->pen.qpen.widthF(), d->pen.strokeStyle.Get()); -} - -void QWindowsDirect2DPaintEngine::stroke(ID2D1Geometry *geometry, const QPen &pen) -{ - Q_D(QWindowsDirect2DPaintEngine); - D2D_TAG(D2DDebugFillTag); - - ensurePen(pen); - if (!d->pen.brush) - return; - - d->dc()->DrawGeometry(geometry, d->pen.brush.Get(), d->pen.qpen.widthF(), d->pen.strokeStyle.Get()); + d->stroke(path); } void QWindowsDirect2DPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) @@ -1301,88 +1373,6 @@ static void adjustLine(QPointF *p1, QPointF *p2) } } -void QWindowsDirect2DPaintEngine::drawLines(const QLine *lines, int lineCount) -{ - Q_D(QWindowsDirect2DPaintEngine); - D2D_TAG(D2DDebugDrawLinesTag); - - ensurePen(); - - if (emulationRequired(PenEmulation)) { - QPaintEngineEx::drawLines(lines, lineCount); - } else if (d->pen.brush) { - for (int i = 0; i < lineCount; i++) { - QPointF p1 = lines[i].p1(); - QPointF p2 = lines[i].p2(); - - // Match raster engine output - if (p1 == p2 && d->pen.qpen.widthF() <= 1.0) { - fillRect(QRectF(p1, QSizeF(d->pen.qpen.widthF(), d->pen.qpen.widthF())), - d->pen.qpen.brush()); - continue; - } - - // Match raster engine output - if (!antiAliasingEnabled()) - adjustLine(&p1, &p2); - - adjustForAliasing(&p1); - adjustForAliasing(&p2); - - D2D1_POINT_2F d2d_p1 = to_d2d_point_2f(p1); - D2D1_POINT_2F d2d_p2 = to_d2d_point_2f(p2); - - if (!d->pen.dashBrush || state()->renderHints.testFlag(QPainter::HighQualityAntialiasing)) { - d->dc()->DrawLine(d2d_p1, d2d_p2, d->pen.brush.Get(), d->pen.qpen.widthF(), d->pen.strokeStyle.Get()); - } else { - d->pen.dashBrush->SetTransform(transformFromLine(lines[i], d->pen.qpen.widthF())); - d->dc()->DrawLine(d2d_p1, d2d_p2, d->pen.dashBrush.Get(), d->pen.qpen.widthF(), NULL); - } - } - } -} - -void QWindowsDirect2DPaintEngine::drawLines(const QLineF *lines, int lineCount) -{ - Q_D(QWindowsDirect2DPaintEngine); - D2D_TAG(D2DDebugDrawLineFsTag); - - ensurePen(); - - if (emulationRequired(PenEmulation)) { - QPaintEngineEx::drawLines(lines, lineCount); - } else if (d->pen.brush) { - for (int i = 0; i < lineCount; i++) { - QPointF p1 = lines[i].p1(); - QPointF p2 = lines[i].p2(); - - // Match raster engine output - if (p1 == p2 && d->pen.qpen.widthF() <= 1.0) { - fillRect(QRectF(p1, QSizeF(d->pen.qpen.widthF(), d->pen.qpen.widthF())), - d->pen.qpen.brush()); - continue; - } - - // Match raster engine output - if (!antiAliasingEnabled()) - adjustLine(&p1, &p2); - - adjustForAliasing(&p1); - adjustForAliasing(&p2); - - D2D1_POINT_2F d2d_p1 = to_d2d_point_2f(p1); - D2D1_POINT_2F d2d_p2 = to_d2d_point_2f(p2); - - if (!d->pen.dashBrush || state()->renderHints.testFlag(QPainter::HighQualityAntialiasing)) { - d->dc()->DrawLine(d2d_p1, d2d_p2, d->pen.brush.Get(), d->pen.qpen.widthF(), d->pen.strokeStyle.Get()); - } else { - d->pen.dashBrush->SetTransform(transformFromLine(lines[i], d->pen.qpen.widthF())); - d->dc()->DrawLine(d2d_p1, d2d_p2, d->pen.dashBrush.Get(), d->pen.qpen.widthF(), NULL); - } - } - } -} - void QWindowsDirect2DPaintEngine::drawEllipse(const QRectF &r) { Q_D(QWindowsDirect2DPaintEngine); diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h index f9fd6eb591..a75c0b6cc7 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h @@ -92,9 +92,6 @@ public: void drawRects(const QRect *rects, int rectCount) Q_DECL_OVERRIDE; void drawRects(const QRectF *rects, int rectCount) Q_DECL_OVERRIDE; - void drawLines(const QLine *lines, int lineCount) Q_DECL_OVERRIDE; - void drawLines(const QLineF *lines, int lineCount) Q_DECL_OVERRIDE; - void drawEllipse(const QRectF &r) Q_DECL_OVERRIDE; void drawEllipse(const QRect &r) Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index 9470d1844e..f36cbaf685 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -138,8 +138,9 @@ QRect previousGeometry = requestedGeometry != actualGeometry ? requestedGeometry : qt_window_private(m_qioswindow->window())->geometry; - QWindowSystemInterface::handleGeometryChange(m_qioswindow->window(), actualGeometry, previousGeometry); - QWindowSystemInterface::flushWindowSystemEvents(); + QWindow *window = m_qioswindow->window(); + QWindowSystemInterface::handleGeometryChange(window, actualGeometry, previousGeometry); + QWindowSystemInterface::flushWindowSystemEvents(window->inherits("QWidgetWindow") ? QEventLoop::ExcludeUserInputEvents : QEventLoop::AllEvents); if (actualGeometry.size() != previousGeometry.size()) { // Trigger expose event on resize diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp index 616e1af6b5..2c61f68e83 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp +++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp @@ -79,6 +79,8 @@ void QLinuxFbIntegration::initialize() m_inputContext = QPlatformInputContextFactory::create(); + m_nativeInterface.reset(new QPlatformNativeInterface); + m_vtHandler.reset(new QFbVtHandler); if (!qEnvironmentVariableIntValue("QT_QPA_FB_DISABLE_INPUT")) @@ -141,4 +143,9 @@ void QLinuxFbIntegration::createInputHandlers() #endif } +QPlatformNativeInterface *QLinuxFbIntegration::nativeInterface() const +{ + return m_nativeInterface.data(); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h index f2fc95c4ce..0a3d5fd6ac 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h +++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h @@ -61,6 +61,8 @@ public: QPlatformServices *services() const Q_DECL_OVERRIDE; QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE { return m_inputContext; } + QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE; + QList<QPlatformScreen *> screens() const; private: @@ -71,6 +73,7 @@ private: QScopedPointer<QPlatformFontDatabase> m_fontDb; QScopedPointer<QPlatformServices> m_services; QScopedPointer<QFbVtHandler> m_vtHandler; + QScopedPointer<QPlatformNativeInterface> m_nativeInterface; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h index 9ead6287fb..644ff7f7de 100644 --- a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h +++ b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h @@ -85,7 +85,7 @@ public: bool makeCurrent(QPlatformSurface *surface) Q_DECL_OVERRIDE; void doneCurrent() Q_DECL_OVERRIDE; void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE; - void (*getProcAddress(const QByteArray &procName)) () Q_DECL_OVERRIDE; + QFunctionPointer getProcAddress(const QByteArray &procName) Q_DECL_OVERRIDE; QSurfaceFormat format() const Q_DECL_OVERRIDE; bool isSharing() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 8f48efc7f9..b397b12311 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -675,6 +675,8 @@ static inline bool findPlatformWindowHelper(const POINT &screenPoint, unsigned c #ifndef Q_OS_WINCE const HWND child = ChildWindowFromPointEx(*hwnd, point, cwexFlags); #else +// Under Windows CE we don't use ChildWindowFromPointEx as it's not available +// and ChildWindowFromPoint does not work properly. Q_UNUSED(cwexFlags) const HWND child = WindowFromPoint(point); #endif @@ -683,7 +685,13 @@ static inline bool findPlatformWindowHelper(const POINT &screenPoint, unsigned c if (QWindowsWindow *window = context->findPlatformWindow(child)) { *result = window; *hwnd = child; +#ifndef Q_OS_WINCE return true; +#else +// WindowFromPoint does not return same handle in two sequential calls, which leads +// to an endless loop, but calling WindowFromPoint once is good enough. + return false; +#endif } #ifndef Q_OS_WINCE // Does not have WS_EX_TRANSPARENT . // QTBUG-40555: despite CWP_SKIPINVISIBLE, it is possible to hit on invisible diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index ef74ef35f5..56adae8ffb 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -1674,8 +1674,10 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, HFONT hfont = 0; hfont = CreateFontIndirect(&lf); - if (!hfont) + if (!hfont) { qErrnoWarning("%s: CreateFontIndirect failed", __FUNCTION__); + hfont = QWindowsFontDatabase::systemFont(); + } bool ttf = false; int avWidth = 0; @@ -1689,18 +1691,17 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, SelectObject(data->hdc, oldObj); if (!useDirectWrite) { - if (hfont && (!ttf || request.stretch != 100)) { + if (!ttf || request.stretch != 100) { DeleteObject(hfont); if (!res) qErrnoWarning("%s: GetTextMetrics failed", __FUNCTION__); lf.lfWidth = avWidth * request.stretch/100; hfont = CreateFontIndirect(&lf); - if (!hfont) + if (!hfont) { qErrnoWarning("%s: CreateFontIndirect with stretch failed", __FUNCTION__); + hfont = QWindowsFontDatabase::systemFont(); + } } - - if (!hfont) - hfont = QWindowsFontDatabase::systemFont(); } #if !defined(QT_NO_DIRECTWRITE) diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp index 0c294c2727..d1ea8a798f 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp @@ -41,6 +41,7 @@ #include <QtCore/QDir> #include <QtCore/QDirIterator> #include <QtCore/QSettings> +#include <QtCore/QRegularExpression> #include <QtGui/private/qfontengine_ft_p.h> #include <QtGui/QGuiApplication> #include <QtGui/QFontDatabase> @@ -101,7 +102,67 @@ static FontFile * createFontFile(const QString &fileName, int index) extern bool localizedName(const QString &name); extern QString getEnglishName(const QString &familyName); -#ifdef Q_OS_WINCE +#ifndef Q_OS_WINCE + +namespace { +struct FontKey +{ + QString fileName; + QStringList fontNames; +}; +} // namespace + +typedef QVector<FontKey> FontKeys; + +static FontKeys &fontKeys() +{ + static FontKeys result; + if (result.isEmpty()) { + const QSettings fontRegistry(QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"), + QSettings::NativeFormat); + const QStringList allKeys = fontRegistry.allKeys(); + const QString trueType = QStringLiteral("(TrueType)"); + const QRegularExpression sizeListMatch(QStringLiteral("\\s(\\d+,)+\\d+")); + Q_ASSERT(sizeListMatch.isValid()); + const int size = allKeys.size(); + result.reserve(size); + for (int i = 0; i < size; ++i) { + FontKey fontKey; + const QString ®istryFontKey = allKeys.at(i); + fontKey.fileName = fontRegistry.value(registryFontKey).toString(); + QString realKey = registryFontKey; + realKey.remove(trueType); + realKey.remove(sizeListMatch); + const QStringList fontNames = realKey.trimmed().split(QLatin1Char('&')); + fontKey.fontNames.reserve(fontNames.size()); + foreach (const QString &fontName, fontNames) + fontKey.fontNames.append(fontName.trimmed()); + result.append(fontKey); + } + } + return result; +} + +static const FontKey *findFontKey(const QString &name, int *indexIn = Q_NULLPTR) +{ + typedef FontKeys::ConstIterator ConstIt; + + const FontKeys &keys = fontKeys(); + for (ConstIt it = keys.constBegin(), cend = keys.constEnd(); it != cend; ++it) { + const int index = it->fontNames.indexOf(name); + if (index >= 0) { + if (indexIn) + *indexIn = index; + return &(*it); + } + } + if (indexIn) + *indexIn = -1; + return Q_NULLPTR; +} + +#else // Q_OS_WINCE + typedef struct { quint16 majorVersion; quint16 minorVersion; @@ -220,24 +281,67 @@ static QString fontNameFromTTFile(const QString &filename) } return retVal; } + +static inline QString fontSettingsOrganization() { return QStringLiteral("Qt-Project"); } +static inline QString fontSettingsApplication() { return QStringLiteral("Qtbase"); } +static inline QString fontSettingsGroup() { return QStringLiteral("CEFontCache"); } + +static QString findFontFile(const QString &faceName) +{ + static QHash<QString, QString> fontCache; + + if (fontCache.isEmpty()) { + QSettings settings(QSettings::SystemScope, fontSettingsOrganization(), fontSettingsApplication()); + settings.beginGroup(fontSettingsGroup()); + foreach (const QString &fontName, settings.allKeys()) + fontCache.insert(fontName, settings.value(fontName).toString()); + settings.endGroup(); + } + + QString value = fontCache.value(faceName); + + //Fallback if we haven't cached the font yet or the font got removed/renamed iterate again over all fonts + if (value.isEmpty() || !QFile::exists(value)) { + QSettings settings(QSettings::SystemScope, fontSettingsOrganization(), fontSettingsApplication()); + settings.beginGroup(fontSettingsGroup()); + + //empty the cache first, as it seems that it is dirty + settings.remove(QString()); + + QDirIterator it(QStringLiteral("/Windows"), QStringList(QStringLiteral("*.ttf")), QDir::Files | QDir::Hidden | QDir::System); + + while (it.hasNext()) { + const QString fontFile = it.next(); + const QString fontName = fontNameFromTTFile(fontFile); + if (fontName.isEmpty()) + continue; + fontCache.insert(fontName, fontFile); + settings.setValue(fontName, fontFile); + + if (localizedName(fontName)) { + QString englishFontName = getEnglishName(fontName); + fontCache.insert(englishFontName, fontFile); + settings.setValue(englishFontName, fontFile); + } + } + settings.endGroup(); + value = fontCache.value(faceName); + } + return value; +} #endif // Q_OS_WINCE -static bool addFontToDatabase(const QString &familyName, uchar charSet, +static bool addFontToDatabase(const QString &faceName, + const QString &fullName, + uchar charSet, const TEXTMETRIC *textmetric, const FONTSIGNATURE *signature, int type) { - typedef QPair<QString, QStringList> FontKey; - // the "@family" fonts are just the same as "family". Ignore them. - if (familyName.isEmpty() || familyName.at(0) == QLatin1Char('@') || familyName.startsWith(QLatin1String("WST_"))) + if (faceName.isEmpty() || faceName.at(0) == QLatin1Char('@') || faceName.startsWith(QLatin1String("WST_"))) return false; - const int separatorPos = familyName.indexOf(QStringLiteral("::")); - const QString faceName = - separatorPos != -1 ? familyName.left(separatorPos) : familyName; - const QString fullName = - separatorPos != -1 ? familyName.mid(separatorPos + 2) : QString(); static const int SMOOTH_SCALABLE = 0xffff; const QString foundryName; // No such concept. const NEWTEXTMETRIC *tm = (NEWTEXTMETRIC *)textmetric; @@ -254,7 +358,7 @@ static bool addFontToDatabase(const QString &familyName, uchar charSet, if (QWindowsContext::verbose > 2) { QString message; QTextStream str(&message); - str << __FUNCTION__ << ' ' << familyName << ' ' << charSet << " TTF=" << ttf; + str << __FUNCTION__ << ' ' << faceName << "::" << fullName << ' ' << charSet << " TTF=" << ttf; if (type & DEVICE_FONTTYPE) str << " DEVICE"; if (type & RASTER_FONTTYPE) @@ -297,93 +401,19 @@ static bool addFontToDatabase(const QString &familyName, uchar charSet, writingSystems.setSupported(ws); } -#ifndef Q_OS_WINCE - const QSettings fontRegistry(QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"), - QSettings::NativeFormat); - - static QVector<FontKey> allFonts; - if (allFonts.isEmpty()) { - const QStringList allKeys = fontRegistry.allKeys(); - allFonts.reserve(allKeys.size()); - const QString trueType = QStringLiteral("(TrueType)"); - const QRegExp sizeListMatch(QStringLiteral("\\s(\\d+,)+\\d+")); - foreach (const QString &key, allKeys) { - QString realKey = key; - realKey.remove(trueType); - realKey.remove(sizeListMatch); - QStringList fonts; - const QStringList fontNames = realKey.trimmed().split(QLatin1Char('&')); - foreach (const QString &fontName, fontNames) - fonts.push_back(fontName.trimmed()); - allFonts.push_back(FontKey(key, fonts)); - } - } - - QString value; int index = 0; - for (int k = 0; k < allFonts.size(); ++k) { - const FontKey &fontKey = allFonts.at(k); - for (int i = 0; i < fontKey.second.length(); ++i) { - const QString &font = fontKey.second.at(i); - if (font == faceName || fullName == font || englishName == font) { - value = fontRegistry.value(fontKey.first).toString(); - index = i; - break; - } - } - if (!value.isEmpty()) - break; +#ifndef Q_OS_WINCE + const FontKey *key = findFontKey(faceName, &index); + if (!key) { + key = findFontKey(fullName, &index); + if (!key && !englishName.isEmpty()) + key = findFontKey(englishName, &index); + if (!key) + return false; } + QString value = key->fileName; #else - QString value; - int index = 0; - - static QHash<QString, QString> fontCache; - - if (fontCache.isEmpty()) { - QSettings settings(QSettings::SystemScope, QStringLiteral("Qt-Project"), QStringLiteral("Qtbase")); - settings.beginGroup(QStringLiteral("CEFontCache")); - - foreach (const QString &fontName, settings.allKeys()) { - const QString fontFileName = settings.value(fontName).toString(); - fontCache.insert(fontName, fontFileName); - } - - settings.endGroup(); // CEFontCache - } - - value = fontCache.value(faceName); - - //Fallback if we haven't cached the font yet or the font got removed/renamed iterate again over all fonts - if (value.isEmpty() || !QFile::exists(value)) { - QSettings settings(QSettings::SystemScope, QStringLiteral("Qt-Project"), QStringLiteral("Qtbase")); - settings.beginGroup(QStringLiteral("CEFontCache")); - - //empty the cache first, as it seems that it is dirty - foreach (const QString &fontName, settings.allKeys()) - settings.remove(fontName); - - QDirIterator it(QStringLiteral("/Windows"), QStringList(QStringLiteral("*.ttf")), QDir::Files | QDir::Hidden | QDir::System); - - while (it.hasNext()) { - const QString fontFile = it.next(); - const QString fontName = fontNameFromTTFile(fontFile); - if (fontName.isEmpty()) - continue; - fontCache.insert(fontName, fontFile); - settings.setValue(fontName, fontFile); - - if (localizedName(fontName)) { - QString englishFontName = getEnglishName(fontName); - fontCache.insert(englishFontName, fontFile); - settings.setValue(englishFontName, fontFile); - } - } - - value = fontCache.value(faceName); - - settings.endGroup(); // CEFontCache - } + QString value = findFontFile(faceName); #endif if (value.isEmpty()) @@ -440,9 +470,9 @@ static int QT_WIN_CALLBACK storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetr int type, LPARAM namesSetIn) { typedef QSet<QString> StringSet; - const QString familyName = QString::fromWCharArray(f->elfLogFont.lfFaceName) - + QStringLiteral("::") - + QString::fromWCharArray(f->elfFullName); + + const QString faceName = QString::fromWCharArray(f->elfLogFont.lfFaceName); + const QString fullName = QString::fromWCharArray(f->elfFullName); const uchar charSet = f->elfLogFont.lfCharSet; #ifndef Q_OS_WINCE @@ -476,8 +506,10 @@ static int QT_WIN_CALLBACK storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetr // NEWTEXTMETRICEX is a NEWTEXTMETRIC, which according to the documentation is // identical to a TEXTMETRIC except for the last four members, which we don't use // anyway - if (addFontToDatabase(familyName, charSet, (TEXTMETRIC *)textmetric, &signature, type)) - reinterpret_cast<StringSet *>(namesSetIn)->insert(familyName); + if (addFontToDatabase(faceName, fullName, + charSet, (TEXTMETRIC *)textmetric, &signature, type)) { + reinterpret_cast<StringSet *>(namesSetIn)->insert(faceName + QStringLiteral("::") + fullName); + } // keep on enumerating return 1; diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index db89402c05..0e26a17223 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -567,16 +567,15 @@ static inline int toKeyOrUnicode(int vk, int scancode, unsigned char *kbdBuffer, Q_ASSERT(vk > 0 && vk < 256); int code = 0; QChar unicodeBuffer[5]; - // While key combinations containing alt and ctrl might trigger the third assignment of a key - // (for example "alt+ctrl+q" causes '@' on a German layout), ToUnicode often does not return the - // wanted character if only the ctrl modifier is used. Thus we unset this modifier temporarily - // if it is not used together with alt. - const unsigned char controlState = kbdBuffer[VK_MENU] ? 0 : kbdBuffer[VK_CONTROL]; - if (controlState) - kbdBuffer[VK_CONTROL] = 0; int res = ToUnicode(vk, scancode, kbdBuffer, reinterpret_cast<LPWSTR>(unicodeBuffer), 5, 0); - if (controlState) + // When Ctrl modifier is used ToUnicode does not return correct values. In order to assign the + // right key the control modifier is removed for just that function if the previous call failed. + if (res == 0 && kbdBuffer[VK_CONTROL]) { + const unsigned char controlState = kbdBuffer[VK_CONTROL]; + kbdBuffer[VK_CONTROL] = 0; + res = ToUnicode(vk, scancode, kbdBuffer, reinterpret_cast<LPWSTR>(unicodeBuffer), 5, 0); kbdBuffer[VK_CONTROL] = controlState; + } if (res) code = unicodeBuffer[0].toUpper().unicode(); diff --git a/src/plugins/platforms/winrt/qwinrttheme.cpp b/src/plugins/platforms/winrt/qwinrttheme.cpp index ba8fcee829..f33e07901a 100644 --- a/src/plugins/platforms/winrt/qwinrttheme.cpp +++ b/src/plugins/platforms/winrt/qwinrttheme.cpp @@ -232,7 +232,7 @@ QVariant QWinRTTheme::styleHint(QPlatformIntegration::StyleHint hint) return false; case QPlatformIntegration::ShowIsMaximized: return false; - case MousePressAndHoldInterval: + case QPlatformIntegration::MousePressAndHoldInterval: return defaultThemeHint(MousePressAndHoldInterval); default: break; diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h index 15e11e7d0c..7725855327 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h @@ -57,7 +57,7 @@ public: bool makeCurrent(QPlatformSurface *surface) Q_DECL_OVERRIDE; void doneCurrent() Q_DECL_OVERRIDE; void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE; - void (*getProcAddress(const QByteArray &procName)) () Q_DECL_OVERRIDE; + QFunctionPointer getProcAddress(const QByteArray &procName) Q_DECL_OVERRIDE; QSurfaceFormat format() const Q_DECL_OVERRIDE; bool isSharing() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 250527e3ae..e1584999db 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -789,6 +789,15 @@ void QXcbConnection::handleButtonRelease(xcb_generic_event_t *ev) qCDebug(lcQpaXInput, "xcb: released mouse button %d, button state %X", event->detail, static_cast<unsigned int>(m_buttons)); } +void QXcbConnection::handleMotionNotify(xcb_generic_event_t *ev) +{ + xcb_motion_notify_event_t *event = (xcb_motion_notify_event_t *)ev; + + m_buttons = (m_buttons & ~0x7) | translateMouseButtons(event->state); + if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled())) + qDebug("xcb: moved mouse to %4d, %4d; button state %X", event->event_x, event->event_y, static_cast<unsigned int>(m_buttons)); +} + #ifndef QT_NO_XKB namespace { typedef union { @@ -839,11 +848,8 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) handleButtonRelease(event); HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent); case XCB_MOTION_NOTIFY: - if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled())) { - xcb_motion_notify_event_t *mev = (xcb_motion_notify_event_t *)event; - qDebug("xcb: moved mouse to %4d, %4d; button state %X", mev->event_x, mev->event_y, static_cast<unsigned int>(m_buttons)); - } m_keyboard->updateXKBStateFromCore(((xcb_motion_notify_event_t *)event)->state); + handleMotionNotify(event); HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent); case XCB_CONFIGURE_NOTIFY: HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent); diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index e3d9766a4b..90b859e612 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -497,6 +497,7 @@ private: void updateScreens(); void handleButtonPress(xcb_generic_event_t *event); void handleButtonRelease(xcb_generic_event_t *event); + void handleMotionNotify(xcb_generic_event_t *event); bool m_xi2Enabled; int m_xi2Minor; @@ -507,6 +508,7 @@ private: XInput2TouchDeviceData *touchDeviceForId(int id); void xi2HandleEvent(xcb_ge_event_t *event); void xi2HandleHierachyEvent(void *event); + void xi2HandleDeviceChangedEvent(void *event); int m_xiOpCode, m_xiEventBase, m_xiErrorBase; #ifndef QT_NO_TABLETEVENT struct TabletData { @@ -540,6 +542,7 @@ private: Qt::Orientations legacyOrientations; QPointF lastScrollPosition; }; + void updateScrollingDevice(ScrollingDevice& scrollingDevice, int num_classes, void *classes); void xi2HandleScrollEvent(void *event, ScrollingDevice &scrollingDevice); QHash<int, ScrollingDevice> m_scrollingDevices; #endif // XCB_USE_XINPUT2 diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index f225518cb9..e9fb47dabd 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -348,6 +348,7 @@ void QXcbConnection::xi2Select(xcb_window_t window) // Listen for hotplug events XIEventMask xiEventMask; bitMask = XI_HierarchyChangedMask; + bitMask |= XI_DeviceChangedMask; xiEventMask.deviceid = XIAllDevices; xiEventMask.mask_len = sizeof(bitMask); xiEventMask.mask = xiBitMask; @@ -468,6 +469,11 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) xi2HandleHierachyEvent(xiEvent); return; } + if (xiEvent->evtype == XI_DeviceChanged) { + xi2HandleDeviceChangedEvent(xiEvent); + return; + } + #ifndef QT_NO_TABLETEVENT for (int i = 0; i < m_tabletData.count(); ++i) { if (m_tabletData.at(i).deviceId == xiEvent->deviceid) { @@ -628,6 +634,64 @@ void QXcbConnection::xi2HandleHierachyEvent(void *event) } } +void QXcbConnection::xi2HandleDeviceChangedEvent(void *event) +{ + xXIDeviceChangedEvent *xiEvent = reinterpret_cast<xXIDeviceChangedEvent *>(event); + + // ### If a slave device changes (XIDeviceChange), we should probably run setup on it again. + if (xiEvent->reason != XISlaveSwitch) + return; + +#ifdef XCB_USE_XINPUT21 + // This code handles broken scrolling device drivers that reset absolute positions + // when they are made active. Whenever a new slave device is made active the + // primary pointer sends a DeviceChanged event with XISlaveSwitch, and the new + // active slave in sourceid. + + QHash<int, ScrollingDevice>::iterator device = m_scrollingDevices.find(xiEvent->sourceid); + if (device == m_scrollingDevices.end()) + return; + + int nrDevices = 0; + XIDeviceInfo* xiDeviceInfo = XIQueryDevice(static_cast<Display *>(m_xlib_display), xiEvent->sourceid, &nrDevices); + if (nrDevices <= 0) { + qCDebug(lcQpaXInputDevices, "scrolling device %d no longer present", xiEvent->sourceid); + return; + } + updateScrollingDevice(*device, xiDeviceInfo->num_classes, xiDeviceInfo->classes); + XIFreeDeviceInfo(xiDeviceInfo); +#endif +} + +void QXcbConnection::updateScrollingDevice(ScrollingDevice &scrollingDevice, int num_classes, void *classInfo) +{ +#ifdef XCB_USE_XINPUT21 + XIAnyClassInfo **classes = reinterpret_cast<XIAnyClassInfo**>(classInfo); + QPointF lastScrollPosition; + if (lcQpaXInput().isDebugEnabled()) + lastScrollPosition = scrollingDevice.lastScrollPosition; + for (int c = 0; c < num_classes; ++c) { + if (classes[c]->type == XIValuatorClass) { + XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classes[c]); + const int valuatorAtom = qatom(vci->label); + if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel) + scrollingDevice.lastScrollPosition.setX(vci->value); + else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel) + scrollingDevice.lastScrollPosition.setY(vci->value); + } + } + if (lcQpaXInput().isDebugEnabled() && lastScrollPosition != scrollingDevice.lastScrollPosition) + qCDebug(lcQpaXInput, "scrolling device %d moved from (%f, %f) to (%f, %f)", scrollingDevice.deviceId, + lastScrollPosition.x(), lastScrollPosition.y(), + scrollingDevice.lastScrollPosition.x(), + scrollingDevice.lastScrollPosition.y()); +#else + Q_UNUSED(scrollingDevice); + Q_UNUSED(num_classes); + Q_UNUSED(classInfo); +#endif +} + void QXcbConnection::handleEnterEvent(const xcb_enter_notify_event_t *) { #ifdef XCB_USE_XINPUT21 @@ -638,19 +702,11 @@ void QXcbConnection::handleEnterEvent(const xcb_enter_notify_event_t *) int nrDevices = 0; XIDeviceInfo* xiDeviceInfo = XIQueryDevice(static_cast<Display *>(m_xlib_display), scrollingDevice.deviceId, &nrDevices); if (nrDevices <= 0) { + qCDebug(lcQpaXInputDevices, "scrolling device %d no longer present", scrollingDevice.deviceId); it = m_scrollingDevices.erase(it); continue; } - for (int c = 0; c < xiDeviceInfo->num_classes; ++c) { - if (xiDeviceInfo->classes[c]->type == XIValuatorClass) { - XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(xiDeviceInfo->classes[c]); - const int valuatorAtom = qatom(vci->label); - if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel) - scrollingDevice.lastScrollPosition.setX(vci->value); - else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel) - scrollingDevice.lastScrollPosition.setY(vci->value); - } - } + updateScrollingDevice(scrollingDevice, xiDeviceInfo->num_classes, xiDeviceInfo->classes); XIFreeDeviceInfo(xiDeviceInfo); ++it; } diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 1d8ba69e55..2253dfecef 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -207,6 +207,18 @@ static inline QImage::Format imageFormatForVisual(int depth, quint32 red_mask, q break; } qWarning("Unsupported screen format: depth: %d, red_mask: %x, blue_mask: %x", depth, red_mask, blue_mask); + + switch (depth) { + case 24: + qWarning("Using RGB32 fallback, if this works your X11 server is reporting a bad screen format."); + return QImage::Format_RGB32; + case 16: + qWarning("Using RGB16 fallback, if this works your X11 server is reporting a bad screen format."); + return QImage::Format_RGB16; + default: + break; + } + return QImage::Format_Invalid; } |