Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2443 lines
67 KiB

  1. //
  2. // hotkey.cpp
  3. //
  4. #include "private.h"
  5. #include "tim.h"
  6. #include "dim.h"
  7. #include "ic.h"
  8. #include "hotkey.h"
  9. #include "nuictrl.h"
  10. #include "nuihkl.h"
  11. #include "cregkey.h"
  12. #include "ime.h"
  13. #include "ctffunc.h"
  14. #include "profiles.h"
  15. #define TF_MOD_ALL (TF_MOD_ALT | \
  16. TF_MOD_CONTROL | \
  17. TF_MOD_SHIFT | \
  18. TF_MOD_RALT | \
  19. TF_MOD_RCONTROL | \
  20. TF_MOD_RSHIFT | \
  21. TF_MOD_LALT | \
  22. TF_MOD_LCONTROL | \
  23. TF_MOD_LSHIFT | \
  24. TF_MOD_ON_KEYUP | \
  25. TF_MOD_IGNORE_ALL_MODIFIER | \
  26. TF_MOD_WIN | \
  27. TF_MOD_LWIN | \
  28. TF_MOD_RWIN)
  29. static const TCHAR c_szKbdToggleKey[] = TEXT("Keyboard Layout\\Toggle");
  30. static const TCHAR c_szHotKey[] = TEXT("Control Panel\\Input Method\\Hot Keys");
  31. static const TCHAR c_szModifiers[] = TEXT("Key Modifiers");
  32. static const TCHAR c_szVKey[] = TEXT("Virtual Key");
  33. UINT g_uLangHotKeyModifiers = 0;
  34. UINT g_uLangHotKeyVKey[2] = {0,0};
  35. UINT g_uKeyTipHotKeyModifiers = 0;
  36. UINT g_uKeyTipHotKeyVKey[2] = {0,0};
  37. UINT g_uModifiers = 0;
  38. #define CHSLANGID MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
  39. #define CHTLANGID MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)
  40. //
  41. // default IMM32 hotkeys.
  42. //
  43. // we use these default hotkey values if there is no entry in
  44. // HKCU\Control Panel\Input Method\Hot Keys.
  45. //
  46. //
  47. IMM32HOTKEY g_ImmHotKeys411[] = {
  48. {IME_JHOTKEY_CLOSE_OPEN , VK_KANJI, TF_MOD_IGNORE_ALL_MODIFIER, FALSE},
  49. {0 , 0, 0, FALSE}
  50. };
  51. IMM32HOTKEY g_ImmHotKeys412[] = {
  52. {IME_KHOTKEY_SHAPE_TOGGLE , -1, -1, FALSE},
  53. {IME_KHOTKEY_HANJACONVERT , -1, -1, FALSE},
  54. {IME_KHOTKEY_ENGLISH , -1, -1, FALSE},
  55. {0 , 0, 0, FALSE}
  56. };
  57. IMM32HOTKEY g_ImmHotKeys804[] = {
  58. {IME_CHOTKEY_IME_NONIME_TOGGLE , VK_SPACE, TF_MOD_CONTROL, FALSE},
  59. {IME_CHOTKEY_SHAPE_TOGGLE , VK_SPACE, TF_MOD_SHIFT, FALSE},
  60. {IME_CHOTKEY_SYMBOL_TOGGLE , -1, -1, FALSE},
  61. {0 , 0, 0, FALSE}
  62. };
  63. IMM32HOTKEY g_ImmHotKeys404[] = {
  64. {IME_THOTKEY_IME_NONIME_TOGGLE , VK_SPACE, TF_MOD_CONTROL, FALSE},
  65. {IME_THOTKEY_SHAPE_TOGGLE , VK_SPACE, TF_MOD_SHIFT, FALSE},
  66. {IME_THOTKEY_SYMBOL_TOGGLE , -1, -1, FALSE},
  67. {IME_ITHOTKEY_RESEND_RESULTSTR , -1, -1, FALSE},
  68. {IME_ITHOTKEY_PREVIOUS_COMPOSITION , -1, -1, FALSE},
  69. {IME_ITHOTKEY_UISTYLE_TOGGLE , -1, -1, FALSE},
  70. {IME_ITHOTKEY_RECONVERTSTRING , -1, -1, FALSE},
  71. {0 , 0, 0, FALSE}
  72. };
  73. //////////////////////////////////////////////////////////////////////////////
  74. //
  75. // CAsyncProcessHotKeyQueueItem
  76. //
  77. //////////////////////////////////////////////////////////////////////////////
  78. class CAsyncProcessHotKeyQueueItem : public CAsyncQueueItem
  79. {
  80. public:
  81. CAsyncProcessHotKeyQueueItem(WPARAM wParam, LPARAM lParam, TimSysHotkey tsh, BOOL fTest, BOOL fSync) : CAsyncQueueItem(fSync)
  82. {
  83. _wParam = wParam;
  84. _lParam = lParam;
  85. _tsh = tsh;
  86. _fTest = fTest;
  87. }
  88. HRESULT DoDispatch(CInputContext *pic)
  89. {
  90. CThreadInputMgr *ptim = CThreadInputMgr::_GetThis();
  91. if (!ptim)
  92. {
  93. Assert(0);
  94. return E_FAIL;
  95. }
  96. ptim->_SyncProcessHotKey(_wParam, _lParam, _tsh, _fTest);
  97. return S_OK;
  98. }
  99. private:
  100. WPARAM _wParam;
  101. LPARAM _lParam;
  102. TimSysHotkey _tsh;
  103. BOOL _fTest;
  104. };
  105. //////////////////////////////////////////////////////////////////////////////
  106. //
  107. // MSCTF default hotkeys.
  108. //
  109. //////////////////////////////////////////////////////////////////////////////
  110. typedef struct tag_DEFAULTHOTKEY
  111. {
  112. const GUID *pguid;
  113. UINT uId;
  114. TF_PRESERVEDKEY prekey;
  115. TfGuidAtom guidatom;
  116. } DEFAULTHOTKEY;
  117. /* 61847d8e-29ff-11d4-97a9-00105a2799b5 */
  118. const GUID GUID_DEFHOTKEY_CORRECTION = {
  119. 0x61847d8e,
  120. 0x29ff,
  121. 0x11d4,
  122. {0x97, 0xa9, 0x00, 0x10, 0x5a, 0x27, 0x99, 0xb5}
  123. };
  124. /* 61847d8f-29ff-11d4-97a9-00105a2799b5 */
  125. const GUID GUID_DEFHOTKEY_VOICE = {
  126. 0x61847d8f,
  127. 0x29ff,
  128. 0x11d4,
  129. {0x97, 0xa9, 0x00, 0x10, 0x5a, 0x27, 0x99, 0xb5}
  130. };
  131. /* 61847d90-29ff-11d4-97a9-00105a2799b5 */
  132. const GUID GUID_DEFHOTKEY_TOGGLE = {
  133. 0x61847d90,
  134. 0x29ff,
  135. 0x11d4,
  136. {0x97, 0xa9, 0x00, 0x10, 0x5a, 0x27, 0x99, 0xb5}
  137. };
  138. /* 61847d91-29ff-11d4-97a9-00105a2799b5 */
  139. const GUID GUID_DEFHOTKEY_HANDWRITE = {
  140. 0x61847d91,
  141. 0x29ff,
  142. 0x11d4,
  143. {0x97, 0xa9, 0x00, 0x10, 0x5a, 0x27, 0x99, 0xb5}
  144. };
  145. #define DHID_CORRECTION 0
  146. #define DHID_VOICE 1
  147. #define DHID_TOGGLE 2
  148. #define DHID_HANDWRITE 3
  149. #define DEFHOTKEYNUM 4
  150. DEFAULTHOTKEY g_DefHotKeys[] = {
  151. {&GUID_DEFHOTKEY_CORRECTION, DHID_CORRECTION, {'C',TF_MOD_WIN}, TF_INVALID_GUIDATOM},
  152. {&GUID_DEFHOTKEY_VOICE, DHID_VOICE, {'V',TF_MOD_WIN}, TF_INVALID_GUIDATOM},
  153. {&GUID_DEFHOTKEY_TOGGLE, DHID_TOGGLE, {'T',TF_MOD_WIN}, TF_INVALID_GUIDATOM},
  154. {&GUID_DEFHOTKEY_HANDWRITE, DHID_HANDWRITE, {'H',TF_MOD_WIN}, TF_INVALID_GUIDATOM},
  155. };
  156. //+---------------------------------------------------------------------------
  157. //
  158. // InitDefaultHotkeys
  159. //
  160. //----------------------------------------------------------------------------
  161. HRESULT CThreadInputMgr::InitDefaultHotkeys()
  162. {
  163. int i;
  164. for (i = 0; i < DEFHOTKEYNUM; i++)
  165. {
  166. CHotKey *pHotKey;
  167. HRESULT hr;
  168. hr = InternalPreserveKey(NULL,
  169. *g_DefHotKeys[i].pguid,
  170. &g_DefHotKeys[i].prekey,
  171. NULL, 0, 0, &pHotKey);
  172. if (SUCCEEDED(hr) && pHotKey)
  173. g_DefHotKeys[i].guidatom = pHotKey->_guidatom;
  174. }
  175. return S_OK;
  176. }
  177. //+---------------------------------------------------------------------------
  178. //
  179. // UninitDefaultHotkeys
  180. //
  181. //----------------------------------------------------------------------------
  182. HRESULT CThreadInputMgr::UninitDefaultHotkeys()
  183. {
  184. int i;
  185. for (i = 0; i < DEFHOTKEYNUM; i++)
  186. {
  187. UnpreserveKey(*g_DefHotKeys[i].pguid,
  188. &g_DefHotKeys[i].prekey);
  189. }
  190. return S_OK;
  191. }
  192. //+---------------------------------------------------------------------------
  193. //
  194. // PreserveKey
  195. //
  196. //----------------------------------------------------------------------------
  197. HRESULT CThreadInputMgr::PreserveKey(TfClientId tid, REFGUID rguid, const TF_PRESERVEDKEY *pprekey, const WCHAR *pchDesc, ULONG cchDesc)
  198. {
  199. CTip *ctip;
  200. if (!_GetCTipfromGUIDATOM(tid, &ctip))
  201. return E_INVALIDARG;
  202. return InternalPreserveKey(ctip, rguid, pprekey, pchDesc, cchDesc, 0, NULL);
  203. }
  204. //+---------------------------------------------------------------------------
  205. //
  206. // PreserveKeyEx
  207. //
  208. //----------------------------------------------------------------------------
  209. HRESULT CThreadInputMgr::PreserveKeyEx(TfClientId tid, REFGUID rguid, const TF_PRESERVEDKEY *pprekey, const WCHAR *pchDesc, ULONG cchDesc, DWORD dwFlags)
  210. {
  211. CTip *ctip;
  212. if (!_GetCTipfromGUIDATOM(tid, &ctip))
  213. return E_INVALIDARG;
  214. return InternalPreserveKey(ctip, rguid, pprekey, pchDesc, cchDesc, dwFlags, NULL);
  215. }
  216. //+---------------------------------------------------------------------------
  217. //
  218. // InternalPreserveKey
  219. //
  220. //----------------------------------------------------------------------------
  221. HRESULT CThreadInputMgr::InternalPreserveKey(CTip *ctip, REFGUID rguid, const TF_PRESERVEDKEY *pprekey, const WCHAR *pchDesc, ULONG cchDesc, DWORD dwFlags, CHotKey **ppHotKey)
  222. {
  223. CHotKey *pHotKey = NULL;
  224. int nCnt;
  225. HRESULT hr = E_FAIL;
  226. if (!pprekey)
  227. return E_INVALIDARG;
  228. if (pprekey->uVKey > 0xff)
  229. {
  230. hr = E_INVALIDARG;
  231. goto Exit;
  232. }
  233. if (ctip && _IsThisHotKey(ctip->_guidatom, pprekey))
  234. {
  235. hr = TF_E_ALREADY_EXISTS;
  236. goto Exit;
  237. }
  238. if (!(pHotKey = new CHotKey()))
  239. {
  240. hr = E_OUTOFMEMORY;
  241. goto Exit;
  242. }
  243. if (!pHotKey->Init(ctip ? ctip->_guidatom : g_gaSystem, pprekey, rguid, dwFlags))
  244. {
  245. hr = E_FAIL;
  246. goto Exit;
  247. }
  248. if (!pHotKey->SetDesc(pchDesc, cchDesc))
  249. {
  250. hr = E_OUTOFMEMORY;
  251. goto Exit;
  252. }
  253. if (!_rgHotKey[pprekey->uVKey])
  254. {
  255. if (!(_rgHotKey[pprekey->uVKey] = new CPtrArray<CHotKey>))
  256. {
  257. hr = E_OUTOFMEMORY;
  258. goto Exit;
  259. }
  260. }
  261. //
  262. // Insert this to VKey list
  263. //
  264. nCnt = _rgHotKey[pprekey->uVKey]->Count();
  265. if (!_rgHotKey[pprekey->uVKey]->Insert(nCnt, 1))
  266. {
  267. hr = E_OUTOFMEMORY;
  268. goto Exit;
  269. }
  270. _rgHotKey[pprekey->uVKey]->Set(nCnt, pHotKey);
  271. //
  272. // Insert this to CTip list
  273. //
  274. if (ctip)
  275. {
  276. nCnt = ctip->_rgHotKey.Count();
  277. if (!ctip->_rgHotKey.Insert(nCnt, 1))
  278. {
  279. hr = E_OUTOFMEMORY;
  280. goto Exit;
  281. }
  282. ctip->_rgHotKey.Set(nCnt, pHotKey);
  283. }
  284. hr = S_OK;
  285. _OnPreservedKeyUpdate(pHotKey);
  286. Exit:
  287. if (pHotKey && (hr != S_OK))
  288. {
  289. delete pHotKey;
  290. }
  291. if (ppHotKey)
  292. *ppHotKey = (hr == S_OK) ? pHotKey : NULL;
  293. return hr;
  294. }
  295. //+---------------------------------------------------------------------------
  296. //
  297. // _IsThisHotKey
  298. //
  299. //----------------------------------------------------------------------------
  300. BOOL CThreadInputMgr::_IsThisHotKey(TfClientId tid, const TF_PRESERVEDKEY *pprekey)
  301. {
  302. int nCnt;
  303. int i;
  304. if (!_rgHotKey[pprekey->uVKey])
  305. return FALSE;
  306. nCnt = _rgHotKey[pprekey->uVKey]->Count();
  307. for (i = 0; i < nCnt; i++)
  308. {
  309. CHotKey *pHotKey;
  310. pHotKey = _rgHotKey[pprekey->uVKey]->Get(i);
  311. Assert(pHotKey);
  312. Assert(pHotKey->_prekey.uVKey == pprekey->uVKey);
  313. if (!pHotKey->IsValidTID(tid))
  314. continue;
  315. if (pHotKey->_prekey.uModifiers == pprekey->uModifiers)
  316. return TRUE;
  317. }
  318. return FALSE;
  319. }
  320. //+---------------------------------------------------------------------------
  321. //
  322. // UnregisterHotKey
  323. //
  324. //----------------------------------------------------------------------------
  325. HRESULT CThreadInputMgr::UnpreserveKey(REFGUID rguid, const TF_PRESERVEDKEY *pprekey)
  326. {
  327. int i;
  328. BOOL bFound = FALSE;
  329. HRESULT hr = CONNECT_E_NOCONNECTION;
  330. CTip *ctip = NULL;
  331. TfGuidAtom guidatom;
  332. CHotKey *pHotKey = NULL;
  333. int nCnt;
  334. if (FAILED(MyRegisterGUID(rguid, &guidatom)))
  335. return E_INVALIDARG;
  336. if (!_rgHotKey[pprekey->uVKey])
  337. return hr;
  338. nCnt = _rgHotKey[pprekey->uVKey]->Count();
  339. Assert(nCnt); // this should not be 0.
  340. for (i = 0; i < nCnt; i++)
  341. {
  342. pHotKey = _rgHotKey[pprekey->uVKey]->Get(i);
  343. if (pHotKey->_guidatom == guidatom)
  344. {
  345. //
  346. // Remove this from VKey list.
  347. //
  348. _rgHotKey[pprekey->uVKey]->Remove(i, 1);
  349. if (!ctip && (pHotKey->GetTID() != g_gaSystem))
  350. _GetCTipfromGUIDATOM(pHotKey->GetTID(), &ctip);
  351. //
  352. // Remove this from CTip list.
  353. //
  354. if (ctip)
  355. {
  356. int nCntTid = ctip->_rgHotKey.Count();
  357. int k;
  358. for (k = 0; k < nCntTid; k++)
  359. {
  360. if (pHotKey == ctip->_rgHotKey.Get(k))
  361. {
  362. ctip->_rgHotKey.Remove(k, 1);
  363. break;
  364. }
  365. }
  366. }
  367. //
  368. // if there is no hotkey in this vkey, delete ptrary.
  369. //
  370. if (!_rgHotKey[pprekey->uVKey]->Count())
  371. {
  372. delete _rgHotKey[pprekey->uVKey];
  373. _rgHotKey[pprekey->uVKey] = NULL;
  374. }
  375. //
  376. // make a notification.
  377. //
  378. _OnPreservedKeyUpdate(pHotKey);
  379. //
  380. // delete it.
  381. //
  382. delete pHotKey;
  383. hr = S_OK;
  384. break;
  385. }
  386. }
  387. return hr;
  388. }
  389. //+---------------------------------------------------------------------------
  390. //
  391. // _ProcessHotKey
  392. //
  393. //----------------------------------------------------------------------------
  394. BOOL CThreadInputMgr::_ProcessHotKey(WPARAM wParam, LPARAM lParam, TimSysHotkey tsh, BOOL fTest, BOOL fSync)
  395. {
  396. UINT uVKey = (UINT)wParam & 0xff;
  397. CAsyncProcessHotKeyQueueItem *pAsyncProcessHotKeyQueueItem;
  398. CHotKey *pHotKey;
  399. BOOL bRet;
  400. HRESULT hr;
  401. if (!_rgHotKey[uVKey])
  402. return FALSE;
  403. if (!_FindHotKeyByTID(TF_INVALID_GUIDATOM,
  404. wParam,
  405. lParam,
  406. &pHotKey,
  407. tsh,
  408. g_uModifiers))
  409. return FALSE;
  410. if (!pHotKey)
  411. return FALSE;
  412. if (!pHotKey->IsNoDimNeeded() && !_pFocusDocInputMgr)
  413. return FALSE;
  414. if (!_pFocusDocInputMgr || (_pFocusDocInputMgr->_GetCurrentStack() < 0))
  415. {
  416. //
  417. // we may need to invoke system hotkey under Empty DIM.
  418. //
  419. BOOL fEaten = FALSE;
  420. if (fTest)
  421. fEaten = TRUE;
  422. else
  423. {
  424. GUID guid;
  425. if (SUCCEEDED(MyGetGUID(pHotKey->_guidatom, &guid)))
  426. _CallSimulatePreservedKey(pHotKey, NULL, guid, &fEaten);
  427. }
  428. return fEaten;
  429. }
  430. //
  431. // Issue:
  432. //
  433. // We don't know which IC in the focus DIM will handle the hotkey yet.
  434. // because the selection is changed by the application so we need to get ec
  435. // to update the current selection pos. We do call GetSelection
  436. // inside the root IC's lock. So it might be failed if hotkey's target
  437. // is TOP IC.
  438. //
  439. CInputContext *pic = _pFocusDocInputMgr->_GetIC(0);
  440. pAsyncProcessHotKeyQueueItem = new CAsyncProcessHotKeyQueueItem(wParam, lParam, tsh, fTest, fSync);
  441. if (!pAsyncProcessHotKeyQueueItem)
  442. return FALSE;
  443. hr = S_OK;
  444. bRet = TRUE;
  445. if ((pic->_QueueItem(pAsyncProcessHotKeyQueueItem->GetItem(), FALSE, &hr) != S_OK) || FAILED(hr))
  446. {
  447. Assert(0);
  448. bRet = FALSE;
  449. }
  450. pAsyncProcessHotKeyQueueItem->_Release();
  451. return bRet;
  452. }
  453. //+---------------------------------------------------------------------------
  454. //
  455. // _SyncProcessHotKey
  456. //
  457. //----------------------------------------------------------------------------
  458. BOOL CThreadInputMgr::_SyncProcessHotKey(WPARAM wParam, LPARAM lParam, TimSysHotkey tsh, BOOL fTest)
  459. {
  460. CHotKey *pHotKey;
  461. CInputContext *pic;
  462. UINT uVKey = (UINT)wParam & 0xff;
  463. BOOL fEaten = FALSE;
  464. if (!_pFocusDocInputMgr)
  465. return FALSE;
  466. if (!_rgHotKey[uVKey])
  467. return FALSE;
  468. if (_FindHotKeyAndIC(wParam, lParam, &pHotKey, &pic, tsh, g_uModifiers))
  469. {
  470. if (fTest)
  471. fEaten = TRUE;
  472. else
  473. {
  474. GUID guid;
  475. if (SUCCEEDED(MyGetGUID(pHotKey->_guidatom, &guid)))
  476. _CallSimulatePreservedKey(pHotKey, pic, guid, &fEaten);
  477. }
  478. }
  479. return fEaten;
  480. }
  481. //+---------------------------------------------------------------------------
  482. //
  483. // _FindHotKeyByTiD
  484. //
  485. //----------------------------------------------------------------------------
  486. BOOL CThreadInputMgr::_FindHotKeyByTID(TfClientId tid, WPARAM wParam, LPARAM lParam, CHotKey **ppHotKey, TimSysHotkey tsh, UINT uModCurrent)
  487. {
  488. UINT uVKey = (UINT)wParam & 0xff;
  489. int nCnt;
  490. int i;
  491. CHotKey *pHotKey;
  492. Assert(_rgHotKey[uVKey]);
  493. nCnt = _rgHotKey[uVKey]->Count();
  494. for (i = 0; i < nCnt; i++)
  495. {
  496. pHotKey = _rgHotKey[uVKey]->Get(i);
  497. Assert(pHotKey);
  498. Assert(pHotKey->_prekey.uVKey == uVKey);
  499. if ((tid != TF_INVALID_GUIDATOM) && !pHotKey->IsValidTID(tid))
  500. continue;
  501. switch (tsh)
  502. {
  503. case TSH_SYSHOTKEY:
  504. if (!pHotKey->IsSysHotkey())
  505. continue;
  506. break;
  507. case TSH_NONSYSHOTKEY:
  508. if (pHotKey->IsSysHotkey())
  509. continue;
  510. break;
  511. case TSH_DONTCARE:
  512. break;
  513. default:
  514. Assert(0);
  515. break;
  516. }
  517. if ((pHotKey->_prekey.uModifiers & TF_MOD_ON_KEYUP) !=
  518. ((lParam & 0x80000000) ? (UINT)TF_MOD_ON_KEYUP : 0))
  519. continue;
  520. if (ModifiersCheck(uModCurrent, pHotKey->_prekey.uModifiers))
  521. {
  522. if (ppHotKey)
  523. *ppHotKey = pHotKey;
  524. return TRUE;
  525. }
  526. }
  527. return FALSE;
  528. }
  529. //+---------------------------------------------------------------------------
  530. //
  531. // _FindHotkeyIC
  532. //
  533. //----------------------------------------------------------------------------
  534. BOOL CThreadInputMgr::_FindHotKeyAndIC(WPARAM wParam, LPARAM lParam, CHotKey **ppHotKey, CInputContext **ppic, TimSysHotkey tsh, UINT uModCurrent)
  535. {
  536. int iStack;
  537. Assert(_pFocusDocInputMgr);
  538. iStack = _pFocusDocInputMgr->_GetCurrentStack();
  539. if (iStack < 0)
  540. return FALSE;
  541. while (iStack >= 0)
  542. {
  543. CInputContext *pic = _pFocusDocInputMgr->_GetIC(iStack);
  544. if (_FindHotKeyInIC(wParam, lParam, ppHotKey, pic, tsh, uModCurrent))
  545. {
  546. if (ppic)
  547. *ppic = pic;
  548. return TRUE;
  549. }
  550. iStack--;
  551. }
  552. return FALSE;
  553. }
  554. //+---------------------------------------------------------------------------
  555. //
  556. // _FindHotkey
  557. //
  558. //----------------------------------------------------------------------------
  559. BOOL CThreadInputMgr::_FindHotKeyInIC(WPARAM wParam, LPARAM lParam, CHotKey **ppHotKey, CInputContext *pic, TimSysHotkey tsh, UINT uModCurrent)
  560. {
  561. TfClientId tid;
  562. pic->_UpdateKeyEventFilter();
  563. //
  564. // try left side of the selection.
  565. //
  566. if ((tid = pic->_gaKeyEventFilterTIP[LEFT_FILTERTIP]) != TF_INVALID_GUIDATOM)
  567. {
  568. if (_FindHotKeyByTID(tid, wParam, lParam, ppHotKey, tsh, uModCurrent))
  569. {
  570. return TRUE;
  571. }
  572. }
  573. //
  574. // try right side of the selection.
  575. //
  576. if ((tid = pic->_gaKeyEventFilterTIP[RIGHT_FILTERTIP]) != TF_INVALID_GUIDATOM)
  577. {
  578. if (_FindHotKeyByTID(tid, wParam, lParam, ppHotKey, tsh, uModCurrent))
  579. {
  580. return TRUE;
  581. }
  582. }
  583. //
  584. // try foreground tip.
  585. //
  586. if ((_tidForeground != TF_INVALID_GUIDATOM) || (tsh == TSH_SYSHOTKEY))
  587. {
  588. if (_FindHotKeyByTID(_tidForeground, wParam, lParam, ppHotKey, tsh, uModCurrent))
  589. {
  590. return TRUE;
  591. }
  592. }
  593. //
  594. // we may have a system hotkey that matched with the wParm and lParam.
  595. //
  596. if (_FindHotKeyByTID(TF_INVALID_GUIDATOM, wParam, lParam, ppHotKey, TSH_SYSHOTKEY, uModCurrent))
  597. {
  598. return TRUE;
  599. }
  600. return FALSE;
  601. }
  602. //+---------------------------------------------------------------------------
  603. //
  604. // CallKeyEventSink
  605. //
  606. //----------------------------------------------------------------------------
  607. HRESULT CThreadInputMgr::_CallSimulatePreservedKey(CHotKey *pHotKey, CInputContext *pic, REFGUID rguid, BOOL *pfEaten)
  608. {
  609. ITfKeyEventSink *pSink;
  610. CTip *ctip;
  611. //
  612. // This is tip's Preserved key.
  613. //
  614. if (pHotKey->GetTID() != g_gaSystem)
  615. {
  616. if (!pHotKey->IsNoDimNeeded() && !pic)
  617. return S_FALSE;
  618. if (!_GetCTipfromGUIDATOM(pHotKey->GetTID(), &ctip))
  619. return E_INVALIDARG;
  620. if (!(pSink = ctip->_pKeyEventSink))
  621. return S_FALSE;
  622. return pSink->OnPreservedKey(pic, rguid, pfEaten);
  623. }
  624. UINT uId = -1;
  625. int i;
  626. HRESULT hr = S_OK;
  627. for (i = 0; i < DEFHOTKEYNUM; i++)
  628. {
  629. if (g_DefHotKeys[i].guidatom == pHotKey->_guidatom)
  630. {
  631. uId = g_DefHotKeys[i].uId;
  632. break;
  633. }
  634. }
  635. switch (g_DefHotKeys[i].uId)
  636. {
  637. case DHID_CORRECTION:
  638. //
  639. // simulate Reconversion Button.
  640. //
  641. hr = AsyncReconversion();
  642. break;
  643. case DHID_VOICE:
  644. hr = MyToggleCompartmentDWORD(g_gaSystem,
  645. GetGlobalComp(),
  646. GUID_COMPARTMENT_SPEECH_OPENCLOSE,
  647. NULL);
  648. if (hr == S_OK)
  649. *pfEaten = TRUE;
  650. break;
  651. case DHID_HANDWRITE:
  652. hr = MyToggleCompartmentDWORD(g_gaSystem,
  653. this,
  654. GUID_COMPARTMENT_HANDWRITING_OPENCLOSE,
  655. NULL);
  656. if (hr == S_OK)
  657. *pfEaten = TRUE;
  658. break;
  659. case DHID_TOGGLE:
  660. DWORD dwMicOn;
  661. if (FAILED(MyGetCompartmentDWORD(GetGlobalComp(),
  662. GUID_COMPARTMENT_SPEECH_OPENCLOSE,
  663. &dwMicOn)))
  664. {
  665. hr = E_FAIL;
  666. break;
  667. }
  668. if ( dwMicOn )
  669. {
  670. DWORD dwSpeechStatus;
  671. if (FAILED(MyGetCompartmentDWORD(GetGlobalComp(),
  672. GUID_COMPARTMENT_SPEECH_GLOBALSTATE,
  673. &dwSpeechStatus)))
  674. {
  675. hr = E_FAIL;
  676. break;
  677. }
  678. if ((dwSpeechStatus & (TF_DICTATION_ON | TF_COMMANDING_ON)) == 0 )
  679. {
  680. // Both dictation and voice command are OFF
  681. // After toggled, we set dictation ON.
  682. dwSpeechStatus |= TF_DICTATION_ON;
  683. }
  684. else
  685. {
  686. dwSpeechStatus ^= TF_DICTATION_ON;
  687. dwSpeechStatus ^= TF_COMMANDING_ON;
  688. }
  689. hr = MySetCompartmentDWORD(g_gaSystem,
  690. GetGlobalComp(),
  691. GUID_COMPARTMENT_SPEECH_GLOBALSTATE,
  692. dwSpeechStatus);
  693. }
  694. if (hr == S_OK)
  695. *pfEaten = TRUE;
  696. break;
  697. default:
  698. Assert(0);
  699. hr = E_FAIL;
  700. break;
  701. }
  702. return hr;
  703. }
  704. //+---------------------------------------------------------------------------
  705. //
  706. // GetPreservedKey
  707. //
  708. //----------------------------------------------------------------------------
  709. STDAPI CThreadInputMgr::GetPreservedKey(ITfContext *pic, const TF_PRESERVEDKEY *pprekey, GUID *pguid)
  710. {
  711. CHotKey *pHotKey;
  712. CInputContext *pcic;
  713. HRESULT hr = S_FALSE; // we return S_FALE, if there is no proper keys.
  714. if (!pguid)
  715. return E_INVALIDARG;
  716. *pguid = GUID_NULL;
  717. if (!pprekey)
  718. return E_INVALIDARG;
  719. if (pprekey->uVKey >= ARRAYSIZE(_rgHotKey))
  720. return E_INVALIDARG;
  721. if (pprekey->uModifiers & ~TF_MOD_ALL)
  722. return E_INVALIDARG;
  723. if (!pic)
  724. return E_INVALIDARG;
  725. if (!(pcic = GetCInputContext(pic)))
  726. return E_INVALIDARG;
  727. if (!_rgHotKey[pprekey->uVKey])
  728. goto Exit;
  729. //
  730. // we always get KeyUp preserve key first.
  731. //
  732. if (_FindHotKeyInIC(pprekey->uVKey, 0x80000000, &pHotKey, pcic, TSH_DONTCARE, pprekey->uModifiers))
  733. {
  734. hr = MyGetGUID(pHotKey->_guidatom, pguid);
  735. }
  736. else if (_FindHotKeyInIC(pprekey->uVKey, 0x0, &pHotKey, pcic, TSH_DONTCARE, pprekey->uModifiers))
  737. {
  738. hr = MyGetGUID(pHotKey->_guidatom, pguid);
  739. }
  740. Exit:
  741. SafeRelease(pcic);
  742. return hr;
  743. }
  744. //+---------------------------------------------------------------------------
  745. //
  746. // isPreservedKeyInfo
  747. //
  748. //----------------------------------------------------------------------------
  749. STDAPI CThreadInputMgr::IsPreservedKey(REFGUID rguid, const TF_PRESERVEDKEY *pprekey, BOOL *pfRegistered)
  750. {
  751. TfGuidAtom guidatom;
  752. int i;
  753. int nCnt;
  754. if (!pfRegistered)
  755. return E_INVALIDARG;
  756. *pfRegistered = FALSE;
  757. if (!pprekey)
  758. return E_INVALIDARG;
  759. if (pprekey->uVKey >= ARRAYSIZE(_rgHotKey))
  760. return E_INVALIDARG;
  761. if (pprekey->uModifiers & ~TF_MOD_ALL)
  762. return E_INVALIDARG;
  763. if (FAILED(MyRegisterGUID(rguid, &guidatom)))
  764. return E_FAIL;
  765. if (!_rgHotKey[pprekey->uVKey])
  766. return S_FALSE;
  767. nCnt = _rgHotKey[pprekey->uVKey]->Count();
  768. for (i = 0; i < nCnt; i++)
  769. {
  770. CHotKey *pHotKey = _rgHotKey[pprekey->uVKey]->Get(i);
  771. if ((guidatom == pHotKey->_guidatom) &&
  772. (pprekey->uModifiers == pHotKey->_prekey.uModifiers))
  773. {
  774. *pfRegistered = TRUE;
  775. return S_OK;
  776. }
  777. }
  778. return S_FALSE;
  779. }
  780. //+---------------------------------------------------------------------------
  781. //
  782. // GetPreservedKeyInfoInternal
  783. //
  784. //----------------------------------------------------------------------------
  785. BOOL CThreadInputMgr::_GetFirstPreservedKey(REFGUID rguid, CHotKey **ppHotKey)
  786. {
  787. UINT uVKey;
  788. TfGuidAtom guidatom;
  789. if (FAILED(MyRegisterGUID(rguid, &guidatom)))
  790. return FALSE;
  791. for (uVKey = 0; uVKey < 256; uVKey++)
  792. {
  793. int nCnt;
  794. int i;
  795. if (!_rgHotKey[uVKey])
  796. continue;
  797. nCnt = _rgHotKey[uVKey]->Count();
  798. for (i = 0; i < nCnt; i++)
  799. {
  800. CHotKey *pHotKey = _rgHotKey[uVKey]->Get(i);
  801. if (guidatom == pHotKey->_guidatom)
  802. {
  803. *ppHotKey = pHotKey;
  804. return TRUE;
  805. }
  806. }
  807. }
  808. return FALSE;
  809. }
  810. //+---------------------------------------------------------------------------
  811. //
  812. // SimulatePreservedKey
  813. //
  814. //----------------------------------------------------------------------------
  815. STDAPI CThreadInputMgr::SimulatePreservedKey(ITfContext *pic, REFGUID rguid, BOOL *pfEaten)
  816. {
  817. CInputContext *pcic;
  818. CHotKey *pHotKey;
  819. HRESULT hr;
  820. if (!pfEaten)
  821. return E_INVALIDARG;
  822. if (!(pcic = GetCInputContext(pic)))
  823. return E_INVALIDARG;
  824. hr = S_OK;
  825. *pfEaten = FALSE;
  826. if (_GetFirstPreservedKey(rguid, &pHotKey))
  827. {
  828. //
  829. // we always get KeyUp preserve key first.
  830. //
  831. if (_FindHotKeyInIC(pHotKey->_prekey.uVKey,
  832. 0x80000000,
  833. NULL,
  834. pcic,
  835. TSH_DONTCARE,
  836. pHotKey->_prekey.uModifiers))
  837. {
  838. hr = _CallSimulatePreservedKey(pHotKey, pcic, rguid, pfEaten);
  839. }
  840. else if (_FindHotKeyInIC(pHotKey->_prekey.uVKey,
  841. 0x0,
  842. NULL,
  843. pcic,
  844. TSH_DONTCARE,
  845. pHotKey->_prekey.uModifiers))
  846. {
  847. hr = _CallSimulatePreservedKey(pHotKey, pcic, rguid, pfEaten);
  848. }
  849. }
  850. SafeRelease(pcic);
  851. return hr;
  852. }
  853. //+---------------------------------------------------------------------------
  854. //
  855. // _OnPreservedKeyUpdate
  856. //
  857. //----------------------------------------------------------------------------
  858. HRESULT CThreadInputMgr::_OnPreservedKeyUpdate(CHotKey *pHotKey)
  859. {
  860. CStructArray<GENERICSINK> *pSinks = _GetPreservedKeyNotifySinks();
  861. int i;
  862. //
  863. // we don't make a notification for system default hotkeys.
  864. //
  865. if (pHotKey->GetTID() == g_gaSystem)
  866. return S_OK;
  867. for (i = 0; i < pSinks->Count(); i++)
  868. {
  869. ((ITfPreservedKeyNotifySink *)pSinks->GetPtr(i)->pSink)->OnUpdated(&pHotKey->_prekey);
  870. }
  871. return S_OK;
  872. }
  873. //+---------------------------------------------------------------------------
  874. //
  875. // SetPreservedKeyDescription
  876. //
  877. //----------------------------------------------------------------------------
  878. STDAPI CThreadInputMgr::SetPreservedKeyDescription(REFGUID rguid, const WCHAR *pchDesc, ULONG cchDesc)
  879. {
  880. CHotKey *pHotKey;
  881. if (!_GetFirstPreservedKey(rguid, &pHotKey))
  882. return E_INVALIDARG;
  883. if (!pHotKey->SetDesc(pchDesc, cchDesc))
  884. return E_FAIL;
  885. _OnPreservedKeyUpdate(pHotKey);
  886. return S_OK;
  887. }
  888. //+---------------------------------------------------------------------------
  889. //
  890. // GetPreservedKeyDescription
  891. //
  892. //----------------------------------------------------------------------------
  893. STDAPI CThreadInputMgr::GetPreservedKeyDescription(REFGUID rguid, BSTR *pbstrDesc)
  894. {
  895. CHotKey *pHotKey;
  896. if (!_GetFirstPreservedKey(rguid, &pHotKey))
  897. return E_INVALIDARG;
  898. if (!pHotKey->GetDesc(pbstrDesc))
  899. return E_FAIL;
  900. return S_OK;
  901. }
  902. //////////////////////////////////////////////////////////////////////////////
  903. //
  904. // Static Functions
  905. //
  906. //////////////////////////////////////////////////////////////////////////////
  907. #define IsAlt(u) ((u & TF_MOD_ALT) ? 1 : 0)
  908. #define IsShift(u) ((u & TF_MOD_SHIFT) ? 1 : 0)
  909. #define IsControl(u) ((u & TF_MOD_CONTROL) ? 1 : 0)
  910. #define IsWin(u) ((u & TF_MOD_WIN) ? 1 : 0)
  911. #define CheckMod(m0, m1, mod) \
  912. if (m1 & TF_MOD_ ## mod ##) \
  913. { \
  914. if (!(m0 & TF_MOD_ ## mod ##)) \
  915. return FALSE; \
  916. } \
  917. else \
  918. { \
  919. if ((m1 ^ m0) & TF_MOD_RL ## mod ##) \
  920. return FALSE; \
  921. }
  922. //+---------------------------------------------------------------------------
  923. //
  924. // ModifiersCheck
  925. //
  926. //----------------------------------------------------------------------------
  927. BOOL ModifiersCheck(UINT uModCurrent, UINT uMod)
  928. {
  929. uMod &= ~TF_MOD_ON_KEYUP;
  930. if (uMod & TF_MOD_IGNORE_ALL_MODIFIER)
  931. return TRUE;
  932. if (uModCurrent == uMod)
  933. return TRUE;
  934. if (uModCurrent && !uMod)
  935. return FALSE;
  936. CheckMod(uModCurrent, uMod, ALT);
  937. CheckMod(uModCurrent, uMod, SHIFT);
  938. CheckMod(uModCurrent, uMod, CONTROL);
  939. CheckMod(uModCurrent, uMod, WIN);
  940. return TRUE;
  941. }
  942. //+---------------------------------------------------------------------------
  943. //
  944. // InitLangChangeHotKey
  945. //
  946. //----------------------------------------------------------------------------
  947. BOOL InitLangChangeHotKey()
  948. {
  949. CMyRegKey key;
  950. TCHAR sz[2] = TEXT("3");
  951. TCHAR sz2[2] = TEXT("3");
  952. if (key.Open(HKEY_CURRENT_USER, c_szKbdToggleKey, KEY_READ) == S_OK)
  953. {
  954. if (key.QueryValueCch(sz, TEXT("Language Hotkey"), ARRAYSIZE(sz)) != S_OK)
  955. {
  956. if (key.QueryValueCch(sz, IsOnNT() ? TEXT("Hotkey") : NULL, ARRAYSIZE(sz)) != S_OK)
  957. {
  958. sz[0] = TEXT('1');
  959. sz[1] = TEXT('\0');
  960. }
  961. if (PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) == LANG_CHINESE)
  962. {
  963. sz[0] = TEXT('1');
  964. sz[1] = TEXT('\0');
  965. }
  966. }
  967. if (key.QueryValueCch(sz2, TEXT("Layout Hotkey"), ARRAYSIZE(sz)) != S_OK)
  968. {
  969. if (lstrcmp(sz, TEXT("2")) == 0)
  970. {
  971. sz2[0] = TEXT('1');
  972. sz2[1] = TEXT('\0');
  973. }
  974. else
  975. {
  976. sz2[0] = TEXT('2');
  977. sz2[1] = TEXT('\0');
  978. }
  979. if (GetSystemMetrics(SM_MIDEASTENABLED))
  980. {
  981. sz2[0] = TEXT('3');
  982. sz2[1] = TEXT('\0');
  983. }
  984. }
  985. }
  986. //
  987. // if lang and layout hotkey is the same key, let's disable the layout hotkey
  988. //
  989. if (lstrcmp(sz, sz2) == 0)
  990. {
  991. if (lstrcmp(sz, TEXT("1")) == 0)
  992. {
  993. sz2[0] = TEXT('2');
  994. sz2[1] = TEXT('\0');
  995. }
  996. else if (lstrcmp(sz, TEXT("2")) == 0)
  997. {
  998. sz2[0] = TEXT('1');
  999. sz2[1] = TEXT('\0');
  1000. }
  1001. else
  1002. {
  1003. sz2[0] = TEXT('3');
  1004. sz2[1] = TEXT('\0');
  1005. }
  1006. }
  1007. CicEnterCriticalSection(g_csInDllMain);
  1008. switch (sz[0])
  1009. {
  1010. case ( TEXT('1') ) :
  1011. default:
  1012. {
  1013. g_uLangHotKeyModifiers = TF_MOD_ALT | TF_MOD_SHIFT;
  1014. g_uLangHotKeyVKey[0] = VK_SHIFT;
  1015. g_uLangHotKeyVKey[1] = VK_MENU;
  1016. break;
  1017. }
  1018. case ( TEXT('2') ) :
  1019. {
  1020. g_uLangHotKeyModifiers = TF_MOD_CONTROL | TF_MOD_SHIFT;
  1021. g_uLangHotKeyVKey[0] = VK_SHIFT;
  1022. g_uLangHotKeyVKey[1] = VK_CONTROL;
  1023. break;
  1024. }
  1025. case ( TEXT('3') ) :
  1026. {
  1027. g_uLangHotKeyModifiers = 0;
  1028. g_uLangHotKeyVKey[0] = 0;
  1029. g_uLangHotKeyVKey[1] = 0;
  1030. break;
  1031. }
  1032. case ( TEXT('4') ) :
  1033. {
  1034. g_uLangHotKeyModifiers = 0;
  1035. g_uLangHotKeyVKey[0] = CHAR_GRAVE;
  1036. g_uLangHotKeyVKey[1] = 0;
  1037. break;
  1038. }
  1039. }
  1040. //
  1041. // Set the layout switch hotkey.
  1042. //
  1043. switch (sz2[0])
  1044. {
  1045. case ( TEXT('1') ) :
  1046. default:
  1047. {
  1048. g_uKeyTipHotKeyModifiers = TF_MOD_LALT | TF_MOD_SHIFT;
  1049. g_uKeyTipHotKeyVKey[0] = VK_SHIFT;
  1050. g_uKeyTipHotKeyVKey[1] = VK_MENU;
  1051. break;
  1052. }
  1053. case ( TEXT('2') ) :
  1054. {
  1055. g_uKeyTipHotKeyModifiers = TF_MOD_CONTROL | TF_MOD_SHIFT;
  1056. g_uKeyTipHotKeyVKey[0] = VK_SHIFT;
  1057. g_uKeyTipHotKeyVKey[1] = VK_CONTROL;
  1058. break;
  1059. }
  1060. case ( TEXT('3') ) :
  1061. {
  1062. g_uKeyTipHotKeyModifiers = 0;
  1063. g_uKeyTipHotKeyVKey[0] = 0;
  1064. g_uKeyTipHotKeyVKey[1] = 0;
  1065. break;
  1066. }
  1067. case ( TEXT('4') ) :
  1068. {
  1069. g_uKeyTipHotKeyModifiers = 0;
  1070. g_uKeyTipHotKeyVKey[0] = VK_GRAVE;
  1071. g_uKeyTipHotKeyVKey[1] = 0;
  1072. break;
  1073. }
  1074. }
  1075. CicLeaveCriticalSection(g_csInDllMain);
  1076. return TRUE;
  1077. }
  1078. //+---------------------------------------------------------------------------
  1079. //
  1080. // UpdateModifiers
  1081. //
  1082. //----------------------------------------------------------------------------
  1083. BOOL UpdateModifiers(WPARAM wParam, LPARAM lParam)
  1084. {
  1085. SHORT sksMenu = GetKeyState(VK_MENU);
  1086. SHORT sksCtrl = GetKeyState(VK_CONTROL);
  1087. SHORT sksShft = GetKeyState(VK_SHIFT);
  1088. SHORT sksLWin = GetKeyState(VK_LWIN);
  1089. SHORT sksRWin = GetKeyState(VK_RWIN);
  1090. CicEnterCriticalSection(g_cs);
  1091. switch (wParam & 0xff)
  1092. {
  1093. case VK_MENU:
  1094. if (sksMenu & 0x8000)
  1095. {
  1096. if (lParam & 0x01000000)
  1097. g_uModifiers |= (TF_MOD_RALT | TF_MOD_ALT);
  1098. else
  1099. g_uModifiers |= (TF_MOD_LALT | TF_MOD_ALT);
  1100. }
  1101. break;
  1102. case VK_CONTROL:
  1103. if (sksCtrl & 0x8000)
  1104. {
  1105. if (lParam & 0x01000000)
  1106. g_uModifiers |= (TF_MOD_RCONTROL | TF_MOD_CONTROL);
  1107. else
  1108. g_uModifiers |= (TF_MOD_LCONTROL | TF_MOD_CONTROL);
  1109. }
  1110. break;
  1111. case VK_SHIFT:
  1112. if (sksShft & 0x8000)
  1113. {
  1114. if (((lParam >> 16) & 0x00ff) == 0x36)
  1115. g_uModifiers |= (TF_MOD_RSHIFT | TF_MOD_SHIFT);
  1116. else
  1117. g_uModifiers |= (TF_MOD_LSHIFT | TF_MOD_SHIFT);
  1118. }
  1119. break;
  1120. case VK_LWIN:
  1121. if (sksLWin & 0x8000)
  1122. g_uModifiers |= (TF_MOD_LWIN | TF_MOD_WIN);
  1123. break;
  1124. case VK_RWIN:
  1125. if (sksRWin & 0x8000)
  1126. g_uModifiers |= (TF_MOD_RWIN | TF_MOD_WIN);
  1127. break;
  1128. }
  1129. if (!(sksMenu & 0x8000))
  1130. g_uModifiers &= ~TF_MOD_ALLALT;
  1131. if (!(sksCtrl & 0x8000))
  1132. g_uModifiers &= ~TF_MOD_ALLCONTROL;
  1133. if (!(sksShft & 0x8000))
  1134. g_uModifiers &= ~TF_MOD_ALLSHIFT;
  1135. if (!(sksRWin & 0x8000))
  1136. g_uModifiers &= ~TF_MOD_RWIN;
  1137. if (!(sksLWin & 0x8000))
  1138. g_uModifiers &= ~TF_MOD_LWIN;
  1139. if (!(sksRWin & 0x8000) && !(sksLWin & 0x8000))
  1140. g_uModifiers &= ~TF_MOD_WIN;
  1141. CicLeaveCriticalSection(g_cs);
  1142. return TRUE;
  1143. }
  1144. //+---------------------------------------------------------------------------
  1145. //
  1146. // IsInLangChangeHotkeyStatus
  1147. //
  1148. // This function check the current keyboard status is in LangChange hotkey.
  1149. // This will be a trigger to eat WM_INPUTLANGUAGECHANGEREQUEST that was
  1150. // genereated by System. This is a fallback code because sometimes we
  1151. // could not eat the message in CheckLangChangeHotKey() (inside keyboard hook).
  1152. //
  1153. //----------------------------------------------------------------------------
  1154. BOOL IsInLangChangeHotkeyStatus()
  1155. {
  1156. //
  1157. // we don't need this hack on NT.
  1158. //
  1159. if (IsOnNT())
  1160. return FALSE;
  1161. //
  1162. // this Modifiers patch works for only Key-Down time hotkey.
  1163. // this hack does not work for Key-Up time hotkey.
  1164. //
  1165. #if 0
  1166. //
  1167. // patch Shift status for g_uModifiers.
  1168. // we might not be able to catch up the current keystatus because
  1169. // sytstem could eat Shift key and no keyboard hook was called.
  1170. //
  1171. if (GetKeyState(VK_SHIFT) & 0x8000)
  1172. g_uModifiers |= TF_MOD_SHIFT;
  1173. else
  1174. g_uModifiers &= ~TF_MOD_ALLSHIFT;
  1175. #endif
  1176. if (g_uLangHotKeyModifiers &&
  1177. ModifiersCheck(g_uModifiers, g_uLangHotKeyModifiers))
  1178. return TRUE;
  1179. if (g_uKeyTipHotKeyModifiers &&
  1180. ModifiersCheck(g_uModifiers, g_uKeyTipHotKeyModifiers))
  1181. return TRUE;
  1182. return FALSE;
  1183. }
  1184. //+---------------------------------------------------------------------------
  1185. //
  1186. // CheckLangChangeHotKey
  1187. //
  1188. //----------------------------------------------------------------------------
  1189. BOOL CheckLangChangeHotKey(SYSTHREAD *psfn, WPARAM wParam, LPARAM lParam)
  1190. {
  1191. BOOL fLangHotKeys;
  1192. BOOL fKeyTipHotKeys;
  1193. if (psfn == NULL)
  1194. return FALSE;
  1195. //
  1196. // we don't care about reperted key down.
  1197. //
  1198. if ((lParam & 0xffff) > 1)
  1199. return FALSE;
  1200. //
  1201. // If we are not interested in the VKey (wParam),
  1202. // clear bToggleReady up and don't eat it.
  1203. //
  1204. if ((g_uLangHotKeyVKey[0] != wParam) &&
  1205. (g_uLangHotKeyVKey[1] != wParam))
  1206. {
  1207. if (psfn->bLangToggleReady)
  1208. {
  1209. psfn->bLangToggleReady = FALSE;
  1210. }
  1211. fLangHotKeys = FALSE;
  1212. }
  1213. else
  1214. {
  1215. fLangHotKeys = TRUE;
  1216. }
  1217. if ((g_uKeyTipHotKeyVKey[0] != wParam) &&
  1218. (g_uKeyTipHotKeyVKey[1] != wParam))
  1219. {
  1220. if (psfn->bKeyTipToggleReady)
  1221. {
  1222. psfn->bKeyTipToggleReady = FALSE;
  1223. }
  1224. fKeyTipHotKeys = FALSE;
  1225. }
  1226. else
  1227. {
  1228. fKeyTipHotKeys = TRUE;
  1229. }
  1230. if (fLangHotKeys && !psfn->bLangToggleReady)
  1231. {
  1232. if (!(lParam & 0x80000000))
  1233. {
  1234. if (g_uLangHotKeyModifiers &&
  1235. ModifiersCheck(g_uModifiers, g_uLangHotKeyModifiers))
  1236. {
  1237. //
  1238. // we will change assembly at next key up.
  1239. //
  1240. psfn->bLangToggleReady = TRUE;
  1241. //
  1242. // we always eat Language change hotkey to stop system
  1243. // to change hKL.
  1244. //
  1245. return FALSE;
  1246. }
  1247. }
  1248. }
  1249. if (fKeyTipHotKeys && !psfn->bKeyTipToggleReady)
  1250. {
  1251. if (!(lParam & 0x80000000))
  1252. {
  1253. if (g_uKeyTipHotKeyModifiers &&
  1254. ModifiersCheck(g_uModifiers, g_uKeyTipHotKeyModifiers))
  1255. {
  1256. if (GetKeyboardItemNum() >= 2)
  1257. {
  1258. //
  1259. // we will change assembly at next key up.
  1260. //
  1261. psfn->bKeyTipToggleReady = TRUE;
  1262. //
  1263. // we don't want to eat KeyTip change hotkey if there is
  1264. // only one keyboard item in this language.
  1265. // Ctrl+Shift is used by apps.
  1266. //
  1267. return FALSE;
  1268. }
  1269. }
  1270. else if (wParam == VK_GRAVE && g_uKeyTipHotKeyVKey[0] == wParam)
  1271. {
  1272. //
  1273. // we will change assembly at next key up.
  1274. //
  1275. psfn->bKeyTipToggleReady = TRUE;
  1276. return TRUE;
  1277. }
  1278. }
  1279. }
  1280. if (!(lParam & 0x80000000))
  1281. {
  1282. //
  1283. // want to eat Grave Accent if it is a layout switching hotkey for ME.
  1284. //
  1285. if (g_uKeyTipHotKeyVKey[0] == wParam && wParam == VK_GRAVE)
  1286. return TRUE;
  1287. else
  1288. return FALSE;
  1289. }
  1290. BOOL bLangToggleReady = psfn->bLangToggleReady;
  1291. BOOL bKeyTipToggleReady = psfn->bKeyTipToggleReady;
  1292. psfn->bLangToggleReady = FALSE;
  1293. psfn->bKeyTipToggleReady = FALSE;
  1294. if (bLangToggleReady)
  1295. {
  1296. //
  1297. // remove all WM_INPUTLANGCHANGEREQUEST message.
  1298. //
  1299. MSG msg;
  1300. while(PeekMessage(&msg, NULL,
  1301. WM_INPUTLANGCHANGEREQUEST,
  1302. WM_INPUTLANGCHANGEREQUEST,
  1303. PM_REMOVE));
  1304. if (g_uLangHotKeyVKey[0] == VK_SHIFT)
  1305. {
  1306. BOOL bRightShift = FALSE;
  1307. if ((((wParam & 0xff) == VK_SHIFT) &&
  1308. (((lParam >> 16) & 0x00ff) == 0x36)) ||
  1309. (g_uModifiers & TF_MOD_RSHIFT))
  1310. bRightShift = TRUE;
  1311. PostThreadMessage(GetCurrentThreadId(),
  1312. g_msgPrivate,
  1313. TFPRIV_LANGCHANGE,
  1314. bRightShift);
  1315. return TRUE;
  1316. }
  1317. else if (g_uLangHotKeyVKey[0] == CHAR_GRAVE)
  1318. {
  1319. //
  1320. // Issue: we need to do something for Thai.
  1321. //
  1322. return TRUE;
  1323. }
  1324. }
  1325. else if (bKeyTipToggleReady)
  1326. {
  1327. //
  1328. // remove all WM_INPUTLANGCHANGEREQUEST message.
  1329. //
  1330. MSG msg;
  1331. while(PeekMessage(&msg, NULL,
  1332. WM_INPUTLANGCHANGEREQUEST,
  1333. WM_INPUTLANGCHANGEREQUEST,
  1334. PM_REMOVE));
  1335. if (g_uKeyTipHotKeyVKey[0] == VK_SHIFT)
  1336. {
  1337. BOOL bRightShift = FALSE;
  1338. if ((((wParam & 0xff) == VK_SHIFT) &&
  1339. (((lParam >> 16) & 0x00ff) == 0x36)) ||
  1340. (g_uModifiers & TF_MOD_RSHIFT))
  1341. bRightShift = TRUE;
  1342. PostThreadMessage(GetCurrentThreadId(),
  1343. g_msgPrivate,
  1344. TFPRIV_KEYTIPCHANGE,
  1345. bRightShift);
  1346. return TRUE;
  1347. }
  1348. else if (g_uKeyTipHotKeyVKey[0] == VK_GRAVE)
  1349. {
  1350. // checking for Middle East(Arabic or Hebrew) layout hotkey to
  1351. // support the third hotkey value(Grave Accent) instead of Ctrl+Shift
  1352. // or Alt+Shift.
  1353. PostThreadMessage(GetCurrentThreadId(),
  1354. g_msgPrivate,
  1355. TFPRIV_KEYTIPCHANGE,
  1356. FALSE);
  1357. return TRUE;
  1358. }
  1359. }
  1360. return FALSE;
  1361. }
  1362. //+---------------------------------------------------------------------------
  1363. //
  1364. // Imm32ModtoCicMod
  1365. //
  1366. //----------------------------------------------------------------------------
  1367. UINT Imm32ModtoCicMod(UINT uImm32Mod)
  1368. {
  1369. UINT uMod = 0;
  1370. if ((uImm32Mod & (MOD_LEFT | MOD_RIGHT)) == (MOD_LEFT | MOD_RIGHT))
  1371. uImm32Mod &= ~(MOD_LEFT | MOD_RIGHT);
  1372. if (uImm32Mod & MOD_LEFT)
  1373. {
  1374. if (uImm32Mod & MOD_ALT) uMod |= TF_MOD_LALT;
  1375. if (uImm32Mod & MOD_CONTROL) uMod |= TF_MOD_LCONTROL;
  1376. if (uImm32Mod & MOD_SHIFT) uMod |= TF_MOD_LSHIFT;
  1377. }
  1378. else if (uImm32Mod & MOD_RIGHT)
  1379. {
  1380. if (uImm32Mod & MOD_ALT) uMod |= TF_MOD_RALT;
  1381. if (uImm32Mod & MOD_CONTROL) uMod |= TF_MOD_RCONTROL;
  1382. if (uImm32Mod & MOD_SHIFT) uMod |= TF_MOD_RSHIFT;
  1383. }
  1384. else
  1385. {
  1386. if (uImm32Mod & MOD_ALT) uMod |= TF_MOD_ALT;
  1387. if (uImm32Mod & MOD_CONTROL) uMod |= TF_MOD_CONTROL;
  1388. if (uImm32Mod & MOD_SHIFT) uMod |= TF_MOD_SHIFT;
  1389. }
  1390. if (uImm32Mod & MOD_ON_KEYUP) uMod |= TF_MOD_ON_KEYUP;
  1391. if (uImm32Mod & MOD_IGNORE_ALL_MODIFIER) uMod |= TF_MOD_IGNORE_ALL_MODIFIER;
  1392. return uMod;
  1393. }
  1394. //+---------------------------------------------------------------------------
  1395. //
  1396. // LoadImmHotkeyFromReg
  1397. //
  1398. //----------------------------------------------------------------------------
  1399. BOOL LoadImmHotkeyFromReg(IMM32HOTKEY *pHotKey)
  1400. {
  1401. CMyRegKey key;
  1402. UINT uMod;
  1403. DWORD dw;
  1404. TCHAR szKey[256];
  1405. pHotKey->fInit = TRUE;
  1406. StringCchPrintf(szKey, ARRAYSIZE(szKey),"%s\\%08x", c_szHotKey, pHotKey->dwId);
  1407. if (key.Open(HKEY_CURRENT_USER, szKey, KEY_READ) != S_OK)
  1408. goto Exit;
  1409. pHotKey->uVKey = (UINT)-2;
  1410. dw = sizeof(DWORD);
  1411. key.QueryBinaryValue(&uMod, dw, c_szModifiers);
  1412. dw = sizeof(DWORD);
  1413. key.QueryBinaryValue(&pHotKey->uVKey, dw, c_szVKey);
  1414. pHotKey->uModifiers = Imm32ModtoCicMod(uMod);
  1415. Exit:
  1416. return TRUE;
  1417. }
  1418. //+---------------------------------------------------------------------------
  1419. //
  1420. // GetImmHotKeyTable()
  1421. //
  1422. //----------------------------------------------------------------------------
  1423. IMM32HOTKEY *GetImmHotKeyTable(LANGID langid)
  1424. {
  1425. IMM32HOTKEY *pHotKeys;
  1426. switch (langid)
  1427. {
  1428. case 0x0411: pHotKeys = g_ImmHotKeys411; break;
  1429. case 0x0412: pHotKeys = g_ImmHotKeys412; break;
  1430. case 0x0404: pHotKeys = g_ImmHotKeys404; break;
  1431. case 0x0804: pHotKeys = g_ImmHotKeys804; break;
  1432. default:
  1433. switch (g_uACP)
  1434. {
  1435. case 932: pHotKeys = g_ImmHotKeys411; break;
  1436. case 936: pHotKeys = g_ImmHotKeys804; break;
  1437. case 949: pHotKeys = g_ImmHotKeys412; break;
  1438. case 950: pHotKeys = g_ImmHotKeys404; break;
  1439. }
  1440. return NULL;
  1441. }
  1442. return pHotKeys;
  1443. }
  1444. //+---------------------------------------------------------------------------
  1445. //
  1446. // IsImmHotkey
  1447. //
  1448. //----------------------------------------------------------------------------
  1449. IMM32HOTKEY *IsImmHotkey(UINT uVKey, BOOL fUp, UINT uModifiers, LANGID langid)
  1450. {
  1451. int i = 0;
  1452. BOOL bRet = FALSE;
  1453. IMM32HOTKEY *pHotKeys;
  1454. IMM32HOTKEY *pHotKeyRet = NULL;
  1455. pHotKeys = GetImmHotKeyTable(langid);
  1456. if (!pHotKeys)
  1457. return NULL;
  1458. CicEnterCriticalSection(g_cs);
  1459. while (pHotKeys[i].dwId)
  1460. {
  1461. if (!pHotKeys[i].fInit)
  1462. LoadImmHotkeyFromReg(&pHotKeys[i]);
  1463. if ((pHotKeys[i].uVKey == uVKey) &&
  1464. pHotKeys[i].uModifiers &&
  1465. ModifiersCheck(uModifiers, pHotKeys[i].uModifiers))
  1466. {
  1467. pHotKeyRet = &pHotKeys[i];
  1468. if ((pHotKeyRet->uModifiers & TF_MOD_ON_KEYUP) && !fUp)
  1469. pHotKeyRet = NULL;
  1470. else if (!(pHotKeyRet->uModifiers & TF_MOD_ON_KEYUP) && fUp)
  1471. pHotKeyRet = NULL;
  1472. goto Exit;
  1473. }
  1474. i++;
  1475. }
  1476. Exit:
  1477. CicLeaveCriticalSection(g_cs);
  1478. return pHotKeyRet;
  1479. }
  1480. //+---------------------------------------------------------------------------
  1481. //
  1482. // IsInImmHotkeyStatus
  1483. //
  1484. //
  1485. // This function check the current keyboard status is in IMM32's hotkey.
  1486. // This will be a trigger to eat WM_INPUTLANGUAGECHANGEREQUEST that was
  1487. // genereated by IMM32. This is a fallback code because sometimes we
  1488. // could not eat the message in CheckImm32HotKey() (inside keyboard hook).
  1489. //
  1490. //----------------------------------------------------------------------------
  1491. IMM32HOTKEY *IsInImmHotkeyStatus(SYSTHREAD *psfn, LANGID langid)
  1492. {
  1493. int i = 0;
  1494. IMM32HOTKEY *pHotKeys;
  1495. IMM32HOTKEY *pHotKeyRet = NULL;
  1496. BYTE bkey[256];
  1497. UINT uModifiers;
  1498. if (!psfn)
  1499. return NULL;
  1500. if (psfn->fRemovingInputLangChangeReq)
  1501. return NULL;
  1502. if (!psfn->ptim)
  1503. return NULL;
  1504. if (!psfn->ptim->_GetFocusDocInputMgr())
  1505. return NULL;
  1506. if (!GetKeyboardState(bkey))
  1507. return NULL;
  1508. pHotKeys = GetImmHotKeyTable(langid);
  1509. if (!pHotKeys)
  1510. return NULL;
  1511. uModifiers = 0;
  1512. if (bkey[VK_MENU] & 0x80)
  1513. uModifiers |= TF_MOD_ALT;
  1514. if (bkey[VK_CONTROL] & 0x80)
  1515. uModifiers |= TF_MOD_CONTROL;
  1516. if (bkey[VK_SHIFT] & 0x80)
  1517. uModifiers |= TF_MOD_SHIFT;
  1518. CicEnterCriticalSection(g_cs);
  1519. while (pHotKeys[i].dwId)
  1520. {
  1521. if (!pHotKeys[i].fInit)
  1522. LoadImmHotkeyFromReg(&pHotKeys[i]);
  1523. if ((bkey[pHotKeys[i].uVKey & 0xff] & 0x80) &&
  1524. pHotKeys[i].uModifiers &&
  1525. ModifiersCheck(uModifiers, pHotKeys[i].uModifiers))
  1526. {
  1527. pHotKeyRet = &pHotKeys[i];
  1528. if (pHotKeyRet->uModifiers & TF_MOD_ON_KEYUP)
  1529. pHotKeyRet = NULL;
  1530. goto Exit;
  1531. }
  1532. i++;
  1533. }
  1534. Exit:
  1535. CicLeaveCriticalSection(g_cs);
  1536. return pHotKeyRet;
  1537. }
  1538. //+---------------------------------------------------------------------------
  1539. //
  1540. // CancelImmHotkey
  1541. //
  1542. //----------------------------------------------------------------------------
  1543. #ifdef SIMULATE_EATENKEYS
  1544. BOOL CancelImmHotkey(SYSTHREAD *psfn, HWND hwnd, IMM32HOTKEY *pHotKey)
  1545. {
  1546. UINT uMsg;
  1547. if (pHotKey->uModifiers & TF_MOD_ON_KEYUP)
  1548. uMsg = WM_KEYUP;
  1549. else
  1550. uMsg = WM_KEYDOWN;
  1551. PostMessage(hwnd, uMsg, (WPARAM)pHotKey->uVKey, 0);
  1552. return TRUE;
  1553. }
  1554. #endif
  1555. //+---------------------------------------------------------------------------
  1556. //
  1557. // void ToggleCHImeNoIme
  1558. //
  1559. //----------------------------------------------------------------------------
  1560. BOOL ToggleCHImeNoIme(SYSTHREAD *psfn, LANGID langidCur, LANGID langid)
  1561. {
  1562. int i;
  1563. LANGID langidPrev;
  1564. GUID guidPrevProfile;
  1565. HKL hklPrev;
  1566. BOOL fCiceroClient= FALSE;
  1567. CAssemblyList *pAsmList;
  1568. CAssembly *pAsm;
  1569. ASSEMBLYITEM *pItem;
  1570. pAsmList = EnsureAssemblyList(psfn);
  1571. if (!pAsmList)
  1572. return FALSE;
  1573. langidPrev = psfn->langidPrevForCHHotkey;
  1574. guidPrevProfile = psfn->guidPrevProfileForCHHotkey;
  1575. hklPrev = psfn->hklPrevForCHHotkey;
  1576. psfn->guidPrevProfileForCHHotkey = GUID_NULL;
  1577. psfn->langidPrevForCHHotkey = 0;
  1578. psfn->hklPrevForCHHotkey = 0;
  1579. pAsm = pAsmList->FindAssemblyByLangId(langidCur);
  1580. if (!pAsm)
  1581. return FALSE;
  1582. if (psfn->ptim && psfn->ptim->_GetFocusDocInputMgr())
  1583. fCiceroClient = TRUE;
  1584. if (fCiceroClient)
  1585. {
  1586. pItem = pAsm->FindActiveKeyboardItem();
  1587. if (!pItem)
  1588. return FALSE;
  1589. }
  1590. else
  1591. {
  1592. pItem = pAsm->FindKeyboardLayoutItem(GetKeyboardLayout(0));
  1593. if (!pItem)
  1594. return FALSE;
  1595. }
  1596. if (!IsEqualGUID(pItem->clsid, GUID_NULL) || IsPureIMEHKL(pItem->hkl))
  1597. {
  1598. //
  1599. // Not the current active keyboard item is TIP or IME.
  1600. //
  1601. psfn->guidPrevProfileForCHHotkey = pItem->guidProfile;
  1602. psfn->hklPrevForCHHotkey = pItem->hkl;
  1603. psfn->langidPrevForCHHotkey = langid;
  1604. for (i = 0; i < pAsm->Count(); i++)
  1605. {
  1606. pItem = pAsm->GetItem(i);
  1607. if (!pItem)
  1608. continue;
  1609. if (IsEqualGUID(pItem->catid, GUID_TFCAT_TIP_KEYBOARD) &&
  1610. IsEqualGUID(pItem->clsid, GUID_NULL) &&
  1611. !IsPureIMEHKL(pItem->hkl))
  1612. {
  1613. ActivateAssemblyItem(psfn,
  1614. langidCur,
  1615. pItem,
  1616. AAIF_CHANGEDEFAULT);
  1617. return TRUE;
  1618. }
  1619. }
  1620. PostThreadMessage(GetCurrentThreadId(),
  1621. g_msgPrivate,
  1622. TFPRIV_ACTIVATELANG,
  1623. 0x0409);
  1624. return TRUE;
  1625. }
  1626. else
  1627. {
  1628. BOOL fActivateFirstIME = FALSE;
  1629. BOOL fCheckItem = FALSE;
  1630. if (langidCur != langid)
  1631. ActivateAssembly(langid, ACTASM_NONE);
  1632. pAsm = pAsmList->FindAssemblyByLangId(langid);
  1633. if (!pAsm)
  1634. return FALSE;
  1635. if ((langidPrev == langid) &&
  1636. (!IsEqualGUID(guidPrevProfile, GUID_NULL) ||
  1637. IsPureIMEHKL(hklPrev)))
  1638. {
  1639. fCheckItem = TRUE;
  1640. }
  1641. else if (!langidPrev &&
  1642. IsEqualGUID(guidPrevProfile, GUID_NULL) &&
  1643. !hklPrev)
  1644. {
  1645. fActivateFirstIME = TRUE;
  1646. }
  1647. if (fActivateFirstIME)
  1648. {
  1649. return ActivateNextKeyTip(FALSE);
  1650. }
  1651. for (i = 0; i < pAsm->Count(); i++)
  1652. {
  1653. pItem = pAsm->GetItem(i);
  1654. if (!pItem)
  1655. continue;
  1656. if (!IsEqualGUID(pItem->catid, GUID_TFCAT_TIP_KEYBOARD))
  1657. continue;
  1658. //
  1659. // Bug#494617 - Check the item is enabled or not.
  1660. //
  1661. if (!pItem->fEnabled)
  1662. continue;
  1663. if (fCheckItem)
  1664. {
  1665. if ((!IsEqualGUID(guidPrevProfile, GUID_NULL) &&
  1666. IsEqualGUID(pItem->guidProfile, guidPrevProfile)) ||
  1667. (IsPureIMEHKL(hklPrev) && (hklPrev == pItem->hkl)))
  1668. {
  1669. ActivateAssemblyItem(psfn,
  1670. langid,
  1671. pItem,
  1672. AAIF_CHANGEDEFAULT);
  1673. return TRUE;
  1674. }
  1675. }
  1676. else if (!IsEqualGUID(pItem->guidProfile, GUID_NULL))
  1677. {
  1678. ActivateAssemblyItem(psfn,
  1679. langid,
  1680. pItem,
  1681. AAIF_CHANGEDEFAULT);
  1682. return TRUE;
  1683. }
  1684. }
  1685. }
  1686. return FALSE;
  1687. }
  1688. //////////////////////////////////////////////////////////////////////////////
  1689. //
  1690. // CAsyncOpenKeyboardTip
  1691. //
  1692. //////////////////////////////////////////////////////////////////////////////
  1693. class CAsyncOpenKeyboardTip : public CAsyncQueueItem
  1694. {
  1695. public:
  1696. CAsyncOpenKeyboardTip(CThreadInputMgr *ptim, BOOL fSync) : CAsyncQueueItem(fSync)
  1697. {
  1698. _ptim = ptim;
  1699. }
  1700. HRESULT DoDispatch(CInputContext *pic)
  1701. {
  1702. if (!_ptim)
  1703. {
  1704. Assert(0);
  1705. return E_FAIL;
  1706. }
  1707. MySetCompartmentDWORD(g_gaSystem,
  1708. _ptim,
  1709. GUID_COMPARTMENT_KEYBOARD_OPENCLOSE,
  1710. TRUE);
  1711. return S_OK;
  1712. }
  1713. private:
  1714. CThreadInputMgr *_ptim;
  1715. };
  1716. //+---------------------------------------------------------------------------
  1717. //
  1718. // void ToggleJImeNoIme
  1719. //
  1720. //----------------------------------------------------------------------------
  1721. BOOL ToggleJImeNoIme(SYSTHREAD *psfn)
  1722. {
  1723. int i;
  1724. CAssemblyList *pAsmList;
  1725. CAssembly *pAsm;
  1726. ASSEMBLYITEM *pItem;
  1727. if (!psfn)
  1728. return FALSE;
  1729. if (!psfn->ptim)
  1730. return FALSE;
  1731. //
  1732. // if there is no Focus DIM, we don't have to do this.
  1733. //
  1734. if (!psfn->ptim->_GetFocusDocInputMgr())
  1735. return FALSE;
  1736. pAsmList = EnsureAssemblyList(psfn);
  1737. if (!pAsmList)
  1738. return FALSE;
  1739. pAsm = pAsmList->FindAssemblyByLangId(0x0411);
  1740. if (!pAsm)
  1741. return FALSE;
  1742. pItem = pAsm->FindActiveKeyboardItem();
  1743. if (!pItem)
  1744. return FALSE;
  1745. if (!IsEqualGUID(pItem->clsid, GUID_NULL))
  1746. return FALSE;
  1747. if (IsPureIMEHKL(pItem->hkl))
  1748. return FALSE;
  1749. ASSEMBLYITEM *pItemNew = NULL;
  1750. for (i = 0; i < pAsm->Count(); i++)
  1751. {
  1752. ASSEMBLYITEM *pItemTemp;
  1753. pItemTemp = pAsm->GetItem(i);
  1754. if (!pItemTemp)
  1755. continue;
  1756. if (pItemTemp == pItem)
  1757. continue;
  1758. if (!IsEqualGUID(pItemTemp->catid, GUID_TFCAT_TIP_KEYBOARD))
  1759. continue;
  1760. if (!IsEqualGUID(pItemTemp->clsid, GUID_NULL))
  1761. {
  1762. pItemNew = pItemTemp;
  1763. break;
  1764. }
  1765. if (IsPureIMEHKL(pItemTemp->hkl))
  1766. {
  1767. pItemNew = pItemTemp;
  1768. break;
  1769. }
  1770. }
  1771. if (pItemNew)
  1772. {
  1773. ActivateAssemblyItem(psfn,
  1774. 0x0411,
  1775. pItemNew,
  1776. AAIF_CHANGEDEFAULT);
  1777. //
  1778. // Open Keyboard TIP.
  1779. //
  1780. CInputContext *pic = NULL;
  1781. pic = psfn->ptim->_GetFocusDocInputMgr()->_GetIC(0);
  1782. if (pic)
  1783. {
  1784. CAsyncOpenKeyboardTip *pAsyncOpenKeyboardTip;
  1785. pAsyncOpenKeyboardTip = new CAsyncOpenKeyboardTip(psfn->ptim, FALSE);
  1786. if (pAsyncOpenKeyboardTip)
  1787. {
  1788. HRESULT hr = S_OK;
  1789. if ((pic->_QueueItem(pAsyncOpenKeyboardTip->GetItem(), FALSE, &hr) != S_OK) || FAILED(hr))
  1790. {
  1791. Assert(0);
  1792. }
  1793. pAsyncOpenKeyboardTip->_Release();
  1794. }
  1795. }
  1796. }
  1797. return TRUE;
  1798. }
  1799. //+---------------------------------------------------------------------------
  1800. //
  1801. // CheckImm32HotKey
  1802. //
  1803. //----------------------------------------------------------------------------
  1804. BOOL CheckImm32HotKey(WPARAM wParam, LPARAM lParam)
  1805. {
  1806. HKL hKL;
  1807. SYSTHREAD *psfn = GetSYSTHREAD();
  1808. IMM32HOTKEY *pHotKey;
  1809. BOOL bRet = FALSE;
  1810. if (psfn == NULL)
  1811. return FALSE;
  1812. //
  1813. // If there is no tim, let system change hKL.
  1814. //
  1815. if (!psfn->ptim)
  1816. return FALSE;
  1817. //
  1818. // If there is focus dim, we need to handle it.
  1819. // If there is no focus dim, but msctfime can eat the hotkey,
  1820. // we need to do this instead of system.
  1821. //
  1822. if (!psfn->ptim->_GetFocusDocInputMgr())
  1823. {
  1824. if (!CtfImmIsCiceroStartedInThread())
  1825. return FALSE;
  1826. }
  1827. hKL = GetKeyboardLayout(NULL);
  1828. pHotKey = IsImmHotkey((UINT)wParam & 0xff,
  1829. (HIWORD(lParam) & KF_UP) ? TRUE : FALSE,
  1830. g_uModifiers,
  1831. (LANGID)LOWORD((UINT_PTR)hKL));
  1832. if (!pHotKey)
  1833. {
  1834. //
  1835. // Chinese IME-NONIME toggle Hack for NT.
  1836. //
  1837. // On NT, we're using non IME as a dummy hKL of CH-Tips.
  1838. // we need to simulate HotKey.
  1839. //
  1840. LANGID langidPrev = psfn->langidPrev;
  1841. //
  1842. // If the Chinese IME-NONIME toggle has never been done in this thread
  1843. // and the current thread locale is Chinese, let's try to do
  1844. // IME-NONIME toggle.
  1845. //
  1846. if ((langidPrev != CHTLANGID) &&
  1847. (langidPrev != CHSLANGID) &&
  1848. !psfn->langidPrevForCHHotkey)
  1849. {
  1850. LANGID langidThread = LANGIDFROMLCID(GetThreadLocale());
  1851. if ((langidThread == CHTLANGID) || (langidThread == CHSLANGID))
  1852. langidPrev = langidThread;
  1853. }
  1854. if (IsOnNT() &&
  1855. ((langidPrev == CHTLANGID) || (langidPrev == CHSLANGID)))
  1856. {
  1857. pHotKey = IsImmHotkey((UINT)wParam & 0xff,
  1858. (HIWORD(lParam) & KF_UP) ? TRUE : FALSE,
  1859. g_uModifiers,
  1860. langidPrev);
  1861. if (pHotKey)
  1862. {
  1863. //
  1864. // if it is a IME-NONIME toggle hotkey
  1865. // we need to simulate it.
  1866. //
  1867. if ((pHotKey->dwId == IME_CHOTKEY_IME_NONIME_TOGGLE) ||
  1868. (pHotKey->dwId == IME_THOTKEY_IME_NONIME_TOGGLE))
  1869. {
  1870. bRet = ToggleCHImeNoIme(psfn,
  1871. LANGIDFROMHKL(hKL),
  1872. langidPrev);
  1873. //
  1874. // On CUAS, Imm32's Hotkey is simulated in ImmProcessKey
  1875. // So this function is called there.
  1876. // We don't need this Toggle status hack.
  1877. //
  1878. if (!CtfImmIsCiceroStartedInThread())
  1879. psfn->bInImeNoImeToggle = TRUE;
  1880. }
  1881. }
  1882. }
  1883. return bRet;
  1884. }
  1885. //
  1886. // remove all WM_INPUTLANGCHANGEREQUEST message.
  1887. //
  1888. // sometimes, this can not catch the IMM32's language change. We
  1889. // fallback hack for them in default.cpp's WM_INPUTLANGCHANGEREQUEST
  1890. // handler. Check IsInImmHotKeyStatus() and CancelImmHotkey().
  1891. //
  1892. MSG msg;
  1893. ULONG ulQuitCode;
  1894. BOOL fQuitReceived = FALSE;
  1895. psfn->fRemovingInputLangChangeReq = TRUE;
  1896. while(PeekMessage(&msg, NULL,
  1897. WM_INPUTLANGCHANGEREQUEST,
  1898. WM_INPUTLANGCHANGEREQUEST,
  1899. PM_REMOVE))
  1900. {
  1901. if (msg.message == WM_QUIT)
  1902. {
  1903. ulQuitCode = (ULONG)(msg.wParam);
  1904. fQuitReceived = TRUE;
  1905. }
  1906. }
  1907. if (fQuitReceived)
  1908. PostQuitMessage(ulQuitCode);
  1909. psfn->fRemovingInputLangChangeReq = FALSE;
  1910. //
  1911. // Chinese IME-NONIME toggle Hack for NT.
  1912. //
  1913. // On NT, we're using non IME as a dummy hKL of CH-Tips.
  1914. // we need to simulate HotKey.
  1915. //
  1916. if (IsOnNT() && !psfn->bInImeNoImeToggle)
  1917. {
  1918. if ((pHotKey->dwId == IME_CHOTKEY_IME_NONIME_TOGGLE) ||
  1919. (pHotKey->dwId == IME_THOTKEY_IME_NONIME_TOGGLE))
  1920. {
  1921. bRet = ToggleCHImeNoIme(psfn, LANGIDFROMHKL(hKL), LANGIDFROMHKL(hKL));
  1922. }
  1923. }
  1924. psfn->bInImeNoImeToggle = FALSE;
  1925. return bRet;
  1926. }
  1927. //////////////////////////////////////////////////////////////////////////////
  1928. //
  1929. // CAsyncProcessDBEKeyQueueItem
  1930. //
  1931. //////////////////////////////////////////////////////////////////////////////
  1932. class CAsyncProcessDBEKeyQueueItem : public CAsyncQueueItem
  1933. {
  1934. public:
  1935. CAsyncProcessDBEKeyQueueItem(CThreadInputMgr *ptim, WPARAM wParam, LPARAM lParam, BOOL fTest, BOOL fSync) : CAsyncQueueItem(fSync)
  1936. {
  1937. _wParam = wParam;
  1938. _lParam = lParam;
  1939. _fTest = fTest;
  1940. _ptim = ptim;
  1941. }
  1942. HRESULT DoDispatch(CInputContext *pic)
  1943. {
  1944. if (!_ptim)
  1945. {
  1946. Assert(0);
  1947. return E_FAIL;
  1948. }
  1949. BOOL fEaten;
  1950. return _ptim->_KeyStroke((_lParam & 0x80000000) ? KS_UP : KS_DOWN,
  1951. _wParam,
  1952. _lParam,
  1953. &fEaten,
  1954. _fTest,
  1955. TF_KEY_INTERNAL);
  1956. }
  1957. private:
  1958. WPARAM _wParam;
  1959. LPARAM _lParam;
  1960. BOOL _fTest;
  1961. CThreadInputMgr *_ptim;
  1962. };
  1963. //+---------------------------------------------------------------------------
  1964. //
  1965. // HandleDBEKeys
  1966. //
  1967. //----------------------------------------------------------------------------
  1968. BOOL HandleDBEKeys(WPARAM wParam, LPARAM lParam)
  1969. {
  1970. SYSTHREAD *psfn = GetSYSTHREAD();
  1971. CThreadInputMgr *ptim;
  1972. LANGID langid;
  1973. //
  1974. // only Japanese layout has DBE keys.
  1975. //
  1976. langid = GetCurrentAssemblyLangId(psfn);
  1977. if (langid != 0x0411)
  1978. return FALSE;
  1979. //
  1980. // no need to forward this on non Cicero apps.
  1981. //
  1982. if (!(ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn)))
  1983. return FALSE;
  1984. if (!ptim->_GetFocusDocInputMgr())
  1985. return FALSE;
  1986. //
  1987. // if ALT is not held, app can forward this to TIPs.
  1988. //
  1989. if (!(g_uModifiers & TF_MOD_ALT))
  1990. return FALSE;
  1991. UINT uVKey = (UINT)wParam & 0xff;
  1992. BOOL fRet = FALSE;
  1993. switch (uVKey)
  1994. {
  1995. case VK_DBE_ALPHANUMERIC:
  1996. case VK_DBE_KATAKANA:
  1997. case VK_DBE_HIRAGANA:
  1998. case VK_DBE_SBCSCHAR:
  1999. case VK_DBE_DBCSCHAR:
  2000. case VK_DBE_ROMAN:
  2001. case VK_DBE_NOROMAN:
  2002. case VK_DBE_CODEINPUT:
  2003. case VK_DBE_NOCODEINPUT:
  2004. case VK_DBE_ENTERWORDREGISTERMODE:
  2005. case VK_DBE_ENTERIMECONFIGMODE:
  2006. case VK_DBE_ENTERDLGCONVERSIONMODE:
  2007. case VK_DBE_DETERMINESTRING:
  2008. case VK_DBE_FLUSHSTRING:
  2009. case VK_CONVERT:
  2010. case VK_KANJI:
  2011. //
  2012. // Issue:
  2013. //
  2014. // We don't know which IC in the focus DIM will handle the hotkey yet.
  2015. // because the selection is changed by the application so we need to get ec
  2016. // to update the current selection pos. We do call GetSelection
  2017. // inside the root IC's lock. So it might be failed if hotkey's target
  2018. // is TOP IC.
  2019. //
  2020. CInputContext *pic = ptim->_GetFocusDocInputMgr()->_GetIC(0);
  2021. if (!pic)
  2022. return FALSE;
  2023. CAsyncProcessDBEKeyQueueItem *pAsyncProcessDBEKeyQueueItem;
  2024. pAsyncProcessDBEKeyQueueItem = new CAsyncProcessDBEKeyQueueItem(ptim, wParam, lParam, FALSE, FALSE);
  2025. if (!pAsyncProcessDBEKeyQueueItem)
  2026. return FALSE;
  2027. HRESULT hr = S_OK;
  2028. fRet = TRUE;
  2029. if ((pic->_QueueItem(pAsyncProcessDBEKeyQueueItem->GetItem(), FALSE, &hr) != S_OK) || FAILED(hr))
  2030. {
  2031. Assert(0);
  2032. fRet = FALSE;
  2033. }
  2034. pAsyncProcessDBEKeyQueueItem->_Release();
  2035. break;
  2036. }
  2037. return fRet;
  2038. }