现在的位置: 首页 > 综合 > 正文

MTK MMI event 小结 6

2013年10月09日 ⁄ 综合 ⁄ 共 4989字 ⁄ 字号 评论关闭

MTK MMI event 小结 5 中,提到了event 处理函数 mmi_frm_key_handle,这个函数主要作用是判断是否需要处理按键,从按键缓存里面持续的读取按键信息,然后调用 mmi_frm_convert_process_key_event 进行处理。这个函数没有什么可说的,最多是在屏幕旋转的情况下,把 导航键 转换一下,接着它调用了 ProcessKeyEvent, 这个函数主要是对于一些状态的处理,防止key down 和up 不成对,出现混乱。

void ProcessKeyEvent(U32 MsgType, U16 DeviceKeyCode)
{
    MMI_BOOL isKeyPaired;
    U16      KeyMapIndex;

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    
   // 按键影射,把驱动的按键码,转换成MMI 的 按键消息
    KeyMapIndex = mmi_frm_get_idx_from_device_key_code(DeviceKeyCode);
  
    if (KeyMapIndex >= MAX_KEYS)
    {
        return;
    }

    // 处理各种按键事件,没有什么可以多说的,
    // 主体结构都一样,
    // 1 判断状态是否正常
    // 2 正常 则调用 KeyEventHandler 处理, 否则忽略该事件
    if (MsgType == WM_KEYPRESS)
    {
        // 这里处理 多案件同时按下的情况。这里需要硬件支持
        if ((KeyMapIndex != prevKeyMapIndex) && (g_kbd_concurrent_key_mode == CONCURRENT_KEY_MODE_1_KEY))
        {
            isKeyPaired = (nKeyPadStatus[prevKeyMapIndex] == KEY_EVENT_UP);
        
            prevKeyMapIndex = KeyMapIndex;
        }
        //判断案件状态是否正常,防止不匹配
        if (nKeyPadStatus[KeyMapIndex] == KEY_EVENT_UP)
        {

            KEYBRD_MESSAGE KeyBrdMsg;

            KeyBrdMsg.nKeyCode = nKeyPadMap[KeyMapIndex].nMMIKeyCode;
            if (mmi_frm_is_2step_keyCode(KeyBrdMsg.nKeyCode))
            {
                nKeyPadStatus[KeyMapIndex] = KEY_HALF_PRESS_DOWN;
                key_is_pressing_count++;
                KeyBrdMsg.nMsgType = KEY_HALF_PRESS_DOWN;
            }
            else
            {
                nKeyPadStatus[KeyMapIndex] = KEY_EVENT_DOWN;    /* same with KEY_FULL_PRESS_DOWN */
                key_is_pressing_count++;
                KeyBrdMsg.nMsgType = KEY_EVENT_DOWN;
            }
            // 处理按键事件
            KeyEventHandler((KEYBRD_MESSAGE*) & KeyBrdMsg);

        }
        else
        {
            /* Ignore the event */
        }
    }

    else if (MsgType == WM_KEYRELEASE)
    {
        if ((nKeyPadStatus[KeyMapIndex] == KEY_EVENT_DOWN)
            || (nKeyPadStatus[KeyMapIndex] == KEY_LONG_PRESS)
            || (nKeyPadStatus[KeyMapIndex] == KEY_REPEAT) || (nKeyPadStatus[KeyMapIndex] == KEY_HALF_PRESS_DOWN))
        {

            KEYBRD_MESSAGE KeyBrdMsg;

            nKeyPadStatus[KeyMapIndex] = KEY_EVENT_UP;
            key_is_pressing_count--;
            KeyBrdMsg.nMsgType = KEY_EVENT_UP;
            KeyBrdMsg.nKeyCode = nKeyPadMap[KeyMapIndex].nMMIKeyCode;
            KeyEventHandler((KEYBRD_MESSAGE*) & KeyBrdMsg);

        }
        else
        {
            /* Ignore the event */
        }
    }
    /* ++Robin, modified by Max Chen */
    else if (MsgType == DRV_WM_KEYLONGPRESS)
    {
        if (nKeyPadStatus[KeyMapIndex] == KEY_EVENT_DOWN)
        {
            KEYBRD_MESSAGE KeyBrdMsg;

            nKeyPadStatus[KeyMapIndex] = KEY_LONG_PRESS;
            KeyBrdMsg.nMsgType = KEY_LONG_PRESS;
            KeyBrdMsg.nKeyCode = nKeyPadMap[KeyMapIndex].nMMIKeyCode;
            KeyEventHandler((KEYBRD_MESSAGE*) & KeyBrdMsg);
        }
        else
        {
            /* Ignore the event */
        }
    }
    else if (MsgType == DRV_WM_KEYREPEATED)
    {
        if ((nKeyPadStatus[KeyMapIndex] == KEY_LONG_PRESS) || (nKeyPadStatus[KeyMapIndex] == KEY_REPEAT))
        {
            KEYBRD_MESSAGE KeyBrdMsg;

            nKeyPadStatus[KeyMapIndex] = KEY_REPEAT;
            KeyBrdMsg.nMsgType = KEY_REPEAT;
            KeyBrdMsg.nKeyCode = nKeyPadMap[KeyMapIndex].nMMIKeyCode;
            KeyEventHandler((KEYBRD_MESSAGE*) & KeyBrdMsg);
        }
        else
        {
            /* Ignore the event */
        }
    }
    else if (MsgType == DRV_WM_KEYFULLPRESS)
    {
        /*
         * Only in two-stage key will have KEY_FULL_PRESS_DOWN, and it followed after KEY_HALF_PRESS_DOWN
         */
        if (nKeyPadStatus[KeyMapIndex] == KEY_HALF_PRESS_DOWN)
        {
            KEYBRD_MESSAGE KeyBrdMsg;

            nKeyPadStatus[KeyMapIndex] = KEY_EVENT_DOWN;
            KeyBrdMsg.nMsgType = KEY_EVENT_DOWN;
            KeyBrdMsg.nKeyCode = nKeyPadMap[KeyMapIndex].nMMIKeyCode;
            KeyEventHandler((struct KEYBRD_MESSAGE*)&KeyBrdMsg);
        }
        else
        {
            /* Ignore the event */
        }
    }
    else if ((MsgType == DRV_WM_ENABLE_TWOKEY_DETECTION) || (MsgType == DRV_WM_ENABLE_THREEKEY_DETECTION) ||
                (MsgType == DRV_WM_DISABLE_MULTIKEY_DETECTION))
    {
        /* Ignore the event */
    }
    else
    {
        MMI_TRACE(MMI_FW_TRC_G6_FRM_DETAIL, MMI_FRM_ERROR_PROC_KEYEVENT_HDLR);

        MMI_ASSERT(0);
    }

}


