160QPointingDevice::QPointingDevice(QObject *parent)
161 : QInputDevice(*(
new QPointingDevicePrivate(
"unknown"_L1, -1,
162 DeviceType::Unknown, PointerType::Unknown,
163 Capability::None, 0, 0)), parent)
176QPointingDevice::QPointingDevice(
const QString &name, qint64 id, QInputDevice::DeviceType deviceType,
177 QPointingDevice::PointerType pointerType, Capabilities capabilities,
int maxPoints,
int buttonCount,
178 const QString &seatName, QPointingDeviceUniqueId uniqueId, QObject *parent)
179 : QInputDevice(*(
new QPointingDevicePrivate(name, id, deviceType, pointerType, capabilities, maxPoints, buttonCount, seatName, uniqueId)), parent)
317const QPointingDevice *QPointingDevice::primaryPointingDevice(
const QString& seatName)
319 const auto v = devices();
320 const QPointingDevice *mouse =
nullptr;
321 const QPointingDevice *touchpad =
nullptr;
322 for (
const QInputDevice *dev : v) {
323 if (!seatName.isNull() && dev->seatName() != seatName)
325 if (dev->type() == QInputDevice::DeviceType::Mouse) {
327 mouse =
static_cast<
const QPointingDevice *>(dev);
329 if (!mouse->parent() || !qobject_cast<
const QInputDevice *>(mouse->parent()))
331 }
else if (dev->type() == QInputDevice::DeviceType::TouchPad) {
332 if (!touchpad || !dev->parent() || dev->parent()->metaObject() != dev->metaObject())
333 touchpad =
static_cast<
const QPointingDevice *>(dev);
336 if (!mouse && !touchpad) {
337 qCDebug(lcQpaInputDevices) <<
"no mouse-like devices registered for seat" << seatName
338 <<
"The platform plugin should have provided one via "
339 "QWindowSystemInterface::registerInputDevice(). Creating a default mouse for now.";
340 mouse =
new QPointingDevice(
"core pointer"_L1, 1, DeviceType::Mouse,
341 PointerType::Generic, Capability::Position, 1, 3, seatName,
342 QPointingDeviceUniqueId(), QCoreApplication::instance());
343 QInputDevicePrivate::registerDevice(mouse);
347 qCDebug(lcQpaInputDevices) <<
"core pointer ambiguous for seat" << seatName;
372const QPointingDevice *QPointingDevicePrivate::queryTabletDevice(QInputDevice::DeviceType deviceType,
373 QPointingDevice::PointerType pointerType,
374 QPointingDeviceUniqueId uniqueId,
375 QPointingDevice::Capabilities capabilities,
378 const auto &devices = QInputDevice::devices();
379 for (
const QInputDevice *dev : devices) {
380 if (dev->type() < QPointingDevice::DeviceType::Puck || dev->type() > QPointingDevice::DeviceType::Airbrush)
382 const QPointingDevice *pdev =
static_cast<
const QPointingDevice *>(dev);
383 const auto devPriv = QPointingDevicePrivate::get(pdev);
384 bool uniqueIdDiscovered = (devPriv->uniqueId.numericId() == 0 && uniqueId.numericId() != 0);
385 if (devPriv->deviceType == deviceType && devPriv->pointerType == pointerType &&
386 (!systemId || devPriv->systemId == systemId) &&
387 (devPriv->uniqueId == uniqueId || uniqueIdDiscovered)) {
388 if (uniqueIdDiscovered) {
389 const_cast<QPointingDevicePrivate *>(devPriv)->uniqueId = uniqueId;
391 const_cast<QPointingDevicePrivate *>(devPriv)->capabilities = capabilities;
392 qCDebug(lcQpaInputDevices) <<
"discovered unique ID and capabilities of tablet tool" << pdev;
405const QPointingDevice *QPointingDevicePrivate::pointingDeviceById(qint64 systemId)
407 const auto &devices = QInputDevice::devices();
408 for (
const QInputDevice *dev : devices) {
409 if (dev->type() >= QPointingDevice::DeviceType::Keyboard)
411 const QPointingDevice *pdev =
static_cast<
const QPointingDevice *>(dev);
412 const auto devPriv = QPointingDevicePrivate::get(pdev);
413 if (devPriv->systemId == systemId)
425void QPointingDevicePrivate::sendTouchCancelEvent(QTouchEvent *cancelEvent)
431 if (cancelEvent->points().isEmpty()) {
432 for (
auto &epd : activePoints.values()) {
433 if (epd.exclusiveGrabber)
434 QMutableTouchEvent::addPoint(cancelEvent, epd.eventPoint);
437 for (
auto &epd : activePoints.values()) {
438 if (epd.exclusiveGrabber)
439 QCoreApplication::sendEvent(epd.exclusiveGrabber, cancelEvent);
441 cancelEvent->setExclusiveGrabber(epd.eventPoint,
nullptr);
442 cancelEvent->clearPassiveGrabbers(epd.eventPoint);
462QPointingDevicePrivate::EventPointData *QPointingDevicePrivate::pointById(
int id)
const
464 const auto [it, inserted] = activePoints.try_emplace(id);
466 Q_Q(
const QPointingDevice);
467 auto &epd = it.value();
468 QMutableEventPoint::setId(epd.eventPoint, id);
469 QMutableEventPoint::setDevice(epd.eventPoint, q);
526void QPointingDevicePrivate::setExclusiveGrabber(
const QPointerEvent *event,
const QEventPoint &point, QObject *exclusiveGrabber)
528 Q_Q(QPointingDevice);
529 auto persistentPoint = queryPointById(point.id());
530 if (!persistentPoint) {
531 qWarning() <<
"point is not in activePoints" << point;
534 Q_ASSERT(persistentPoint->eventPoint.id() == point.id());
535 if (persistentPoint->exclusiveGrabber == exclusiveGrabber)
537 auto oldGrabber = persistentPoint->exclusiveGrabber;
538 persistentPoint->exclusiveGrabber = exclusiveGrabber;
540 emit q->grabChanged(oldGrabber, exclusiveGrabber ? QPointingDevice::CancelGrabExclusive : QPointingDevice::UngrabExclusive,
541 event, persistentPoint->eventPoint);
542 if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
543 qCDebug(lcPointerGrab) << name <<
"point" << point.id() << point.state()
544 <<
"@" << point.scenePosition()
545 <<
": grab" << oldGrabber <<
"->" << exclusiveGrabber;
547 QMutableEventPoint::setGlobalGrabPosition(persistentPoint->eventPoint, point.globalPosition());
548 if (exclusiveGrabber)
549 emit q->grabChanged(exclusiveGrabber, QPointingDevice::GrabExclusive, event, point);
551 persistentPoint->exclusiveGrabberContext.clear();
558bool QPointingDevicePrivate::removeExclusiveGrabber(
const QPointerEvent *event,
const QObject *grabber)
561 for (
auto &pt : activePoints.values()) {
562 if (pt.exclusiveGrabber == grabber) {
563 setExclusiveGrabber(event, pt.eventPoint,
nullptr);
570bool QPointingDevicePrivate::addPassiveGrabber(
const QPointerEvent *event,
const QEventPoint &point, QObject *grabber)
572 Q_Q(QPointingDevice);
573 auto persistentPoint = queryPointById(point.id());
574 if (!persistentPoint) {
575 qWarning() <<
"point is not in activePoints" << point;
578 if (persistentPoint->passiveGrabbers.contains(grabber))
580 if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
581 qCDebug(lcPointerGrab) << name <<
"point" << point.id() << point.state()
582 <<
": grab (passive)" << grabber;
584 persistentPoint->passiveGrabbers << grabber;
585 emit q->grabChanged(grabber, QPointingDevice::GrabPassive, event, point);
589bool QPointingDevicePrivate::setPassiveGrabberContext(QPointingDevicePrivate::EventPointData *epd, QObject *grabber, QObject *context)
591 qsizetype i = epd->passiveGrabbers.indexOf(grabber);
594 if (epd->passiveGrabbersContext.size() <= i)
595 epd->passiveGrabbersContext.resize(i + 1);
596 epd->passiveGrabbersContext[i] = context;
600bool QPointingDevicePrivate::removePassiveGrabber(
const QPointerEvent *event,
const QEventPoint &point, QObject *grabber)
602 Q_Q(QPointingDevice);
603 auto persistentPoint = queryPointById(point.id());
604 if (!persistentPoint) {
605 qWarning() <<
"point is not in activePoints" << point;
608 qsizetype i = persistentPoint->passiveGrabbers.indexOf(grabber);
610 if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
611 qCDebug(lcPointerGrab) << name <<
"point" << point.id() << point.state()
612 <<
": removing passive grabber" << grabber;
614 emit q->grabChanged(grabber, QPointingDevice::UngrabPassive, event, point);
615 persistentPoint->passiveGrabbers.removeAt(i);
616 if (persistentPoint->passiveGrabbersContext.size()) {
617 Q_ASSERT(persistentPoint->passiveGrabbersContext.size() > i);
618 persistentPoint->passiveGrabbersContext.removeAt(i);
625void QPointingDevicePrivate::clearPassiveGrabbers(
const QPointerEvent *event,
const QEventPoint &point)
627 Q_Q(QPointingDevice);
628 auto persistentPoint = queryPointById(point.id());
629 if (!persistentPoint) {
630 qWarning() <<
"point is not in activePoints" << point;
633 if (persistentPoint->passiveGrabbers.isEmpty())
635 if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
636 qCDebug(lcPointerGrab) << name <<
"point" << point.id() << point.state()
637 <<
": clearing" << persistentPoint->passiveGrabbers;
639 for (
auto g : persistentPoint->passiveGrabbers)
640 emit q->grabChanged(g, QPointingDevice::UngrabPassive, event, point);
641 persistentPoint->passiveGrabbers.clear();
642 persistentPoint->passiveGrabbersContext.clear();
656void QPointingDevicePrivate::removeGrabber(QObject *grabber,
bool cancel)
658 Q_Q(QPointingDevice);
659 for (
auto ap : activePoints) {
660 auto &epd = ap.second;
661 if (epd.exclusiveGrabber.data() == grabber) {
662 qCDebug(lcPointerGrab) << name <<
"point" << epd.eventPoint.id() << epd.eventPoint.state()
663 <<
"@" << epd.eventPoint.scenePosition()
664 <<
": grab" << grabber <<
"-> nullptr";
665 epd.exclusiveGrabber.clear();
666 epd.exclusiveGrabberContext.clear();
667 emit q->grabChanged(grabber,
668 cancel ? QPointingDevice::CancelGrabExclusive : QPointingDevice::UngrabExclusive,
669 nullptr, epd.eventPoint);
671 qsizetype pi = epd.passiveGrabbers.indexOf(grabber);
673 qCDebug(lcPointerGrab) << name <<
"point" << epd.eventPoint.id() << epd.eventPoint.state()
674 <<
": removing passive grabber" << grabber;
675 epd.passiveGrabbers.removeAt(pi);
676 if (epd.passiveGrabbersContext.size()) {
677 Q_ASSERT(epd.passiveGrabbersContext.size() > pi);
678 epd.passiveGrabbersContext.removeAt(pi);
680 emit q->grabChanged(grabber,
681 cancel ? QPointingDevice::CancelGrabPassive : QPointingDevice::UngrabPassive,
682 nullptr, epd.eventPoint);
697const QPointingDevice *QPointingDevicePrivate::tabletDevice(QInputDevice::DeviceType deviceType,
698 QPointingDevice::PointerType pointerType,
699 QPointingDeviceUniqueId uniqueId)
701 const QPointingDevice *dev = queryTabletDevice(deviceType, pointerType, uniqueId);
703 qCDebug(lcQpaInputDevices) <<
"failed to find registered tablet device"
704 << deviceType << pointerType << Qt::hex << uniqueId.numericId()
705 <<
"The platform plugin should have provided one via "
706 "QWindowSystemInterface::registerInputDevice(). Creating a default one for now.";
707 dev =
new QPointingDevice(
"fake tablet"_L1, 2, deviceType, pointerType,
708 QInputDevice::Capability::Position | QInputDevice::Capability::Pressure,
709 1, 1, QString(), uniqueId, QCoreApplication::instance());
710 QInputDevicePrivate::registerDevice(dev);
726QDebug operator<<(QDebug debug,
const QPointingDevice *device)
728 QDebugStateSaver saver(debug);
731 debug <<
"QPointingDevice(";
733 debug <<
'"' << device->name() <<
"\" ";
734 QtDebugUtils::formatQEnum(debug, device->type());
735 debug <<
" id=" << device->systemId();
736 if (!device->seatName().isEmpty())
737 debug <<
" seat=" << device->seatName();
738 if (device->pointerType() != QPointingDevice::PointerType::Generic) {
739 debug <<
" ptrType=";
740 QtDebugUtils::formatQEnum(debug, device->pointerType());
742 if (
int(device->capabilities()) !=
int(QInputDevice::Capability::Position)) {
744 QtDebugUtils::formatQFlags(debug, device->capabilities());
746 if (device->buttonCount() > 0)
747 debug <<
" buttonCount=" << device->buttonCount();
748 if (device->maximumPoints() > 1)
749 debug <<
" maxPts=" << device->maximumPoints();
750 if (device->uniqueId().isValid())
751 debug <<
" uniqueId=" << Qt::hex << device->uniqueId().numericId() << Qt::dec;