MTK 按键处理流程和高亮处理机制

本文深入解析了按键处理流程及其与事件响应的关联,同时详细阐述了高亮处理机制,包括函数注册、菜单项查找及触发过程,旨在提供全面的理论与实践指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

声明:以上资料来自网上


1.按键处理流程


主要简单分析一下左右软件的事件,以左软键事件为例

牵涉到的常用函数:

     void SetKeyHandler( FuncPtr funcPtr, U16 keyCode, U16 keyType );

     void SetLeftSoftkeyFunction( void (*f)(void), MMI_key_event_type k );

     void ChangeLeftSoftkey( U16 s, U16 i );

    

1.   SetKeyHandlerSetLeftSoftkeyFunction

     (1). SetKeyHandler

           主要作用就是将需要起作用的函数的指针(funcPtr)

        -->全局矩阵数组currKeyFuncPtrs[keyCode][keyType]的指定位置 ;

     (2). SetLeftSoftkeyFunction

           该函数内部主要流程:

           Step1. call register_left_softkey_handler( )

                  这个函数call SetKeyHandler: 存储需要起作用的函数(left_softkey_down/left_softkey_up)

                      left_softkey为例, 该函数首先首先刷新按键区域图像(redraw_softkey),

                  然后执行关联函数(softkey_functions[key][k]).

           Step2. 在上一步里我们会发现,softkey_functions[key][k]里的函数指针没有初始化

                  通过 call set_left_softkey_function(f, k);

                   --->softkey_functions[key][k] = f;

                  这样,就成功的把按键按下/放开的作用函数与具体的动作关联起来了。

           Step3. 最后call SetInputboxLSKFunction(f)

                  --->将上述函数与特定的输入(如触摸笔)关联起来。

     (3). 以上两个函数的主要区别:

           SetLeftSoftkeyFunction可以识别长按状态并且可以关联触摸笔操作等。

 

2.   ChangeLeftSoftkey

     主要执行流程:

     Step1. call change_left_softkey: 设置左软键图表,文字

     Step2. redraw_softkey: 刷新左软键显示区域



2.高亮处理机制


相关函数和变量列表:

voidRegisterHighlightHandler(void(*f)(S32item_index))

注册窗口的通用高亮处理函数。

MMI_list_highlight_handler

通用高亮处理函数的全局变量指针。

voidExecuteCurrHiliteHandler(S32hiliteid)

当前高亮菜单项的通用处理函数,它会找到菜单项对应的处理函数。一般在窗口创建过程中被创建RegisterHighlightHandler(ExecuteCurrHiliteHandler)

FuncPtrmmi_frm_get_hilite_hdlr(U16menu_id)

获取menu_id对应的菜单高亮函数,从两个函数指针数组里获取。先查找动态菜单的高亮函数指针数组,这个是在程序中动态添加的数组;如果找不到,再到静态数组里查找,这个数组是在编译过程中生成的,通常我们在res_mainmenu.c等函数里增加的菜单会被资源生成工具编译成一个静态数组。

mmi_frm_int_hilite_hdlr_table[]动态数组。

mmi_frm_const_hilite_hdlr_table[]静态数组。

 

currParentID

当前父窗口全局变量

 

voidSetHiliteHandler(U16itemid,FuncPtrhiliteFuncPtr)

设置动态高亮数组的MENUID及它相对应的处理函数,一般用在自定义的菜单项。比如在图片浏览、JAVA应用、WAP记录等不可预期菜单项数目的环境,我们不可能做静态的MENUID和处理函数,就需要用到动态的实现方式。

hintData[][]

[待确认]:这是一个动态菜单的数据缓冲,和MENUID一一对应。通俗一点说,就是菜单的显示字符串。网上有文章对此以及ConstructHintsList()理解应该有误,主要是因为代码里该函数注释说是处理静态的,应该是注释错了。引用一段描述:

2ConstructHintsList()

ConstructsHintListforastaticmenuscreen

voidConstructHintsList(U16parentID,U8**hintArray)

