做了一段時間航海桌面,被長按,短按,組合鍵各種按鍵邏輯搞的死去活來。
功能堆積的太多後,根本是一團漿糊。
正好開發到一個段落,重新整理了按鍵邏輯,把按鍵識別和執行功能分離。
識別模塊負責將按鍵事件串對應成可以接受的按鍵狀態。把不需要關心的噪音過濾掉。後面記作Filter
執行模塊根據按鍵狀態執行功能。
S60的按鍵事件分成3中類型:Down,Event,Up。
其中Event裏的Repeats屬性會變化,有0和1兩種值。還有一個Modify屬性,不過基本沒用。後面把Event且Repeat(0)記作Event,Event且Repeat(1)記作Repeat
一個短按過程
Down Event Up
一個長按過程
Down Event (Repeat)+ Up
常見情況是一個鍵的長按,短按有不同的功能。
必須先出現一個Event事件,然後等待後面的時間出現,如果是Up則是短按,如果是Repeat則是長按。如果是長按,需要忽略後面的Repeat和Up事件。
理想的實現是,通過Filter,在長按的時候收到一個狀態表示長按,短按的時候收到一個狀態表示短按。
由於狀態和之前收到是按鍵事件串是一一對應的,所以,狀態可以用一個堆棧表示,按照接受順序講按鍵事件入棧就可以了。
可以用一棵樹來描述按鍵接受邏輯。當做DFA來處理。
終結節點是可能的接受,在這個節點可以返回。
非終結節點是過度用的輸入事件。
一個識別短按的DFA看起來是這樣的
一個短按長按都要識別的DFA看起來是這樣的
定義下這個DFA。
每個節點包含以下屬性
1. 按鍵掃描碼
2. 按鍵字符碼
3. 重複標誌
4. 按鍵類型
5. 控制位(終結,匹配字符碼,匹配掃描碼,匹配重複標誌)
匹配時根據控制位進行對應判斷。控制位不表明的屬性不參與匹配。
然後把各種按鍵的DFA組合成一個DFA,作爲Filter的控制邏輯。
當一個鍵盤幾乎所有的鍵都有對應功能的時候,這個很管用
比如我現在做的這航海桌面。
每個按鍵的長按短按都有一種功能。
通過這個Filter,就可以簡單的把Event和Repeat組成的時間串,分解成互相沒關聯的事件。否還要記錄狀態,這十分麻煩。
下面 LS表示左鍵,RS表示右鍵,其他的都是字符按鍵。
這個看起來很漂亮。很多部分都一樣,都是長按短按都識別,創建代碼也會很簡單。只有一個左鍵(LS)比較特殊,因爲有短按長按識別還有組合鍵識別。
這裏有個組合鍵,LS再RS。
通過引入超時事件就很容易處理。每次收到UP事件後就引入一個超時。如果超時了,那麼這個匹配路徑就被強制退棧。如果這個路徑上有終結點,就返回最後一個終結點作爲最後結果。
其實這也就是一個普通了不能再普通的連續按鍵判斷邏輯用DFA畫一邊。
識別成功後怎麼知道到底是匹配了那個路徑?把記錄堆棧掃描一下就行了。
終於不用再爲這種東西煩惱了。
以後考慮加入用xml描述DFA,這樣就可以錄下操作,描述不同的行爲。
定義
實現
使用Filter