WindowSystemEvent

Qt中为WindowSystemEvent事件定义了处理函数Handler,通过宏定义和模版来声明定义

---- QT_DEFINE_QPA_EVENT_HANDLER Matches (25 in 1 files) ----
qwindowsysteminterface.cpp (gui\kernel) line 199 : #define QT_DEFINE_QPA_EVENT_HANDLER(ReturnType, HandlerName, ...) \
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(void, handleEnterEvent, QWindow *window, const QPointF &local, const QPointF &global)
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(void, handleLeaveEvent, QWindow *window)
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(void, handleFocusWindowChanged, QWindow *window, Qt::FocusReason r)
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowStateChanged, QWindow *window, Qt::WindowStates newState, int oldState)
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowScreenChanged, QWindow *window, QScreen *screen)
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowDevicePixelRatioChanged, QWindow *window)
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(void, handleSafeAreaMarginsChanged, QWindow *window)
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(void, handleApplicationStateChanged, Qt::ApplicationState newState, bool forcePropagate)
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(bool, handleApplicationTermination)
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const QRect &newRect)
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(bool, handleExposeEvent, QWindow *window, const QRegion &region)
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(bool, handlePaintEvent, QWindow *window, const QRegion &region)
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(bool, handleCloseEvent, QWindow *window)
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(bool, handleMouseEvent, QWindow *window,
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(bool, handleMouseEvent, QWindow *window, const QPointingDevice *device,
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(bool, handleMouseEvent, QWindow *window, ulong timestamp,
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(bool, handleMouseEvent, QWindow *window, ulong timestamp, const QPointingDevice *device,
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(bool, handleKeyEvent, QWindow *window, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) {
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(bool, handleKeyEvent, QWindow *window, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count)
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchEvent, QWindow *window, const QPointingDevice *device,
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchEvent, QWindow *window, ulong timestamp, const QPointingDevice *device,
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchCancelEvent, QWindow *window, const QPointingDevice *device,
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchCancelEvent, QWindow *window, ulong timestamp, const QPointingDevice *device,
QT_DEFINE_QPA_EVENT_HANDLER in qwindowsysteminterface.cpp (gui\kernel) : QT_DEFINE_QPA_EVENT_HANDLER(void, handleThemeChange, QWindow *window)

以MouseEvent为例,最重将事件append到 windowSystemEventQueue 队列里面,然后wakeUp可能休眠的EventDispatcher:

template<>
template<typename EventType, typename ...Args>
bool QWindowSystemHelper<QWindowSystemInterface::AsynchronousDelivery>::handleEvent(Args ...args)
{
    QWindowSystemInterfacePrivate::windowSystemEventQueue.append(new EventType(args...));
    if (QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::qt_qpa_core_dispatcher())
        dispatcher->wakeUp();
    return true;
}

template <typename EventType, typename Delivery = QWindowSystemInterface::DefaultDelivery, typename ...Args>
static bool handleWindowSystemEvent(Args ...args)
{
    return QWindowSystemHelper<Delivery>::template handleEvent<EventType>(args...);
}


#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__)


QT_DEFINE_QPA_EVENT_HANDLER(bool, handleMouseEvent, QWindow *window,
                            const QPointF &local, const QPointF &global, Qt::MouseButtons state,
                            Qt::MouseButton button, QEvent::Type type, Qt::KeyboardModifiers mods,
                            Qt::MouseEventSource source)
{
    unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
    return handleMouseEvent<Delivery>(window, time, local, global, state, button, type, mods, source);
}

QT_DEFINE_QPA_EVENT_HANDLER(bool, handleMouseEvent, QWindow *window, const QPointingDevice *device,
                            const QPointF &local, const QPointF &global, Qt::MouseButtons state,
                            Qt::MouseButton button, QEvent::Type type, Qt::KeyboardModifiers mods,
                            Qt::MouseEventSource source)
{
    unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
    return handleMouseEvent<Delivery>(window, time, device, local, global, state, button, type, mods, source);
}

QT_DEFINE_QPA_EVENT_HANDLER(bool, handleMouseEvent, QWindow *window, ulong timestamp,
                            const QPointF &local, const QPointF &global, Qt::MouseButtons state,
                            Qt::MouseButton button, QEvent::Type type, Qt::KeyboardModifiers mods,
                            Qt::MouseEventSource source)
{
    return handleMouseEvent<Delivery>(window, timestamp, QPointingDevice::primaryPointingDevice(),
                                      local, global, state, button, type, mods, source);
}

QT_DEFINE_QPA_EVENT_HANDLER(bool, handleMouseEvent, QWindow *window, ulong timestamp, const QPointingDevice *device,
                            const QPointF &local, const QPointF &global, Qt::MouseButtons state,
                            Qt::MouseButton button, QEvent::Type type, Qt::KeyboardModifiers mods,
                            Qt::MouseEventSource source)
{

    bool isNonClientArea = {};

    switch (type) {
    case QEvent::MouseButtonDblClick:
    case QEvent::NonClientAreaMouseButtonDblClick:
        Q_ASSERT_X(false, "QWindowSystemInterface::handleMouseEvent",
               "QTBUG-71263: Native double clicks are not implemented.");
        return false;
    case QEvent::MouseMove:
    case QEvent::MouseButtonPress:
    case QEvent::MouseButtonRelease:
        isNonClientArea = false;
        break;
    case QEvent::NonClientAreaMouseMove:
    case QEvent::NonClientAreaMouseButtonPress:
    case QEvent::NonClientAreaMouseButtonRelease:
        isNonClientArea = true;
        break;
    default:
        Q_UNREACHABLE();
    }

    auto localPos = QHighDpi::fromNativeLocalPosition(local, window);
    auto globalPos = QHighDpi::fromNativeGlobalPosition(global, window);

    return handleWindowSystemEvent<QWindowSystemInterfacePrivate::MouseEvent, Delivery>(window,
        timestamp, localPos, globalPos, state, mods, button, type, source, isNonClientArea, device);
}




/*!
     \brief Main windows procedure registered for windows.

     \sa QWindowsGuiEventDispatcher
*/

bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
                                  QtWindows::WindowsEventType et,
                                  WPARAM wParam, LPARAM lParam,
                                  LRESULT *result,
                                  QWindowsWindow **platformWindowPtr)
{
    ......
    ......
    case QtWindows::MouseWheelEvent:
    case QtWindows::MouseEvent:
    case QtWindows::LeaveEvent:
        {
            QWindow *window = platformWindow->window();
            while (window && (window->flags() & Qt::WindowTransparentForInput))
                window = window->parent();
            if (!window)
                return false;
            if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer)
                return sessionManagerInteractionBlocked() || d->m_pointerHandler.translateMouseEvent(window, hwnd, et, msg, result);
            else
                return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(window, hwnd, et, msg, result);
        }
        break;
    ......
    ......
}



struct QWindowsContextPrivate {
    QWindowsContextPrivate();
    ......
    ......
    QWindowsMouseHandler m_mouseHandler;
    QWindowsPointerHandler m_pointerHandler;
    ......
    ......
};


bool QWindowsMouseHandler::translateMouseEvent(QWindow *window,
                                                 HWND hwnd,
                                                 QtWindows::WindowsEventType et,
                                                 MSG msg,
                                                 LRESULT *result)
{
    ......
    ......
    if (!discardEvent && mouseEvent.type != QEvent::None) {
        QWindowSystemInterface::handleMouseEvent(window, device, clientPosition, globalPosition, buttons,
                                                 mouseEvent.button, mouseEvent.type,
                                                 keyModifiers, source);
    }
    ......
    ......
}


extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    LRESULT result;
    const QtWindows::WindowsEventType et = windowsEventType(message, wParam, lParam);
    QWindowsWindow *platformWindow = nullptr;
    const RECT ncCalcSizeFrame = rectFromNcCalcSize(message, wParam, lParam, 0);
    const bool handled = QWindowsContext::instance()->windowsProc(hwnd, message, et, wParam, lParam, &result, &platformWindow);
    ......
    ......
    if (!handled)
        result = DefWindowProc(hwnd, message, wParam, lParam);
    ......
    ......
    return result;
}



// Window class registering code (from qapplication_win.cpp)

QString QWindowsContext::registerWindowClass(const QWindow *w)
{
    ......
    ......
    return registerWindowClass(cname, qWindowsWndProc, style, nullptr, icon);
}

QString QWindowsContext::registerWindowClass(QString cname,
                                             WNDPROC proc,
                                             unsigned style,
                                             HBRUSH brush,
                                             bool icon)
{
    // since multiple Qt versions can be used in one process
    // each one has to have window class names with a unique name
    // The first instance gets the unmodified name; if the class
    // has already been registered by another instance of Qt then
    // add a UUID. The check needs to be performed for each name
    // in case new message windows are added (QTBUG-81347).
    // Note: GetClassInfo() returns != 0 when a class exists.
    const auto appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));
    ......
    ......
    WNDCLASSEX wc;
    wc.cbSize       = sizeof(WNDCLASSEX);
    wc.style        = style;
    wc.lpfnWndProc  = proc;
    wc.cbClsExtra   = 0;
    wc.cbWndExtra   = 0;
    wc.hInstance    = appInstance;
    wc.hCursor      = nullptr;
    wc.hbrBackground = brush;
    ......
    ......

    wc.lpszMenuName  = nullptr;
    wc.lpszClassName = reinterpret_cast<LPCWSTR>(cname.utf16());
    ATOM atom = RegisterClassEx(&wc);
    ......
    ......
    return cname;
}



