summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Griebl <robert.griebl@pelagicore.com>2017-11-14 16:22:06 +0100
committerDominik Holland <dominik.holland@pelagicore.com>2017-11-29 14:31:46 +0000
commit9a679121f4257ab71a1ebb09a012fa2206f300df (patch)
tree2770bf703609a3420c558ff5d4e3dab717659182
parent37163471be41ab57599820066306885d116ccb28 (diff)
Move the MouseTouchAdaptor from neptune to the application-manager
This way we can (a) re-use the functionality in other system-uis and (b) easily disable it when e.g. testing with Squish. Change-Id: Icbfb3dfac5283eebe1cf4855386e27c6d1a430dc Reviewed-by: Dominik Holland <dominik.holland@pelagicore.com>
-rw-r--r--application-manager.pro2
-rw-r--r--config.tests/touchemulation/main.cpp49
-rw-r--r--config.tests/touchemulation/touchemulation.pro8
-rw-r--r--qmake-features/am-config.prf1
-rw-r--r--src/main-lib/defaultconfiguration.cpp6
-rw-r--r--src/main-lib/defaultconfiguration.h1
-rw-r--r--src/main-lib/main.cpp16
-rw-r--r--src/main-lib/main.h1
-rw-r--r--src/window-lib/touchemulation.cpp83
-rw-r--r--src/window-lib/touchemulation.h70
-rw-r--r--src/window-lib/touchemulation_x11.cpp274
-rw-r--r--src/window-lib/touchemulation_x11.h78
-rw-r--r--src/window-lib/window-lib.pro12
13 files changed, 600 insertions, 1 deletions
diff --git a/application-manager.pro b/application-manager.pro
index cec08b52..9d6f85a5 100644
--- a/application-manager.pro
+++ b/application-manager.pro
@@ -13,6 +13,7 @@ else:contains(QT_BUILD_PARTS, "examples"):CONFIG += enable-examples
load(configure)
qtCompileTest(libarchive)
qtCompileTest(libyaml)
+!headless:qtCompileTest(touchemulation)
qtHaveModule(compositor)|if(qtHaveModule(waylandcompositor):qtHaveModule(waylandcompositor-private)) {
CONFIG += am_compatible_compositor
@@ -84,6 +85,7 @@ printConfigLine("Installation prefix", $$INSTALL_PREFIX, auto)
printConfigLine("Tools only build", $$yesNo(CONFIG(tools-only)), no)
printConfigLine("Enable support for QtWidgets", $$yesNo(CONFIG(enable-widgets)), auto)
printConfigLine("Headless", $$yesNo(CONFIG(headless)), auto)
+printConfigLine("Touch emulation", $$yesNo(CONFIG(config_touchemulation)), auto)
printConfigLine("QtCompositor support", $$yesNo(CONFIG(am_compatible_compositor)), auto)
printConfigLine("Multi-process mode", $$check_multi, auto)
printConfigLine("Installer enabled", $$yesNo(!CONFIG(disable-installer)), auto)
diff --git a/config.tests/touchemulation/main.cpp b/config.tests/touchemulation/main.cpp
new file mode 100644
index 00000000..bdb25f60
--- /dev/null
+++ b/config.tests/touchemulation/main.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:LGPL-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite licenses may use
+** this file in accordance with the commercial license agreement provided
+** with the Software or, alternatively, in accordance with the terms
+** contained in a written agreement between you and The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: LGPL-3.0
+**
+****************************************************************************/
+
+#include <xcb/xcb.h>
+#include <X11/extensions/XInput2.h>
+#include <X11/extensions/XI2proto.h>
+
+int main()
+{
+ return 0;
+}
diff --git a/config.tests/touchemulation/touchemulation.pro b/config.tests/touchemulation/touchemulation.pro
new file mode 100644
index 00000000..6a88ef05
--- /dev/null
+++ b/config.tests/touchemulation/touchemulation.pro
@@ -0,0 +1,8 @@
+TARGET = touchemulation
+CONFIG -= qt
+CONFIG += console
+
+SOURCES += main.cpp
+
+PKGCONFIG += xcb x11 xi
+CONFIG += link_pkgconfig
diff --git a/qmake-features/am-config.prf b/qmake-features/am-config.prf
index 6b29967c..b0fd235a 100644
--- a/qmake-features/am-config.prf
+++ b/qmake-features/am-config.prf
@@ -16,6 +16,7 @@ disable-external-dbus-interfaces:DEFINES *= AM_DISABLE_EXTERNAL_DBUS_INTERFACES
systemd-workaround:DEFINES *= AM_SYSTEMD_WORKAROUND
headless:DEFINES *= AM_HEADLESS
enable-widgets:DEFINES *= AM_ENABLE_WIDGETS
+config_touchemulation:DEFINES += AM_ENABLE_TOUCH_EMULATION
linux:!android:!disable-libbacktrace:if(enable-libbacktrace|CONFIG(debug, debug|release)):DEFINES *= AM_USE_LIBBACKTRACE
!force-single-process {
diff --git a/src/main-lib/defaultconfiguration.cpp b/src/main-lib/defaultconfiguration.cpp
index b4a514a0..8384c095 100644
--- a/src/main-lib/defaultconfiguration.cpp
+++ b/src/main-lib/defaultconfiguration.cpp
@@ -116,6 +116,7 @@ DefaultConfiguration::DefaultConfiguration(const QStringList &defaultConfigFileP
m_clp.addOption({ qSL("single-app"), qSL("runs a single application only (ignores the database)"), qSL("info.yaml file") });
m_clp.addOption({ qSL("logging-rule"), qSL("adds a standard Qt logging rule."), qSL("rule") });
m_clp.addOption({ qSL("qml-debug"), qSL("enables QML debugging and profiling.") });
+ m_clp.addOption({ qSL("enable-touch-emulation"), qSL("enables the touch emulation, converting mouse to touch events.") });
}
DefaultConfiguration::~DefaultConfiguration()
@@ -252,6 +253,11 @@ QString DefaultConfiguration::style() const
return value<QString>(nullptr, { "ui", "style" });
}
+bool DefaultConfiguration::enableTouchEmulation() const
+{
+ return value<bool>("enable-touch-emulation", { "ui", "enableTouchEmulation" });
+}
+
QString DefaultConfiguration::openGLESProfile() const
{
return value<QString>(nullptr, { "ui", "opengl", "desktopProfile" });
diff --git a/src/main-lib/defaultconfiguration.h b/src/main-lib/defaultconfiguration.h
index cf456e0e..405204c0 100644
--- a/src/main-lib/defaultconfiguration.h
+++ b/src/main-lib/defaultconfiguration.h
@@ -83,6 +83,7 @@ public:
QString singleApp() const;
QStringList loggingRules() const;
QString style() const;
+ bool enableTouchEmulation() const;
QString openGLESProfile() const;
int openGLESVersionMajor() const;
diff --git a/src/main-lib/main.cpp b/src/main-lib/main.cpp
index bec59abc..998ec8ad 100644
--- a/src/main-lib/main.cpp
+++ b/src/main-lib/main.cpp
@@ -119,6 +119,7 @@
# if defined(QT_DBUS_LIB) && !defined(AM_DISABLE_EXTERNAL_DBUS_INTERFACES)
# include "windowmanagerdbuscontextadaptor.h"
# endif
+# include "touchemulation.h"
#endif
#include "configuration.h"
@@ -265,6 +266,7 @@ void Main::setup(const DefaultConfiguration *cfg) Q_DECL_NOEXCEPT_EXPR(false)
setupQmlEngine(cfg->importPaths(), cfg->style());
setupWindowTitle(QString(), cfg->windowIcon());
setupWindowManager(cfg->waylandSocketName(), cfg->slowAnimations(), cfg->noUiWatchdog());
+ setupTouchEmulation(cfg->enableTouchEmulation());
setupShellServer(cfg->telnetAddress(), cfg->telnetPort());
setupSSDPService();
}
@@ -757,6 +759,20 @@ void Main::setupWindowManager(const QString &waylandSocketName, bool slowAnimati
#endif
}
+void Main::setupTouchEmulation(bool enableTouchEmulation)
+{
+ if (enableTouchEmulation) {
+ if (TouchEmulation::isSupported()) {
+ TouchEmulation::createInstance();
+ qCDebug(LogGraphics) << "Touch emulation is enabled: all mouse events will be converted "
+ "to touch events.";
+ } else {
+ qCWarning(LogGraphics) << "Touch emulation cannot be enabled. Either it was disabled at "
+ "build time or the platform does not support it.";
+ }
+ }
+}
+
void Main::loadQml(bool loadDummyData) Q_DECL_NOEXCEPT_EXPR(false)
{
for (auto iface : qAsConst(m_startupPlugins))
diff --git a/src/main-lib/main.h b/src/main-lib/main.h
index 6cf22185..a2c13269 100644
--- a/src/main-lib/main.h
+++ b/src/main-lib/main.h
@@ -123,6 +123,7 @@ protected:
void setupQmlEngine(const QStringList &importPaths, const QString &quickControlsStyle = QString());
void setupWindowTitle(const QString &title, const QString &iconPath);
void setupWindowManager(const QString &waylandSocketName, bool slowAnimations, bool uiWatchdog);
+ void setupTouchEmulation(bool enableTouchEmulation);
void setupOpenGL(const QString &profileName, int majorVersion, int minorVersion);
void setupShellServer(const QString &telnetAddress, quint16 telnetPort) Q_DECL_NOEXCEPT_EXPR(false);
diff --git a/src/window-lib/touchemulation.cpp b/src/window-lib/touchemulation.cpp
new file mode 100644
index 00000000..bec2b33e
--- /dev/null
+++ b/src/window-lib/touchemulation.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:LGPL-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite licenses may use
+** this file in accordance with the commercial license agreement provided
+** with the Software or, alternatively, in accordance with the terms
+** contained in a written agreement between you and The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: LGPL-3.0
+**
+****************************************************************************/
+
+#include <QtAppManCommon/global.h>
+#include "touchemulation.h"
+#if defined(AM_ENABLE_TOUCH_EMULATION)
+# include "touchemulation_x11.h"
+#endif
+
+QT_BEGIN_NAMESPACE_AM
+
+TouchEmulation *TouchEmulation::s_instance = nullptr;
+
+TouchEmulation::~TouchEmulation()
+{
+ s_instance = nullptr;
+}
+
+TouchEmulation *TouchEmulation::instance()
+{
+ return s_instance;
+}
+
+TouchEmulation *TouchEmulation::createInstance()
+{
+ if (Q_UNLIKELY(s_instance))
+ qFatal("TouchEmulation::createInstance() was called a second time.");
+
+#if defined(AM_ENABLE_TOUCH_EMULATION)
+ s_instance = new TouchEmulationX11();
+#endif
+
+ return s_instance;
+}
+
+bool TouchEmulation::isSupported()
+{
+#if defined(AM_ENABLE_TOUCH_EMULATION)
+ return true;
+#else
+ return false;
+#endif
+}
+
+QT_END_NAMESPACE_AM
diff --git a/src/window-lib/touchemulation.h b/src/window-lib/touchemulation.h
new file mode 100644
index 00000000..de5b3b4d
--- /dev/null
+++ b/src/window-lib/touchemulation.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:LGPL-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite licenses may use
+** this file in accordance with the commercial license agreement provided
+** with the Software or, alternatively, in accordance with the terms
+** contained in a written agreement between you and The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: LGPL-3.0
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QtAppManCommon/global.h>
+#include <QObject>
+
+QT_BEGIN_NAMESPACE_AM
+
+/*
+ Converts native mouse events into touch events
+
+ Useful for emulating touch interaction using a mouse device since touch input
+ follows a completely different code path from mouse events in Qt.
+*/
+class TouchEmulation : public QObject
+{
+ Q_OBJECT
+
+public:
+ virtual ~TouchEmulation();
+ static TouchEmulation *createInstance();
+ static TouchEmulation *instance();
+
+ static bool isSupported();
+
+private:
+ static TouchEmulation *s_instance;
+};
+
+QT_END_NAMESPACE_AM
diff --git a/src/window-lib/touchemulation_x11.cpp b/src/window-lib/touchemulation_x11.cpp
new file mode 100644
index 00000000..2fef4a60
--- /dev/null
+++ b/src/window-lib/touchemulation_x11.cpp
@@ -0,0 +1,274 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:LGPL-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite licenses may use
+** this file in accordance with the commercial license agreement provided
+** with the Software or, alternatively, in accordance with the terms
+** contained in a written agreement between you and The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: LGPL-3.0
+**
+****************************************************************************/
+
+#include <QtAppManCommon/global.h>
+
+#include "touchemulation_x11.h"
+
+#include <QGuiApplication>
+#include <QMouseEvent>
+#include <QTouchDevice>
+#include <QWindow>
+#include <QTest>
+
+#include <QtAppManCommon/logging.h>
+
+#include <qpa/qplatformnativeinterface.h>
+#include <qpa/qwindowsysteminterface.h>
+
+#include <xcb/xcb.h>
+#include <X11/extensions/XInput2.h>
+#include <X11/extensions/XI2proto.h>
+
+// this event type was added in libxcb 1.10,
+// but we support also older version
+#ifndef XCB_GE_GENERIC
+# define XCB_GE_GENERIC 35
+#endif
+
+QT_BEGIN_NAMESPACE_AM
+
+using QTest::QTouchEventSequence;
+
+
+static Qt::MouseButton xcbButtonToQtMouseButton(xcb_button_t detail)
+{
+ switch (detail) {
+ case 1: return Qt::LeftButton;
+ case 2: return Qt::MidButton;
+ case 3: return Qt::RightButton;
+ // don't care about the rest
+ default: return Qt::NoButton;
+ }
+}
+
+static void xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event)
+{
+ // xcb event structs contain stuff that wasn't on the wire, the full_sequence field
+ // adds an extra 4 bytes and generic events cookie data is on the wire right after the standard 32 bytes.
+ // Move this data back to have the same layout in memory as it was on the wire
+ // and allow casting, overwriting the full_sequence field.
+ memmove((char*) event + 32, (char*) event + 36, event->length * 4);
+}
+
+static qreal fixed1616ToReal(FP1616 val)
+{
+ return qreal(val) / 0x10000;
+}
+
+
+TouchEmulationX11::TouchEmulationX11()
+{
+ qGuiApp->installNativeEventFilter(this);
+
+ // Create a fake touch device to deliver our synthesized events
+ m_touchDevice = new QTouchDevice;
+ m_touchDevice->setType(QTouchDevice::TouchScreen);
+ QWindowSystemInterface::registerTouchDevice(m_touchDevice);
+
+ queryForXInput2();
+}
+
+void TouchEmulationX11::queryForXInput2()
+{
+ QPlatformNativeInterface *nativeInterface = qGuiApp->platformNativeInterface();
+ Display *xDisplay = static_cast<Display*>(nativeInterface->nativeResourceForIntegration("Display"));
+
+ int xiOpCode, xiEventBase, xiErrorBase;
+ if (xDisplay && XQueryExtension(xDisplay, "XInputExtension", &xiOpCode, &xiEventBase, &xiErrorBase)) {
+ // 2.0 is enough for our needs
+ int xiMajor = 2;
+ int xi2Minor = 0;
+ m_haveXInput2 = XIQueryVersion(xDisplay, &xiMajor, &xi2Minor) != BadRequest;
+ }
+}
+
+bool TouchEmulationX11::nativeEventFilter(const QByteArray &eventType, void *message, long * /*result*/)
+{
+ if (eventType != "xcb_generic_event_t")
+ return false; // just ignore non-XCB-native events
+
+ xcb_generic_event_t *xcbEvent = static_cast<xcb_generic_event_t *>(message);
+
+ switch (xcbEvent->response_type & ~0x80) {
+ case XCB_BUTTON_PRESS: {
+ auto xcbPress = reinterpret_cast<xcb_button_press_event_t *>(xcbEvent);
+ return handleButtonPress(static_cast<WId>(xcbPress->event), xcbPress->detail, 0,
+ xcbPress->event_x, xcbPress->event_y);
+ }
+ case XCB_BUTTON_RELEASE: {
+ auto xcbRelease = reinterpret_cast<xcb_button_release_event_t *>(xcbEvent);
+ return handleButtonRelease(static_cast<WId>(xcbRelease->event), xcbRelease->detail, 0,
+ xcbRelease->event_x, xcbRelease->event_y);
+ }
+ case XCB_MOTION_NOTIFY: {
+ auto xcbMotion = reinterpret_cast<xcb_motion_notify_event_t *>(xcbEvent);
+ return handleMotionNotify(static_cast<WId>(xcbMotion->event), 0,
+ xcbMotion->event_x, xcbMotion->event_y);
+ }
+ case XCB_GE_GENERIC: {
+ if (!m_haveXInput2)
+ return false;
+
+ auto xcbGeneric = reinterpret_cast<xcb_ge_event_t *>(xcbEvent);
+ xi2PrepareXIGenericDeviceEvent(xcbGeneric);
+ auto xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(xcbGeneric);
+ xXIDeviceEvent *xiDeviceEvent = nullptr;
+
+ switch (xiEvent->evtype) {
+ case XI_ButtonPress:
+ case XI_ButtonRelease:
+ case XI_Motion:
+ xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(xcbGeneric);
+ break;
+ default:
+ break;
+ }
+
+ if (!xiDeviceEvent)
+ return false;
+
+ switch (xiDeviceEvent->evtype) {
+ case XI_ButtonPress:
+ return handleButtonPress(
+ static_cast<WId>(xiDeviceEvent->event),
+ xiDeviceEvent->detail,
+ xiDeviceEvent->mods.base_mods,
+ fixed1616ToReal(xiDeviceEvent->event_x),
+ fixed1616ToReal(xiDeviceEvent->event_y));
+ case XI_ButtonRelease:
+ return handleButtonRelease(
+ static_cast<WId>(xiDeviceEvent->event),
+ xiDeviceEvent->detail,
+ xiDeviceEvent->mods.base_mods,
+ fixed1616ToReal(xiDeviceEvent->event_x),
+ fixed1616ToReal(xiDeviceEvent->event_y));
+ case XI_Motion:
+ return handleMotionNotify(
+ static_cast<WId>(xiDeviceEvent->event),
+ xiDeviceEvent->mods.base_mods,
+ fixed1616ToReal(xiDeviceEvent->event_x),
+ fixed1616ToReal(xiDeviceEvent->event_y));
+ return true;
+ default:
+ return false;
+ }
+ }
+ default:
+ return false;
+ };
+}
+
+bool TouchEmulationX11::handleButtonPress(WId windowId, uint32_t detail, uint32_t /*modifiers*/, int x, int y)
+{
+ Qt::MouseButton button = xcbButtonToQtMouseButton(detail);
+
+ // Filter out the other mouse buttons
+ if (button != Qt::LeftButton)
+ return true;
+
+ QWindow *targetWindow = findQWindowWithXWindowID(windowId);
+
+ QPoint windowPos(x / targetWindow->devicePixelRatio(), y / targetWindow->devicePixelRatio());
+
+ QTouchEventSequence touchEvent = QTest::touchEvent(targetWindow, m_touchDevice, false /* autoCommit */);
+ touchEvent.press(0 /* touchId */, windowPos);
+ touchEvent.commit(false /* processEvents */);
+
+ m_leftButtonIsPressed = true;
+ return true;
+}
+
+bool TouchEmulationX11::handleButtonRelease(WId windowId, uint32_t detail, uint32_t, int x, int y)
+{
+ Qt::MouseButton button = xcbButtonToQtMouseButton(detail);
+
+ // Don't eat the event if it wasn't a left mouse press
+ if (button != Qt::LeftButton)
+ return false;
+
+ QWindow *targetWindow = findQWindowWithXWindowID(windowId);
+
+ QPoint windowPos(x / targetWindow->devicePixelRatio(), y / targetWindow->devicePixelRatio());
+
+ QTouchEventSequence touchEvent = QTest::touchEvent(targetWindow, m_touchDevice, false /* autoCommit */);
+ touchEvent.release(0 /* touchId */, windowPos);
+ touchEvent.commit(false /* processEvents */);
+
+ m_leftButtonIsPressed = false;
+ return true;
+}
+
+bool TouchEmulationX11::handleMotionNotify(WId windowId, uint32_t /*modifiers*/, int x, int y)
+{
+ if (!m_leftButtonIsPressed)
+ return true;
+
+ QWindow *targetWindow = findQWindowWithXWindowID(windowId);
+
+ QPoint windowPos(x / targetWindow->devicePixelRatio(), y / targetWindow->devicePixelRatio());
+
+ QTouchEventSequence touchEvent = QTest::touchEvent(targetWindow, m_touchDevice, false /* autoCommit */);
+ touchEvent.move(0 /* touchId */, windowPos);
+ touchEvent.commit(false /* processEvents */);
+
+ return true;
+}
+
+QWindow *TouchEmulationX11::findQWindowWithXWindowID(WId windowId)
+{
+ QWindowList windowList = QGuiApplication::topLevelWindows();
+ QWindow *foundWindow = nullptr;
+
+ int i = 0;
+ while (!foundWindow && (i < windowList.count())) {
+ QWindow *window = windowList[i];
+ if (window->winId() == windowId)
+ foundWindow = window;
+ else
+ ++i;
+ }
+
+ Q_ASSERT(foundWindow);
+ return foundWindow;
+}
+
+QT_END_NAMESPACE_AM
diff --git a/src/window-lib/touchemulation_x11.h b/src/window-lib/touchemulation_x11.h
new file mode 100644
index 00000000..8f089636
--- /dev/null
+++ b/src/window-lib/touchemulation_x11.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:LGPL-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite licenses may use
+** this file in accordance with the commercial license agreement provided
+** with the Software or, alternatively, in accordance with the terms
+** contained in a written agreement between you and The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: LGPL-3.0
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QtAppManCommon/global.h>
+#include "touchemulation.h"
+
+#if defined(AM_ENABLE_TOUCH_EMULATION)
+
+#include <QAbstractNativeEventFilter>
+#include <QObject>
+#include <QWindow>
+
+QT_FORWARD_DECLARE_CLASS(QTouchDevice)
+QT_FORWARD_DECLARE_CLASS(QWindow)
+
+QT_BEGIN_NAMESPACE_AM
+
+class TouchEmulationX11 : public TouchEmulation, public QAbstractNativeEventFilter
+{
+public:
+ TouchEmulationX11();
+ bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override;
+
+private:
+ void queryForXInput2();
+ bool handleButtonPress(WId windowId, uint32_t detail, uint32_t modifiers, int x, int y);
+ bool handleButtonRelease(WId windowId, uint32_t detail, uint32_t, int x, int y);
+ bool handleMotionNotify(WId windowId, uint32_t modifiers, int x, int y);
+ QWindow *findQWindowWithXWindowID(WId windowId);
+
+ QTouchDevice *m_touchDevice = nullptr;
+ bool m_haveXInput2 = false;
+ bool m_leftButtonIsPressed = false;
+};
+
+QT_END_NAMESPACE_AM
+
+#endif // AM_ENABLE_TOUCH_EMULATION
diff --git a/src/window-lib/window-lib.pro b/src/window-lib/window-lib.pro
index 8e4a08c2..2f0272c2 100644
--- a/src/window-lib/window-lib.pro
+++ b/src/window-lib/window-lib.pro
@@ -37,11 +37,21 @@ multi-process:!headless {
inprocesswindow.h \
windowmanager.h \
windowmanager_p.h \
+ touchemulation.h \
+
!headless:SOURCES += \
window.cpp \
inprocesswindow.cpp \
windowmanager.cpp \
+ touchemulation.cpp \
+
+# build the touch emulation only on X11 setups
+!headless:config_touchemulation {
+ PKGCONFIG *= xcb x11 xi
+ QT *= gui-private testlib
+ HEADERS += touchemulation_x11.h
+ SOURCES += touchemulation_x11.cpp
+}
load(qt_module)
-