Beispiel #1
0
/**
 * Handle tablet proximity events. When the eraser is brought near
 * the tablet surface, switch to eraser tool on all windows.
 * When the tip leaves the surface, switch back to whatever tool
 * we were using before.
 *
 * Also, on MacOS we must also handle the Open File event.
 */
bool DrawpileApp::event(QEvent *e) {
    if(e->type() == QEvent::TabletEnterProximity || e->type() == QEvent::TabletLeaveProximity) {
        QTabletEvent *te = static_cast<QTabletEvent*>(e);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
        if(te->pointerType()==QTabletEvent::Eraser)
            emit eraserNear(e->type() == QEvent::TabletEnterProximity);
#else
        if(e->type() == QEvent::TabletEnterProximity) {
            if(te->pointerType()==QTabletEvent::Eraser)
                emit eraserNear(true);
            else
                emit eraserNear(false);
        }
#endif
        return true;

    } else if(e->type() == QEvent::FileOpen) {
        QFileOpenEvent *fe = static_cast<QFileOpenEvent*>(e);

        // Note. This is currently broken in Qt 5.3.1:
        // https://bugreports.qt-project.org/browse/QTBUG-39972
        openUrl(fe->url());

        return true;
    }

    return QApplication::event(e);
}
Beispiel #2
0
bool TabletWidget::eventFilter(QObject *, QEvent *ev)
{
    switch (ev->type()) {
    case QEvent::TabletEnterProximity:
    case QEvent::TabletLeaveProximity:
    case QEvent::TabletMove:
    case QEvent::TabletPress:
    case QEvent::TabletRelease:
        {
            QTabletEvent *event = static_cast<QTabletEvent*>(ev);
            mType = event->type();
            mPos = event->pos();
            mGPos = event->globalPos();
            mHiResGlobalPos = event->hiResGlobalPos();
            mDev = event->device();
            mPointerType = event->pointerType();
            mUnique = event->uniqueId();
            mXT = event->xTilt();
            mYT = event->yTilt();
            mZ = event->z();
            mPress = event->pressure();
            mTangential = event->tangentialPressure();
            mRot = event->rotation();
            mButton = event->button();
            mButtons = event->buttons();
            if (isVisible())
                update();
            break;
        }
    case QEvent::MouseMove:
        if (mMouseToo) {
            resetAttributes();
            QMouseEvent *event = static_cast<QMouseEvent*>(ev);
            mType = event->type();
            mPos = event->pos();
            mGPos = event->globalPos();
        }
    default:
        break;
    }
    return false;
}
// override QApplication::notify() for greatest control over event handling
bool TouchApplication::notify(QObject* receiver, QEvent* event)
{
  //DebugEventFilter::printEvent(receiver, event);
  QEvent::Type evtype = event->type();
  // first, try to pass TabletPress/TouchBegin event and see if anyone accepts it
  // In Qt, events are first sent to a QWindow, which then figures out what widget they should be sent to.
  // Unfortunately, QWindow event handler always returns true and doesn't change accepted state of event (it
  //  sends a copy of the event and discards the accepted state of the copy), so we must save result from
  //  sending event to final widget (by incrementing acceptCount)
  // When faking mouse events, we must send them to the QWindow instead of a widget, since some of the
  //  routing logic is there, e.g., for handling popup windows
  if((evtype == QEvent::TabletPress || evtype == QEvent::TouchBegin) && inputState == None) {
    if(receiver->isWindowType()) {
      int prevacceptcount = acceptCount;
      receiver = getRecvWindow(receiver);
      QApplication::notify(receiver, event);
      if(acceptCount > prevacceptcount) {
        acceptCount = prevacceptcount;
        inputState = PassThru;
        return true;
      }
      // else, fall through and resend as mouse event
      // we must send a tablet release to put QWidgetWindow in consistent state
      //  doesn't appear to be necessary for TouchBegin
      if(evtype == QEvent::TabletPress) {
        QTabletEvent* tev = static_cast<QTabletEvent*>(event);
        QTabletEvent rlev(QEvent::TabletRelease, tev->posF(), tev->globalPosF(), tev->device(),
                                 tev->pointerType(), 0, 0, 0, 0, 0, 0, tev->modifiers(), tev->uniqueId());
        QApplication::notify(receiver, &rlev);
      }
    }
    else {
      event->setAccepted(false);
      bool res = QApplication::notify(receiver, event);
      if(event->isAccepted())
        acceptCount++;
      return res;
    }
  }

  switch(evtype) {
  // reject external mouse events if we are translating touch or tablet input
  case QEvent::MouseButtonRelease:
  case QEvent::MouseMove:
  case QEvent::MouseButtonPress:
    // QWidgetWindow always forwards mouse event to widget as spontaneous event (why?)
    if(inputState != None && event->spontaneous() && receiver->isWindowType())
      return true;   // qDebug("This event should be rejected!");
    break;
  case QEvent::TabletRelease:
    if(inputState == PassThru)
      inputState = None;
  case QEvent::TabletMove:
  case QEvent::TabletPress:
  {
    // TODO: should this only be done if inputState == TabletInput?
    receiver = getRecvWindow(receiver);
    QTabletEvent* tabletevent = static_cast<QTabletEvent*>(event);
    QEvent::Type mevtype = QEvent::MouseMove;
    if(inputState == None && evtype == QEvent::TabletPress) {
      mevtype = QEvent::MouseButtonPress;
      inputState = TabletInput;
    }
    else if(inputState != TabletInput)  // this covers PassThru
      break;
    if(evtype == QEvent::TabletRelease) {
      mevtype = QEvent::MouseButtonRelease;
      inputState = None;
    }
    return sendMouseEvent(receiver, mevtype, tabletevent->globalPos(), tabletevent->modifiers());
  }
#ifdef QT_5
  case QEvent::TouchCancel:
    evtype = QEvent::TouchEnd;
#endif
  case QEvent::TouchEnd:
    if(inputState == PassThru) // && touchPoints.count() == 1)
      inputState = None;
  case QEvent::TouchUpdate:
  case QEvent::TouchBegin:
  {
    receiver = getRecvWindow(receiver);
    QTouchEvent* touchevent = static_cast<QTouchEvent*>(event);
    QEvent::Type mevtype = QEvent::MouseMove;
    if(inputState == None && evtype == QEvent::TouchBegin
        && touchevent->touchPoints().size() == 1 && touchevent->device()->type() != QTouchDevice::TouchPad) {
      activeTouchId = touchevent->touchPoints().first().id();
      mevtype = QEvent::MouseButtonPress;
      inputState = TouchInput;
    }
    else if(inputState != TouchInput)  // this covers PassThru
      break;
    if(evtype == QEvent::TouchEnd)
      inputState = None;
    event->setAccepted(true);
    QList<QTouchEvent::TouchPoint> touchPoints = touchevent->touchPoints();
    for(int ii = 0; ii < touchPoints.count(); ++ii) {
      const QTouchEvent::TouchPoint& touchpt = touchPoints.at(ii);
      if(touchpt.id() == activeTouchId) {
        if(touchpt.state() == Qt::TouchPointReleased) {
          mevtype = QEvent::MouseButtonRelease;
          activeTouchId = -1;
        }
        return sendMouseEvent(receiver, mevtype, touchpt.screenPos().toPoint(), touchevent->modifiers());
      }
    }
    // swallow all touch events until TouchEnd
    // another option would be to propagate the touch event with the activeTouchId point removed, if >1 point
    return true;
  }
  default:
    break;
  }
  return QApplication::notify(receiver, event);
}