xcb: don't keep objects for disconnected touch devices
... as XI2 reuses device ids and we might end up with some bogus objects in m_touchDevices (the same touch device after reconnecting might have a new device id). With this patch, m_touchDevices is handled similarly to tablets and scolling devices. This patch also removes unnecessary calls to X (XIQueryDevice). We already have device information available for all devices when populating m_touchDevices list, so calling XIQueryDevice again for every device id (which we haven't already concluded to be a tablet device) is a redundant round trip to X. For consistency with other device types, extend touch device data structure to store the necessary device details, instead of holding pointers to XIDeviceInfo. And allocate touch device objects on stack instead of heap, also for the consistency reasons (this way we won't need to special case m_touchDevices when running some management task on _all_ devices, e.g. removing a device with id=n when it was disconnected). Change-Id: I9f6edfaf24da911dd21ec45cd48dfdd6d0dcdf8b Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
This commit is contained in:
parent
545458cb77
commit
7499d4404f
@ -646,11 +646,6 @@ QXcbConnection::~QXcbConnection()
|
|||||||
#ifndef QT_NO_DRAGANDDROP
|
#ifndef QT_NO_DRAGANDDROP
|
||||||
delete m_drag;
|
delete m_drag;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if QT_CONFIG(xinput2)
|
|
||||||
finalizeXInput2();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (m_reader->isRunning()) {
|
if (m_reader->isRunning()) {
|
||||||
sendConnectionEvent(QXcbAtom::_QT_CLOSE_CONNECTION);
|
sendConnectionEvent(QXcbAtom::_QT_CLOSE_CONNECTION);
|
||||||
m_reader->wait();
|
m_reader->wait();
|
||||||
|
@ -79,7 +79,6 @@
|
|||||||
#define XCB_USE_XINPUT22 // XI 2.2 adds multi-point touch support
|
#define XCB_USE_XINPUT22 // XI 2.2 adds multi-point touch support
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
struct XInput2TouchDeviceData;
|
|
||||||
#endif // QT_CONFIG(xinput2)
|
#endif // QT_CONFIG(xinput2)
|
||||||
|
|
||||||
struct xcb_randr_get_output_info_reply_t;
|
struct xcb_randr_get_output_info_reply_t;
|
||||||
@ -518,7 +517,7 @@ public:
|
|||||||
|
|
||||||
#ifdef XCB_USE_XINPUT22
|
#ifdef XCB_USE_XINPUT22
|
||||||
bool xi2MouseEvents() const;
|
bool xi2MouseEvents() const;
|
||||||
bool isTouchScreen(int id) const;
|
bool isTouchScreen(int id);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -556,9 +555,27 @@ private:
|
|||||||
bool m_xi2Enabled = false;
|
bool m_xi2Enabled = false;
|
||||||
int m_xi2Minor = 2;
|
int m_xi2Minor = 2;
|
||||||
void initializeXInput2();
|
void initializeXInput2();
|
||||||
void finalizeXInput2();
|
|
||||||
void xi2SetupDevices();
|
void xi2SetupDevices();
|
||||||
XInput2TouchDeviceData *touchDeviceForId(int id);
|
struct TouchDeviceData {
|
||||||
|
QTouchDevice *qtTouchDevice = nullptr;
|
||||||
|
QHash<int, QWindowSystemInterface::TouchPoint> touchPoints;
|
||||||
|
QHash<int, QPointF> pointPressedPosition; // in screen coordinates where each point was pressed
|
||||||
|
struct ValuatorClassInfo {
|
||||||
|
double min = 0;
|
||||||
|
double max = 0;
|
||||||
|
int number = -1;
|
||||||
|
QXcbAtom::Atom label;
|
||||||
|
};
|
||||||
|
QVector<ValuatorClassInfo> valuatorInfo;
|
||||||
|
|
||||||
|
// Stuff that is relevant only for touchpads
|
||||||
|
QPointF firstPressedPosition; // in screen coordinates where the first point was pressed
|
||||||
|
QPointF firstPressedNormalPosition; // device coordinates (0 to 1, 0 to 1) where the first point was pressed
|
||||||
|
QSizeF size; // device size in mm
|
||||||
|
bool providesTouchOrientation = false;
|
||||||
|
};
|
||||||
|
TouchDeviceData *populateTouchDevices(void *info);
|
||||||
|
TouchDeviceData *touchDeviceForId(int id);
|
||||||
void xi2HandleEvent(xcb_ge_event_t *event);
|
void xi2HandleEvent(xcb_ge_event_t *event);
|
||||||
void xi2HandleHierachyEvent(void *event);
|
void xi2HandleHierachyEvent(void *event);
|
||||||
void xi2HandleDeviceChangedEvent(void *event);
|
void xi2HandleDeviceChangedEvent(void *event);
|
||||||
@ -637,8 +654,9 @@ private:
|
|||||||
void *m_xlib_display = nullptr;
|
void *m_xlib_display = nullptr;
|
||||||
#endif
|
#endif
|
||||||
QXcbEventReader *m_reader = nullptr;
|
QXcbEventReader *m_reader = nullptr;
|
||||||
|
|
||||||
#if QT_CONFIG(xinput2)
|
#if QT_CONFIG(xinput2)
|
||||||
QHash<int, XInput2TouchDeviceData*> m_touchDevices;
|
QHash<int, TouchDeviceData> m_touchDevices;
|
||||||
#ifdef XCB_USE_XINPUT22
|
#ifdef XCB_USE_XINPUT22
|
||||||
struct StartSystemResizeInfo {
|
struct StartSystemResizeInfo {
|
||||||
xcb_window_t window;
|
xcb_window_t window;
|
||||||
|
@ -50,19 +50,6 @@
|
|||||||
#include <X11/extensions/XInput2.h>
|
#include <X11/extensions/XInput2.h>
|
||||||
#include <X11/extensions/XI2proto.h>
|
#include <X11/extensions/XI2proto.h>
|
||||||
|
|
||||||
struct XInput2TouchDeviceData {
|
|
||||||
XIDeviceInfo *xiDeviceInfo = nullptr;
|
|
||||||
QTouchDevice *qtTouchDevice = nullptr;
|
|
||||||
QHash<int, QWindowSystemInterface::TouchPoint> touchPoints;
|
|
||||||
QHash<int, QPointF> pointPressedPosition; // in screen coordinates where each point was pressed
|
|
||||||
|
|
||||||
// Stuff that is relevant only for touchpads
|
|
||||||
QPointF firstPressedPosition; // in screen coordinates where the first point was pressed
|
|
||||||
QPointF firstPressedNormalPosition; // device coordinates (0 to 1, 0 to 1) where the first point was pressed
|
|
||||||
QSizeF size; // device size in mm
|
|
||||||
bool providesTouchOrientation = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
void QXcbConnection::initializeXInput2()
|
void QXcbConnection::initializeXInput2()
|
||||||
{
|
{
|
||||||
// TODO Qt 6 (or perhaps earlier): remove these redundant env variables
|
// TODO Qt 6 (or perhaps earlier): remove these redundant env variables
|
||||||
@ -102,6 +89,7 @@ void QXcbConnection::xi2SetupDevices()
|
|||||||
m_tabletData.clear();
|
m_tabletData.clear();
|
||||||
#endif
|
#endif
|
||||||
m_scrollingDevices.clear();
|
m_scrollingDevices.clear();
|
||||||
|
m_touchDevices.clear();
|
||||||
|
|
||||||
if (!m_xi2Enabled)
|
if (!m_xi2Enabled)
|
||||||
return;
|
return;
|
||||||
@ -119,9 +107,10 @@ void QXcbConnection::xi2SetupDevices()
|
|||||||
#endif
|
#endif
|
||||||
ScrollingDevice scrollingDevice;
|
ScrollingDevice scrollingDevice;
|
||||||
for (int c = 0; c < devices[i].num_classes; ++c) {
|
for (int c = 0; c < devices[i].num_classes; ++c) {
|
||||||
switch (devices[i].classes[c]->type) {
|
XIAnyClassInfo *classinfo = devices[i].classes[c];
|
||||||
|
switch (classinfo->type) {
|
||||||
case XIValuatorClass: {
|
case XIValuatorClass: {
|
||||||
XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(devices[i].classes[c]);
|
XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
|
||||||
const int valuatorAtom = qatom(vci->label);
|
const int valuatorAtom = qatom(vci->label);
|
||||||
qCDebug(lcQpaXInputDevices) << " has valuator" << atomName(vci->label) << "recognized?" << (valuatorAtom < QXcbAtom::NAtoms);
|
qCDebug(lcQpaXInputDevices) << " has valuator" << atomName(vci->label) << "recognized?" << (valuatorAtom < QXcbAtom::NAtoms);
|
||||||
#if QT_CONFIG(tabletevent)
|
#if QT_CONFIG(tabletevent)
|
||||||
@ -141,7 +130,7 @@ void QXcbConnection::xi2SetupDevices()
|
|||||||
}
|
}
|
||||||
#ifdef XCB_USE_XINPUT21
|
#ifdef XCB_USE_XINPUT21
|
||||||
case XIScrollClass: {
|
case XIScrollClass: {
|
||||||
XIScrollClassInfo *sci = reinterpret_cast<XIScrollClassInfo *>(devices[i].classes[c]);
|
XIScrollClassInfo *sci = reinterpret_cast<XIScrollClassInfo *>(classinfo);
|
||||||
if (sci->scroll_type == XIScrollTypeVertical) {
|
if (sci->scroll_type == XIScrollTypeVertical) {
|
||||||
scrollingDevice.orientations |= Qt::Vertical;
|
scrollingDevice.orientations |= Qt::Vertical;
|
||||||
scrollingDevice.verticalIndex = sci->number;
|
scrollingDevice.verticalIndex = sci->number;
|
||||||
@ -155,7 +144,7 @@ void QXcbConnection::xi2SetupDevices()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case XIButtonClass: {
|
case XIButtonClass: {
|
||||||
XIButtonClassInfo *bci = reinterpret_cast<XIButtonClassInfo *>(devices[i].classes[c]);
|
XIButtonClassInfo *bci = reinterpret_cast<XIButtonClassInfo *>(classinfo);
|
||||||
if (bci->num_buttons >= 5) {
|
if (bci->num_buttons >= 5) {
|
||||||
Atom label4 = bci->labels[3];
|
Atom label4 = bci->labels[3];
|
||||||
Atom label5 = bci->labels[4];
|
Atom label5 = bci->labels[4];
|
||||||
@ -180,11 +169,11 @@ void QXcbConnection::xi2SetupDevices()
|
|||||||
break;
|
break;
|
||||||
#ifdef XCB_USE_XINPUT22
|
#ifdef XCB_USE_XINPUT22
|
||||||
case XITouchClass:
|
case XITouchClass:
|
||||||
// will be handled in deviceForId()
|
// will be handled in populateTouchDevices()
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
qCDebug(lcQpaXInputDevices) << " has class" << devices[i].classes[c]->type;
|
qCDebug(lcQpaXInputDevices) << " has class" << classinfo->type;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -252,9 +241,7 @@ void QXcbConnection::xi2SetupDevices()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!isTablet) {
|
if (!isTablet) {
|
||||||
// touchDeviceForId populates XInput2DeviceData the first time it is called
|
TouchDeviceData *dev = populateTouchDevices(&devices[i]);
|
||||||
// with a new deviceId. On subsequent calls it will return the cached object.
|
|
||||||
XInput2TouchDeviceData *dev = touchDeviceForId(devices[i].deviceid);
|
|
||||||
if (dev && lcQpaXInputDevices().isDebugEnabled()) {
|
if (dev && lcQpaXInputDevices().isDebugEnabled()) {
|
||||||
if (dev->qtTouchDevice->type() == QTouchDevice::TouchScreen)
|
if (dev->qtTouchDevice->type() == QTouchDevice::TouchScreen)
|
||||||
qCDebug(lcQpaXInputDevices, " it's a touchscreen with type %d capabilities 0x%X max touch points %d",
|
qCDebug(lcQpaXInputDevices, " it's a touchscreen with type %d capabilities 0x%X max touch points %d",
|
||||||
@ -271,15 +258,6 @@ void QXcbConnection::xi2SetupDevices()
|
|||||||
XIFreeDeviceInfo(devices);
|
XIFreeDeviceInfo(devices);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QXcbConnection::finalizeXInput2()
|
|
||||||
{
|
|
||||||
for (XInput2TouchDeviceData *dev : qAsConst(m_touchDevices)) {
|
|
||||||
if (dev->xiDeviceInfo)
|
|
||||||
XIFreeDeviceInfo(dev->xiDeviceInfo);
|
|
||||||
delete dev;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QXcbConnection::xi2Select(xcb_window_t window)
|
void QXcbConnection::xi2Select(xcb_window_t window)
|
||||||
{
|
{
|
||||||
if (!m_xi2Enabled || window == rootWindow())
|
if (!m_xi2Enabled || window == rootWindow())
|
||||||
@ -384,100 +362,105 @@ void QXcbConnection::xi2Select(xcb_window_t window)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
|
QXcbConnection::TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
|
||||||
{
|
{
|
||||||
XInput2TouchDeviceData *dev = Q_NULLPTR;
|
TouchDeviceData *dev = nullptr;
|
||||||
QHash<int, XInput2TouchDeviceData*>::const_iterator devIt = m_touchDevices.constFind(id);
|
if (m_touchDevices.contains(id))
|
||||||
if (devIt != m_touchDevices.cend()) {
|
dev = &m_touchDevices[id];
|
||||||
dev = devIt.value();
|
return dev;
|
||||||
} else {
|
}
|
||||||
int nrDevices = 0;
|
|
||||||
QTouchDevice::Capabilities caps = 0;
|
|
||||||
dev = new XInput2TouchDeviceData;
|
|
||||||
dev->xiDeviceInfo = XIQueryDevice(static_cast<Display *>(m_xlib_display), id, &nrDevices);
|
|
||||||
if (nrDevices <= 0) {
|
|
||||||
delete dev;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int type = -1;
|
|
||||||
int maxTouchPoints = 1;
|
|
||||||
bool hasRelativeCoords = false;
|
|
||||||
for (int i = 0; i < dev->xiDeviceInfo->num_classes; ++i) {
|
|
||||||
XIAnyClassInfo *classinfo = dev->xiDeviceInfo->classes[i];
|
|
||||||
switch (classinfo->type) {
|
|
||||||
#ifdef XCB_USE_XINPUT22
|
|
||||||
case XITouchClass: {
|
|
||||||
XITouchClassInfo *tci = reinterpret_cast<XITouchClassInfo *>(classinfo);
|
|
||||||
maxTouchPoints = tci->num_touches;
|
|
||||||
qCDebug(lcQpaXInputDevices, " has touch class with mode %d", tci->mode);
|
|
||||||
switch (tci->mode) {
|
|
||||||
case XIDependentTouch:
|
|
||||||
type = QTouchDevice::TouchPad;
|
|
||||||
break;
|
|
||||||
case XIDirectTouch:
|
|
||||||
type = QTouchDevice::TouchScreen;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif // XCB_USE_XINPUT22
|
|
||||||
case XIValuatorClass: {
|
|
||||||
XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
|
|
||||||
// Some devices (mice) report a resolution of 0; they will be excluded later,
|
|
||||||
// for now just prevent a division by zero
|
|
||||||
const int vciResolution = vci->resolution ? vci->resolution : 1;
|
|
||||||
if (vci->label == atom(QXcbAtom::AbsMTPositionX))
|
|
||||||
caps |= QTouchDevice::Position | QTouchDevice::NormalizedPosition;
|
|
||||||
else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor))
|
|
||||||
caps |= QTouchDevice::Area;
|
|
||||||
else if (vci->label == atom(QXcbAtom::AbsMTOrientation))
|
|
||||||
dev->providesTouchOrientation = true;
|
|
||||||
else if (vci->label == atom(QXcbAtom::AbsMTPressure) || vci->label == atom(QXcbAtom::AbsPressure))
|
|
||||||
caps |= QTouchDevice::Pressure;
|
|
||||||
else if (vci->label == atom(QXcbAtom::RelX)) {
|
|
||||||
hasRelativeCoords = true;
|
|
||||||
dev->size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution);
|
|
||||||
} else if (vci->label == atom(QXcbAtom::RelY)) {
|
|
||||||
hasRelativeCoords = true;
|
|
||||||
dev->size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution);
|
|
||||||
} else if (vci->label == atom(QXcbAtom::AbsX)) {
|
|
||||||
caps |= QTouchDevice::Position;
|
|
||||||
dev->size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution);
|
|
||||||
} else if (vci->label == atom(QXcbAtom::AbsY)) {
|
|
||||||
caps |= QTouchDevice::Position;
|
|
||||||
dev->size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (type < 0 && caps && hasRelativeCoords) {
|
|
||||||
type = QTouchDevice::TouchPad;
|
|
||||||
if (dev->size.width() < 10 || dev->size.height() < 10 ||
|
|
||||||
dev->size.width() > 10000 || dev->size.height() > 10000)
|
|
||||||
dev->size = QSizeF(130, 110);
|
|
||||||
}
|
|
||||||
if (!isAtLeastXI22() || type == QTouchDevice::TouchPad)
|
|
||||||
caps |= QTouchDevice::MouseEmulation;
|
|
||||||
|
|
||||||
if (type >= QTouchDevice::TouchScreen && type <= QTouchDevice::TouchPad) {
|
QXcbConnection::TouchDeviceData *QXcbConnection::populateTouchDevices(void *info)
|
||||||
dev->qtTouchDevice = new QTouchDevice;
|
{
|
||||||
dev->qtTouchDevice->setName(QString::fromUtf8(dev->xiDeviceInfo->name));
|
XIDeviceInfo *deviceinfo = reinterpret_cast<XIDeviceInfo *>(info);
|
||||||
dev->qtTouchDevice->setType((QTouchDevice::DeviceType)type);
|
QTouchDevice::Capabilities caps = 0;
|
||||||
dev->qtTouchDevice->setCapabilities(caps);
|
int type = -1;
|
||||||
dev->qtTouchDevice->setMaximumTouchPoints(maxTouchPoints);
|
int maxTouchPoints = 1;
|
||||||
if (caps != 0)
|
bool isTouchDevice = false;
|
||||||
QWindowSystemInterface::registerTouchDevice(dev->qtTouchDevice);
|
bool hasRelativeCoords = false;
|
||||||
m_touchDevices[id] = dev;
|
TouchDeviceData dev;
|
||||||
} else {
|
for (int i = 0; i < deviceinfo->num_classes; ++i) {
|
||||||
XIFreeDeviceInfo(dev->xiDeviceInfo);
|
XIAnyClassInfo *classinfo = deviceinfo->classes[i];
|
||||||
delete dev;
|
switch (classinfo->type) {
|
||||||
dev = 0;
|
#ifdef XCB_USE_XINPUT22
|
||||||
|
case XITouchClass: {
|
||||||
|
XITouchClassInfo *tci = reinterpret_cast<XITouchClassInfo *>(classinfo);
|
||||||
|
maxTouchPoints = tci->num_touches;
|
||||||
|
qCDebug(lcQpaXInputDevices, " has touch class with mode %d", tci->mode);
|
||||||
|
switch (tci->mode) {
|
||||||
|
case XIDependentTouch:
|
||||||
|
type = QTouchDevice::TouchPad;
|
||||||
|
break;
|
||||||
|
case XIDirectTouch:
|
||||||
|
type = QTouchDevice::TouchScreen;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif // XCB_USE_XINPUT22
|
||||||
|
case XIValuatorClass: {
|
||||||
|
XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
|
||||||
|
const QXcbAtom::Atom valuatorAtom = qatom(vci->label);
|
||||||
|
if (valuatorAtom < QXcbAtom::NAtoms) {
|
||||||
|
TouchDeviceData::ValuatorClassInfo info;
|
||||||
|
info.min = vci->min;
|
||||||
|
info.max = vci->max;
|
||||||
|
info.number = vci->number;
|
||||||
|
info.label = valuatorAtom;
|
||||||
|
dev.valuatorInfo.append(info);
|
||||||
|
}
|
||||||
|
// Some devices (mice) report a resolution of 0; they will be excluded later,
|
||||||
|
// for now just prevent a division by zero
|
||||||
|
const int vciResolution = vci->resolution ? vci->resolution : 1;
|
||||||
|
if (valuatorAtom == QXcbAtom::AbsMTPositionX)
|
||||||
|
caps |= QTouchDevice::Position | QTouchDevice::NormalizedPosition;
|
||||||
|
else if (valuatorAtom == QXcbAtom::AbsMTTouchMajor)
|
||||||
|
caps |= QTouchDevice::Area;
|
||||||
|
else if (valuatorAtom == QXcbAtom::AbsMTOrientation)
|
||||||
|
dev.providesTouchOrientation = true;
|
||||||
|
else if (valuatorAtom == QXcbAtom::AbsMTPressure || valuatorAtom == QXcbAtom::AbsPressure)
|
||||||
|
caps |= QTouchDevice::Pressure;
|
||||||
|
else if (valuatorAtom == QXcbAtom::RelX) {
|
||||||
|
hasRelativeCoords = true;
|
||||||
|
dev.size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution);
|
||||||
|
} else if (valuatorAtom == QXcbAtom::RelY) {
|
||||||
|
hasRelativeCoords = true;
|
||||||
|
dev.size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution);
|
||||||
|
} else if (valuatorAtom == QXcbAtom::AbsX) {
|
||||||
|
caps |= QTouchDevice::Position;
|
||||||
|
dev.size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution);
|
||||||
|
} else if (valuatorAtom == QXcbAtom::AbsY) {
|
||||||
|
caps |= QTouchDevice::Position;
|
||||||
|
dev.size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dev;
|
if (type < 0 && caps && hasRelativeCoords) {
|
||||||
|
type = QTouchDevice::TouchPad;
|
||||||
|
if (dev.size.width() < 10 || dev.size.height() < 10 ||
|
||||||
|
dev.size.width() > 10000 || dev.size.height() > 10000)
|
||||||
|
dev.size = QSizeF(130, 110);
|
||||||
|
}
|
||||||
|
if (!isAtLeastXI22() || type == QTouchDevice::TouchPad)
|
||||||
|
caps |= QTouchDevice::MouseEmulation;
|
||||||
|
|
||||||
|
if (type >= QTouchDevice::TouchScreen && type <= QTouchDevice::TouchPad) {
|
||||||
|
dev.qtTouchDevice = new QTouchDevice;
|
||||||
|
dev.qtTouchDevice->setName(QString::fromUtf8(deviceinfo->name));
|
||||||
|
dev.qtTouchDevice->setType((QTouchDevice::DeviceType)type);
|
||||||
|
dev.qtTouchDevice->setCapabilities(caps);
|
||||||
|
dev.qtTouchDevice->setMaximumTouchPoints(maxTouchPoints);
|
||||||
|
if (caps != 0)
|
||||||
|
QWindowSystemInterface::registerTouchDevice(dev.qtTouchDevice);
|
||||||
|
m_touchDevices[deviceinfo->deviceid] = dev;
|
||||||
|
isTouchDevice = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isTouchDevice ? &m_touchDevices[deviceinfo->deviceid] : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(XCB_USE_XINPUT21) || QT_CONFIG(tabletevent)
|
#if defined(XCB_USE_XINPUT21) || QT_CONFIG(tabletevent)
|
||||||
@ -582,19 +565,10 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef XCB_USE_XINPUT22
|
#ifdef XCB_USE_XINPUT22
|
||||||
static qreal valuatorNormalized(double value, XIValuatorClassInfo *vci)
|
|
||||||
{
|
|
||||||
if (value > vci->max)
|
|
||||||
value = vci->max;
|
|
||||||
if (value < vci->min)
|
|
||||||
value = vci->min;
|
|
||||||
return (value - vci->min) / (vci->max - vci->min);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindow)
|
void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindow)
|
||||||
{
|
{
|
||||||
xXIDeviceEvent *xiDeviceEvent = static_cast<xXIDeviceEvent *>(xiDevEvent);
|
xXIDeviceEvent *xiDeviceEvent = static_cast<xXIDeviceEvent *>(xiDevEvent);
|
||||||
XInput2TouchDeviceData *dev = touchDeviceForId(xiDeviceEvent->sourceid);
|
TouchDeviceData *dev = touchDeviceForId(xiDeviceEvent->sourceid);
|
||||||
Q_ASSERT(dev);
|
Q_ASSERT(dev);
|
||||||
const bool firstTouch = dev->touchPoints.isEmpty();
|
const bool firstTouch = dev->touchPoints.isEmpty();
|
||||||
if (xiDeviceEvent->evtype == XI_TouchBegin) {
|
if (xiDeviceEvent->evtype == XI_TouchBegin) {
|
||||||
@ -611,53 +585,53 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
|
|||||||
qreal nx = -1.0, ny = -1.0;
|
qreal nx = -1.0, ny = -1.0;
|
||||||
qreal w = 0.0, h = 0.0;
|
qreal w = 0.0, h = 0.0;
|
||||||
bool majorAxisIsY = touchPoint.area.height() > touchPoint.area.width();
|
bool majorAxisIsY = touchPoint.area.height() > touchPoint.area.width();
|
||||||
for (int i = 0; i < dev->xiDeviceInfo->num_classes; ++i) {
|
for (const TouchDeviceData::ValuatorClassInfo vci : dev->valuatorInfo) {
|
||||||
XIAnyClassInfo *classinfo = dev->xiDeviceInfo->classes[i];
|
double value;
|
||||||
if (classinfo->type == XIValuatorClass) {
|
if (!xi2GetValuatorValueIfSet(xiDeviceEvent, vci.number, &value))
|
||||||
XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
|
continue;
|
||||||
int n = vci->number;
|
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
|
||||||
double value;
|
qCDebug(lcQpaXInputEvents, " valuator %20s value %lf from range %lf -> %lf",
|
||||||
if (!xi2GetValuatorValueIfSet(xiDeviceEvent, n, &value))
|
atomName(vci.label).constData(), value, vci.min, vci.max);
|
||||||
continue;
|
if (value > vci.max)
|
||||||
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
|
value = vci.max;
|
||||||
qCDebug(lcQpaXInputEvents, " valuator %20s value %lf from range %lf -> %lf",
|
if (value < vci.min)
|
||||||
atomName(vci->label).constData(), value, vci->min, vci->max );
|
value = vci.min;
|
||||||
if (vci->label == atom(QXcbAtom::RelX)) {
|
qreal valuatorNormalized = (value - vci.min) / (vci.max - vci.min);
|
||||||
nx = valuatorNormalized(value, vci);
|
if (vci.label == QXcbAtom::RelX) {
|
||||||
} else if (vci->label == atom(QXcbAtom::RelY)) {
|
nx = valuatorNormalized;
|
||||||
ny = valuatorNormalized(value, vci);
|
} else if (vci.label == QXcbAtom::RelY) {
|
||||||
} else if (vci->label == atom(QXcbAtom::AbsX)) {
|
ny = valuatorNormalized;
|
||||||
nx = valuatorNormalized(value, vci);
|
} else if (vci.label == QXcbAtom::AbsX) {
|
||||||
} else if (vci->label == atom(QXcbAtom::AbsY)) {
|
nx = valuatorNormalized;
|
||||||
ny = valuatorNormalized(value, vci);
|
} else if (vci.label == QXcbAtom::AbsY) {
|
||||||
} else if (vci->label == atom(QXcbAtom::AbsMTPositionX)) {
|
ny = valuatorNormalized;
|
||||||
nx = valuatorNormalized(value, vci);
|
} else if (vci.label == QXcbAtom::AbsMTPositionX) {
|
||||||
} else if (vci->label == atom(QXcbAtom::AbsMTPositionY)) {
|
nx = valuatorNormalized;
|
||||||
ny = valuatorNormalized(value, vci);
|
} else if (vci.label == QXcbAtom::AbsMTPositionY) {
|
||||||
} else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor)) {
|
ny = valuatorNormalized;
|
||||||
const qreal sw = screen->geometry().width();
|
} else if (vci.label == QXcbAtom::AbsMTTouchMajor) {
|
||||||
const qreal sh = screen->geometry().height();
|
const qreal sw = screen->geometry().width();
|
||||||
w = valuatorNormalized(value, vci) * std::sqrt(sw * sw + sh * sh);
|
const qreal sh = screen->geometry().height();
|
||||||
} else if (vci->label == atom(QXcbAtom::AbsMTTouchMinor)) {
|
w = valuatorNormalized * std::sqrt(sw * sw + sh * sh);
|
||||||
const qreal sw = screen->geometry().width();
|
} else if (vci.label == QXcbAtom::AbsMTTouchMinor) {
|
||||||
const qreal sh = screen->geometry().height();
|
const qreal sw = screen->geometry().width();
|
||||||
h = valuatorNormalized(value, vci) * std::sqrt(sw * sw + sh * sh);
|
const qreal sh = screen->geometry().height();
|
||||||
} else if (vci->label == atom(QXcbAtom::AbsMTOrientation)) {
|
h = valuatorNormalized * std::sqrt(sw * sw + sh * sh);
|
||||||
// Find the closest axis.
|
} else if (vci.label == QXcbAtom::AbsMTOrientation) {
|
||||||
// 0 corresponds to the Y axis, vci->max to the X axis.
|
// Find the closest axis.
|
||||||
// Flipping over the Y axis and rotating by 180 degrees
|
// 0 corresponds to the Y axis, vci.max to the X axis.
|
||||||
// don't change the result, so normalize value to range
|
// Flipping over the Y axis and rotating by 180 degrees
|
||||||
// [0, vci->max] first.
|
// don't change the result, so normalize value to range
|
||||||
value = qAbs(value);
|
// [0, vci.max] first.
|
||||||
while (value > vci->max)
|
value = qAbs(value);
|
||||||
value -= 2 * vci->max;
|
while (value > vci.max)
|
||||||
value = qAbs(value);
|
value -= 2 * vci.max;
|
||||||
majorAxisIsY = value < vci->max - value;
|
value = qAbs(value);
|
||||||
} else if (vci->label == atom(QXcbAtom::AbsMTPressure) ||
|
majorAxisIsY = value < vci.max - value;
|
||||||
vci->label == atom(QXcbAtom::AbsPressure)) {
|
} else if (vci.label == QXcbAtom::AbsMTPressure || vci.label == QXcbAtom::AbsPressure) {
|
||||||
touchPoint.pressure = valuatorNormalized(value, vci);
|
touchPoint.pressure = valuatorNormalized;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// If any value was not updated, use the last-known value.
|
// If any value was not updated, use the last-known value.
|
||||||
if (nx == -1.0) {
|
if (nx == -1.0) {
|
||||||
@ -759,12 +733,12 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
|
|||||||
|
|
||||||
bool QXcbConnection::startSystemResizeForTouchBegin(xcb_window_t window, const QPoint &point, Qt::Corner corner)
|
bool QXcbConnection::startSystemResizeForTouchBegin(xcb_window_t window, const QPoint &point, Qt::Corner corner)
|
||||||
{
|
{
|
||||||
QHash<int, XInput2TouchDeviceData*>::const_iterator devIt = m_touchDevices.constBegin();
|
QHash<int, TouchDeviceData>::const_iterator devIt = m_touchDevices.constBegin();
|
||||||
for (; devIt != m_touchDevices.constEnd(); ++devIt) {
|
for (; devIt != m_touchDevices.constEnd(); ++devIt) {
|
||||||
XInput2TouchDeviceData *deviceData = devIt.value();
|
TouchDeviceData deviceData = devIt.value();
|
||||||
if (deviceData->qtTouchDevice->type() == QTouchDevice::TouchScreen) {
|
if (deviceData.qtTouchDevice->type() == QTouchDevice::TouchScreen) {
|
||||||
QHash<int, QPointF>::const_iterator pointIt = deviceData->pointPressedPosition.constBegin();
|
QHash<int, QPointF>::const_iterator pointIt = deviceData.pointPressedPosition.constBegin();
|
||||||
for (; pointIt != deviceData->pointPressedPosition.constEnd(); ++pointIt) {
|
for (; pointIt != deviceData.pointPressedPosition.constEnd(); ++pointIt) {
|
||||||
if (pointIt.value().toPoint() == point) {
|
if (pointIt.value().toPoint() == point) {
|
||||||
m_startSystemResizeInfo.window = window;
|
m_startSystemResizeInfo.window = window;
|
||||||
m_startSystemResizeInfo.deviceid = devIt.key();
|
m_startSystemResizeInfo.deviceid = devIt.key();
|
||||||
@ -1066,11 +1040,10 @@ Qt::MouseButton QXcbConnection::xiToQtMouseButton(uint32_t b)
|
|||||||
return Qt::NoButton;
|
return Qt::NoButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QXcbConnection::isTouchScreen(int id) const
|
bool QXcbConnection::isTouchScreen(int id)
|
||||||
{
|
{
|
||||||
auto device = m_touchDevices.value(id);
|
auto device = touchDeviceForId(id);
|
||||||
return device && device->qtTouchDevice
|
return device && device->qtTouchDevice->type() == QTouchDevice::TouchScreen;
|
||||||
&& device->qtTouchDevice->type() == QTouchDevice::TouchScreen;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if QT_CONFIG(tabletevent)
|
#if QT_CONFIG(tabletevent)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user