Qt之Gui的事件转换

文章详细解释了QGuiApplication如何通过QWindowSystemInterface处理window系统事件,以及QEvdevKeyboardPlugin和QEvdevMousePlugin如何创建和管理输入设备,涉及QEvdevMouseManager的事件分发和QWindowSystemInterface事件转换。重点讨论了QPA(Qt平台抽象)在事件处理中的角色。
摘要由CSDN通过智能技术生成

QGuiApplication的实现类QGuiApplicationPrivate方法processWindowSystemEvent处理window系统事件

static void processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e);

在QWindowSystemInterface的处理事件方法中会调用上面的processWindowSystemEvent方法

flushWindowSystemEvents发送消息
QT_DEFINE_QPA_EVENT_HANDLER
定义为

#define QT_DEFINE_QPA_EVENT_HANDLER(ReturnType, HandlerName, ...) \
    template Q_GUI_EXPORT ReturnType QWindowSystemInterface::HandlerName<QWindowSystemInterface::DefaultDelivery>(__VA_ARGS__); \
    template Q_GUI_EXPORT ReturnType QWindowSystemInterface::HandlerName<QWindowSystemInterface::SynchronousDelivery>(__VA_ARGS__); \
    template Q_GUI_EXPORT ReturnType QWindowSystemInterface::HandlerName<QWindowSystemInterface::AsynchronousDelivery>(__VA_ARGS__); \
    template<typename Delivery> ReturnType QWindowSystemInterface::HandlerName(__VA_ARGS__)

QGuiApplication初始化时会加载QGeneralPlugin

  • 键盘对应 QEvdevKeyboardPlugin,创建QEvdevKeyboardManager
QEvdevMouseManager::QEvdevMouseManager(const QString &key, const QString &specification, QObject *parent)
    : QObject(parent), m_x(0), m_y(0), m_xoffset(0), m_yoffset(0)
{
    Q_UNUSED(key);

    QString spec = QString::fromLocal8Bit(qgetenv("QT_QPA_EVDEV_MOUSE_PARAMETERS"));

    if (spec.isEmpty())
        spec = specification;

    auto parsed = QEvdevUtil::parseSpecification(spec);
    m_spec = std::move(parsed.spec);

    for (const QStringRef &arg : qAsConst(parsed.args)) {
        if (arg.startsWith(QLatin1String("xoffset="))) {
            m_xoffset = arg.mid(8).toInt();
        } else if (arg.startsWith(QLatin1String("yoffset="))) {
            m_yoffset = arg.mid(8).toInt();
        }
    }

    // add all mice for devices specified in the argument list
    for (const QString &device : qAsConst(parsed.devices))
        addMouse(device);

    if (parsed.devices.isEmpty()) {
        qCDebug(qLcEvdevMouse, "evdevmouse: Using device discovery");
        if (auto deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Mouse | QDeviceDiscovery::Device_Touchpad, this)) {
            // scan and add already connected keyboards
            const QStringList devices = deviceDiscovery->scanConnectedDevices();
            for (const QString &device : devices)
                addMouse(device);

            connect(deviceDiscovery, &QDeviceDiscovery::deviceDetected,
                    this, &QEvdevMouseManager::addMouse);
            connect(deviceDiscovery, &QDeviceDiscovery::deviceRemoved,
                    this, &QEvdevMouseManager::removeMouse);
        }
    }

    QInputDeviceManager *manager = QGuiApplicationPrivate::inputDeviceManager();
    connect(manager, &QInputDeviceManager::cursorPositionChangeRequested, [this](const QPoint &pos) {
        m_x = pos.x();
        m_y = pos.y();
        clampPosition();
    });
}

addMouse会创建QEvdevMouseHandler打开设备,并且根据文件描述符创建QSocketNotifier注册到事件分发器中
将QEvdevMouseHandler的鼠标信号与QEvdevMouseManager对应的槽函数建立联系,信号触发时,对应的槽函数会调用,执行QWindowSystemInterface的事件处理函数,将事件转化为QEvent

  • 鼠标对应 QEvdevMousePlugin

QPA

qt的平台抽象,window实现代码在plugins/platforms/window下
判断window的事件函数为

QtWindows::WindowEventType windowEventType(UINT message, WPARAM wParam, LPARAM lParam);

QWindowsContext的windowsProc处理事件,其实现类为QWindowsContextPrivate

struct QWindowsContextPrivate {
    QWindowsContextPrivate();

    unsigned m_systemInfo = 0;
    QSet<QString> m_registeredWindowClassNames;
    HandleBaseWindowHash m_windows;
    HDC m_displayContext = nullptr;
    int m_defaultDPI = 96;
    QWindowsKeyMapper m_keyMapper;
    QWindowsMouseHandler m_mouseHandler;
    QWindowsPointerHandler m_pointerHandler;
    QWindowsMimeConverter m_mimeConverter;
    QWindowsScreenManager m_screenManager;
    QSharedPointer<QWindowCreationContext> m_creationContext;
#if QT_CONFIG(tabletevent)
    QScopedPointer<QWindowsTabletSupport> m_tabletSupport;
#endif
    const HRESULT m_oleInitializeResult;
    QWindow *m_lastActiveWindow = nullptr;
    bool m_asyncExpose = false;
    HPOWERNOTIFY m_powerNotification = nullptr;
    HWND m_powerDummyWindow = nullptr;
};

m_mouseHandler:将windows事件转换为Qt的鼠标事件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kgduu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值