159QPointingDevice::QPointingDevice(QObject *parent)
160 : QInputDevice(*(
new QPointingDevicePrivate(
"unknown"_L1, -1,
161 DeviceType::Unknown, PointerType::Unknown,
162 Capability::None, 0, 0)), parent)
175QPointingDevice::QPointingDevice(
const QString &name, qint64 id, QInputDevice::DeviceType deviceType,
176 QPointingDevice::PointerType pointerType, Capabilities capabilities,
int maxPoints,
int buttonCount,
177 const QString &seatName, QPointingDeviceUniqueId uniqueId, QObject *parent)
178 : QInputDevice(*(
new QPointingDevicePrivate(name, id, deviceType, pointerType, capabilities, maxPoints, buttonCount, seatName, uniqueId)), parent)
293const QPointingDevice *QPointingDevice::primaryPointingDevice(
const QString& seatName)
295 const auto v = devices();
296 const QPointingDevice *mouse =
nullptr;
297 const QPointingDevice *touchpad =
nullptr;
298 for (
const QInputDevice *dev : v) {
299 if (!seatName.isNull() && dev->seatName() != seatName)
301 if (dev->type() == QInputDevice::DeviceType::Mouse) {
303 mouse =
static_cast<
const QPointingDevice *>(dev);
305 if (!mouse->parent() || !qobject_cast<
const QInputDevice *>(mouse->parent()))
307 }
else if (dev->type() == QInputDevice::DeviceType::TouchPad) {
308 if (!touchpad || !dev->parent() || dev->parent()->metaObject() != dev->metaObject())
309 touchpad =
static_cast<
const QPointingDevice *>(dev);
312 if (!mouse && !touchpad) {
313 qCDebug(lcQpaInputDevices) <<
"no mouse-like devices registered for seat" << seatName
314 <<
"The platform plugin should have provided one via "
315 "QWindowSystemInterface::registerInputDevice(). Creating a default mouse for now.";
316 mouse =
new QPointingDevice(
"core pointer"_L1, 1, DeviceType::Mouse,
317 PointerType::Generic, Capability::Position, 1, 3, seatName,
318 QPointingDeviceUniqueId(), QCoreApplication::instance());
319 QInputDevicePrivate::registerDevice(mouse);
323 qCDebug(lcQpaInputDevices) <<
"core pointer ambiguous for seat" << seatName;
348const QPointingDevice *QPointingDevicePrivate::queryTabletDevice(QInputDevice::DeviceType deviceType,
349 QPointingDevice::PointerType pointerType,
350 QPointingDeviceUniqueId uniqueId,
351 QPointingDevice::Capabilities capabilities,
354 const auto &devices = QInputDevice::devices();
355 for (
const QInputDevice *dev : devices) {
356 if (dev->type() < QPointingDevice::DeviceType::Puck || dev->type() > QPointingDevice::DeviceType::Airbrush)
358 const QPointingDevice *pdev =
static_cast<
const QPointingDevice *>(dev);
359 const auto devPriv = QPointingDevicePrivate::get(pdev);
360 bool uniqueIdDiscovered = (devPriv->uniqueId.numericId() == 0 && uniqueId.numericId() != 0);
361 if (devPriv->deviceType == deviceType && devPriv->pointerType == pointerType &&
362 (!systemId || devPriv->systemId == systemId) &&
363 (devPriv->uniqueId == uniqueId || uniqueIdDiscovered)) {
364 if (uniqueIdDiscovered) {
365 const_cast<QPointingDevicePrivate *>(devPriv)->uniqueId = uniqueId;
367 const_cast<QPointingDevicePrivate *>(devPriv)->capabilities = capabilities;
368 qCDebug(lcQpaInputDevices) <<
"discovered unique ID and capabilities of tablet tool" << pdev;
381const QPointingDevice *QPointingDevicePrivate::pointingDeviceById(qint64 systemId)
383 const auto &devices = QInputDevice::devices();
384 for (
const QInputDevice *dev : devices) {
385 if (dev->type() >= QPointingDevice::DeviceType::Keyboard)
387 const QPointingDevice *pdev =
static_cast<
const QPointingDevice *>(dev);
388 const auto devPriv = QPointingDevicePrivate::get(pdev);
389 if (devPriv->systemId == systemId)
401void QPointingDevicePrivate::sendTouchCancelEvent(QTouchEvent *cancelEvent)
407 if (cancelEvent->points().isEmpty()) {
408 for (
auto &epd : activePoints.values()) {
409 if (epd.exclusiveGrabber)
410 QMutableTouchEvent::addPoint(cancelEvent, epd.eventPoint);
413 for (
auto &epd : activePoints.values()) {
414 if (epd.exclusiveGrabber)
415 QCoreApplication::sendEvent(epd.exclusiveGrabber, cancelEvent);
417 cancelEvent->setExclusiveGrabber(epd.eventPoint,
nullptr);
418 cancelEvent->clearPassiveGrabbers(epd.eventPoint);
438QPointingDevicePrivate::EventPointData *QPointingDevicePrivate::pointById(
int id)
const
440 const auto [it, inserted] = activePoints.try_emplace(id);
442 Q_Q(
const QPointingDevice);
443 auto &epd = it.value();
444 QMutableEventPoint::setId(epd.eventPoint, id);
445 QMutableEventPoint::setDevice(epd.eventPoint, q);
502void QPointingDevicePrivate::setExclusiveGrabber(
const QPointerEvent *event,
const QEventPoint &point, QObject *exclusiveGrabber)
504 Q_Q(QPointingDevice);
505 auto persistentPoint = queryPointById(point.id());
506 if (!persistentPoint) {
507 qWarning() <<
"point is not in activePoints" << point;
510 Q_ASSERT(persistentPoint->eventPoint.id() == point.id());
511 if (persistentPoint->exclusiveGrabber == exclusiveGrabber)
513 auto oldGrabber = persistentPoint->exclusiveGrabber;
514 persistentPoint->exclusiveGrabber = exclusiveGrabber;
516 emit q->grabChanged(oldGrabber, exclusiveGrabber ? QPointingDevice::CancelGrabExclusive : QPointingDevice::UngrabExclusive,
517 event, persistentPoint->eventPoint);
518 if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
519 qCDebug(lcPointerGrab) << name <<
"point" << point.id() << point.state()
520 <<
"@" << point.scenePosition()
521 <<
": grab" << oldGrabber <<
"->" << exclusiveGrabber;
523 QMutableEventPoint::setGlobalGrabPosition(persistentPoint->eventPoint, point.globalPosition());
524 if (exclusiveGrabber)
525 emit q->grabChanged(exclusiveGrabber, QPointingDevice::GrabExclusive, event, point);
527 persistentPoint->exclusiveGrabberContext.clear();
534bool QPointingDevicePrivate::removeExclusiveGrabber(
const QPointerEvent *event,
const QObject *grabber)
537 for (
auto &pt : activePoints.values()) {
538 if (pt.exclusiveGrabber == grabber) {
539 setExclusiveGrabber(event, pt.eventPoint,
nullptr);
546bool QPointingDevicePrivate::addPassiveGrabber(
const QPointerEvent *event,
const QEventPoint &point, QObject *grabber)
548 Q_Q(QPointingDevice);
549 auto persistentPoint = queryPointById(point.id());
550 if (!persistentPoint) {
551 qWarning() <<
"point is not in activePoints" << point;
554 if (persistentPoint->passiveGrabbers.contains(grabber))
556 if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
557 qCDebug(lcPointerGrab) << name <<
"point" << point.id() << point.state()
558 <<
": grab (passive)" << grabber;
560 persistentPoint->passiveGrabbers << grabber;
561 emit q->grabChanged(grabber, QPointingDevice::GrabPassive, event, point);
565bool QPointingDevicePrivate::setPassiveGrabberContext(QPointingDevicePrivate::EventPointData *epd, QObject *grabber, QObject *context)
567 qsizetype i = epd->passiveGrabbers.indexOf(grabber);
570 if (epd->passiveGrabbersContext.size() <= i)
571 epd->passiveGrabbersContext.resize(i + 1);
572 epd->passiveGrabbersContext[i] = context;
576bool QPointingDevicePrivate::removePassiveGrabber(
const QPointerEvent *event,
const QEventPoint &point, QObject *grabber)
578 Q_Q(QPointingDevice);
579 auto persistentPoint = queryPointById(point.id());
580 if (!persistentPoint) {
581 qWarning() <<
"point is not in activePoints" << point;
584 qsizetype i = persistentPoint->passiveGrabbers.indexOf(grabber);
586 if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
587 qCDebug(lcPointerGrab) << name <<
"point" << point.id() << point.state()
588 <<
": removing passive grabber" << grabber;
590 emit q->grabChanged(grabber, QPointingDevice::UngrabPassive, event, point);
591 persistentPoint->passiveGrabbers.removeAt(i);
592 if (persistentPoint->passiveGrabbersContext.size()) {
593 Q_ASSERT(persistentPoint->passiveGrabbersContext.size() > i);
594 persistentPoint->passiveGrabbersContext.removeAt(i);
601void QPointingDevicePrivate::clearPassiveGrabbers(
const QPointerEvent *event,
const QEventPoint &point)
603 Q_Q(QPointingDevice);
604 auto persistentPoint = queryPointById(point.id());
605 if (!persistentPoint) {
606 qWarning() <<
"point is not in activePoints" << point;
609 if (persistentPoint->passiveGrabbers.isEmpty())
611 if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
612 qCDebug(lcPointerGrab) << name <<
"point" << point.id() << point.state()
613 <<
": clearing" << persistentPoint->passiveGrabbers;
615 for (
auto g : persistentPoint->passiveGrabbers)
616 emit q->grabChanged(g, QPointingDevice::UngrabPassive, event, point);
617 persistentPoint->passiveGrabbers.clear();
618 persistentPoint->passiveGrabbersContext.clear();
632void QPointingDevicePrivate::removeGrabber(QObject *grabber,
bool cancel)
634 Q_Q(QPointingDevice);
635 for (
auto ap : activePoints) {
636 auto &epd = ap.second;
637 if (epd.exclusiveGrabber.data() == grabber) {
638 qCDebug(lcPointerGrab) << name <<
"point" << epd.eventPoint.id() << epd.eventPoint.state()
639 <<
"@" << epd.eventPoint.scenePosition()
640 <<
": grab" << grabber <<
"-> nullptr";
641 epd.exclusiveGrabber.clear();
642 epd.exclusiveGrabberContext.clear();
643 emit q->grabChanged(grabber,
644 cancel ? QPointingDevice::CancelGrabExclusive : QPointingDevice::UngrabExclusive,
645 nullptr, epd.eventPoint);
647 qsizetype pi = epd.passiveGrabbers.indexOf(grabber);
649 qCDebug(lcPointerGrab) << name <<
"point" << epd.eventPoint.id() << epd.eventPoint.state()
650 <<
": removing passive grabber" << grabber;
651 epd.passiveGrabbers.removeAt(pi);
652 if (epd.passiveGrabbersContext.size()) {
653 Q_ASSERT(epd.passiveGrabbersContext.size() > pi);
654 epd.passiveGrabbersContext.removeAt(pi);
656 emit q->grabChanged(grabber,
657 cancel ? QPointingDevice::CancelGrabPassive : QPointingDevice::UngrabPassive,
658 nullptr, epd.eventPoint);
673const QPointingDevice *QPointingDevicePrivate::tabletDevice(QInputDevice::DeviceType deviceType,
674 QPointingDevice::PointerType pointerType,
675 QPointingDeviceUniqueId uniqueId)
677 const QPointingDevice *dev = queryTabletDevice(deviceType, pointerType, uniqueId);
679 qCDebug(lcQpaInputDevices) <<
"failed to find registered tablet device"
680 << deviceType << pointerType << Qt::hex << uniqueId.numericId()
681 <<
"The platform plugin should have provided one via "
682 "QWindowSystemInterface::registerInputDevice(). Creating a default one for now.";
683 dev =
new QPointingDevice(
"fake tablet"_L1, 2, deviceType, pointerType,
684 QInputDevice::Capability::Position | QInputDevice::Capability::Pressure,
685 1, 1, QString(), uniqueId, QCoreApplication::instance());
686 QInputDevicePrivate::registerDevice(dev);
702QDebug operator<<(QDebug debug,
const QPointingDevice *device)
704 QDebugStateSaver saver(debug);
707 debug <<
"QPointingDevice(";
709 debug <<
'"' << device->name() <<
"\" ";
710 QtDebugUtils::formatQEnum(debug, device->type());
711 debug <<
" id=" << device->systemId();
712 if (!device->seatName().isEmpty())
713 debug <<
" seat=" << device->seatName();
714 if (device->pointerType() != QPointingDevice::PointerType::Generic) {
715 debug <<
" ptrType=";
716 QtDebugUtils::formatQEnum(debug, device->pointerType());
718 if (
int(device->capabilities()) !=
int(QInputDevice::Capability::Position)) {
720 QtDebugUtils::formatQFlags(debug, device->capabilities());
722 if (device->buttonCount() > 0)
723 debug <<
" buttonCount=" << device->buttonCount();
724 if (device->maximumPoints() > 1)
725 debug <<
" maxPts=" << device->maximumPoints();
726 if (device->uniqueId().isValid())
727 debug <<
" uniqueId=" << Qt::hex << device->uniqueId().numericId() << Qt::dec;