// // // Sapilayr TIP Key event related functions. // // #include "private.h" #include "sapilayr.h" #include "nui.h" #include "keyevent.h" #include "cregkey.h" // // hot key for TTS Play/Stop. const KESPRESERVEDKEY g_prekeyList[] = { { &GUID_HOTKEY_TTS_PLAY_STOP, { 'S', TF_MOD_WIN }, L"TTS Speech" }, { NULL, { 0, 0}, NULL } }; KESPRESERVEDKEY g_prekeyList_Mode[] = { { &GUID_HOTKEY_MODE_DICTATION, {VK_F11 , 0}, L"Dictation Button" }, { &GUID_HOTKEY_MODE_COMMAND, {VK_F12 , 0}, L"Command Button" }, { NULL, { 0, 0}, NULL } }; //+--------------------------------------------------------------------------- // // CSptipKeyEventSink::RegisterEx: Registr the special speech mode buttons. // //---------------------------------------------------------------------------- HRESULT CSptipKeyEventSink::_RegisterEx(ITfThreadMgr *ptim, TfClientId tid, const KESPRESERVEDKEY *pprekey) { HRESULT hr; ITfKeystrokeMgr_P *pKeyMgr; if (FAILED(ptim->QueryInterface(IID_ITfKeystrokeMgr_P, (void **)&pKeyMgr))) return E_FAIL; hr = E_FAIL; while (pprekey->pguid) { if (FAILED(pKeyMgr->PreserveKeyEx(tid, *pprekey->pguid, &pprekey->tfpk, pprekey->psz, wcslen(pprekey->psz), TF_PKEX_SYSHOTKEY | TF_PKEX_NONEEDDIM))) goto Exit; pprekey++; } ptim->AddRef(); hr = S_OK; Exit: SafeRelease(pKeyMgr); return hr; } HRESULT CSapiIMX::_PreKeyEventCallback(ITfContext *pic, REFGUID rguid, BOOL *pfEaten, void *pv) { CSapiIMX *_this = (CSapiIMX *)pv; CSpeechUIServer *pSpeechUIServer; BOOL fButtonEnable; TraceMsg(TF_SPBUTTON, "_PreKeyEventCallback is called"); *pfEaten = FALSE; if (_this == NULL) return S_OK; pSpeechUIServer = _this->GetSpeechUIServer( ); if (!pSpeechUIServer) return S_OK; fButtonEnable = pSpeechUIServer->GetTtsButtonStatus( ); if (IsEqualGUID(rguid, GUID_HOTKEY_TTS_PLAY_STOP)) { if ( fButtonEnable ) { _this->_HandleEventOnPlayButton( ); *pfEaten = TRUE; } } else if ( IsEqualGUID(rguid, GUID_HOTKEY_MODE_DICTATION) || IsEqualGUID(rguid, GUID_HOTKEY_MODE_COMMAND) ) { if ( _this->_IsModeKeysEnabled( ) ) *pfEaten = TRUE; else *pfEaten = FALSE; } TraceMsg(TF_SPBUTTON, "_PreKeyEventCallback fEaten=%d", *pfEaten); return S_OK; } //+--------------------------------------------------------------------------- // // _KeyEventCallback // //---------------------------------------------------------------------------- HRESULT CSapiIMX::_KeyEventCallback(UINT uCode, ITfContext *pic, WPARAM wParam, LPARAM lParam, BOOL *pfEaten, void *pv) { CSapiIMX *pimx; HRESULT hr = S_OK; CSapiIMX *_this = (CSapiIMX *)pv; *pfEaten = FALSE; Assert(uCode != KES_CODE_FOCUS); // we should never get this callback because we shouldn't take the keyboard focus if (!(uCode & KES_CODE_KEYDOWN)) return S_OK; // only want key downs if (pic == NULL) // no focus ic? return S_OK; pimx = (CSapiIMX *)pv; *pfEaten = TRUE; switch (wParam & 0xFF) { case VK_F8: if (!(uCode & KES_CODE_TEST)) { CSapiPlayBack *ppb; if (ppb = new CSapiPlayBack(pimx)) { CPlayBackEditSession *pes; if (pes = new CPlayBackEditSession(ppb, pic)) { pes->_SetEditSessionData(ESCB_PLAYBK_PLAYSNDSELECTION, NULL, 0); pic->RequestEditSession(_this->_tid, pes, TF_ES_READ | TF_ES_SYNC, &hr); pes->Release(); } ppb->Release(); } } break; case VK_ESCAPE: if (!(uCode & KES_CODE_TEST)) { if (_this->m_pCSpTask) hr = _this->m_pCSpTask->_StopInput(); } *pfEaten = FALSE; break; default: *pfEaten = FALSE; #ifdef LONGHORN // // For english composition scenario, I'm trying to see if this works. // Note that this is not the final design to support typing while // composing dictation. m_pMouseSink != NULL only when composition // is active so I'm overriding it as a flag. // if (_this->GetLangID() == 0x0409) { if ((BYTE)wParam != VK_LEFT && (BYTE)wParam != VK_RIGHT && (isprint((BYTE)wParam) || (VK_OEM_1 <= (BYTE)wParam && (BYTE)wParam < VK_OEM_8)) && _this->m_pMouseSink) { WCHAR wc[3]; BYTE keystate[256]; if (GetKeyboardState(keystate)) { if (ToUnicodeEx(wParam,(UINT)lParam, keystate, wc, ARRAYSIZE(wc), 0, GetKeyboardLayout(NULL)) > 0) { *pfEaten = TRUE; // want this key only if there is // a printable character if (!(uCode & KES_CODE_TEST)) { // we don't handle deadkeys here for now wc[1] = L'\0'; // call InjectSpelledText() with fOwnerId == TRUE hr = _this->InjectSpelledText(wc, _this->GetLangID(), TRUE); } } } } } break; #endif } return hr; } // // ITfKeyTraceEventSink method functions. // // STDAPI CSapiIMX::OnKeyTraceUp(WPARAM wParam,LPARAM lParam) { // We just check KeyDown, ignore KeyUp event. // so just return S_OK immediately. TraceMsg(TF_SPBUTTON, "OnKeyTraceUp is called"); UNREFERENCED_PARAMETER(lParam); HandleModeKeyEvent( (DWORD)wParam, FALSE); return S_OK; } // // Take use this method to detect if user is typing // // if it is typing, disable dictation rule temporally. // STDAPI CSapiIMX::OnKeyTraceDown(WPARAM wParam,LPARAM lParam) { BOOL fDictOn; TraceMsg(TF_SPBUTTON, "OnKeyTraceDown is called, wParam=%x", wParam); if ( HandleModeKeyEvent((DWORD)wParam, TRUE )) { // if the mode key is pressed, don't disable dictation as usual. return S_OK; } fDictOn = (GetOnOff( ) && GetDICTATIONSTAT_DictOnOff( )); if (fDictOn && !m_ulSimulatedKey && m_pCSpTask && S_OK == IsActiveThread()) // Only want this to happen on the active thread which could be the stage. { // User is typing. // // Temporally disable Dictation if Dictation Mode is ON // if ( _NeedDisableDictationWhileTyping( ) ) { if ( _GetNumCharTyped( ) == 0 ) { m_pCSpTask->_SetDictRecoCtxtState(FALSE); m_pCSpTask->_SetRecognizerInterest(0); m_pCSpTask->_UpdateBalloon(IDS_BALLOON_DICTAT_PAUSED, IDS_BALLOON_TOOLTIP_TYPING); } // // and then start a timer to watch for the end of typing. // _SetCharTypeTimer( ); } } if ( m_ulSimulatedKey > 0 ) m_ulSimulatedKey --; return S_OK; } // +-------------------------------------------------------------------------- // HandleModeKeySettingChange // // When any mode button setting is changed, such as mode button's // enable/disable status change, virtual keys for dictation and command // are changed, this function will respond for this change. // // --------------------------------------------------------------------------- void CSapiIMX::HandleModeKeySettingChange(BOOL fSetttingChanged ) { BOOL fModeKeyEnabled = _IsModeKeysEnabled( ); DWORD dwDictVirtKey = _GetDictationButton( ); DWORD dwCommandVirtKey = _GetCommandButton( ); if ( !fSetttingChanged || !_pkes ) return; // mode button setting is changed. // unregister the hotkey first if the keys were registered before. if ( m_fModeKeyRegistered ) { _pkes->_Unregister(_tim, _tid, (const KESPRESERVEDKEY *)g_prekeyList_Mode); m_fModeKeyRegistered = FALSE; } // Update the virtual keys in g_prekeyList_Mode g_prekeyList_Mode[0].tfpk.uVKey = (UINT)dwDictVirtKey; g_prekeyList_Mode[1].tfpk.uVKey = (UINT)dwCommandVirtKey; // register hotkeys again based on the mode button enable status setting if ( fModeKeyEnabled ) { _pkes->_RegisterEx(_tim, _tid, (const KESPRESERVEDKEY *)g_prekeyList_Mode); m_fModeKeyRegistered = TRUE; } } // +-------------------------------------------------------------------------- // HandleModeKeyEvent // // dwModeKey to indicate which mode key is process. // fDown to indicate if the button is down or up // // Return TRUE means this key is a correct mode key and processed sucessfully // otherwisze, the keyevent is not handled correctly or not a mode key. // --------------------------------------------------------------------------- BOOL CSapiIMX::HandleModeKeyEvent(DWORD dwModeKey, BOOL fDown) { BOOL fRet=FALSE; BOOL fModeKeyEnabled; DWORD DictVirtKey, CommandVirtKey; fModeKeyEnabled = _IsModeKeysEnabled( ); DictVirtKey = _GetDictationButton( ); CommandVirtKey = _GetCommandButton( ); if ( fModeKeyEnabled && ((dwModeKey == DictVirtKey) || (dwModeKey == CommandVirtKey)) ) { if ( !m_pSpButtonControl ) m_pSpButtonControl = new SpButtonControl(this); if ( m_pSpButtonControl ) { // GetMessageTime( ) will return the real time when // KEYDOWN and KEYUP event was generated. UINT uTimeKey=(UINT)GetMessageTime( ); if ( dwModeKey == DictVirtKey ) m_pSpButtonControl->SetDictationButton(fDown,uTimeKey); else m_pSpButtonControl->SetCommandingButton(fDown, uTimeKey); fRet = TRUE; } } return fRet; }