webOS: Support mapping evdev keyboard and touchscreen to specific window
First we refactor QTouchOutputMapping into a QOutputMapping base class and a QDefaultOutputMapping subclass, because it will be used to map more kinds of devices, not only touchscreens. On WebOS, the plan is to have a custom subclass that overrides an additional windowForDeviceNode() virtual function, so that events from specific devices can be sent to specific windows. But in the future, Qt may have a more generic mechanism for mapping devices to screens, and of course windows are displayed on screens; so this direct device->window mapping is likely to be temporary. In the QT_QPA_EGLFS_KMS_CONFIG JSON configuration, symlinked device nodes are now supported. Task-number: QTBUG-85268 Change-Id: Id1f0bb59f4a439abaec6bd35016c95de1cbdb26a Reviewed-by: Elvis Lee <kwangwoong.lee@lge.com> Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
parent
fd8e6a203e
commit
4b899a29fa
@ -91,7 +91,7 @@ qt_internal_extend_target(InputSupport CONDITION QT_FEATURE_evdev OR QT_FEATURE_
|
|||||||
SOURCES
|
SOURCES
|
||||||
shared/devicehandlerlist_p.h
|
shared/devicehandlerlist_p.h
|
||||||
shared/qevdevutil.cpp shared/qevdevutil_p.h
|
shared/qevdevutil.cpp shared/qevdevutil_p.h
|
||||||
shared/qtouchoutputmapping.cpp shared/qtouchoutputmapping_p.h
|
shared/qoutputmapping.cpp shared/qoutputmapping_p.h
|
||||||
)
|
)
|
||||||
|
|
||||||
qt_internal_extend_target(InputSupport CONDITION QT_FEATURE_integrityhid
|
qt_internal_extend_target(InputSupport CONDITION QT_FEATURE_integrityhid
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "qevdevkeyboardhandler_p.h"
|
#include "qevdevkeyboardhandler_p.h"
|
||||||
|
#include "qoutputmapping_p.h"
|
||||||
|
|
||||||
#include <qplatformdefs.h>
|
#include <qplatformdefs.h>
|
||||||
|
|
||||||
@ -240,7 +241,11 @@ void QEvdevKeyboardHandler::processKeyEvent(int nativecode, int unicode, int qtc
|
|||||||
if (!autoRepeat)
|
if (!autoRepeat)
|
||||||
QGuiApplicationPrivate::inputDeviceManager()->setKeyboardModifiers(QEvdevKeyboardHandler::toQtModifiers(m_modifiers));
|
QGuiApplicationPrivate::inputDeviceManager()->setKeyboardModifiers(QEvdevKeyboardHandler::toQtModifiers(m_modifiers));
|
||||||
|
|
||||||
QWindowSystemInterface::handleExtendedKeyEvent(0, (isPress ? QEvent::KeyPress : QEvent::KeyRelease),
|
QWindow *window = nullptr;
|
||||||
|
#ifdef Q_OS_WEBOS
|
||||||
|
window = QOutputMapping::get()->windowForDeviceNode(m_device);
|
||||||
|
#endif
|
||||||
|
QWindowSystemInterface::handleExtendedKeyEvent(window, (isPress ? QEvent::KeyPress : QEvent::KeyRelease),
|
||||||
qtcode, modifiers, nativecode + 8, 0, int(modifiers),
|
qtcode, modifiers, nativecode + 8, 0, int(modifiers),
|
||||||
(unicode != 0xffff ) ? QString(QChar(unicode)) : QString(), autoRepeat);
|
(unicode != 0xffff ) ? QString(QChar(unicode)) : QString(), autoRepeat);
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "qevdevtouchhandler_p.h"
|
#include "qevdevtouchhandler_p.h"
|
||||||
#include "qtouchoutputmapping_p.h"
|
#include "qoutputmapping_p.h"
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QSocketNotifier>
|
#include <QSocketNotifier>
|
||||||
@ -350,9 +350,9 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const
|
|||||||
if (inverty)
|
if (inverty)
|
||||||
d->m_rotate *= QTransform::fromTranslate(0.5, 0.5).scale(1.0, -1.0).translate(-0.5, -0.5);
|
d->m_rotate *= QTransform::fromTranslate(0.5, 0.5).scale(1.0, -1.0).translate(-0.5, -0.5);
|
||||||
|
|
||||||
QTouchOutputMapping mapping;
|
QOutputMapping *mapping = QOutputMapping::get();
|
||||||
if (mapping.load()) {
|
d->m_screenName = mapping->screenNameForDeviceNode(d->deviceNode);
|
||||||
d->m_screenName = mapping.screenNameForDeviceNode(d->deviceNode);
|
if (mapping->load()) {
|
||||||
if (!d->m_screenName.isEmpty())
|
if (!d->m_screenName.isEmpty())
|
||||||
qCDebug(qLcEvdevTouch, "evdevtouch: Mapping device %ls to screen %ls",
|
qCDebug(qLcEvdevTouch, "evdevtouch: Mapping device %ls to screen %ls",
|
||||||
qUtf16Printable(d->deviceNode), qUtf16Printable(d->m_screenName));
|
qUtf16Printable(d->deviceNode), qUtf16Printable(d->m_screenName));
|
||||||
@ -728,7 +728,7 @@ QRect QEvdevTouchScreenData::screenGeometry() const
|
|||||||
// suddenly it was all broken.
|
// suddenly it was all broken.
|
||||||
//
|
//
|
||||||
// For now we only support the display configuration of the KMS/DRM
|
// For now we only support the display configuration of the KMS/DRM
|
||||||
// backends of eglfs. See QTouchOutputMapping.
|
// backends of eglfs. See QOutputMapping.
|
||||||
//
|
//
|
||||||
// The good news it that once winRect refers to the correct screen
|
// The good news it that once winRect refers to the correct screen
|
||||||
// geometry in the full virtual desktop space, there is nothing else
|
// geometry in the full virtual desktop space, there is nothing else
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "qlibinputtouch_p.h"
|
#include "qlibinputtouch_p.h"
|
||||||
#include "qtouchoutputmapping_p.h"
|
#include "qoutputmapping_p.h"
|
||||||
#include <libinput.h>
|
#include <libinput.h>
|
||||||
#include <QtGui/QGuiApplication>
|
#include <QtGui/QGuiApplication>
|
||||||
#include <QtGui/QPointingDevice>
|
#include <QtGui/QPointingDevice>
|
||||||
@ -68,9 +68,8 @@ QLibInputTouch::DeviceState *QLibInputTouch::deviceState(libinput_event_touch *e
|
|||||||
return &m_devState[dev];
|
return &m_devState[dev];
|
||||||
}
|
}
|
||||||
|
|
||||||
QPointF QLibInputTouch::getPos(libinput_event_touch *e)
|
QRect QLibInputTouch::screenGeometry(DeviceState *state)
|
||||||
{
|
{
|
||||||
DeviceState *state = deviceState(e);
|
|
||||||
QScreen *screen = QGuiApplication::primaryScreen();
|
QScreen *screen = QGuiApplication::primaryScreen();
|
||||||
if (!state->m_screenName.isEmpty()) {
|
if (!state->m_screenName.isEmpty()) {
|
||||||
if (!m_screen) {
|
if (!m_screen) {
|
||||||
@ -85,7 +84,13 @@ QPointF QLibInputTouch::getPos(libinput_event_touch *e)
|
|||||||
if (m_screen)
|
if (m_screen)
|
||||||
screen = m_screen;
|
screen = m_screen;
|
||||||
}
|
}
|
||||||
const QRect geom = QHighDpi::toNativePixels(screen->geometry(), screen);
|
return QHighDpi::toNativePixels(screen->geometry(), screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPointF QLibInputTouch::getPos(libinput_event_touch *e)
|
||||||
|
{
|
||||||
|
DeviceState *state = deviceState(e);
|
||||||
|
QRect geom = screenGeometry(state);
|
||||||
const double x = libinput_event_touch_get_x_transformed(e, geom.width());
|
const double x = libinput_event_touch_get_x_transformed(e, geom.width());
|
||||||
const double y = libinput_event_touch_get_y_transformed(e, geom.height());
|
const double y = libinput_event_touch_get_y_transformed(e, geom.height());
|
||||||
return geom.topLeft() + QPointF(x, y);
|
return geom.topLeft() + QPointF(x, y);
|
||||||
@ -101,19 +106,26 @@ void QLibInputTouch::registerDevice(libinput_device *dev)
|
|||||||
qCDebug(qLcLibInput, "libinput: registerDevice %s - %s",
|
qCDebug(qLcLibInput, "libinput: registerDevice %s - %s",
|
||||||
qPrintable(devNode), qPrintable(devName));
|
qPrintable(devNode), qPrintable(devName));
|
||||||
|
|
||||||
QTouchOutputMapping mapping;
|
QOutputMapping *mapping = QOutputMapping::get();
|
||||||
if (mapping.load()) {
|
QRect geom;
|
||||||
m_devState[dev].m_screenName = mapping.screenNameForDeviceNode(devNode);
|
if (mapping->load()) {
|
||||||
if (!m_devState[dev].m_screenName.isEmpty())
|
m_devState[dev].m_screenName = mapping->screenNameForDeviceNode(devNode);
|
||||||
qCDebug(qLcLibInput, "libinput: Mapping device %s to screen %s",
|
if (!m_devState[dev].m_screenName.isEmpty()) {
|
||||||
qPrintable(devNode), qPrintable(m_devState[dev].m_screenName));
|
geom = screenGeometry(&m_devState[dev]);
|
||||||
|
qCDebug(qLcLibInput) << "libinput: Mapping device" << devNode
|
||||||
|
<< "to screen" << m_devState[dev].m_screenName
|
||||||
|
<< "with geometry" << geom;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QPointingDevice *&td = m_devState[dev].m_touchDevice;
|
QPointingDevice *&td = m_devState[dev].m_touchDevice;
|
||||||
td = new QPointingDevice(devName, udev_device_get_devnum(udev_device),
|
td = new QPointingDevice(devName, udev_device_get_devnum(udev_device),
|
||||||
QInputDevice::DeviceType::TouchScreen, QPointingDevice::PointerType::Finger,
|
QInputDevice::DeviceType::TouchScreen, QPointingDevice::PointerType::Finger,
|
||||||
QPointingDevice::Capability::Position | QPointingDevice::Capability::Area, 16, 0);
|
QPointingDevice::Capability::Position | QPointingDevice::Capability::Area, 16, 0);
|
||||||
QPointingDevicePrivate::get(td)->busId = QString::fromLocal8Bit(udev_device_get_syspath(udev_device)); // TODO is that the best to choose?
|
auto devPriv = QPointingDevicePrivate::get(td);
|
||||||
|
devPriv->busId = QString::fromLocal8Bit(udev_device_get_syspath(udev_device)); // TODO is that the best to choose?
|
||||||
|
if (!geom.isNull())
|
||||||
|
devPriv->setAvailableVirtualGeometry(geom);
|
||||||
QWindowSystemInterface::registerInputDevice(td);
|
QWindowSystemInterface::registerInputDevice(td);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,6 +83,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
DeviceState *deviceState(libinput_event_touch *e);
|
DeviceState *deviceState(libinput_event_touch *e);
|
||||||
|
QRect screenGeometry(DeviceState *state);
|
||||||
QPointF getPos(libinput_event_touch *e);
|
QPointF getPos(libinput_event_touch *e);
|
||||||
|
|
||||||
QHash<libinput_device *, DeviceState> m_devState;
|
QHash<libinput_device *, DeviceState> m_devState;
|
||||||
|
@ -37,8 +37,9 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "qtouchoutputmapping_p.h"
|
#include "qoutputmapping_p.h"
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QFileInfo>
|
||||||
#include <QVariantMap>
|
#include <QVariantMap>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
@ -46,7 +47,44 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
bool QTouchOutputMapping::load()
|
static QOutputMapping *s_outputMapping = nullptr;
|
||||||
|
|
||||||
|
QOutputMapping *QOutputMapping::get()
|
||||||
|
{
|
||||||
|
if (!s_outputMapping)
|
||||||
|
s_outputMapping = new QDefaultOutputMapping;
|
||||||
|
|
||||||
|
return s_outputMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QOutputMapping::load()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QOutputMapping::screenNameForDeviceNode(const QString &deviceNode)
|
||||||
|
{
|
||||||
|
Q_UNUSED(deviceNode);
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_WEBOS
|
||||||
|
QWindow *QOutputMapping::windowForDeviceNode(const QString &deviceNode)
|
||||||
|
{
|
||||||
|
Q_UNUSED(deviceNode);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QOutputMapping::set(QOutputMapping *mapping)
|
||||||
|
{
|
||||||
|
if (s_outputMapping)
|
||||||
|
delete s_outputMapping;
|
||||||
|
|
||||||
|
s_outputMapping = mapping;
|
||||||
|
}
|
||||||
|
#endif // Q_OS_WEBOS
|
||||||
|
|
||||||
|
bool QDefaultOutputMapping::load()
|
||||||
{
|
{
|
||||||
static QByteArray configFile = qgetenv("QT_QPA_EGLFS_KMS_CONFIG");
|
static QByteArray configFile = qgetenv("QT_QPA_EGLFS_KMS_CONFIG");
|
||||||
if (configFile.isEmpty())
|
if (configFile.isEmpty())
|
||||||
@ -75,15 +113,15 @@ bool QTouchOutputMapping::load()
|
|||||||
qWarning("evdevtouch: Output %d specifies touchDevice but not name, this is wrong", i);
|
qWarning("evdevtouch: Output %d specifies touchDevice but not name, this is wrong", i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const QString &deviceNode = output.value(QStringLiteral("touchDevice")).toString();
|
QFileInfo deviceNode(output.value(QStringLiteral("touchDevice")).toString());
|
||||||
const QString &screenName = output.value(QStringLiteral("name")).toString();
|
const QString &screenName = output.value(QStringLiteral("name")).toString();
|
||||||
m_screenTable.insert(deviceNode, screenName);
|
m_screenTable.insert(deviceNode.canonicalFilePath(), screenName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QTouchOutputMapping::screenNameForDeviceNode(const QString &deviceNode)
|
QString QDefaultOutputMapping::screenNameForDeviceNode(const QString &deviceNode)
|
||||||
{
|
{
|
||||||
return m_screenTable.value(deviceNode);
|
return m_screenTable.value(deviceNode);
|
||||||
}
|
}
|
@ -37,8 +37,8 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifndef QTOUCHOUTPUTMAPPING_P_H
|
#ifndef QOUTPUTMAPPING_P_H
|
||||||
#define QTOUCHOUTPUTMAPPING_P_H
|
#define QOUTPUTMAPPING_P_H
|
||||||
|
|
||||||
//
|
//
|
||||||
// W A R N I N G
|
// W A R N I N G
|
||||||
@ -56,11 +56,28 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QTouchOutputMapping
|
class QWindow;
|
||||||
|
|
||||||
|
class QOutputMapping
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool load();
|
virtual ~QOutputMapping() {}
|
||||||
QString screenNameForDeviceNode(const QString &deviceNode);
|
|
||||||
|
static QOutputMapping *get();
|
||||||
|
virtual bool load();
|
||||||
|
virtual QString screenNameForDeviceNode(const QString &deviceNode);
|
||||||
|
|
||||||
|
#ifdef Q_OS_WEBOS
|
||||||
|
virtual QWindow *windowForDeviceNode(const QString &deviceNode);
|
||||||
|
static void set(QOutputMapping *mapping);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
class QDefaultOutputMapping : public QOutputMapping
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool load() override;
|
||||||
|
QString screenNameForDeviceNode(const QString &deviceNode) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QHash<QString, QString> m_screenTable;
|
QHash<QString, QString> m_screenTable;
|
||||||
@ -68,4 +85,4 @@ private:
|
|||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QTOUCHOUTPUTMAPPING_P_H
|
#endif // QOUTPUTMAPPING_P_H
|
@ -1,8 +1,8 @@
|
|||||||
HEADERS += \
|
HEADERS += \
|
||||||
$$PWD/devicehandlerlist_p.h \
|
$$PWD/devicehandlerlist_p.h \
|
||||||
$$PWD/qevdevutil_p.h \
|
$$PWD/qevdevutil_p.h \
|
||||||
$$PWD/qtouchoutputmapping_p.h
|
$$PWD/qoutputmapping_p.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
$$PWD/qevdevutil.cpp \
|
$$PWD/qevdevutil.cpp \
|
||||||
$$PWD/qtouchoutputmapping.cpp
|
$$PWD/qoutputmapping.cpp
|
||||||
|
Loading…
x
Reference in New Issue
Block a user