Qt5-触摸屏输入事件分析

一、引言

    由于需要分析qtbase中的触摸屏处理事件,所以下载源码进行分析。思路为:widgets窗口线程起来之后,怎样通过libinput进行触摸识别。(理解了触摸屏的识别之后,键盘、鼠标、案件的识别也是类似的)

二、源码分析 

路径:qtbase/src/widgets/kernel/qgesturemanager.cpp 
 for (ContextIterator context = contexts.begin(); context != contextEnd; ++context) {
        Qt::GestureType gestureType = context.value();
        const QMap<Qt::GestureType, QGestureRecognizer *> &const_recognizers = m_recognizers;
        QMap<Qt::GestureType, QGestureRecognizer *>::const_iterator
                typeToRecognizerIterator = const_recognizers.lowerBound(gestureType),
                typeToRecognizerEnd = const_recognizers.upperBound(gestureType);
        for (; typeToRecognizerIterator != typeToRecognizerEnd; ++typeToRecognizerIterator) {
            QGestureRecognizer *recognizer = typeToRecognizerIterator.value();
            QObject *target = context.key();  //获取事件key码
            QGesture *state = getState(target, recognizer, gestureType);//通过key码来确定事件类型的状态
            if (!state)
                continue;
            QGestureRecognizer::Result recognizerResult = recognizer->recognize(state, target, event);
            QGestureRecognizer::Result recognizerState = recognizerResult & QGestureRecognizer::ResultState_Mask;
            QGestureRecognizer::Result resultHint = recognizerResult & QGestureRecognizer::ResultHint_Mask;
            if (recognizerState == QGestureRecognizer::TriggerGesture) {
                qCDebug(lcGestureManager) << "QGestureManager:Recognizer: gesture triggered: " << state << event;
                triggeredGestures << state;
            } else if (recognizerState == QGestureRecognizer::FinishGesture) {
                qCDebug(lcGestureManager) << "QGestureManager:Recognizer: gesture finished: " << state << event;
                finishedGestures << state;
            } else if (recognizerState == QGestureRecognizer::MayBeGesture) {
                qCDebug(lcGestureManager) << "QGestureManager:Recognizer: maybe gesture: " << state << event;//触摸屏事件类型输出
                newMaybeGestures << state;
            } else if (recognizerState == QGestureRecognizer::CancelGesture) {
                qCDebug(lcGestureManager) << "QGestureManager:Recognizer: not gesture: " << state << event;
                notGestures << state;
            } else if (recognizerState == QGestureRecognizer::Ignore) {
                qCDebug(lcGestureManager) << "QGestureManager:Recognizer: ignored the event: " << state << event;
            } else {
                qCDebug(lcGestureManager) << "QGestureManager:Recognizer: hm, lets assume the recognizer"
                        << "ignored the event: " << state << event;
            }
            if (resultHint & QGestureRecognizer::ConsumeEventHint) {
                qCDebug(lcGestureManager) << "QGestureManager: we were asked to consume the event: "
                        << state << event;
                consumeEventHint = true;
            }
        }
    }
state << event类型的来源:qtbase/src/platformsupport/input/libinput/qlibinputtouch.cpp
//触屏被按下
void QLibInputTouch::processTouchDown(libinput_event_touch *e)
{
    int slot = libinput_event_touch_get_slot(e);//输入事件的获取是通过libinput
    DeviceState *state = deviceState(e);
    QWindowSystemInterface::TouchPoint *tp = state->point(slot);
    if (tp) {
        qWarning("Incorrect touch state");
    } else {
        QWindowSystemInterface::TouchPoint newTp;
        newTp.id = qMax(0, slot);
        newTp.state = Qt::TouchPointPressed;//手指按下
        newTp.area = QRect(0, 0, 8, 8);
        newTp.area.moveCenter(getPos(e));
        state->m_points.append(newTp);//将按下的状态数据存储到state中
    }
}
//手指松开
void QLibInputTouch::processTouchUp(libinput_event_touch *e)
{
    int slot = libinput_event_touch_get_slot(e);
    DeviceState *state = deviceState(e);
    QWindowSystemInterface::TouchPoint *tp = state->point(slot);
    if (tp) {
        tp->state = Qt::TouchPointReleased;
        // There may not be a Frame event after the last Up. Work this around.
        Qt::TouchPointStates s = 0;
        for (int i = 0; i < state->m_points.count(); ++i)//触控的点数
            s |= state->m_points.at(i).state;
        if (s == Qt::TouchPointReleased)
            processTouchFrame(e);//多点触控处理
    } else {
        qWarning("Inconsistent touch state (got 'up' without 'down')");
    }
}
void QLibInputTouch::processTouchFrame(libinput_event_touch *e)
{
    DeviceState *state = deviceState(e);
    if (!state->m_touchDevice) {
        qWarning("TouchFrame without registered device"); 
        return;
    }
    if (state->m_points.isEmpty())
        return;

    QWindowSystemInterface::handleTouchEvent(Q_NULLPTR, state->m_touchDevice, state->m_points,
                                             QGuiApplication::keyboardModifiers());

    for (int i = 0; i < state->m_points.count(); ++i) {
        QWindowSystemInterface::TouchPoint &tp(state->m_points[i]);
        if (tp.state == Qt::TouchPointReleased)
            state->m_points.removeAt(i--);//每松开一个手指,则触控的点数减1
        else if (tp.state == Qt::TouchPointPressed)
            tp.state = Qt::TouchPointStationary;
    }
}

