MiniGUI事件传递机制分析

本文深入剖析MiniGUI的事件传递机制,从IAL初始化、内核事件上报、桌面获取事件流程到应用获取事件,详细解释了如何从内核驱动到应用层处理触摸事件。通过tslib获取事件后,事件被存储于消息队列,经过一系列处理分发给对应应用。理解此机制有助于在嵌入式平台上进行MiniGUI的定制和优化。
摘要由CSDN通过智能技术生成

前言

这段时间学习了一下MiniGUI中的事件传递机制,包括从内核驱动上报事件到MiniGUI分发事件这一整条通路,在嵌入式平台上,获取触摸事件可以使用tslib框架,通过tslib获取到事件之后,会把消息保存在桌面消息队列中,然后进一步分发到应用消息队列,我会在这篇文章中详细说明

1. IAL初始化流程

IAL全拼是Input Abstract Layer,也就是输入抽象层,在MiniGUI中抽象了很多输入设备,比如tslibial、ipaqh3600ial、consoleial和nexusial等等,本文以tslibial为例进行说明

首先看一下初始化流程图,有一个初步的印象
MiniGUI输入引擎UML图-初始化流程图
整个MiniGUI的初始化会调用到InitGUI()函数中,本文主要关注IAL初始化相关的代码

/* libminigui-gpl-3.2/src/kernel/init.c */
int GUIAPI InitGUI (int args, const char *agr[])
{
   
	/*...*/
    /*初始化应用窗口默认事件处理进程*/
    __mg_def_proc[0] = PreDefMainWinProc;
    /*初始化应用对话框默认事件处理进程*/
    __mg_def_proc[1] = PreDefDialogProc;
    /*初始化应用控件窗口默认事件处理进程*/
    __mg_def_proc[2] = PreDefControlProc;
    
	/*...*/
	/*初始化输入引擎*/
    if(!mg_InitLWEvent()) {
   
        fprintf(stderr, "KERNEL>InitGUI: Low level event initialization failure!\n");
        goto failure1;
    }
    
    /*...*/
	/*创建桌面接受消息线程*/
    if (!SystemThreads()) {
   
        fprintf (stderr, "KERNEL>InitGUI: Init system threads failure!\n");
        goto failure;
    }
    
    /*...*/
}

static BOOL SystemThreads(void)
{
   
	/*...*/
	/*这里以MiniGUI-Threads模式为例*/
	/*创建桌面接受消息线程,会初始化桌面消息队列和一个while循环去取消息*/
	pthread_create (&__mg_desktop, NULL, DesktopMain, &wait);
	
	/*...*/
	/*创建接受内核上报事件线程,会等待内核事件,如果有事件则解析并上报*/
	pthread_create (&__mg_parsor, NULL, EventLoop, &wait);
	
	/*...*/
}
/* libminigui-gpl-3.2/src/kernel/event.c */
BOOL mg_InitLWEvent (void)
{
   
	/*获取双击最小事件间隔,可以配置MiniGUI.cfg中的dblclicktime字段,默认300*/
    GetDblclickTime ();
    /*获取超时时间,可以配置MiniGUI.cfg中的timeoutusec字段,默认300000,该值是每一次循环获取事件的最大等待时间*/
    GetTimeout ();

	/*初始化具体的输入引擎*/
    if (mg_InitIAL ())
        return FALSE;

	/*重置鼠标按键状态*/
    ResetMouseEvent();
    ResetKeyEvent();

    return TRUE;
}
/* libminigui-gpl-3.2/src/ial/ial.c */
int mg_InitIAL (void)
{
   
	/*...*/
	/*会解析MiniGUI.cfg中的ial_engine、mdev和mtype字段,判断使用哪种输入引擎*/
	/*IAL_InitInput会最终调用到具体的输入引擎中,tslibial会调用到InitTSLibInput函数*/
	if (!IAL_InitInput (__mg_cur_input, mdev, mtype)) {
   
        fprintf (stderr, "IAL: Init IAL engine failure.\n");
        return ERR_INPUT_ENGINE;
    }
    
	/*...*/
}

上面写到会创建桌面接受消息线程,因为用的是MiniGUI-Threads模式,所以在desktop-ths.c中

/* libminigui-gpl-3.2/src/kernel/desktop-ths.c */
void* DesktopMain (void* data)
{
   
	/*...*/
	/*__mg_dsk_msg_queue就是桌面消息队列了,默认DEF_MSGQUEUE_LEN是16,也就是最多保存16个消息*/
	if (!(__mg_dsk_msg_queue = mg_InitMsgQueueThisThread ()) ) {
   
        _MG_PRINTF ("KERNEL>Desktop: mg_InitMsgQueueThisThread failure!\n");
        return NULL;
    }
	
	/*...*/
	/*开启一个while循环,调用GetMessage,指定HWND_DESKTOP,每次从__mg_dsk_msg_queue队列中取一个消息*/
	while (GetMessage(&Msg, HWND_DESKTOP)) {
   
			/*...*/
			/*如果取到消息的话,就把消息丢给桌面事件处理函数进行分发,具体怎么分发,下节详解*/
	        lRet = DesktopWinProc (HWND_DESKTOP, 
                        Msg.message, Msg.wParam, Msg.lParam);
            /*...*/
	}
	
	/*...*/
}

2. 内核事件上报流程

在初始化的时候,开启了一个接受并解析内核事件的线程EventLoop,这一小节重点分析改函数,先看图
MiniGUI输入引擎UML图-内核事件上报流程图
EventLoop函数中,主要是一个while循环,IAL_WaitEvent会调用到输入引擎的wait_event函数中去等待内核事件

/* libminigui-gpl-3.2/src/kernel/init.c */
static void* EventLoop (void* data)
{
   
    LWEVENT lwe;
    int event;

    lwe.data.me.x = 0; lwe.data.me.y = 0;

    sem_post ((sem_t*)data);

    while (__mg_quiting_stage > _MG_QUITING_STAGE_EVENT) {
   
    	/*等待内核上报事件,__mg_event_timeout是等待超时时间,在超时时间内没有事件的话会再次进入while循环*/
        event = IAL_WaitEvent (IAL_MOUSEEVENT | IAL_KEYEVENT
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值