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)
316const QPointingDevice *QPointingDevice::primaryPointingDevice(
const QString& seatName)
318 const auto v = devices();
319 const QPointingDevice *mouse =
nullptr;
320 const QPointingDevice *touchpad =
nullptr;
321 for (
const QInputDevice *dev : v) {
322 if (!seatName.isNull() && dev->seatName() != seatName)
324 if (dev->type() == QInputDevice::DeviceType::Mouse) {
326 mouse =
static_cast<
const QPointingDevice *>(dev);
328 if (!mouse->parent() || !qobject_cast<
const QInputDevice *>(mouse->parent()))
330 }
else if (dev->type() == QInputDevice::DeviceType::TouchPad) {
331 if (!touchpad || !dev->parent() || dev->parent()->metaObject() != dev->metaObject())
332 touchpad =
static_cast<
const QPointingDevice *>(dev);
335 if (!mouse && !touchpad) {
336 qCDebug(lcQpaInputDevices) <<
"no mouse-like devices registered for seat" << seatName
337 <<
"The platform plugin should have provided one via "
338 "QWindowSystemInterface::registerInputDevice(). Creating a default mouse for now.";
339 mouse =
new QPointingDevice(
"core pointer"_L1, 1, DeviceType::Mouse,
340 PointerType::Generic, Capability::Position, 1, 3, seatName,
341 QPointingDeviceUniqueId(), QCoreApplication::instance());
342 QInputDevicePrivate::registerDevice(mouse);
346 qCDebug(lcQpaInputDevices) <<
"core pointer ambiguous for seat" << seatName;
371const QPointingDevice *QPointingDevicePrivate::queryTabletDevice(QInputDevice::DeviceType deviceType,
372 QPointingDevice::PointerType pointerType,
373 QPointingDeviceUniqueId uniqueId,
374 QPointingDevice::Capabilities capabilities,
377 const auto &devices = QInputDevice::devices();
378 for (
const QInputDevice *dev : devices) {
379 if (dev->type() < QPointingDevice::DeviceType::Puck || dev->type() > QPointingDevice::DeviceType::Airbrush)
381 const QPointingDevice *pdev =
static_cast<
const QPointingDevice *>(dev);
382 const auto devPriv = QPointingDevicePrivate::get(pdev);
383 bool uniqueIdDiscovered = (devPriv->uniqueId.numericId() == 0 && uniqueId.numericId() != 0);
384 if (devPriv->deviceType == deviceType && devPriv->pointerType == pointerType &&
385 (!systemId || devPriv->systemId == systemId) &&
386 (devPriv->uniqueId == uniqueId || uniqueIdDiscovered)) {
387 if (uniqueIdDiscovered) {
388 const_cast<QPointingDevicePrivate *>(devPriv)->uniqueId = uniqueId;
390 const_cast<QPointingDevicePrivate *>(devPriv)->capabilities = capabilities;
391 qCDebug(lcQpaInputDevices) <<
"discovered unique ID and capabilities of tablet tool" << pdev;
404const QPointingDevice *QPointingDevicePrivate::pointingDeviceById(qint64 systemId)
406 const auto &devices = QInputDevice::devices();
407 for (
const QInputDevice *dev : devices) {
408 if (dev->type() >= QPointingDevice::DeviceType::Keyboard)
410 const QPointingDevice *pdev =
static_cast<
const QPointingDevice *>(dev);
411 const auto devPriv = QPointingDevicePrivate::get(pdev);
412 if (devPriv->systemId == systemId)
424void QPointingDevicePrivate::sendTouchCancelEvent(QTouchEvent *cancelEvent)
430 if (cancelEvent->points().isEmpty()) {
431 for (
auto &epd : activePoints.values()) {
432 if (epd.exclusiveGrabber)
433 QMutableTouchEvent::addPoint(cancelEvent, epd.eventPoint);
436 for (
auto &epd : activePoints.values()) {
437 if (epd.exclusiveGrabber)
438 QCoreApplication::sendEvent(epd.exclusiveGrabber, cancelEvent);
440 cancelEvent->setExclusiveGrabber(epd.eventPoint,
nullptr);
441 cancelEvent->clearPassiveGrabbers(epd.eventPoint);
461QPointingDevicePrivate::EventPointData *QPointingDevicePrivate::pointById(
int id)
const
463 const auto [it, inserted] = activePoints.try_emplace(id);
465 Q_Q(
const QPointingDevice);
466 auto &epd = it.value();
467 QMutableEventPoint::setId(epd.eventPoint, id);
468 QMutableEventPoint::setDevice(epd.eventPoint, q);
525void QPointingDevicePrivate::setExclusiveGrabber(
const QPointerEvent *event,
const QEventPoint &point, QObject *exclusiveGrabber)
527 Q_Q(QPointingDevice);
528 auto persistentPoint = queryPointById(point.id());
529 if (!persistentPoint) {
530 qWarning() <<
"point is not in activePoints" << point;
533 Q_ASSERT(persistentPoint->eventPoint.id() == point.id());
534 if (persistentPoint->exclusiveGrabber == exclusiveGrabber)
536 auto oldGrabber = persistentPoint->exclusiveGrabber;
537 persistentPoint->exclusiveGrabber = exclusiveGrabber;
539 emit q->grabChanged(oldGrabber, exclusiveGrabber ? QPointingDevice::CancelGrabExclusive : QPointingDevice::UngrabExclusive,
540 event, persistentPoint->eventPoint);
541 if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
542 qCDebug(lcPointerGrab) << name <<
"point" << point.id() << point.state()
543 <<
"@" << point.scenePosition()
544 <<
": grab" << oldGrabber <<
"->" << exclusiveGrabber;
546 QMutableEventPoint::setGlobalGrabPosition(persistentPoint->eventPoint, point.globalPosition());
547 if (exclusiveGrabber)
548 emit q->grabChanged(exclusiveGrabber, QPointingDevice::GrabExclusive, event, point);
550 persistentPoint->exclusiveGrabberContext.clear();
557bool QPointingDevicePrivate::removeExclusiveGrabber(
const QPointerEvent *event,
const QObject *grabber)
560 for (
auto &pt : activePoints.values()) {
561 if (pt.exclusiveGrabber == grabber) {
562 setExclusiveGrabber(event, pt.eventPoint,
nullptr);
569bool QPointingDevicePrivate::addPassiveGrabber(
const QPointerEvent *event,
const QEventPoint &point, QObject *grabber)
571 Q_Q(QPointingDevice);
572 auto persistentPoint = queryPointById(point.id());
573 if (!persistentPoint) {
574 qWarning() <<
"point is not in activePoints" << point;
577 if (persistentPoint->passiveGrabbers.contains(grabber))
579 if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
580 qCDebug(lcPointerGrab) << name <<
"point" << point.id() << point.state()
581 <<
": grab (passive)" << grabber;
583 persistentPoint->passiveGrabbers << grabber;
584 emit q->grabChanged(grabber, QPointingDevice::GrabPassive, event, point);
588bool QPointingDevicePrivate::setPassiveGrabberContext(QPointingDevicePrivate::EventPointData *epd, QObject *grabber, QObject *context)
590 qsizetype i = epd->passiveGrabbers.indexOf(grabber);
593 if (epd->passiveGrabbersContext.size() <= i)
594 epd->passiveGrabbersContext.resize(i + 1);
595 epd->passiveGrabbersContext[i] = context;
599bool QPointingDevicePrivate::removePassiveGrabber(
const QPointerEvent *event,
const QEventPoint &point, QObject *grabber)
601 Q_Q(QPointingDevice);
602 auto persistentPoint = queryPointById(point.id());
603 if (!persistentPoint) {
604 qWarning() <<
"point is not in activePoints" << point;
607 qsizetype i = persistentPoint->passiveGrabbers.indexOf(grabber);
609 if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
610 qCDebug(lcPointerGrab) << name <<
"point" << point.id() << point.state()
611 <<
": removing passive grabber" << grabber;
613 emit q->grabChanged(grabber, QPointingDevice::UngrabPassive, event, point);
614 persistentPoint->passiveGrabbers.removeAt(i);
615 if (persistentPoint->passiveGrabbersContext.size()) {
616 Q_ASSERT(persistentPoint->passiveGrabbersContext.size() > i);
617 persistentPoint->passiveGrabbersContext.removeAt(i);
624void QPointingDevicePrivate::clearPassiveGrabbers(
const QPointerEvent *event,
const QEventPoint &point)
626 Q_Q(QPointingDevice);
627 auto persistentPoint = queryPointById(point.id());
628 if (!persistentPoint) {
629 qWarning() <<
"point is not in activePoints" << point;
632 if (persistentPoint->passiveGrabbers.isEmpty())
634 if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
635 qCDebug(lcPointerGrab) << name <<
"point" << point.id() << point.state()
636 <<
": clearing" << persistentPoint->passiveGrabbers;
638 for (
auto g : persistentPoint->passiveGrabbers)
639 emit q->grabChanged(g, QPointingDevice::UngrabPassive, event, point);
640 persistentPoint->passiveGrabbers.clear();
641 persistentPoint->passiveGrabbersContext.clear();
655void QPointingDevicePrivate::removeGrabber(QObject *grabber,
bool cancel)
657 Q_Q(QPointingDevice);
658 for (
auto ap : activePoints) {
659 auto &epd = ap.second;
660 if (epd.exclusiveGrabber.data() == grabber) {
661 qCDebug(lcPointerGrab) << name <<
"point" << epd.eventPoint.id() << epd.eventPoint.state()
662 <<
"@" << epd.eventPoint.scenePosition()
663 <<
": grab" << grabber <<
"-> nullptr";
664 epd.exclusiveGrabber.clear();
665 epd.exclusiveGrabberContext.clear();
666 emit q->grabChanged(grabber,
667 cancel ? QPointingDevice::CancelGrabExclusive : QPointingDevice::UngrabExclusive,
668 nullptr, epd.eventPoint);
670 qsizetype pi = epd.passiveGrabbers.indexOf(grabber);
672 qCDebug(lcPointerGrab) << name <<
"point" << epd.eventPoint.id() << epd.eventPoint.state()
673 <<
": removing passive grabber" << grabber;
674 epd.passiveGrabbers.removeAt(pi);
675 if (epd.passiveGrabbersContext.size()) {
676 Q_ASSERT(epd.passiveGrabbersContext.size() > pi);
677 epd.passiveGrabbersContext.removeAt(pi);
679 emit q->grabChanged(grabber,
680 cancel ? QPointingDevice::CancelGrabPassive : QPointingDevice::UngrabPassive,
681 nullptr, epd.eventPoint);
696const QPointingDevice *QPointingDevicePrivate::tabletDevice(QInputDevice::DeviceType deviceType,
697 QPointingDevice::PointerType pointerType,
698 QPointingDeviceUniqueId uniqueId)
700 const QPointingDevice *dev = queryTabletDevice(deviceType, pointerType, uniqueId);
702 qCDebug(lcQpaInputDevices) <<
"failed to find registered tablet device"
703 << deviceType << pointerType << Qt::hex << uniqueId.numericId()
704 <<
"The platform plugin should have provided one via "
705 "QWindowSystemInterface::registerInputDevice(). Creating a default one for now.";
706 dev =
new QPointingDevice(
"fake tablet"_L1, 2, deviceType, pointerType,
707 QInputDevice::Capability::Position | QInputDevice::Capability::Pressure,
708 1, 1, QString(), uniqueId, QCoreApplication::instance());
709 QInputDevicePrivate::registerDevice(dev);
725QDebug operator<<(QDebug debug,
const QPointingDevice *device)
727 QDebugStateSaver saver(debug);
730 debug <<
"QPointingDevice(";
732 debug <<
'"' << device->name() <<
"\" ";
733 QtDebugUtils::formatQEnum(debug, device->type());
734 debug <<
" id=" << device->systemId();
735 if (!device->seatName().isEmpty())
736 debug <<
" seat=" << device->seatName();
737 if (device->pointerType() != QPointingDevice::PointerType::Generic) {
738 debug <<
" ptrType=";
739 QtDebugUtils::formatQEnum(debug, device->pointerType());
741 if (
int(device->capabilities()) !=
int(QInputDevice::Capability::Position)) {
743 QtDebugUtils::formatQFlags(debug, device->capabilities());
745 if (device->buttonCount() > 0)
746 debug <<
" buttonCount=" << device->buttonCount();
747 if (device->maximumPoints() > 1)
748 debug <<
" maxPts=" << device->maximumPoints();
749 if (device->uniqueId().isValid())
750 debug <<
" uniqueId=" << Qt::hex << device->uniqueId().numericId() << Qt::dec;