processTouchDown和processTouchUp事件处理是怎么来的呢?

见路径:qtbase/src/platformsupport/input/libinput/qlibinputhandler.cpp

首先看一下头文件定义:

class QLibInputHandler : public QObject
{
    Q_OBJECT

public:
    QLibInputHandler(const QString &key, const QString &spec);
    ~QLibInputHandler();

signals:
    void deviceAdded(const QString &sysname, const QString &name);
    void deviceRemoved(const QString &sysname, const QString &name);

private slots:
    void onReadyRead();
    void onCursorPositionChangeRequested(const QPoint &pos);

private:
    void processEvent(libinput_event *ev);

    udev *m_udev;
    libinput *m_li;  //libinput定义
    int m_liFd;
    QScopedPointer<QSocketNotifier> m_notifier;//监听系统文件操作,将操作转换为Qt事件进入系统的消息循环队列
    QScopedPointer<QLibInputPointer> m_pointer;
    QScopedPointer<QLibInputKeyboard> m_keyboard;
    QScopedPointer<QLibInputTouch> m_touch;
    QMap<int, int> m_devCount;
};

然后.cpp文件分析:

m_li = libinput_udev_create_context(&liInterface, Q_NULLPTR, m_udev);
    if (Q_UNLIKELY(!m_li))
        qFatal("Failed to get libinput context");

    libinput_log_set_handler(m_li, liLogHandler);
    if (qLcLibInput().isDebugEnabled())
        libinput_log_set_priority(m_li, LIBINPUT_LOG_PRIORITY_DEBUG);

    if (Q_UNLIKELY(libinput_udev_assign_seat(m_li, "seat0")))
        qFatal("Failed to assign seat");

    m_liFd = libinput_get_fd(m_li);
	qDebug() << "[qlibinputhandler.cpp] m_liFd is: " << m_liFd;
    m_notifier.reset(new QSocketNotifier(m_liFd, QSocketNotifier::Read));
//若监听到发生触摸、按键等事件,立即通知onReadyRead
    connect(m_notifier.data(), SIGNAL(activated(int)), SLOT(onReadyRead()));
void QLibInputHandler::onReadyRead()
{
    qDebug() << "have a event";
	qDebug() << "[qlibinputhandler.cpp] enter to onReadyRead";
    if (libinput_dispatch(m_li)) {
        qWarning("libinput_dispatch failed");
        return;
    }

    libinput_event *ev;
    while ((ev = libinput_get_event(m_li)) != Q_NULLPTR) {
        processEvent(ev);  //按键处理事件
        libinput_event_destroy(ev);
    }
}

在processEvent(ev)中进行了一系列的处理:

void QLibInputHandler::processEvent(libinput_event *ev)
{
    libinput_event_type type = libinput_event_get_type(ev); //按键的事件类型
    qDebug() << "[qlibinputhandler.cpp] libinput_event_type is: " << type;
    libinput_device *dev = libinput_event_get_device(ev);
	
    switch (type) {
    case LIBINPUT_EVENT_DEVICE_ADDED:
    {
       .
       .
       .
    case LIBINPUT_EVENT_TOUCH_DOWN://触摸事件处理
        m_touch->processTouchDown(libinput_event_get_touch_event(ev));
        break;
    case LIBINPUT_EVENT_TOUCH_MOTION://触摸移动处理
        m_touch->processTouchMotion(libinput_event_get_touch_event(ev));
        break;
    case LIBINPUT_EVENT_TOUCH_UP://触摸松开处理
        m_touch->processTouchUp(libinput_event_get_touch_event(ev));
        break;
    case LIBINPUT_EVENT_TOUCH_CANCEL:
        m_touch->processTouchCancel(libinput_event_get_touch_event(ev));
        break;
    case LIBINPUT_EVENT_TOUCH_FRAME:
        m_touch->processTouchFrame(libinput_event_get_touch_event(ev));
        break;
    default:
        break;
    }
}

到此与qtbase/src/platformsupport/input/libinput/qlibinputtouch.cpp中的各类触摸事件结合了起来。

上述事件的流程图如下所示:

  • 3
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值