0
votes

TabletEvents comes as mouse events.

Actual for MAC OS Qt 4.8.0 - 4.8.5. Works fine in Qt 4.7.3 on any OS and Qt 4.8.0 on Windows and Linux.

I have two instances of QGraphcisScene and two instances of QGraphicsView. The same types, but one view have a parent, and the another - doesn't (also it's transparent, used for drawing something over desktop).

I'm using tablet (wacom pen and touch) for painting. I handle QTabletEvents and it works only for QGrahicsView instance that doesn't have parent (means parent==0).

On the view with parent (

QMainWindow->centralWidget->ControlContainerWidget->QStackedLayout->QGraphicsView

) tablet events doesn't comes. They comes to QApplication::eventFilter fine, but doesn't comes to view. They comes to QMainWindow as mouseEvents. If i set parent to 0, tablet events delivers fine.

The 1st receiver of tablet event is QMainWindow. I see that inside qt_mac_handleTabletEvent:

QWidget *qwidget = [theView qt_qwidget];
QWidget *widgetToGetMouse = qwidget;

And then:

`qt_sendSpontaneousEvent(widgetToGetMouse, &qtabletEvent);`

qtabletEvent - is not accepted event created just before calling sendSpontaneousEvent.

Then inside QApplication::notify():

QWidget *w = static_cast<QWidget *>(receiver);
QTabletEvent *tablet = static_cast<QTabletEvent*>(e);
QPoint relpos = tablet->pos();
bool eventAccepted = tablet->isAccepted();
while (w) {
    QTabletEvent te(tablet->type(), relpos, tablet->globalPos(),
                    tablet->hiResGlobalPos(), tablet->device(), tablet->pointerType(),
                    tablet->pressure(), tablet->xTilt(), tablet->yTilt(),
                    tablet->tangentialPressure(), tablet->rotation(), tablet->z(),
                    tablet->modifiers(), tablet->uniqueId());
                    te.spont = e->spontaneous();
    res = d->notify_helper(w, w == receiver ? tablet : &te);
    eventAccepted = ((w == receiver) ? tablet : &te)->isAccepted();
    e->spont = false;
    if ((res && eventAccepted)
         || w->isWindow()
         || w->testAttribute(Qt::WA_NoMousePropagation))
        break;

    relpos += w->pos();
    w = w->parentWidget();
    }
    tablet->setAccepted(eventAccepted);

As we can see:

res = d->notify_helper(w, w == receiver ? tablet : &te);

It calls event processing by filters, layouts and then - QMainWindow::tabletEvent. Default implementation is event->ignore().

Since QMainWindow have no Parent, it is all. So tablet event doesn't comes to QMainWindow childs.

Then seems it is QWidget *qwidget = [theView qt_qwidget]; works wrong. Unfortunately, i can't debug it...

Please give me some hints... i'm stucked...

1
check out this post it may be relatedixSci
Thanks, but it is workaround and it will not helps me. Standard QWidget::tabletEvent() can be overloaded for the case you gave me. But it is not the problem. Problems appeared just on MAC OS. On windows and on Linux all is fine.Inq
your question is diffused inside lot of code. What is exactly your issue? Put it on top of your post.UmNyobe
On MAC OS tabletEvents doesn't comes to right widget as it happens under Windows and linux. But it works fine with qt 4.7.3.Inq

1 Answers

0
votes

I spent more time on comparison Qt 4.8.0 and 4.7.3 and now i see that it is the problem in internal qt event dispatcher. It sends event to NSWindow (QMainWindow) instead of NSView (QGraphicsView). I didn't found where is the problem, but i found that QMainWindow returns false from ::event() method. So i reimplemented that method and parsed tablet event there:

bool UBMainWindow::event(QEvent *event)
{
    bool bRes = QMainWindow::event(event);

    if (NULL != UBApplication::boardController)
    {
        UBBoardView *controlV = UBApplication::boardController->controlView();
        if (controlV && controlV->isVisible())
        {
            switch (event->type())
            {
            case QEvent::TabletEnterProximity:
            case QEvent::TabletLeaveProximity:
            case QEvent::TabletMove:
            case QEvent::TabletPress:
            case QEvent::TabletRelease:
                {
                    return controlV->directTabletEvent(event);
                }
            }
        }
    }
    return bRes;
}

The problem is: i need to use tablet for any controls in application, so i need to determine when QGraphicsView is under mouse cursor:

bool UBBoardView::directTabletEvent(QEvent *event)
{
    QTabletEvent *tEvent = static_cast<QTabletEvent *>(event);
    tEvent = new QTabletEvent(tEvent->type()
        , mapFromGlobal(tEvent->pos())
        , tEvent->globalPos()
        , tEvent->hiResGlobalPos()
        , tEvent->device()
        , tEvent->pointerType()
        , tEvent->pressure()
        , tEvent->xTilt()
        , tEvent->yTilt()
        , tEvent->tangentialPressure()
        , tEvent->rotation()
        , tEvent->z()
        , tEvent->modifiers()
        , tEvent->uniqueId());

    if (geometry().contains(tEvent->pos()))
    {
        if (NULL == widgetForTabletEvent(this->parentWidget(), tEvent->pos()))
        {
            tabletEvent(tEvent);
            return true;
        }
    }
    return false;
}

Also i need to stop handle tablet events for QGraphicsView childs.

QWidget *UBBoardView::widgetForTabletEvent(QWidget *w, const QPoint &pos)
{
    Q_ASSERT(w);


    UBBoardView *board = qobject_cast<UBBoardView *>(w);

    QWidget *childAtPos = NULL;

    QList<QObject *> childs = w->children();
    foreach(QObject *child, childs)
    {
        QWidget *childWidget = qobject_cast<QWidget *>(child);
        if (childWidget)
        {
            if (childWidget->isVisible() && childWidget->geometry().contains(pos))
            {
                QWidget *lastChild = widgetForTabletEvent(childWidget, pos);

                if (board && board->viewport() == lastChild)
                    continue;

                if (NULL != lastChild)
                    childAtPos = lastChild;
                else
                    childAtPos = childWidget;

                break;
            }
            else
                childAtPos = NULL;
        }
    }
    return childAtPos;
}

Maybe when i will have more time - i will investigate qt more deeply and fix that problem at all.