Qt之事件循环源码剖析(二)-----源码面前了无秘密

上一篇说到QApplication注册了一个qt_internal_proc方法来处理消息循环,但是在整个过程中都没有看到处理用户输入事件的过程。例如鼠标事件、键盘事件等。

int main(int argc, char *argv[])
{
   
   
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

上篇文章分析了QApplication的构造,主事件循环启动、运行。 对于鼠标、键盘事件的响应肯定依托于一个可见的窗口,QApplication本身并不属于窗体,接下来针对于QWidget展开分析。

一、启动用户输入事件循环

Step 1

// src\widgets\kernel\qwidget.cpp
void QWidget::show()
{
   
   
    Qt::WindowState defaultState = QGuiApplicationPrivate::platformIntegration()->defaultWindowState(data->window_flags);
    if (defaultState == Qt::WindowFullScreen)
        showFullScreen();
    else if (defaultState == Qt::WindowMaximized)
        showMaximized();
    else
        setVisible(true); // Don't call showNormal() as not to clobber Qt::Window(Max/Min)imized
}
void QWidget::setVisible(bool visible)
{
   
   
    if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden) == !visible)
        return;

    // Remember that setVisible was called explicitly
    setAttribute(Qt::WA_WState_ExplicitShowHide);

    Q_D(QWidget);
    d->setVisible(visible);
}
void QWidgetPrivate::setVisible(bool visible)
{
   
   
    Q_Q(QWidget);
    if (visible) {
   
    // show
    /**
	* 代码省略 .......
	*/
        //create toplevels but not children of non-visible parents
        QWidget *pw = q->parentWidget();
        if (!q->testAttribute(Qt::WA_WState_Created)
            && (q->isWindow() || pw->testAttribute(Qt::WA_WState_Created))) {
   
   
            q->create();
        }
    }
}

QWidget在调用show函数显示一个窗口时,无论是全屏显示还是最大化显示最总都会调用QWidgetPrivate::setVisible函数。由于此Widget无父对象,在构造时将type设置为Qt::Window,因此会调用QWidget::create函数
Step 2

// src\widgets\kernel\qwidget.cpp
void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
{
   
   
    /**
	* 代码省略 .......
	*/
    setAttribute(Qt::WA_WState_Created);                        // set created flag
    d->create();
    /**
	* 代码省略 .......
	*/
}
void QWidgetPrivate::create()
{
   
   
    /**
	* 代码省略 .......
	*/
    QWidgetWindow *win = topData()->window;
    // topData() ensures the extra is created but does not ensure 'window' is non-null
    // in case the extra was already valid.
    if (!win) {
   
   
        createTLSysExtra();
        win = topData()->window;
    }
    /**
	* 代码省略 .......
	*/
    if (q->windowType() != Qt::Desktop || q->testAttribute(Qt::WA_NativeWindow)) {
   
   
        win->create();
        // Enable nonclient-area events for QDockWidget and other NonClientArea-mouse event processing.
        if (QPlatformWindow *platformWindow = win->handle())
            platformWindow->setFrameStrutEventsEnabled(true);
    }  
    /**
	* 代码省略 .......
	*/      
}
void QWidgetPrivate::createTLSysExtra()
{
   
   
    Q_Q(QWidget);
    if (!extra->topextra->window && (q->testAttribute(Qt::WA_NativeWindow) || q->isWindow())) {
   
   
        extra->topextra->window = new QWidgetWindow(q);
    /**
	* 代码省略 .......
	*/    
    }
}

通过QWidgetPrivate::createTLSysExtra()创建QWidgetWindow对象,q->windowType()的类型为Qt::Window,通过QWindowPrivate::create创建窗口
Step 3

// src\widgets\kernel\qwidget.cpp
void QWindowPrivate::create(bool recursive, WId nativeHandle)
{
   
   
    Q_Q(QWindow);
    if (platformWindow)
        return;

    // avoid losing update requests when re-creating
    const bool needsUpdate = updateRequestPending;
    // the platformWindow, if there was one, is now gone, so make this flag reflect reality now
    updateRequestPending = false;

    if (q->parent())
        q->parent()->create();

    QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
    platformWindow = nativeHandle ? platformIntegration->createForeignWindow(q, nativeHandle)
        : platformIntegration->createPlatformWindow(q);
    /**
	* 代码省略 .......
	*/           
}
// src\plugins\platforms\windows\qwindowsintegration.cpp
QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) const
{
   
   
    if (window->type() == Qt::Desktop) {
   
   
        auto *result = new QWindowsDesktopWindow(window);
        qCDebug(lcQpaWindows) << "Desktop window:" << window
            << Qt::showbase << Qt::hex << result->winId() << Qt::noshowbase << Qt::dec << result->geometry();
        return result;
    }

    QWindowsWindowData requested;
    requested.flags = window->flags();
    requested.geometry = window->isTopLevel()
        ? QHighDpi::toNativePixels(window->geometry(), window)
        : QHighDpi::toNativeLocalPosition(window->geometry(), window);
    // Apply custom margins (see  QWindowsWindow::setCustomMargins())).
    const QVariant customMarginsV = window->property("_q_windowsCustomMargins");
    if (customMarginsV.isValid())
        requested.customMargins = qvariant_cast<QMargins>(customMarginsV);

    QWindowsWindowData obtained =
        QWindowsWindowData::create(window, requested,
                                   QWindowsWindow
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值