https://github.com/zytc2009/BigTeam_learning
分类: C/C++
2008-06-23 13:27:42
pdf文档
通过鼠标事件来看QT/Embedded 窗体事件是如何派发的
To study QT/Embedded how to dispatch window event through QT mouse event transfer track
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的消息队列里。
Windows List是如何建立的?
我们在创建每一个QWidget对象时,系统会调用QWidget::create函数,如果我们创建的这个QWidget为TOP-LEVEL则将发送消息到QWSSever在这里创建一个GlobalWinowsID(参看QWSServer中get_object_id()调用),如果QWidget为Child widget则在这个应用中创建了一个LocaWindowslId,(参看takeLocalId())不管得到的winodwsId在哪儿被创建,在每个独立的Application中都会通过QWidget::setWinId保存。GlobalWindows与LocalWindows的区别是:在QWSServer中创建的GlobalwindowsID用于全局QApp即:按键,鼠标等事件通过QWSSever传递至相应的应用。按键,鼠标事件则在获得这些事件的QApp的Focus Widget中处理,这些Focus Widget可以是GlobalWindows 也可以是LocalWindows。在这个窗口没有show之前,我们还只是得到了WindowsId,当窗口被显示时,在QWSServer中将创建一个基于GlobalWindowsID的QWSWindow对象并将此对象保存在QWSServer的windows List中。
QApplication中Mouse Event的传递与处理
当application的消息队列不空时调用processEvents来处理消息队列。如果应用没有模式对话框,并且没有绑定Mouse Event的widget,则在Application中遍历GlobalWindow(对用户而言是可以鼠标所在的那个窗体)所对应的Widget所有子QWidget对象,也就是说首先从他的child widget开始查找响应Mouse Event的Widget,如果这个窗口没有被优先级更高的窗口被遮盖,便会调用raise函数,将窗体调整到windows list的最上层。
QWSSever与Application之间通信管道的建立
QT支持多进程,对一个嵌入式设备而言,存在一个独立的GuiServer类型的应用,这个应用作为服务器,其他的应用作为客户端。服务器与客户端的连接在应用初始化的时候完成。
服务器:
Server Application进程通过调用QWSServer::startup完成Server的建立。
客户端:
Application 调用QWSDisplayData::init创建QWSSocket对象并通过connectToLocalFile建立与服务器的连接。