diff options
author | Frederik Gladhorn <frederik.gladhorn@theqtcompany.com> | 2015-02-24 17:19:40 +0100 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@theqtcompany.com> | 2015-02-24 21:02:08 +0100 |
commit | 34b14a8472f44f8517577756e033b92ebd4c5912 (patch) | |
tree | 66a0575156d0a17a835430137e218e2b3f04cc65 /src/plugins | |
parent | d34353a065c443aac20376cbd88323480d769183 (diff) | |
parent | edd555425a08f9e074f0a4d9333862636ccaae8d (diff) |
Merge remote-tracking branch 'origin/5.4' into 5.5
Conflicts:
examples/xml/htmlinfo/simpleexample.html
examples/xml/rsslisting/rsslisting.cpp
qmake/generators/win32/msbuild_objectmodel.cpp
src/3rdparty/harfbuzz-ng/src/hb-private.hh
src/corelib/global/qlogging.cpp
src/corelib/io/qstorageinfo_unix.cpp
src/corelib/thread/qwaitcondition_unix.cpp
src/gui/kernel/qguiapplication.cpp
src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
src/testlib/doc/src/qt-webpages.qdoc
tests/auto/other/qaccessibility/tst_qaccessibility.cpp
Change-Id: Ib272ff0bc30a1a5d51275eb3cd2f201dc82c11ff
Diffstat (limited to 'src/plugins')
15 files changed, 243 insertions, 162 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/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/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/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 34289fb90e..54ebca0532 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -206,6 +206,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; } |