这一阶段一直在做MTK平台的开发,所以今天就准备了一些MTK的东西,与大家分享,今天主要的内容是
MTK的窗口历史管理。
MTK的窗口是由函数
U8 EntryNewScreen(U16 newscrnID, FuncPtr newExitHandler, FuncPtr newEntryHandler, void *flag)
来实现的。
该函数中参数的意义如下:
newscrID:新窗口的ID,每个窗口都有全局唯一的序号,该序号被定义于
newexithandler:新窗口的退出函数执行句柄
newentryhandler:新窗口的进入函数执行句柄,如果不为空,将会被系统自动加入窗口历史中
flag:不是很明白,碰到的基本都是NULL或者(void *)1;
NULL是采用普通方式进入新窗口,(void*)1则是全屏方式
其实还有
#define MMI_SMALL_SCREEN ((void*)2) /* *RESERVED* identify small-screen APP in EntryNewScreen() */
#define MMI_TAB_PAGE ((void*)3)
但是我没碰见过,所以此处不予考虑。
用户调用该函数后,将会先调用
currTopScrnID = newscrID
执行ExecuteCurrExitHandler
执行
而此时currEntryFuncPtr仍旧保存在原来屏幕的入口函数,它会去执行
GenericExitScreen(currExitScrnID, currEntryFuncPtr);
内部的核心代码正是
history h;
U16 nHistory = 0;
h.scrnID = scrnID;
h.entryFuncPtr = entryFuncPtr;
mmi_ucs2cpy((S8*) h.inputBuffer, (S8*) & nHistory);
GetCategoryHistory(h.guiBuffer);
AddHistory(h);
而AddHistory完成了压栈的过程。
那么历史记录又是如何保存的呢?我们可以去看history.c文件,可见Addhistory实际的工作如下:
if (IsBackHistory != MMI_TRUE)//如果是进入窗口那么它是false,如果是用户回退,那么它是true
{
increment();//使得当前堆栈栈顶指针加1
/* 3. Store History to History Data Structure */
memset(&historyData[currHistoryIndex], 0, sizeof(historyNode));//初始化新结点
historyData[currHistoryIndex].scrnID = addHistory->scrnID;//往新结点填入窗口ID
historyData[currHistoryIndex].entryFuncPtr = addHistory->entryFuncPtr;//往新结点填入入口函数指针
#ifdef __MMI_UI_SMALL_SCREEN_SUPPORT__
historyData[currHistoryIndex].isSmallScreen = (U16) small_history_node;
#endif
length = mmi_ucs2strlen((PS8) addHistory->inputBuffer);
MMI_ASSERT(length * ENCODING_LENGTH + ENCODING_LENGTH <= MAX_INPUT_BUFFER);
if (length)
{
historyData[currHistoryIndex].inputBuffer = OslMalloc(length * ENCODING_LENGTH + ENCODING_LENGTH);
mmi_ucs2cpy((PS8) historyData[currHistoryIndex].inputBuffer, (PS8) addHistory->inputBuffer);
}
historyData[currHistoryIndex].guiBuffer = OslMalloc(MAX_GUI_BUFFER);
memcpy(historyData[currHistoryIndex].guiBuffer, addHistory->guiBuffer, MAX_GUI_BUFFER);
}
#ifdef __MMI_UI_SMALL_SCREEN_SUPPORT__
small_history_node = 0;
#endif
IsBackHistory = MMI_FALSE;
在这里,大家可能跟我一样,都会很疑惑为什么系统没有去保存退出函数,下面的gobackhistory的分析我们就会明白。
完成记录之后,它会去执行currExitFuncPtr,使得退出前一个窗口。
最后SetGenericExitHandler会将新窗口的id,入口函数,退出函数都设置为curr的变量上。
下面我们来看退出函数Gobackhistory,我们这里为方便起见,抓了一组由菜单退到mainmenu的过程的堆栈情况:
ExecuteCurrExitHandler_Ext() line 985
ExecuteCurrExitHandler() line 763
EntryNewScreen(unsigned short 1502, void (void)* 0x0083ac45 exit_main_menu(void), void (void)* 0x00000000, void * 0x00000001) line 878
goto_main_menu() line 1581 + 19 bytes
ExecutePopHistory() line 1511 + 18 bytes
GoBackHistory() line 1227
可以看见,在gobackhistory里面,我们会去做堆栈的退栈操作,褪出来的是我们的入口函数,也就是说这个入口函数就是goto_main_menu,所以这
就相当于再次进入了mainmenu,而这时候的这些参数(例如退出函数)是具备的。
以上讨论的就是整体的history管理。有空我会继续对退出部分也作出细化。