MiniGUI内核事件线程简单分析

前言

之前看了一篇介绍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_MOUSEMOVE
            if (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;
            else
                me->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;
            else
                me->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函数对事件进行处理后,决定是否放入消息队列中。

你可能感兴趣的:(minigui,gui)