KeyEventHandler 函数主要判断是否要真的处理该事件,可以看成是一个按键事件的拦截,比如应用切换过程中,需要一个切换动画,而这个动画工程中,需要处理忽略这些按键。就需要特殊的处理。

static void KeyEventHandler(KEYBRD_MESSAGE *eventKey)
{

    MMI_BOOL is_hdlr_enabled = MMI_TRUE;
    
   // 主要处理一些特殊相应:屏幕背光,屏幕锁定,按键声音
    mmi_kbd_app_key_hdlr(eventKey);

    // 判断是否有前置处理函数
    if (g_mmi_frm_cntx.kbd_pre_func)
    {
        is_hdlr_enabled = g_mmi_frm_cntx.kbd_pre_func(eventKey);
    }
   
    // 根据前置处理函数结果,判断是否要处理该 key event
    if (is_hdlr_enabled)
    {
        //处理 案件事件
        ExecuteCurrKeyHandler((S16) eventKey->nKeyCode, (S16) eventKey->nMsgType);
    }

    // 是否有后置处理函数,可以进行一些监视
    if (g_mmi_frm_cntx.kbd_post_func)
    {
        g_mmi_frm_cntx.kbd_post_func(eventKey);
    }

}


 

接下来是 ExecuteCurrKeyHandler 这个函数就是根据 按键事件,获得处理函数,进行处理。

void ExecuteCurrKeyHandler(S16 keyCode, S16 keyType)
{
  FuncPtr currFuncPtr = NULL;

    // 重新设定 键盘锁和屏保timer
    mmi_idle_restart_keypad_lock_timer();
    mmi_idle_restart_screensaver_timer();

    frm_p->currKeyCode = keyCode;
    frm_p->currKeyType = keyType;

        // 对电话状态下,挂电话键的特殊处理.
        if (frm_p->currKeyType == KEY_EVENT_DOWN && 
            isInCall() && !GetWapCallPresent() && 
            IsBitReset(g_mmi_frm_cntx.end_key_flag, frm_p->currKeyType) )
        {
                      RegisterEndKeyHandlerInCall();
        }


        // 获得按键处理函数
        currFuncPtr = currKeyFuncPtrs[keyCode][keyType];

       // 导航的选择键,默认和左功能键的效果一样。
        if (keyCode == KEY_ENTER && currFuncPtr == NULL)
        {
               if (currKeyFuncPtrs[KEY_ENTER][KEY_EVENT_UP] == NULL &&
                currKeyFuncPtrs[KEY_ENTER][KEY_EVENT_DOWN] == NULL &&
                currKeyFuncPtrs[KEY_ENTER][KEY_HALF_PRESS_DOWN] == NULL &&
                currKeyFuncPtrs[KEY_ENTER][KEY_REPEAT] == NULL && currKeyFuncPtrs[KEY_ENTER][KEY_LONG_PRESS] == NULL)

            {
                currFuncPtr = currKeyFuncPtrs[KEY_LSK][keyType];
            }
        }
      
        // 处理按键 消息
        if (currFuncPtr)
        {
            (*currFuncPtr)();
        }
    }
  
    // 重置状态
    if (keyType == KEY_EVENT_UP)
    {    
        frm_p->currKeyCode = KEY_INVALID;
        frm_p->currKeyType = MAX_KEY_TYPE;
    }

}


从整个按键事件的处理流程来看,也没有什么特殊的地方,就是收到消息后,从按键buffer里取出按键事件,然后处理。如果有有别的事件要处理,那么就break出来,等到处理完这个消息后,在 MMI task 调用 mmi_frm_key_handle 继续处理剩下的按键事件。

这里无非多了很多的判断,是否要进行按键处理,MTK的代码函数名字上虽然看不出什么东西,但是一层一层函数,每一层函数的功能还是比较独立的,所以也不是很难看懂。

待续

抱歉!评论已关闭.