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.

682 lines
18 KiB

  1. //
  2. // ksmgr.cpp
  3. //
  4. #include "private.h"
  5. #include "dim.h"
  6. #include "tim.h"
  7. #include "ic.h"
  8. #include "computil.h"
  9. //////////////////////////////////////////////////////////////////////////////
  10. //
  11. // CAsyncProcessKeyQueueItem
  12. //
  13. //////////////////////////////////////////////////////////////////////////////
  14. class CAsyncProcessKeyQueueItem : public CAsyncQueueItem
  15. {
  16. public:
  17. CAsyncProcessKeyQueueItem(WPARAM wParam, LPARAM lParam, DWORD dwFlags, BOOL *pfEaten) : CAsyncQueueItem(dwFlags & TIM_AKH_SYNC ? TRUE : FALSE)
  18. {
  19. _wParam = wParam;
  20. _lParam = lParam;
  21. if ((dwFlags & TIM_AKH_SYNC) && pfEaten)
  22. _pfEaten = pfEaten;
  23. else
  24. {
  25. if (pfEaten)
  26. *pfEaten = TRUE;
  27. _pfEaten = &_fEaten;
  28. }
  29. _dwFlags = dwFlags;
  30. }
  31. HRESULT DoDispatch(CInputContext *pic)
  32. {
  33. CThreadInputMgr *ptim = CThreadInputMgr::_GetThis();
  34. if (!ptim)
  35. {
  36. Assert(0);
  37. return E_FAIL;
  38. }
  39. if (HIWORD(_lParam) & KF_UP)
  40. {
  41. ptim->TestKeyUp(_wParam, _lParam, _pfEaten);
  42. if (*_pfEaten && !(_dwFlags & TIM_AKH_TESTONLY))
  43. ptim->KeyUp(_wParam, _lParam, _pfEaten);
  44. }
  45. else
  46. {
  47. ptim->TestKeyDown(_wParam, _lParam, _pfEaten);
  48. if (*_pfEaten && !(_dwFlags & TIM_AKH_TESTONLY))
  49. ptim->KeyDown(_wParam, _lParam, _pfEaten);
  50. }
  51. //
  52. // We needs to simulate keydown message because
  53. // we might return *pfEaten = TRUE;
  54. // When it is async,
  55. // When it was not eaten by keystroke mgr.
  56. // When it has TIM_AKH_SIMULATEKEYMSG
  57. //
  58. if (!(_dwFlags & TIM_AKH_SYNC) &&
  59. !*_pfEaten &&
  60. (_dwFlags & TIM_AKH_SIMULATEKEYMSGS))
  61. {
  62. UINT uMsg = WM_KEYDOWN;
  63. // key up msg?
  64. if (HIWORD(_lParam) & KF_UP)
  65. uMsg++;
  66. // sys key msg?
  67. if (HIWORD(_lParam) & (KF_MENUMODE | KF_ALTDOWN))
  68. uMsg |= 0x04;
  69. PostMessage(GetFocus(), uMsg, _wParam, _lParam);
  70. }
  71. return S_OK;
  72. }
  73. private:
  74. WPARAM _wParam;
  75. LPARAM _lParam;
  76. BOOL *_pfEaten;
  77. BOOL _fEaten;
  78. BOOL _dwFlags;
  79. };
  80. //+---------------------------------------------------------------------------
  81. //
  82. // _AsyncKeyHandler
  83. //
  84. //----------------------------------------------------------------------------
  85. BOOL CThreadInputMgr::_AsyncKeyHandler(WPARAM wParam, LPARAM lParam, DWORD dwFlags, BOOL *pfEaten)
  86. {
  87. CAsyncProcessKeyQueueItem *pAsyncProcessKeyQueueItem;
  88. BOOL bRet;
  89. HRESULT hr;
  90. if (!_pFocusDocInputMgr)
  91. return FALSE;
  92. if (_pFocusDocInputMgr->_GetCurrentStack() < 0)
  93. return FALSE;
  94. //
  95. // Issue:
  96. //
  97. // We don't know which IC in the focus DIM will handle the hotkey yet.
  98. // because the selection is changed by the application so we need to get ec
  99. // to update the current selection pos. We do call GetSelection
  100. // inside the root IC's lock. So it might be failed if hotkey's target
  101. // is TOP IC.
  102. //
  103. CInputContext *pic = _pFocusDocInputMgr->_GetIC(0);
  104. pAsyncProcessKeyQueueItem = new CAsyncProcessKeyQueueItem(wParam, lParam, dwFlags, pfEaten);
  105. if (!pAsyncProcessKeyQueueItem)
  106. return FALSE;
  107. hr = S_OK;
  108. bRet = TRUE;
  109. if ((pic->_QueueItem(pAsyncProcessKeyQueueItem->GetItem(), FALSE, &hr) != S_OK) || FAILED(hr))
  110. {
  111. Assert(0);
  112. bRet = FALSE;
  113. }
  114. pAsyncProcessKeyQueueItem->_Release();
  115. return bRet;
  116. }
  117. //+---------------------------------------------------------------------------
  118. //
  119. // AdviseSink
  120. //
  121. //----------------------------------------------------------------------------
  122. STDAPI CThreadInputMgr::AdviseKeyEventSink(TfClientId tid, ITfKeyEventSink *pSink, BOOL fForeground)
  123. {
  124. CTip *ctip;
  125. if (!_GetCTipfromGUIDATOM(tid, &ctip))
  126. return E_INVALIDARG;
  127. if (ctip->_pKeyEventSink != NULL)
  128. return CONNECT_E_ADVISELIMIT;
  129. ctip->_pKeyEventSink = pSink;
  130. ctip->_pKeyEventSink->AddRef();
  131. ctip->_fForegroundKeyEventSink = fForeground;
  132. //
  133. // overwrite the foreground tip.
  134. //
  135. if (fForeground)
  136. _SetForeground(tid);
  137. return S_OK;
  138. }
  139. //+---------------------------------------------------------------------------
  140. //
  141. // UnadviseSink
  142. //
  143. //----------------------------------------------------------------------------
  144. STDAPI CThreadInputMgr::UnadviseKeyEventSink(TfClientId tid)
  145. {
  146. CTip *ctip;
  147. if (!_GetCTipfromGUIDATOM(tid, &ctip))
  148. return E_INVALIDARG;
  149. if (ctip->_pKeyEventSink == NULL)
  150. return CONNECT_E_NOCONNECTION;
  151. SafeReleaseClear(ctip->_pKeyEventSink);
  152. if (_tidForeground == tid)
  153. {
  154. _SetForeground(TF_INVALID_GUIDATOM);
  155. }
  156. return S_OK;
  157. }
  158. //+---------------------------------------------------------------------------
  159. //
  160. // GetForeground
  161. //
  162. //----------------------------------------------------------------------------
  163. STDAPI CThreadInputMgr::GetForeground(CLSID *pclsid)
  164. {
  165. if (!pclsid)
  166. return E_INVALIDARG;
  167. *pclsid = GUID_NULL;
  168. if (_tidForeground == TF_INVALID_GUIDATOM)
  169. return S_FALSE;
  170. return MyGetGUID(_tidForeground, pclsid);
  171. }
  172. //+---------------------------------------------------------------------------
  173. //
  174. // SetForeground
  175. //
  176. //----------------------------------------------------------------------------
  177. HRESULT CThreadInputMgr::_SetForeground(TfClientId tid)
  178. {
  179. HRESULT hr;
  180. CTip *ctip;
  181. CTip *ctipForeground;
  182. ctip = NULL;
  183. if (tid != TF_INVALID_GUIDATOM)
  184. {
  185. _GetCTipfromGUIDATOM(tid, &ctip);
  186. }
  187. if (ctip)
  188. {
  189. if (ctip->_pKeyEventSink == NULL || !ctip->_fForegroundKeyEventSink)
  190. {
  191. hr = E_INVALIDARG;
  192. goto Exit;
  193. }
  194. }
  195. hr = S_OK;
  196. if (_tidForeground != TF_INVALID_GUIDATOM)
  197. {
  198. if (_tidForeground == tid)
  199. goto Exit;
  200. _GetCTipfromGUIDATOM(_tidForeground, &ctipForeground);
  201. Assert(ctipForeground != NULL);
  202. if (ctipForeground->_pKeyEventSink != NULL) // might be NULL if we got here from ITfKeyEventMgr::Unadvise
  203. {
  204. ctipForeground->_pKeyEventSink->OnSetFocus(FALSE);
  205. }
  206. _tidForeground = 0;
  207. }
  208. if (ctip != NULL)
  209. {
  210. if (ctip->_pKeyEventSink == NULL || !ctip->_fForegroundKeyEventSink)
  211. {
  212. // highly unlikely, but the tip Unadvise'd when we called OnSetFocus(FALSE) on the old foreground tip
  213. hr = E_FAIL;
  214. goto Exit;
  215. }
  216. _tidForeground = tid;
  217. ctip->_pKeyEventSink->OnSetFocus(TRUE);
  218. }
  219. Exit:
  220. return hr;
  221. }
  222. //+---------------------------------------------------------------------------
  223. //
  224. // TestKeyDown
  225. //
  226. //----------------------------------------------------------------------------
  227. HRESULT CThreadInputMgr::TestKeyDown(WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
  228. {
  229. HRESULT hr;
  230. Perf_StartStroke(PERF_STROKE_TESTDOWN);
  231. hr = _KeyStroke(KS_DOWN_TEST, wParam, lParam, pfEaten, TRUE, 0);
  232. Perf_EndStroke(PERF_STROKE_TESTDOWN);
  233. return hr;
  234. }
  235. //+---------------------------------------------------------------------------
  236. //
  237. // KeyDown
  238. //
  239. //----------------------------------------------------------------------------
  240. HRESULT CThreadInputMgr::KeyDown(WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
  241. {
  242. HRESULT hr;
  243. Perf_IncCounter(PERF_KEYDOWN_COUNT);
  244. Perf_StartStroke(PERF_STROKE_DOWN);
  245. hr = _KeyStroke(KS_DOWN, wParam, lParam, pfEaten, TRUE, 0);
  246. Perf_EndStroke(PERF_STROKE_DOWN);
  247. return hr;
  248. }
  249. //+---------------------------------------------------------------------------
  250. //
  251. // TestKeyUp
  252. //
  253. //----------------------------------------------------------------------------
  254. HRESULT CThreadInputMgr::TestKeyUp(WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
  255. {
  256. HRESULT hr;
  257. Perf_StartStroke(PERF_STROKE_TESTUP);
  258. hr = _KeyStroke(KS_UP_TEST, wParam, lParam, pfEaten, TRUE, 0);
  259. Perf_EndStroke(PERF_STROKE_TESTUP);
  260. return hr;
  261. }
  262. //+---------------------------------------------------------------------------
  263. //
  264. // KeyUp
  265. //
  266. //----------------------------------------------------------------------------
  267. HRESULT CThreadInputMgr::KeyUp(WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
  268. {
  269. HRESULT hr;
  270. Perf_StartStroke(PERF_STROKE_UP);
  271. hr = _KeyStroke(KS_UP, wParam, lParam, pfEaten, TRUE, 0);
  272. Perf_EndStroke(PERF_STROKE_UP);
  273. return hr;
  274. }
  275. //+---------------------------------------------------------------------------
  276. //
  277. // KeyDownUpEx
  278. //
  279. //----------------------------------------------------------------------------
  280. HRESULT CThreadInputMgr::KeyDownUpEx(WPARAM wParam, LPARAM lParam, DWORD dwFlags, BOOL *pfEaten)
  281. {
  282. HRESULT hr;
  283. if (HIWORD(lParam) & KF_UP)
  284. {
  285. if (dwFlags & TF_KEY_TEST)
  286. {
  287. Perf_StartStroke(PERF_STROKE_TESTUP);
  288. hr = _KeyStroke(KS_UP_TEST, wParam, lParam, pfEaten, TRUE, dwFlags);
  289. Perf_EndStroke(PERF_STROKE_TESTUP);
  290. }
  291. else
  292. {
  293. Perf_StartStroke(PERF_STROKE_UP);
  294. hr = _KeyStroke(KS_UP, wParam, lParam, pfEaten, TRUE, dwFlags);
  295. Perf_EndStroke(PERF_STROKE_UP);
  296. }
  297. }
  298. else
  299. {
  300. if (dwFlags & TF_KEY_TEST)
  301. {
  302. Perf_StartStroke(PERF_STROKE_TESTDOWN);
  303. hr = _KeyStroke(KS_DOWN_TEST, wParam, lParam, pfEaten, TRUE, dwFlags);
  304. Perf_EndStroke(PERF_STROKE_TESTDOWN);
  305. }
  306. else
  307. {
  308. Perf_IncCounter(PERF_KEYDOWN_COUNT);
  309. Perf_StartStroke(PERF_STROKE_DOWN);
  310. hr = _KeyStroke(KS_DOWN, wParam, lParam, pfEaten, TRUE, dwFlags);
  311. Perf_EndStroke(PERF_STROKE_DOWN);
  312. }
  313. }
  314. return hr;
  315. }
  316. //+---------------------------------------------------------------------------
  317. //
  318. // KeyStroke
  319. //
  320. //----------------------------------------------------------------------------
  321. HRESULT CThreadInputMgr::_KeyStroke(KSEnum ksenum, WPARAM wParam, LPARAM lParam, BOOL *pfEaten, BOOL fSync, DWORD dwFlags)
  322. {
  323. CInputContext *pic;
  324. int iStack;
  325. HRESULT hr;
  326. ITfDocumentMgr *pdim;
  327. int i;
  328. if (pfEaten == NULL)
  329. return E_INVALIDARG;
  330. hr = S_OK;
  331. *pfEaten = FALSE;
  332. if (_pFocusDocInputMgr == NULL) // no focus ic?
  333. {
  334. return S_OK;
  335. }
  336. pdim = _GetFocusDocInputMgr();
  337. if (!(dwFlags & TF_KEY_INTERNAL))
  338. {
  339. if (!(dwFlags & TF_KEY_MSCTFIME) && (pdim && _IsMsctfimeDim(pdim)))
  340. {
  341. return S_OK;
  342. }
  343. }
  344. if (_CheckPreservedKey(ksenum, wParam, lParam, fSync))
  345. {
  346. *pfEaten = TRUE;
  347. return S_OK;
  348. }
  349. iStack = _pFocusDocInputMgr->_GetCurrentStack();
  350. if (iStack < 0)
  351. goto Exit;
  352. while (iStack >= 0)
  353. {
  354. pic = _pFocusDocInputMgr->_GetIC(iStack);
  355. pic->_UpdateKeyEventFilter();
  356. // try left/right side of the selection.
  357. for (i=LEFT_FILTERTIP; i<=RIGHT_FILTERTIP; i++)
  358. {
  359. hr = _CallKeyEventSinkNotForeground(pic->_gaKeyEventFilterTIP[i],
  360. pic, ksenum, wParam, lParam, pfEaten);
  361. if (hr == S_OK && *pfEaten)
  362. goto Exit;
  363. // _CallKeyEventSinkNotForeground returns "error" codes on valid input
  364. // this just means, keep going
  365. hr = S_OK; // keep trying other sinks if there's an error
  366. *pfEaten = FALSE;
  367. if (_pFocusDocInputMgr->_GetCurrentStack() < iStack)
  368. goto NextIC;
  369. }
  370. // try foreground tip.
  371. if (_tidForeground != TF_INVALID_GUIDATOM)
  372. {
  373. hr = _CallKeyEventSink(_tidForeground,
  374. pic, ksenum, wParam, lParam, pfEaten);
  375. if (hr == S_OK && *pfEaten)
  376. break;
  377. hr = S_OK; // keep trying other sinks if there's an error
  378. *pfEaten = FALSE;
  379. if (_pFocusDocInputMgr == NULL)
  380. {
  381. // this can happen if the app is buggy and switches the focus
  382. // inside a SetText or whatever call (perhaps to bring up an
  383. // error dialog, etc.).
  384. hr = E_UNEXPECTED;
  385. goto Exit;
  386. }
  387. if (_pFocusDocInputMgr->_GetCurrentStack() < iStack)
  388. goto NextIC;
  389. }
  390. if (pic->_pICKbdSink)
  391. {
  392. switch (ksenum)
  393. {
  394. case KS_DOWN:
  395. hr = pic->_pICKbdSink->OnKeyDown(wParam, lParam, pfEaten);
  396. break;
  397. case KS_UP:
  398. hr = pic->_pICKbdSink->OnKeyUp(wParam, lParam, pfEaten);
  399. break;
  400. case KS_DOWN_TEST:
  401. hr = pic->_pICKbdSink->OnTestKeyDown(wParam, lParam, pfEaten);
  402. break;
  403. case KS_UP_TEST:
  404. hr = pic->_pICKbdSink->OnTestKeyUp(wParam, lParam, pfEaten);
  405. break;
  406. }
  407. if (hr == S_OK && *pfEaten)
  408. break;
  409. hr = S_OK; // keep trying other sinks if there's an error
  410. *pfEaten = FALSE;
  411. }
  412. NextIC:
  413. iStack--;
  414. if (_pFocusDocInputMgr->_GetCurrentStack() < iStack)
  415. {
  416. iStack = _pFocusDocInputMgr->_GetCurrentStack();
  417. }
  418. }
  419. Exit:
  420. return hr;
  421. }
  422. //+---------------------------------------------------------------------------
  423. //
  424. // CallKeyEventSinkNotForeground
  425. //
  426. //----------------------------------------------------------------------------
  427. HRESULT CThreadInputMgr::_CallKeyEventSinkNotForeground(TfClientId tid, CInputContext *pic, KSEnum ksenum, WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
  428. {
  429. CTip *ctip;
  430. if (tid == _tidForeground)
  431. return E_INVALIDARG;
  432. if (!_GetCTipfromGUIDATOM(tid, &ctip))
  433. return E_INVALIDARG;
  434. if (ctip->_fForegroundKeyEventSink ||
  435. ctip->_pKeyEventSink == NULL)
  436. {
  437. return E_INVALIDARG;
  438. }
  439. return _CallKeyEventSink(tid, pic, ksenum, wParam, lParam, pfEaten);
  440. }
  441. //+---------------------------------------------------------------------------
  442. //
  443. // CallKeyEventSink
  444. //
  445. //----------------------------------------------------------------------------
  446. HRESULT CThreadInputMgr::_CallKeyEventSink(TfClientId tid, CInputContext *pic, KSEnum ksenum, WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
  447. {
  448. ITfKeyEventSink *pSink;
  449. CTip *ctip;
  450. HRESULT hr;
  451. if (!_GetCTipfromGUIDATOM(tid, &ctip))
  452. return E_INVALIDARG;
  453. if (!(pSink = ctip->_pKeyEventSink))
  454. return S_FALSE;
  455. switch (ksenum)
  456. {
  457. case KS_DOWN:
  458. hr = pSink->OnKeyDown(pic, wParam, lParam, pfEaten);
  459. break;
  460. case KS_DOWN_TEST:
  461. hr = pSink->OnTestKeyDown(pic, wParam, lParam, pfEaten);
  462. break;
  463. case KS_UP:
  464. hr = pSink->OnKeyUp(pic, wParam, lParam, pfEaten);
  465. break;
  466. case KS_UP_TEST:
  467. hr = pSink->OnTestKeyUp(pic, wParam, lParam, pfEaten);
  468. break;
  469. default:
  470. Assert(0);
  471. hr = E_FAIL;
  472. break;
  473. }
  474. return hr;
  475. }
  476. //+---------------------------------------------------------------------------
  477. //
  478. // CheckPreservedKey
  479. //
  480. //----------------------------------------------------------------------------
  481. BOOL CThreadInputMgr::_CheckPreservedKey(KSEnum ksenum, WPARAM wParam, LPARAM lParam, BOOL fSync)
  482. {
  483. BOOL bRet = FALSE;
  484. switch (ksenum)
  485. {
  486. case KS_DOWN:
  487. if (!(lParam & 0x80000000))
  488. bRet = _ProcessHotKey(wParam, lParam, TSH_NONSYSHOTKEY, FALSE, fSync);
  489. break;
  490. case KS_DOWN_TEST:
  491. if (!(lParam & 0x80000000))
  492. bRet = _ProcessHotKey(wParam, lParam, TSH_NONSYSHOTKEY, TRUE, fSync);
  493. break;
  494. case KS_UP:
  495. if (lParam & 0x80000000)
  496. bRet = _ProcessHotKey(wParam, lParam, TSH_NONSYSHOTKEY, FALSE, fSync);
  497. break;
  498. case KS_UP_TEST:
  499. if (lParam & 0x80000000)
  500. bRet = _ProcessHotKey(wParam, lParam, TSH_NONSYSHOTKEY, TRUE, fSync);
  501. break;
  502. default:
  503. Assert(0);
  504. break;
  505. }
  506. return bRet;
  507. }
  508. //+---------------------------------------------------------------------------
  509. //
  510. // _NotifyKeyTraceEventSink
  511. //
  512. //----------------------------------------------------------------------------
  513. void CThreadInputMgr::_NotifyKeyTraceEventSink(WPARAM wParam, LPARAM lParam)
  514. {
  515. CStructArray<GENERICSINK> *rgKeyTraceEventSinks;
  516. int i;
  517. rgKeyTraceEventSinks = _GetKeyTraceEventSinks();
  518. for (i=0; i<rgKeyTraceEventSinks->Count(); i++)
  519. {
  520. if (lParam & 0x80000000)
  521. ((ITfKeyTraceEventSink *)rgKeyTraceEventSinks->GetPtr(i)->pSink)->OnKeyTraceUp(wParam, lParam);
  522. else
  523. ((ITfKeyTraceEventSink *)rgKeyTraceEventSinks->GetPtr(i)->pSink)->OnKeyTraceDown(wParam, lParam);
  524. }
  525. }
  526. //+---------------------------------------------------------------------------
  527. //
  528. // _IsMsctfimeDim
  529. //
  530. //----------------------------------------------------------------------------
  531. BOOL CThreadInputMgr::_IsMsctfimeDim(ITfDocumentMgr *pdim)
  532. {
  533. // Get GUID_COMPARTMENT_CTFIME_DIMFLAGS from ..\msctfime\globals.cpp
  534. const GUID GUID_COMPARTMENT_CTFIME_DIMFLAGS = {0xa94c5fd2, 0xc471, 0x4031, {0x95, 0x46, 0x70, 0x9c, 0x17, 0x30, 0x0c, 0xb9}};
  535. HRESULT hr;
  536. DWORD dwFlags;
  537. hr = GetCompartmentDWORD(pdim, GUID_COMPARTMENT_CTFIME_DIMFLAGS,
  538. &dwFlags, FALSE);
  539. if (SUCCEEDED(hr))
  540. {
  541. // Check COMPDIMFLAG_OWNEDDIM(0x0001).
  542. return (dwFlags & 0x0001) ? TRUE : FALSE;
  543. }
  544. return FALSE;
  545. }