From 9a679121f4257ab71a1ebb09a012fa2206f300df Mon Sep 17 00:00:00 2001 From: Robert Griebl Date: Tue, 14 Nov 2017 16:22:06 +0100 Subject: 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 --- application-manager.pro | 2 + config.tests/touchemulation/main.cpp | 49 +++++ config.tests/touchemulation/touchemulation.pro | 8 + qmake-features/am-config.prf | 1 + src/main-lib/defaultconfiguration.cpp | 6 + src/main-lib/defaultconfiguration.h | 1 + src/main-lib/main.cpp | 16 ++ src/main-lib/main.h | 1 + src/window-lib/touchemulation.cpp | 83 ++++++++ src/window-lib/touchemulation.h | 70 +++++++ src/window-lib/touchemulation_x11.cpp | 274 +++++++++++++++++++++++++ src/window-lib/touchemulation_x11.h | 78 +++++++ src/window-lib/window-lib.pro | 12 +- 13 files changed, 600 insertions(+), 1 deletion(-) create mode 100644 config.tests/touchemulation/main.cpp create mode 100644 config.tests/touchemulation/touchemulation.pro create mode 100644 src/window-lib/touchemulation.cpp create mode 100644 src/window-lib/touchemulation.h create mode 100644 src/window-lib/touchemulation_x11.cpp create mode 100644 src/window-lib/touchemulation_x11.h 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 +#include +#include + +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(nullptr, { "ui", "style" }); } +bool DefaultConfiguration::enableTouchEmulation() const +{ + return value("enable-touch-emulation", { "ui", "enableTouchEmulation" }); +} + QString DefaultConfiguration::openGLESProfile() const { return value(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 +#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 +#include + +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 + +#include "touchemulation_x11.h" + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +// 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(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(message); + + switch (xcbEvent->response_type & ~0x80) { + case XCB_BUTTON_PRESS: { + auto xcbPress = reinterpret_cast(xcbEvent); + return handleButtonPress(static_cast(xcbPress->event), xcbPress->detail, 0, + xcbPress->event_x, xcbPress->event_y); + } + case XCB_BUTTON_RELEASE: { + auto xcbRelease = reinterpret_cast(xcbEvent); + return handleButtonRelease(static_cast(xcbRelease->event), xcbRelease->detail, 0, + xcbRelease->event_x, xcbRelease->event_y); + } + case XCB_MOTION_NOTIFY: { + auto xcbMotion = reinterpret_cast(xcbEvent); + return handleMotionNotify(static_cast(xcbMotion->event), 0, + xcbMotion->event_x, xcbMotion->event_y); + } + case XCB_GE_GENERIC: { + if (!m_haveXInput2) + return false; + + auto xcbGeneric = reinterpret_cast(xcbEvent); + xi2PrepareXIGenericDeviceEvent(xcbGeneric); + auto xiEvent = reinterpret_cast(xcbGeneric); + xXIDeviceEvent *xiDeviceEvent = nullptr; + + switch (xiEvent->evtype) { + case XI_ButtonPress: + case XI_ButtonRelease: + case XI_Motion: + xiDeviceEvent = reinterpret_cast(xcbGeneric); + break; + default: + break; + } + + if (!xiDeviceEvent) + return false; + + switch (xiDeviceEvent->evtype) { + case XI_ButtonPress: + return handleButtonPress( + static_cast(xiDeviceEvent->event), + xiDeviceEvent->detail, + xiDeviceEvent->mods.base_mods, + fixed1616ToReal(xiDeviceEvent->event_x), + fixed1616ToReal(xiDeviceEvent->event_y)); + case XI_ButtonRelease: + return handleButtonRelease( + static_cast(xiDeviceEvent->event), + xiDeviceEvent->detail, + xiDeviceEvent->mods.base_mods, + fixed1616ToReal(xiDeviceEvent->event_x), + fixed1616ToReal(xiDeviceEvent->event_y)); + case XI_Motion: + return handleMotionNotify( + static_cast(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 +#include "touchemulation.h" + +#if defined(AM_ENABLE_TOUCH_EMULATION) + +#include +#include +#include + +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) - -- cgit v1.2.3