{。。。。。。

(*maxHiliteInfo[hiliteItemID[i]].hintFuncPtr)(idx);//SetHintHandler注册的函数的函数在此被执行

hintArray[idx]=hintData[idx];//该语句是该函数的核心,就是将全局变量hintData[idx]数组地址

//赋给用户传过来的指针数组;至于hintData[idx]中是否有数据不

//管;hintData[idx]的数据会在调用SetHintHandler注册的函数时对其

//进行初始化;要记住SetHintHandler注册的函数在SetHiliteHandler注册的

//函数之前执行。

我认为ConstructHintsList()是创建动态菜单的,时间关系,待分析。

 

3高亮机制说明:

3.1使用流程

每个窗口进入后基本都有类似下面的一段程序:

。。。。。。

EntryNewScreen(EM_DEBUG_INFO_SCR,NULL,EntryEMDebugInfo,NULL);

 

guiBuffer=GetCurrGuiBuffer(EM_DEBUG_INFO_SCR);

nItems=GetNumOfChild(EM_DEBUG_INFO_MENUID);

GetSequenceStringIds(EM_DEBUG_INFO_MENUID,ItemList);

SetParentHandler(EM_DEBUG_INFO_MENUID);

RegisterHighlightHandler(ExecuteCurrHiliteHandler);

ShowCategory52Screen(。。。)

SetRightSoftkeyFunction(GoBackHistory,KEY_EVENT_UP);

。。。。。。

3.2分析

这是窗口建立过程的一个通用处理结构,这里简单说明一下,每个函数的具体实现和功能请阅读代码。

EntryNewScreen初始化建立一个窗口需要的变量和过程,并退出上一个窗口,清除按键处理函数等;

SetParentHandler很重要,设置当前父窗口全局变量的MENUID,用来定位到当前是在哪一个窗口,后面依据他来在菜单树中查找到高亮的菜单项的MENUID,找到菜单项的MENUID后,通过mmi_frm_get_hilite_hdlr(U16menu_id)可以找到菜单项对应的高亮函数;RegisterHighlightHandlerExecuteCurrHiliteHandler注册成一个通用的高亮处理函数,我们只要告诉ExecuteCurrHiliteHandler当前高亮的菜单项的MENUID,它就能找到执行函数并开始执行了。到这里就应该已经基本明白了高亮机制了,弄明白了其实也很简单的^_^

ShowCategory52Screen()只是一个窗口界面绘制函数,和事件处理逻辑没有关系。

SetRightSoftkeyFunction(GoBackHistory,KEY_EVENT_UP)等函数设置这个窗口要响应哪些按键事件,并设置好相应的处理函数。

 

3.3高亮函数触发过程

RegisterHighlightHandlerExecuteCurrHiliteHandler注册成一个通用的高亮处理函数,实际上是给MMI_list_highlight_handler函数指针赋值。触发则需要调用MMI_list_highlight_handler

由于MTK平台支持各种菜单形式,比如纯文本的菜单、带CHECKBOX的、带RADIO的、带一个图片的、带两个图片的、两行的。我们现在只对一种标准菜单进行分析,其他形式的分析方法相同。

standard_list_highlight_handler(S32item_index)里会执行注册的高亮处理函数MMI_list_highlight_handler,而standard_list_highlight_handler本身又是一个注册函数,在wgui_fixed_list_create_text_menu()里会被注册到MMI_fixed_list_menu.item_highlightedMMI_fixed_list_menu是菜单组件的数据结构,包含有菜单组件从显示到功能处理函数的所有数据,具体每个组件怎么被显示,怎么响应功能按键就不在这里讨论了,后续我可能会写出文档,有兴趣的同学自己看代码,效果会更好。

这里简单说一下,MMI_fixed_list_menu.item_highlighted在这个组件里,会被gui_fixed_list_menu_switch_highlighted_item()函数来执行,而gui_fixed_list_menu_switch_highlighted_item()则在上下按键执行的时候被执行,比响应上按键的函数是voidfixed_list_goto_previous_item(void),它调用voidgui_fixed_list_menu_goto_previous_item(fixed_list_menu*m),而voidgui_fixed_list_menu_goto_previous_item(fixed_list_menu*m)则调用gui_fixed_list_menu_switch_highlighted_item(),整个触发过程就完成了。

关于上下按键的注册,则在wgui_fixed_list_create_text_menu()里有:

if(flag&WGUI_LIST_MENU_DISABLE_VOL_KEY)

register_fixed_list_keys_ex();

else

register_fixed_list_keys();

来注册按键事件处理函数,其实现过程很简单:

voidregister_fixed_list_keys(void)

{

/*----------------------------------------------------------------*/

/*LocalVariables*/

/*----------------------------------------------------------------*/

 

/*----------------------------------------------------------------*/

/*CodeBody*/

/*----------------------------------------------------------------*/

SetKeyHandler(fixed_list_goto_previous_item,KEY_UP_ARROW,KEY_EVENT_DOWN);

SetKeyHandler(fixed_list_goto_next_item,KEY_DOWN_ARROW,KEY_EVENT_DOWN);

SetKeyHandler(fixed_list_goto_previous_item,KEY_VOL_UP,KEY_EVENT_DOWN);

SetKeyHandler(fixed_list_goto_next_item,KEY_VOL_DOWN,KEY_EVENT_DOWN);

}

 

关于如何实现按键事件的响应、按键的处理逻辑,又是一个专题了。大致包括键盘中断、去抖、键盘映射、检测、进程通信、应用部分按键处理机制等,有机会再写出文档。

 

4相关知识点说明:

4.1初始化相关

 

高亮的一些全局变量会在InitEvents()里进行初始化,在event.c文件里。这个函数在开机过程中的一个调用栈关系如下:

InitEvents();

InitEventHandlersBeforePowerOn();

voidMMI_task(oslEntryType*entry_param)

 

InitEvents();还会在InitFramework()中被调用,而InitFramework()会由于开机的状态不同,如USB开机、闹钟开机等,调用流程也不尽相同。具体的可参见我的另一篇应用开机流程的文档。

 

4.2菜单结构及查找

4.2.1菜单数数组示意

constCUSTOM_MENUmtk_nCustMenus[]={

{1,0,18,0,16,2,10933,11062,(U16*)nOrderMenuItem_0},

{2,0,3,1,0,1,26218,26085,(U16*)nOrderMenuItem_1},

{3,2,0,1,0,1,555,0,(U16*)0},

{4,2,0,1,0,1,552,0,(U16*)0},

{5,2,0,1,0,1,26173,0,(U16*)0},

{0,0,0,0,0,0,0,0,(U16*)0},

{0,0,0,0,0,0,0,0,(U16*)0},

{0,0,0,0,0,0,0,0,(U16*)0},

{0,0,0,0,0,0,0,0,(U16*)0},

{0,0,0,0,0,0,0,0,(U16*)0},

{0,0,0,0,0,0,0,0,(U16*)0},

。。。。。。。。

}


CUSTOM_MENUnCustMenus[MAX_MENU_ITEMS];

 

4.2.2通过父窗口MENUID及高亮INDEX找到高亮窗口MENUID

U16GetSeqItemId_Ext(U16parent_item_id,U16index)

{

/*----------------------------------------------------------------*/

/*LocalVariables*/

/*----------------------------------------------------------------*/

U8i=0,idx=0;

U16item_id=0;

U8child_count=(U8)nCustMenus[parent_item_id-1].nNumofMenuItem;

 

/*----------------------------------------------------------------*/

/*CodeBody*/

/*----------------------------------------------------------------*/

#ifdefDEVAPP_RESOURCE

if(parent_item_id>=MENU_ID_DEVAPP_START)

{

returnDevAppGetSeqItemId_Ext(parent_item_id,index);

}

#endif

 

for(i=0;i<child_count;i++)

{

item_id=nCustMenus[parent_item_id-1].nOrderMenuItemId[i];

if(!mmi_frm_test_menu_item_hide(item_id))/*theitemisnothidden*/

{

if(idx==index)

{

break;

}

else

{

idx++;

}

}

}

MMI_TRACE(MMI_FW_TRC_G2_GUI,MMI_RESGEN_ALL_MENU_HIDE,parent_item_id);

returnitem_id;

}

 

42.3通过高亮窗口MENUID找到对应的高亮函数

FuncPtrmmi_frm_get_hilite_hdlr(U16menu_id)

{

/*----------------------------------------------------------------*/

/*LocalVariables*/

/*----------------------------------------------------------------*/

U32index;

 

/*----------------------------------------------------------------*/

/*CodeBody*/

/*----------------------------------------------------------------*/

 

/*Firstlysearchthedynamictable*/

if(mmi_frm_binary_search((U32)menu_id,(mmi_frm_pair_data_struct*)mmi_frm_int_hilite_hdlr_table,

(U32)mmi_frm_int_hilite_hdlr_count,&index))

{

returnmmi_frm_int_hilite_hdlr_table[index].hilite_hdlr;

}

/*Andthensearchtheconstanttable.Theconstanttableisgenerantedbyresgen.*/

elseif(mmi_frm_binary_search((U32)menu_id,

(mmi_frm_pair_data_struct*)mmi_frm_const_hilite_hdlr_table,

(U32)ARRAY_COUNT(mmi_frm_const_hilite_hdlr_table),&index))

{

returnmmi_frm_const_hilite_hdlr_table[index].hilite_hdlr;

}

else

{

returnNULL;

}

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值