Beispiel #1
0
/**
 * Tablet events are handled here
 * @param event event info
 */
bool CanvasView::viewportEvent(QEvent *event)
{
	if(event->type() == QEvent::Gesture) {
		gestureEvent(static_cast<QGestureEvent*>(event));

	} else if(event->type() == QEvent::TabletMove && _enableTabletEvents) {
		// Stylus moved
		QTabletEvent *tabev = static_cast<QTabletEvent*>(event);
		tabev->accept();

		paintcore::Point point = mapToScene(tabev->posF(), tabev->pressure());
		updateOutline(point);

		if(!_prevpoint.intSame(point)) {
			if(_isdragging)
				moveDrag(tabev->x(), tabev->y());
			else {
				if(_pendown) {
					_pointervelocity = point.distance(_prevpoint);
					_pointerdistance += _pointervelocity;
					point.setPressure(mapPressure(point.pressure(), true));
					onPenMove(point, false, tabev->modifiers() & Qt::ShiftModifier, tabev->modifiers() & Qt::AltModifier);
				}
			}
			_prevpoint = point;
		}
	} else if(event->type() == QEvent::TabletPress && _enableTabletEvents) {
		// Stylus touches the tablet surface
		QTabletEvent *tabev = static_cast<QTabletEvent*>(event);
		tabev->accept();

		if(_dragbtndown) {
			startDrag(tabev->x(), tabev->y(), _dragbtndown);
		} else {
			if(_pendown == NOTDOWN) {
				_pointerdistance = 0;
				_pointervelocity = 0;

				const paintcore::Point point = mapToScene(tabev->posF(), mapPressure(tabev->pressure(), true));

				_specialpenmode = tabev->modifiers() & Qt::ControlModifier; /* note: modifiers doesn't seem to work, at least on Qt 5.2.0 */
				_pendown = TABLETDOWN;
				onPenDown(point, false);
				updateOutline(point);
				_prevpoint = point;

			}
		}
	} else if(event->type() == QEvent::TabletRelease && _enableTabletEvents) {
		// Stylus lifted
		// Ignore this event: a mouseRelease event is also generated, so we let
		// the mouseRleaseEvent function handle this.
	} else {
		return QGraphicsView::viewportEvent(event);
	}
	
	return true;
}
// 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);
}