summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@theqtcompany.com>2015-02-24 17:19:40 +0100
committerFrederik Gladhorn <frederik.gladhorn@theqtcompany.com>2015-02-24 21:02:08 +0100
commit34b14a8472f44f8517577756e033b92ebd4c5912 (patch)
tree66a0575156d0a17a835430137e218e2b3f04cc65 /src/plugins/platforms
parentd34353a065c443aac20376cbd88323480d769183 (diff)
parentedd555425a08f9e074f0a4d9333862636ccaae8d (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/platforms')
-rw-r--r--src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp248
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h3
-rw-r--r--src/plugins/platforms/ios/quiview.mm5
-rw-r--r--src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp7
-rw-r--r--src/plugins/platforms/linuxfb/qlinuxfbintegration.h3
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp8
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp15
-rw-r--r--src/plugins/platforms/winrt/qwinrttheme.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp14
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h3
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp76
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp12
13 files changed, 240 insertions, 158 deletions
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;
}