前言
之前看了一篇介绍MiniGUI事件分发的文章MiniGUI事件分发机制,但是最近项目中遇到问题需要排查下事件分发的细节,周六看了下,这里做个记录.
1. 关于EventLoop
文件路径: ./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) {event = IAL_WaitEvent (IAL_MOUSEEVENT | IAL_KEYEVENT, 0,NULL, NULL, NULL, (void*)&__mg_event_timeout);if (event < 0) {usleep(10*1000); /*reduce the CPU usage frequency*/continue;}lwe.status = 0L;lwe.data.me.status = 0;// 鼠标事件if (event & IAL_MOUSEEVENT && kernel_GetLWEvent (IAL_MOUSEEVENT, &lwe))ParseEvent (&lwe);lwe.status = 0L;lwe.data.ke.status = 0;// 按键事件if (event & IAL_KEYEVENT && kernel_GetLWEvent (IAL_KEYEVENT, &lwe))ParseEvent (&lwe);if (event == 0 && kernel_GetLWEvent (0, &lwe))ParseEvent (&lwe);}/* printf("Quit from EventLoop()\n"); */return NULL;
}
- while循环一开始会调用IAL_WaitEvent函数获取事件,获取到事件的话会实时处理, 没有事件的话会延时10毫秒等待(防止CPU过度使用),IAL_WaitEvent函数会调用对应输入引擎的实现,tslib中是使用select监听输入事件。
- 接下来,会根据事件类型对事件进行加工,事件类型这里分为鼠标事件和按键事件,TFT屏幕设备的话主要关心的可能还是鼠标事件,因为这里面有按下,抬起,滑动事件。
- kernel_GetLWEvent 函数会对事件进行加工处理,需要保留的事件就会交给parseEvent函数进行解析,不需要保留的函数就会丢弃。
2. kernel_GetLWEvent
BOOL kernel_GetLWEvent (int event, PLWEVENT lwe)
{/*---省略---*/timeout_count = 0;/* There was an event occurred. */if (event & IAL_MOUSEEVENT) {lwe->type = LWETYPE_MOUSE;// 获取button事件if (kernel_RefreshCursor(&me->x, &me->y, &button)) {me->event = ME_MOVED;time1 = 0;time2 = 0;//Note:should contains button state in MSG_MOUSEMOVEif (button == oldbutton)goto mouseret;}// 左键的处理逻辑if ( !(oldbutton & IAL_MOUSE_LEFTBUTTON) && (button & IAL_MOUSE_LEFTBUTTON) ){license_on_input();interval = __mg_timer_counter - time1;if (interval <= dblclicktime)me->event = ME_LEFTDBLCLICK;elseme->event = ME_LEFTDOWN;time1 = __mg_timer_counter;goto mouseret;}if ( (oldbutton & IAL_MOUSE_LEFTBUTTON) && !(button & IAL_MOUSE_LEFTBUTTON) ){license_on_input();me->event = ME_LEFTUP;goto mouseret;}// 下面是右键的button事件--暂不分析if ( !(oldbutton & IAL_MOUSE_RIGHTBUTTON) && (button & IAL_MOUSE_RIGHTBUTTON) ){interval = __mg_timer_counter - time2;if (interval <= dblclicktime)me->event = ME_RIGHTDBLCLICK;elseme->event = ME_RIGHTDOWN;time2 = __mg_timer_counter;goto mouseret;}if ( (oldbutton & IAL_MOUSE_RIGHTBUTTON) && !(button & IAL_MOUSE_RIGHTBUTTON) ){me->event = ME_RIGHTUP;goto mouseret;}}/*-------keyevent事件暂不展开------*/old_lwe.type = 0;return 0;mouseret:status &= ~(MASK_KS_BUTTONS);oldbutton = button;if (oldbutton & IAL_MOUSE_LEFTBUTTON)status |= KS_LEFTBUTTON;if (oldbutton & IAL_MOUSE_RIGHTBUTTON)status |= KS_RIGHTBUTTON;me->status = status;memcpy (&old_lwe, lwe, sizeof (LWEVENT));__mg_event_timeout.tv_sec = 0;__mg_event_timeout.tv_usec = timeoutusec;return 1;
}
- 该函数包含了对鼠标事件和按键事件的处理逻辑,按键事件此处不进行分析,主要是对鼠标事件进行分析
- 一开始会调用kernel_RefreshCursor函数获取button是按下还是抬起,并获取坐标值。获取button的方法是调用输入引擎的IAL_GetMouseButton函数,该函数获取的button值最终又是由mouse_update函数赋值的,赋值的原理就是,压力值>0认为是按下,反之认为是抬起。
(mouse_update函数中使用的是ts_read函数获取触摸数值,该函数只支持单指,多指的话需要调用ts_read_mt函数获取) - kernel_GetLWEvent 函数接下来会用oldbutton 和 button来判断按下还是抬起逻辑,oldbutton = 0,button = 1是按下,oldbutton = 1,button = 0是抬起,这里没有对oldbutton = 0,button = 0 或者oldbutton = 1,button = 1进行处理,原因是单指操作时,只有这两种逻辑,如果有多指操作的话,这里就需要添加全0或者全1逻辑的处理。
- kernel_GetLWEvent 函数的返回结果会决定接下来是否进入事件解析逻辑,即parseEvent,parseEvent函数对事件进行处理后,决定是否放入消息队列中。