QWindowsWindowData WindowCreationData::create(const QWindow *w, const WindowData &data, QString title) const
{
    WindowData result;
    result.flags = flags;

    const auto appinst = reinterpret_cast<HINSTANCE>(GetModuleHandle(nullptr));

    const QString windowClassName = QWindowsContext::instance()->registerWindowClass(w);

    const QScreen *screen{};
    const QRect rect = QPlatformWindow::initialGeometry(w, data.geometry,defaultWindowWidth, defaultWindowHeight,&screen);
    ......
    ......
    result.hwnd = CreateWindowEx(exStyle, classNameUtf16, titleUtf16,style,pos.x(), pos.y(),
                                 context->frameWidth, context->frameHeight,
                                 parentHandle, nullptr, appinst, nullptr);
    ......
    ......
    return result;
}



============================================================================================================================================

下面看看是如何消费windowSystemEventQueue中的事件

void QWindowsGuiEventDispatcher::sendPostedEvents()
{
    QEventDispatcherWin32::sendPostedEvents();
    QWindowSystemInterface::sendWindowSystemEvents(m_flags);
}



bool QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)
{
    int nevents = 0;

    while (QWindowSystemInterfacePrivate::windowSystemEventsQueued()) {
        QWindowSystemInterfacePrivate::WindowSystemEvent *event =
                flags & QEventLoop::ExcludeUserInputEvents ?
                        QWindowSystemInterfacePrivate::getNonUserInputWindowSystemEvent() :
                        QWindowSystemInterfacePrivate::getWindowSystemEvent();
        if (!event)
            break;

        if (QWindowSystemInterfacePrivate::eventHandler) {
            if (QWindowSystemInterfacePrivate::eventHandler->sendEvent(event))
                nevents++;
        } else {
            nevents++;
            QGuiApplicationPrivate::processWindowSystemEvent(event);
        }

        // Record the accepted state for the processed event
        // (excluding flush events). This state can then be
        // returned by flushWindowSystemEvents().
        if (event->type != QWindowSystemInterfacePrivate::FlushEvents)
            QWindowSystemInterfacePrivate::eventAccepted.storeRelaxed(event->eventAccepted);

        delete event;
    }

    return (nevents > 0);
}



