From ca2b8b23a20207addfb6742030af0bdec576733a Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Thu, 31 Mar 2016 23:48:47 +0800 Subject: [PATCH] support EditSession in filterKeyDown/filterKeyUp --- TextService.cpp | 85 ++++++++++++++++++++++++++++--------------------- TextService.h | 10 +++--- 2 files changed, 54 insertions(+), 41 deletions(-) diff --git a/TextService.cpp b/TextService.cpp index 5b9acc0..a95b0c5 100644 --- a/TextService.cpp +++ b/TextService.cpp @@ -488,7 +488,7 @@ void TextService::onDeactivate() { } // virtual -bool TextService::filterKeyDown(KeyEvent& keyEvent) { +bool TextService::filterKeyDown(KeyEvent& keyEvent, EditSession* session) { return false; } @@ -498,7 +498,7 @@ bool TextService::onKeyDown(KeyEvent& keyEvent, EditSession* session) { } // virtual -bool TextService::filterKeyUp(KeyEvent& keyEvent) { +bool TextService::filterKeyUp(KeyEvent& keyEvent, EditSession *session) { return false; } @@ -861,34 +861,33 @@ STDMETHODIMP TextService::OnTestKeyDown(ITfContext *pContext, WPARAM wParam, LPA *pfEaten = FALSE; else { KeyEvent keyEvent(WM_KEYDOWN, wParam, lParam); - *pfEaten = (BOOL)filterKeyDown(keyEvent); + HRESULT sessionResult; + KeyEditSession* session = new KeyEditSession(this, pContext, keyEvent, true); + pContext->RequestEditSession(clientId_, session, TF_ES_SYNC | TF_ES_READWRITE, &sessionResult); + *pfEaten = session->result_; // tell TSF if we handled the key + session->Release(); } return S_OK; } STDMETHODIMP TextService::OnKeyDown(ITfContext *pContext, WPARAM wParam, LPARAM lParam, BOOL *pfEaten) { - // Some applications do not trigger OnTestKeyDown() - // So we need to test it again here! Windows TSF sucks! if(isKeyboardDisabled(pContext) || !isKeyboardOpened()) *pfEaten = FALSE; else { KeyEvent keyEvent(WM_KEYDOWN, wParam, lParam); - *pfEaten = (BOOL)filterKeyDown(keyEvent); - if(*pfEaten) { // we want to eat the key - HRESULT sessionResult; - // ask TSF for an edit session. If editing is approved by TSF, - // KeyEditSession::DoEditSession will be called, which in turns - // call back to TextService::doKeyEditSession(). - // So the real key handling is relayed to TextService::doKeyEditSession(). - KeyEditSession* session = new KeyEditSession(this, pContext, keyEvent); - - // We use TF_ES_SYNC here, so the request becomes synchronus and blocking. - // KeyEditSession::DoEditSession() and TextService::doKeyEditSession() will be - // called before RequestEditSession() returns. - pContext->RequestEditSession(clientId_, session, TF_ES_SYNC|TF_ES_READWRITE, &sessionResult); - *pfEaten = session->result_; // tell TSF if we handled the key - session->Release(); - } + HRESULT sessionResult; + // ask TSF for an edit session. If editing is approved by TSF, + // KeyEditSession::DoEditSession will be called, which in turns + // call back to TextService::doKeyEditSession(). + // So the real key handling is relayed to TextService::doKeyEditSession(). + KeyEditSession* session = new KeyEditSession(this, pContext, keyEvent, false); + + // We use TF_ES_SYNC here, so the request becomes synchronus and blocking. + // KeyEditSession::DoEditSession() and TextService::doKeyEditSession() will be + // called before RequestEditSession() returns. + pContext->RequestEditSession(clientId_, session, TF_ES_SYNC|TF_ES_READWRITE, &sessionResult); + *pfEaten = session->result_; // tell TSF if we handled the key + session->Release(); } return S_OK; } @@ -897,8 +896,12 @@ STDMETHODIMP TextService::OnTestKeyUp(ITfContext *pContext, WPARAM wParam, LPARA if(isKeyboardDisabled(pContext) || !isKeyboardOpened()) *pfEaten = FALSE; else { - KeyEvent keyEvent(WM_KEYDOWN, wParam, lParam); - *pfEaten = (BOOL)filterKeyUp(keyEvent); + KeyEvent keyEvent(WM_KEYUP, wParam, lParam); + HRESULT sessionResult; + KeyEditSession* session = new KeyEditSession(this, pContext, keyEvent, true); + pContext->RequestEditSession(clientId_, session, TF_ES_SYNC | TF_ES_READWRITE, &sessionResult); + *pfEaten = session->result_; // tell TSF if we handled the key + session->Release(); } return S_OK; } @@ -910,14 +913,11 @@ STDMETHODIMP TextService::OnKeyUp(ITfContext *pContext, WPARAM wParam, LPARAM lP *pfEaten = FALSE; else { KeyEvent keyEvent(WM_KEYUP, wParam, lParam); - *pfEaten = (BOOL)filterKeyUp(keyEvent); - if(*pfEaten) { - HRESULT sessionResult; - KeyEditSession* session = new KeyEditSession(this, pContext, keyEvent); - pContext->RequestEditSession(clientId_, session, TF_ES_SYNC|TF_ES_READWRITE, &sessionResult); - *pfEaten = session->result_; // tell TSF if we handled the key - session->Release(); - } + HRESULT sessionResult; + KeyEditSession* session = new KeyEditSession(this, pContext, keyEvent, false); + pContext->RequestEditSession(clientId_, session, TF_ES_SYNC|TF_ES_READWRITE, &sessionResult); + *pfEaten = session->result_; // tell TSF if we handled the key + session->Release(); } return S_OK; } @@ -1005,7 +1005,7 @@ STDMETHODIMP TextService::OnActivated(REFCLSID clsid, REFGUID guidProfile, BOOL // edit session handling STDMETHODIMP TextService::KeyEditSession::DoEditSession(TfEditCookie ec) { EditSession::DoEditSession(ec); - return textService_->doKeyEditSession(ec, this); + return textService_->doKeyEditSession(ec, this, testOnly_); } // edit session handling @@ -1021,11 +1021,22 @@ STDMETHODIMP TextService::EndCompositionEditSession::DoEditSession(TfEditCookie } // callback from edit session of key events -HRESULT TextService::doKeyEditSession(TfEditCookie cookie, KeyEditSession* session) { - if(session->keyEvent_.type() == WM_KEYDOWN) - session->result_ = onKeyDown(session->keyEvent_, session); - else if(session->keyEvent_.type() == WM_KEYUP) - session->result_ = onKeyUp(session->keyEvent_, session); +HRESULT TextService::doKeyEditSession(TfEditCookie cookie, KeyEditSession* session, bool testOnly) { + // Some applications do not trigger OnTestKeyDown() + // So we need to test it again here! Windows TSF sucks! + + UINT type = session->keyEvent_.type(); + if (type == WM_KEYDOWN) + session->result_ = filterKeyDown(session->keyEvent_, session); + else if (type == WM_KEYUP) + session->result_ = filterKeyUp(session->keyEvent_, session); + + if (session->result_ && !testOnly) { + if (type == WM_KEYDOWN) + session->result_ = onKeyDown(session->keyEvent_, session); + else if (type == WM_KEYUP) + session->result_ = onKeyUp(session->keyEvent_, session); + } return S_OK; } diff --git a/TextService.h b/TextService.h index cae1853..e933c15 100644 --- a/TextService.h +++ b/TextService.h @@ -154,10 +154,10 @@ class TextService: virtual void onSetFocus(); virtual void onKillFocus(); - virtual bool filterKeyDown(KeyEvent& keyEvent); + virtual bool filterKeyDown(KeyEvent& keyEvent, EditSession* session); virtual bool onKeyDown(KeyEvent& keyEvent, EditSession* session); - virtual bool filterKeyUp(KeyEvent& keyEvent); + virtual bool filterKeyUp(KeyEvent& keyEvent, EditSession* session); virtual bool onKeyUp(KeyEvent& keyEvent, EditSession* session); virtual bool onPreservedKey(const GUID& guid); @@ -240,14 +240,16 @@ class TextService: // edit session classes, used with TSF class KeyEditSession: public EditSession { public: - KeyEditSession(TextService* service, ITfContext* context, KeyEvent& keyEvent): + KeyEditSession(TextService* service, ITfContext* context, KeyEvent& keyEvent, bool testOnly): EditSession(service, context), keyEvent_(keyEvent), + testOnly_(testOnly), result_(false) { } STDMETHODIMP DoEditSession(TfEditCookie ec); KeyEvent keyEvent_; + bool testOnly_; bool result_; }; @@ -267,7 +269,7 @@ class TextService: STDMETHODIMP DoEditSession(TfEditCookie ec); }; - HRESULT doKeyEditSession(TfEditCookie cookie, KeyEditSession* session); + HRESULT doKeyEditSession(TfEditCookie cookie, KeyEditSession* session, bool testOnly); HRESULT doStartCompositionEditSession(TfEditCookie cookie, StartCompositionEditSession* session); HRESULT doEndCompositionEditSession(TfEditCookie cookie, EndCompositionEditSession* session);