QT的窗体系统可以包含多个进程,对于Linux上的应用,一个进程可以对应一个应用程序,每个应用程序都有自己的MainWindow,也可以有自己的Widget stack.。假设一种情况:同时打开多个应用,并且各个应用之间的Windows不存在完全覆盖,当我们用鼠标点击某个应用的窗体,这个应用的窗体便会出现在屏幕的最上层。对于了解windows窗体服务器的同行来说,理解这个并不难,可能有一个类似于Windows XP X-Windows Sever的进程负责管理鼠标、键盘、与LCD显示的操作。对于智能手机的GUI我是第一次接触,非智能手机的窗体管理是比较简单的,以我以前从事的一个手机平台为例,手机只存在一个dialog Stack, 把这个stack 看成一个Z坐标,栈底位于坐标原点,显示一整屏幕完整的画面就是从栈顶沿Z坐标向下找到没有被完全覆盖的windows直到整个屏幕数据被完全填充,按键事件传入到ui_task(ui_task 负责初始化其他应用,所有windows event都由dialogstack 应用负责分发)。回归正卷,QT是如何管理窗体的呢?下面详述。
QApplication如何取得Mouse Event?
查看QApplication的代码,存在一个GuiSever类型的应用,GuiServer类型的应用与其他类型的应用有什么区别的呢?最大的区别就在于通过qt_init初始化函数调用QWSServer::startup这个应用建立了一个窗体服务器。在QWSServer的构造函数中:
openDisplay(); //初始化显示、屏幕参数,打开LCD。
openMouse(); //打开鼠标设备
openKeyboard(); //打开键盘设备
openMouse() :QWSMouseHandler* h = newMouseHandler(ms)打开鼠标设备,打开鼠标设备后,通过QSocketNotifier接口监听打开的鼠标设备文件描述符,在QWSMouseHandler构造函数中通过调用setMouseHandler 建立了window Server与鼠标设备之间的通信即:在QWSServer中 connected SIGNAL(mouseChanged)与SLOT(setMouse)(目前这个平台与新的QT开发包有出入,在qt-embedded-free-3.3.6中 鼠标与windows Server之间通讯是通过在qmouse_ws.cpp中直接调用QWSServer::sendMouseEvent 来实现的)。走到这,我们已经能够获取鼠标数据了。这些数据最终会传递到哪个窗体,在sendMouseEvent中通过调用window.At(pos)查找windows List所有应用的TOP-LEVEL windows保存在此链表中,(TOP-LEVEL窗体是指无parent或者style为:WType_TopLevel的窗体)中请求响应区域包含鼠标坐标的窗体(requested-region: 窗体显示的区域),一旦找到数据便会传递到此窗体(消息放入到QApplication的incoming消息队列中,由QApplication负责派发)然后通过Client Socket将此消息传递到相应的application的消息队列里。
QWSSever与Application之间通信管道的建立
QT支持多进程,对一个嵌入式设备而言,存在一个独立的GuiServer类型的应用,这个应用作为服务器,其他的应用作为客户端。服务器与客户端的连接在应用初始化的时候完成。
服务器:
Server Application进程通过调用QWSServer::startup完成Server的建立。
客户端:
Application 调用QWSDisplayData::init创建QWSSocket对象并通过connectToLocalFile建立与服务器的连接。