void Q_TRACE_INSTRUMENT(qtgui) QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e)
{
    Q_TRACE_PARAM_REPLACE(QWindowSystemInterfacePrivate::WindowSystemEvent *, int);
    Q_TRACE_SCOPE(QGuiApplicationPrivate_processWindowSystemEvent, e->type);

    switch(e->type) {
    case QWindowSystemInterfacePrivate::Mouse:
        QGuiApplicationPrivate::processMouseEvent(static_cast<QWindowSystemInterfacePrivate::MouseEvent *>(e));
        break;
    ......
    ......
    default:
        qWarning() << "Unknown user input event type:" << e->type;
        break;
    }
}

void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent *e)
{
    QWindow *window = e->window.data();
    ......
    ......
    QMouseEvent ev(type, localPoint, localPoint, globalPoint, button, e->buttons, e->modifiers, e->source, device);
    ......
    QGuiApplication::sendSpontaneousEvent(window, &ev);
    ......
    ......
}

bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event)
{
    ......
    ......
    event->m_spont = true;
    return notifyInternal2(receiver, event);
}

bool QCoreApplication::notifyInternal2(QObject *receiver, QEvent *event)
{
    ......
    ......
    return self->notify(receiver, event);
}

bool QCoreApplication::notify(QObject *receiver, QEvent *event)
{
    Q_ASSERT(receiver);
    Q_ASSERT(event);

#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
    Q_ASSERT(receiver->d_func()->threadData.loadAcquire()->thread.loadRelaxed()
             == QCoreApplicationPrivate::mainThread());
#endif

    // no events are delivered after ~QCoreApplication() has started
    if (QCoreApplicationPrivate::is_app_closing)
        return true;
    return doNotify(receiver, event);
}

static bool doNotify(QObject *receiver, QEvent *event)
{
    ......
    ......

    return receiver->isWidgetType() ? false : QCoreApplicationPrivate::notify_helper(receiver, event);
}

bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)
{
    // Note: when adjusting the tracepoints in here
    // consider adjusting QApplicationPrivate::notify_helper too.
    Q_TRACE(QCoreApplication_notify_entry, receiver, event, event->type());
    bool consumed = false;
    bool filtered = false;
    Q_TRACE_EXIT(QCoreApplication_notify_exit, consumed, filtered);

    // send to all application event filters (only does anything in the main thread)
    if (receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread()
            && QCoreApplication::self
            && QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event)) {
        filtered = true;
        return filtered;
    }
    // send to all receiver event filters
    if (sendThroughObjectEventFilters(receiver, event)) {
        filtered = true;
        return filtered;
    }

    // deliver the event
    consumed = receiver->event(event);
    return consumed;
}

posted @   MarsCactus  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
点击右上角即可分享
微信分享提示