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
|
||||
shared/devicehandlerlist_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
|
||||
|
@ -38,6 +38,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "qevdevkeyboardhandler_p.h"
|
||||
#include "qoutputmapping_p.h"
|
||||
|
||||
#include <qplatformdefs.h>
|
||||
|
||||
@ -240,7 +241,11 @@ void QEvdevKeyboardHandler::processKeyEvent(int nativecode, int unicode, int qtc
|
||||
if (!autoRepeat)
|
||||
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),
|
||||
(unicode != 0xffff ) ? QString(QChar(unicode)) : QString(), autoRepeat);
|
||||
}
|
||||
|
@ -39,7 +39,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "qevdevtouchhandler_p.h"
|
||||
#include "qtouchoutputmapping_p.h"
|
||||
#include "qoutputmapping_p.h"
|
||||
#include <QStringList>
|
||||
#include <QHash>
|
||||
#include <QSocketNotifier>
|
||||
@ -350,9 +350,9 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const
|
||||
if (inverty)
|
||||
d->m_rotate *= QTransform::fromTranslate(0.5, 0.5).scale(1.0, -1.0).translate(-0.5, -0.5);
|
||||
|
||||
QTouchOutputMapping mapping;
|
||||
if (mapping.load()) {
|
||||
d->m_screenName = mapping.screenNameForDeviceNode(d->deviceNode);
|
||||
QOutputMapping *mapping = QOutputMapping::get();
|
||||
d->m_screenName = mapping->screenNameForDeviceNode(d->deviceNode);
|
||||
if (mapping->load()) {
|
||||
if (!d->m_screenName.isEmpty())
|
||||
qCDebug(qLcEvdevTouch, "evdevtouch: Mapping device %ls to screen %ls",
|
||||
qUtf16Printable(d->deviceNode), qUtf16Printable(d->m_screenName));
|
||||
@ -728,7 +728,7 @@ QRect QEvdevTouchScreenData::screenGeometry() const
|
||||
// suddenly it was all broken.
|
||||
//
|
||||
// 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
|
||||
// geometry in the full virtual desktop space, there is nothing else
|
||||
|
@ -38,7 +38,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "qlibinputtouch_p.h"
|
||||
#include "qtouchoutputmapping_p.h"
|
||||
#include "qoutputmapping_p.h"
|
||||
#include <libinput.h>
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QPointingDevice>
|
||||
@ -68,9 +68,8 @@ QLibInputTouch::DeviceState *QLibInputTouch::deviceState(libinput_event_touch *e
|
||||
return &m_devState[dev];
|
||||
}
|
||||
|
||||
QPointF QLibInputTouch::getPos(libinput_event_touch *e)
|
||||
QRect QLibInputTouch::screenGeometry(DeviceState *state)
|
||||
{
|
||||
DeviceState *state = deviceState(e);
|
||||
QScreen *screen = QGuiApplication::primaryScreen();
|
||||
if (!state->m_screenName.isEmpty()) {
|
||||
if (!m_screen) {
|
||||
@ -85,7 +84,13 @@ QPointF QLibInputTouch::getPos(libinput_event_touch *e)
|
||||
if (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 y = libinput_event_touch_get_y_transformed(e, geom.height());
|
||||
return geom.topLeft() + QPointF(x, y);
|
||||
@ -101,19 +106,26 @@ void QLibInputTouch::registerDevice(libinput_device *dev)
|
||||
qCDebug(qLcLibInput, "libinput: registerDevice %s - %s",
|
||||
qPrintable(devNode), qPrintable(devName));
|
||||
|
||||
QTouchOutputMapping mapping;
|
||||
if (mapping.load()) {
|
||||
m_devState[dev].m_screenName = mapping.screenNameForDeviceNode(devNode);
|
||||
if (!m_devState[dev].m_screenName.isEmpty())
|
||||
qCDebug(qLcLibInput, "libinput: Mapping device %s to screen %s",
|
||||
qPrintable(devNode), qPrintable(m_devState[dev].m_screenName));
|
||||
QOutputMapping *mapping = QOutputMapping::get();
|
||||
QRect geom;
|
||||
if (mapping->load()) {
|
||||
m_devState[dev].m_screenName = mapping->screenNameForDeviceNode(devNode);
|
||||
if (!m_devState[dev].m_screenName.isEmpty()) {
|
||||
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;
|
||||
td = new QPointingDevice(devName, udev_device_get_devnum(udev_device),
|
||||
QInputDevice::DeviceType::TouchScreen, QPointingDevice::PointerType::Finger,
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -83,6 +83,7 @@ private:
|
||||
};
|
||||
|
||||
DeviceState *deviceState(libinput_event_touch *e);
|
||||
QRect screenGeometry(DeviceState *state);
|
||||
QPointF getPos(libinput_event_touch *e);
|
||||
|
||||
QHash<libinput_device *, DeviceState> m_devState;
|
||||
|
@ -37,8 +37,9 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qtouchoutputmapping_p.h"
|
||||
#include "qoutputmapping_p.h"
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QVariantMap>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
@ -46,7 +47,44 @@
|
||||
|
||||
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");
|
||||
if (configFile.isEmpty())
|
||||
@ -75,15 +113,15 @@ bool QTouchOutputMapping::load()
|
||||
qWarning("evdevtouch: Output %d specifies touchDevice but not name, this is wrong", i);
|
||||
continue;
|
||||
}
|
||||
const QString &deviceNode = output.value(QStringLiteral("touchDevice")).toString();
|
||||
QFileInfo deviceNode(output.value(QStringLiteral("touchDevice")).toString());
|
||||
const QString &screenName = output.value(QStringLiteral("name")).toString();
|
||||
m_screenTable.insert(deviceNode, screenName);
|
||||
m_screenTable.insert(deviceNode.canonicalFilePath(), screenName);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QString QTouchOutputMapping::screenNameForDeviceNode(const QString &deviceNode)
|
||||
QString QDefaultOutputMapping::screenNameForDeviceNode(const QString &deviceNode)
|
||||
{
|
||||
return m_screenTable.value(deviceNode);
|
||||
}
|
@ -37,8 +37,8 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QTOUCHOUTPUTMAPPING_P_H
|
||||
#define QTOUCHOUTPUTMAPPING_P_H
|
||||
#ifndef QOUTPUTMAPPING_P_H
|
||||
#define QOUTPUTMAPPING_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
@ -56,11 +56,28 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QTouchOutputMapping
|
||||
class QWindow;
|
||||
|
||||
class QOutputMapping
|
||||
{
|
||||
public:
|
||||
bool load();
|
||||
QString screenNameForDeviceNode(const QString &deviceNode);
|
||||
virtual ~QOutputMapping() {}
|
||||
|
||||
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:
|
||||
QHash<QString, QString> m_screenTable;
|
||||
@ -68,4 +85,4 @@ private:
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QTOUCHOUTPUTMAPPING_P_H
|
||||
#endif // QOUTPUTMAPPING_P_H
|
@ -1,8 +1,8 @@
|
||||
HEADERS += \
|
||||
$$PWD/devicehandlerlist_p.h \
|
||||
$$PWD/qevdevutil_p.h \
|
||||
$$PWD/qtouchoutputmapping_p.h
|
||||
$$PWD/qoutputmapping_p.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/qevdevutil.cpp \
|
||||
$$PWD/qtouchoutputmapping.cpp
|
||||
$$PWD/qoutputmapping.cpp
|
||||
|
Loading…
x
Reference in New Issue
Block a user