昨天说了一下key event 的基本情况,今天直接从代码开始吧
先看执行key event 函数 mmi_frm_key_handle
void mmi_frm_key_handle(void *paraBuff) { kbd_data k; U32 msg_count; mmi_eq_keypad_detect_ind_struct *p; // 判断参数是否为空 // 在 初始化时,系统就注册了 MSG_ID_MMI_EQ_KEYPAD_DETECT_IND 的回调函数为 mmi_frm_key_handle // 当收到这个消息是,表示有按键事件要处理, // 这个paraBuff 是 keyTask 传过来的参数,里面的内容是获取按键信息的函数指针 if (paraBuff != NULL) { drv_get_key_func new_key_ptr; p = (mmi_eq_keypad_detect_ind_struct*) paraBuff; new_key_ptr = (drv_get_key_func) (p->func); //判断是否是新的函数指针,如果是的话,需要进行一些清理工作 if (new_key_ptr != keypad_ptr) { // 新的函数指针,则进行清理,并且判断是否有按键需要处理 if (!mmi_kbd_process_keyptr_change((void *)new_key_ptr)) { return; } //清理 按键 事件缓存buffer ClearKeyEvents(); keypad_ptr = new_key_ptr; } } // 通过 while 1 来 不停的从 按键缓存里获取按键信息 // 当然这里不会无限死循环,后面会进行相应处理 while (1) { //1)判读是否是挂起,2)是否key需要处理 if ((g_mmi_suspend_key_flag == MMI_FALSE) && keypad_ptr &&((*(keypad_ptr))(&k) == MMI_TRUE)) { if (k.Keydata[0] != KEY_INVALID) { #if defined(__MMI_TOUCH_SCREEN__) || defined(__MMI_HANDWRITING_PAD__) kal_bool is_pen_enabled, is_pen_down; // 获得触摸屏状态 mmi_pen_get_state(&is_pen_enabled, &is_pen_down); #endif /* defined(__MMI_TOUCH_SCREEN__) || defined(__MMI_HANDWRITING_PAD__) */ #if defined(__MMI_TOUCH_SCREEN__) || defined(__MMI_HANDWRITING_PAD__) //如果触摸屏按下,那么保存状态 if (is_pen_down && (k.Keyevent == WM_KEYPRESS)) { U16 KeyMapIndex; // 不允许 按键处理 is_allow_key_action = MMI_FALSE; // 把驱动的按键和MMI 按键进行转换 KeyMapIndex = mmi_frm_get_idx_from_device_key_code(k.Keydata[0]); 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; pressKey = HALF_DOWN_STATUS; key_is_pressing_count++; } else { nKeyPadStatus[KeyMapIndex] = KEY_EVENT_DOWN; pressKey = FULL_DOWN_STATUS; key_is_pressing_count++; } } } else #endif /* defined(__MMI_TOUCH_SCREEN__) || defined(__MMI_HANDWRITING_PAD__) */ //如果按键是弹起,那么还原原来按键状态,也就是弹起状态 // if ((k.Keyevent == WM_KEYRELEASE) && (is_allow_key_action == MMI_FALSE)) { #if defined(__MMI_TOUCH_SCREEN__) || defined(__MMI_HANDWRITING_PAD__) /* Reset allow key flag and Update key status even if pen is down*/ U16 KeyMapIndex; KeyMapIndex = mmi_frm_get_idx_from_device_key_code(k.Keydata[0]); if ((nKeyPadStatus[KeyMapIndex] == KEY_EVENT_DOWN) || (nKeyPadStatus[KeyMapIndex] == KEY_HALF_PRESS_DOWN) || (nKeyPadStatus[KeyMapIndex] == KEY_LONG_PRESS) || (nKeyPadStatus[KeyMapIndex] == KEY_REPEAT)) { nKeyPadStatus[KeyMapIndex] = KEY_EVENT_UP; key_is_pressing_count--; } prevKeyMapIndex = prevKeyMapIndex; #endif /* defined(__MMI_TOUCH_SCREEN__) || defined(__MMI_HANDWRITING_PAD__) */ is_allow_key_action = MMI_TRUE; } // 按键是否可以处理 if (is_allow_key_action == MMI_TRUE) { if (((k.Keyevent == WM_KEYPRESS) && (mmi_kbd_get_key_is_pressing_count() == 0)) || k.Keyevent == DRV_WM_KEYLONGPRESS || k.Keyevent == DRV_WM_KEYREPEATED || k.Keyevent == DRV_WM_KEYFULLPRESS) { #if defined(__MMI_TOUCH_SCREEN__) || defined(__MMI_HANDWRITING_PAD__) //关闭触摸屏 mmi_pen_disable(); #endif } //真正处理按键事件 mmi_frm_convert_process_key_event(k.Keyevent, k.Keydata[0]); if ((k.Keyevent == WM_KEYRELEASE) && (mmi_kbd_get_key_is_pressing_count() == 0)) { #if defined(__MMI_TOUCH_SCREEN__) || defined(__MMI_HANDWRITING_PAD__) //重新打开触摸屏 mmi_pen_enable(); #endif } } } // 获得MMI task 消息队列消息个数 msg_get_ext_queue_info(mmi_ext_qid, &msg_count); //如果外部有消息或者内部消息,则跳出该循环 if (msg_count > 0 || OslNumOfCircularQMsgs() > 0) { //表示还有key需要处理,在MMI task 里会直接调用这个函数进行再处理 g_keypad_flag = MMI_TRUE; break; } } else { // 没有key消息要处理 g_keypad_flag = MMI_FALSE; break; } } /* while(1) */ MMI_TRACE(MMI_FW_TRC_G1_FRM, MMI_FRM_KEY_HDLR_END); }
1) 这里key 用while (1)来处理,不停的从key 消息buffer里取出按键信息,然后处理,这么做可以防止task中不停的发送消息,可以理解为共享内存。同样当有其他消息来时,需要跳出来处理其他消息,处理完毕后还需要再来处理。
2)这里跟触摸屏的事件进行了冲突处理,也就是按键和触摸屏不能同时工作,这两者也没有优先级。
3)实际真正处理按键 是在 mmi_frm_convert_process_key_event里面,下次在分析