162QPointingDevice::QPointingDevice(QObject *parent)
163 : QInputDevice(*(
new QPointingDevicePrivate(
"unknown"_L1, -1,
164 DeviceType::Unknown, PointerType::Unknown,
165 Capability::None, 0, 0)), parent)
178QPointingDevice::QPointingDevice(
const QString &name, qint64 id, QInputDevice::DeviceType deviceType,
179 QPointingDevice::PointerType pointerType, Capabilities capabilities,
int maxPoints,
int buttonCount,
180 const QString &seatName, QPointingDeviceUniqueId uniqueId, QObject *parent)
181 : QInputDevice(*(
new QPointingDevicePrivate(name, id, deviceType, pointerType, capabilities, maxPoints, buttonCount, seatName, uniqueId)), parent)
319const QPointingDevice *QPointingDevice::primaryPointingDevice(
const QString& seatName)
321 const auto v = devices();
322 const QPointingDevice *mouse =
nullptr;
323 const QPointingDevice *touchpad =
nullptr;
324 for (
const QInputDevice *dev : v) {
325 if (!seatName.isNull() && dev->seatName() != seatName)
327 if (dev->type() == QInputDevice::DeviceType::Mouse) {
329 mouse =
static_cast<
const QPointingDevice *>(dev);
331 if (!mouse->parent() || !qobject_cast<
const QInputDevice *>(mouse->parent()))
333 }
else if (dev->type() == QInputDevice::DeviceType::TouchPad) {
334 if (!touchpad || !dev->parent() || dev->parent()->metaObject() != dev->metaObject())
335 touchpad =
static_cast<
const QPointingDevice *>(dev);
338 if (!mouse && !touchpad) {
339 qCDebug(lcQpaInputDevices) <<
"no mouse-like devices registered for seat" << seatName
340 <<
"The platform plugin should have provided one via "
341 "QWindowSystemInterface::registerInputDevice(). Creating a default mouse for now.";
342 mouse =
new QPointingDevice(
"core pointer"_L1, 1, DeviceType::Mouse,
343 PointerType::Generic, Capability::Position, 1, 3, seatName,
344 QPointingDeviceUniqueId(), QCoreApplication::instance());
345 QInputDevicePrivate::registerDevice(mouse);
349 qCDebug(lcQpaInputDevices) <<
"core pointer ambiguous for seat" << seatName;
374const QPointingDevice *QPointingDevicePrivate::queryTabletDevice(QInputDevice::DeviceType deviceType,
375 QPointingDevice::PointerType pointerType,
376 QPointingDeviceUniqueId uniqueId,
377 QPointingDevice::Capabilities capabilities,
380 const auto &devices = QInputDevice::devices();
381 for (
const QInputDevice *dev : devices) {
382 if (dev->type() < QPointingDevice::DeviceType::Puck || dev->type() > QPointingDevice::DeviceType::Airbrush)
384 const QPointingDevice *pdev =
static_cast<
const QPointingDevice *>(dev);
385 const auto devPriv = QPointingDevicePrivate::get(pdev);
386 bool uniqueIdDiscovered = (devPriv->uniqueId.numericId() == 0 && uniqueId.numericId() != 0);
387 if (devPriv->deviceType == deviceType && devPriv->pointerType == pointerType &&
388 (!systemId || devPriv->systemId == systemId) &&
389 (devPriv->uniqueId == uniqueId || uniqueIdDiscovered)) {
390 if (uniqueIdDiscovered) {
391 const_cast<QPointingDevicePrivate *>(devPriv)->uniqueId = uniqueId;
393 const_cast<QPointingDevicePrivate *>(devPriv)->capabilities = capabilities;
394 qCDebug(lcQpaInputDevices) <<
"discovered unique ID and capabilities of tablet tool" << pdev;
407const QPointingDevice *QPointingDevicePrivate::pointingDeviceById(qint64 systemId)
409 const auto &devices = QInputDevice::devices();
410 for (
const QInputDevice *dev : devices) {
411 if (dev->type() >= QPointingDevice::DeviceType::Keyboard)
413 const QPointingDevice *pdev =
static_cast<
const QPointingDevice *>(dev);
414 const auto devPriv = QPointingDevicePrivate::get(pdev);
415 if (devPriv->systemId == systemId)
427void QPointingDevicePrivate::sendTouchCancelEvent(QTouchEvent *cancelEvent)
433 if (cancelEvent->points().isEmpty()) {
434 for (
auto &epd : activePoints.values()) {
435 if (epd.exclusiveGrabber)
436 QMutableTouchEvent::addPoint(cancelEvent, epd.eventPoint);
439 for (
auto &epd : activePoints.values()) {
440 if (epd.exclusiveGrabber)
441 QCoreApplication::sendEvent(epd.exclusiveGrabber, cancelEvent);
443 cancelEvent->setExclusiveGrabber(epd.eventPoint,
nullptr);
444 cancelEvent->clearPassiveGrabbers(epd.eventPoint);
464QPointingDevicePrivate::EventPointData *QPointingDevicePrivate::pointById(
int id)
const
466 const auto [it, inserted] = activePoints.try_emplace(id);
468 Q_Q(
const QPointingDevice);
469 auto &epd = it.value();
470 QMutableEventPoint::setId(epd.eventPoint, id);
471 QMutableEventPoint::setDevice(epd.eventPoint, q);
528void QPointingDevicePrivate::setExclusiveGrabber(
const QPointerEvent *event,
const QEventPoint &point, QObject *exclusiveGrabber)
530 Q_Q(QPointingDevice);
531 auto persistentPoint = queryPointById(point.id());
532 if (!persistentPoint) {
533 qWarning() <<
"point is not in activePoints" << point;
536 Q_ASSERT(persistentPoint->eventPoint.id() == point.id());
537 if (persistentPoint->exclusiveGrabber == exclusiveGrabber)
539 auto oldGrabber = persistentPoint->exclusiveGrabber;
540 persistentPoint->exclusiveGrabber = exclusiveGrabber;
542 emit q->grabChanged(oldGrabber, exclusiveGrabber ? QPointingDevice::CancelGrabExclusive : QPointingDevice::UngrabExclusive,
543 event, persistentPoint->eventPoint);
544 if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
545 qCDebug(lcPointerGrab) << name <<
"point" << point.id() << point.state()
546 <<
"@" << point.scenePosition()
547 <<
": grab" << oldGrabber <<
"->" << exclusiveGrabber;
549 QMutableEventPoint::setGlobalGrabPosition(persistentPoint->eventPoint, point.globalPosition());
550 if (exclusiveGrabber)
551 emit q->grabChanged(exclusiveGrabber, QPointingDevice::GrabExclusive, event, point);
553 persistentPoint->exclusiveGrabberContext.clear();
560bool QPointingDevicePrivate::removeExclusiveGrabber(
const QPointerEvent *event,
const QObject *grabber)
563 for (
auto &pt : activePoints.values()) {
564 if (pt.exclusiveGrabber == grabber) {
565 setExclusiveGrabber(event, pt.eventPoint,
nullptr);
572bool QPointingDevicePrivate::addPassiveGrabber(
const QPointerEvent *event,
const QEventPoint &point, QObject *grabber)
574 Q_Q(QPointingDevice);
575 auto persistentPoint = queryPointById(point.id());
576 if (!persistentPoint) {
577 qWarning() <<
"point is not in activePoints" << point;
580 if (persistentPoint->passiveGrabbers.contains(grabber))
582 if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
583 qCDebug(lcPointerGrab) << name <<
"point" << point.id() << point.state()
584 <<
": grab (passive)" << grabber;
586 persistentPoint->passiveGrabbers << grabber;
587 emit q->grabChanged(grabber, QPointingDevice::GrabPassive, event, point);
591bool QPointingDevicePrivate::setPassiveGrabberContext(QPointingDevicePrivate::EventPointData *epd, QObject *grabber, QObject *context)
593 qsizetype i = epd->passiveGrabbers.indexOf(grabber);
596 if (epd->passiveGrabbersContext.size() <= i)
597 epd->passiveGrabbersContext.resize(i + 1);
598 epd->passiveGrabbersContext[i] = context;
602bool QPointingDevicePrivate::removePassiveGrabber(
const QPointerEvent *event,
const QEventPoint &point, QObject *grabber)
604 Q_Q(QPointingDevice);
605 auto persistentPoint = queryPointById(point.id());
606 if (!persistentPoint) {
607 qWarning() <<
"point is not in activePoints" << point;
610 qsizetype i = persistentPoint->passiveGrabbers.indexOf(grabber);
612 if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
613 qCDebug(lcPointerGrab) << name <<
"point" << point.id() << point.state()
614 <<
": removing passive grabber" << grabber;
616 emit q->grabChanged(grabber, QPointingDevice::UngrabPassive, event, point);
617 persistentPoint->passiveGrabbers.removeAt(i);
618 if (persistentPoint->passiveGrabbersContext.size()) {
619 Q_ASSERT(persistentPoint->passiveGrabbersContext.size() > i);
620 persistentPoint->passiveGrabbersContext.removeAt(i);
627void QPointingDevicePrivate::clearPassiveGrabbers(
const QPointerEvent *event,
const QEventPoint &point)
629 Q_Q(QPointingDevice);
630 auto persistentPoint = queryPointById(point.id());
631 if (!persistentPoint) {
632 qWarning() <<
"point is not in activePoints" << point;
635 if (persistentPoint->passiveGrabbers.isEmpty())
637 if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
638 qCDebug(lcPointerGrab) << name <<
"point" << point.id() << point.state()
639 <<
": clearing" << persistentPoint->passiveGrabbers;
641 for (
auto g : persistentPoint->passiveGrabbers)
642 emit q->grabChanged(g, QPointingDevice::UngrabPassive, event, point);
643 persistentPoint->passiveGrabbers.clear();
644 persistentPoint->passiveGrabbersContext.clear();
658void QPointingDevicePrivate::removeGrabber(QObject *grabber,
bool cancel)
660 Q_Q(QPointingDevice);
661 for (
auto ap : activePoints) {
662 auto &epd = ap.second;
663 if (epd.exclusiveGrabber.data() == grabber) {
664 qCDebug(lcPointerGrab) << name <<
"point" << epd.eventPoint.id() << epd.eventPoint.state()
665 <<
"@" << epd.eventPoint.scenePosition()
666 <<
": grab" << grabber <<
"-> nullptr";
667 epd.exclusiveGrabber.clear();
668 epd.exclusiveGrabberContext.clear();
669 emit q->grabChanged(grabber,
670 cancel ? QPointingDevice::CancelGrabExclusive : QPointingDevice::UngrabExclusive,
671 nullptr, epd.eventPoint);
673 qsizetype pi = epd.passiveGrabbers.indexOf(grabber);
675 qCDebug(lcPointerGrab) << name <<
"point" << epd.eventPoint.id() << epd.eventPoint.state()
676 <<
": removing passive grabber" << grabber;
677 epd.passiveGrabbers.removeAt(pi);
678 if (epd.passiveGrabbersContext.size()) {
679 Q_ASSERT(epd.passiveGrabbersContext.size() > pi);
680 epd.passiveGrabbersContext.removeAt(pi);
682 emit q->grabChanged(grabber,
683 cancel ? QPointingDevice::CancelGrabPassive : QPointingDevice::UngrabPassive,
684 nullptr, epd.eventPoint);
699const QPointingDevice *QPointingDevicePrivate::tabletDevice(QInputDevice::DeviceType deviceType,
700 QPointingDevice::PointerType pointerType,
701 QPointingDeviceUniqueId uniqueId)
703 const QPointingDevice *dev = queryTabletDevice(deviceType, pointerType, uniqueId);
705 qCDebug(lcQpaInputDevices) <<
"failed to find registered tablet device"
706 << deviceType << pointerType << Qt::hex << uniqueId.numericId()
707 <<
"The platform plugin should have provided one via "
708 "QWindowSystemInterface::registerInputDevice(). Creating a default one for now.";
709 dev =
new QPointingDevice(
"fake tablet"_L1, 2, deviceType, pointerType,
710 QInputDevice::Capability::Position | QInputDevice::Capability::Pressure,
711 1, 1, QString(), uniqueId, QCoreApplication::instance());
712 QInputDevicePrivate::registerDevice(dev);
728QDebug operator<<(QDebug debug,
const QPointingDevice *device)
730 QDebugStateSaver saver(debug);
733 debug <<
"QPointingDevice(";
735 debug <<
'"' << device->name() <<
"\" ";
736 QtDebugUtils::formatQEnum(debug, device->type());
737 debug <<
" id=" << device->systemId();
738 if (!device->seatName().isEmpty())
739 debug <<
" seat=" << device->seatName();
740 if (device->pointerType() != QPointingDevice::PointerType::Generic) {
741 debug <<
" ptrType=";
742 QtDebugUtils::formatQEnum(debug, device->pointerType());
744 if (
int(device->capabilities()) !=
int(QInputDevice::Capability::Position)) {
746 QtDebugUtils::formatQFlags(debug, device->capabilities());
748 if (device->buttonCount() > 0)
749 debug <<
" buttonCount=" << device->buttonCount();
750 if (device->maximumPoints() > 1)
751 debug <<
" maxPts=" << device->maximumPoints();
752 if (device->uniqueId().isValid())
753 debug <<
" uniqueId=" << Qt::hex << device->uniqueId().numericId() << Qt::dec;