Signed-off-by: Jactry Zeng jzeng@codeweavers.com --- dlls/msctf/tests/inputprocessor.c | 49 +++++++++ dlls/msctf/threadmgr.c | 176 ++++++++++++++++++++++++++++++ include/msctf.idl | 23 ++++ 3 files changed, 248 insertions(+)
diff --git a/dlls/msctf/tests/inputprocessor.c b/dlls/msctf/tests/inputprocessor.c index 1222085fe0..ebc0e36154 100644 --- a/dlls/msctf/tests/inputprocessor.c +++ b/dlls/msctf/tests/inputprocessor.c @@ -2558,6 +2558,54 @@ static void test_MultiThreadApartment(void) CloseHandle(thread); }
+static void test_thread_mgr2(void) +{ + TfClientId clientid1, clientid2, clientid3; + ITfDocumentMgr *docmgr; + ITfThreadMgr2 *thmgr2; + ITfThreadMgr *thmgr; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, + &IID_ITfThreadMgr2, (void**)&thmgr2); + ok(hr == S_OK || broken(hr == E_NOINTERFACE), /* pre-win8 */ + "Couldn't create ITfThreadMgr2: %#x.\n", hr); + + if (FAILED(hr)) + { + win_skip("ITfThreadMgr2 interface isn't available.\n"); + return; + } + + hr = ITfThreadMgr2_QueryInterface(thmgr2, &IID_ITfThreadMgr, (void **)&thmgr); + ok(hr == S_OK, "ITfThreadMgr2_QueryInterface failed: %#x.\n", hr); + ITfThreadMgr_Release(thmgr); + + hr = ITfThreadMgr2_ActivateEx(thmgr2, &clientid1, 0); + ok(hr == S_OK, "ITfThreadMgr2_ActivateEx failed: %#x.\n", hr); + + hr = ITfThreadMgr_Activate(g_tm, &clientid2); + ok(hr == S_OK, "ITfThreadMgr_Activate failed: %#x.\n", hr); + ok(clientid1 == clientid2, "Got unexpected client ID.\n"); + + hr = ITfThreadMgr_Activate(thmgr, &clientid3); + ok(hr == S_OK, "ITfThreadMgr_Activate failed: %#x.\n", hr); + ok(clientid1 == clientid3, "Got unexpected client ID.\n"); + + hr = ITfThreadMgr2_CreateDocumentMgr(thmgr2, &docmgr); + ok(hr == S_OK, "ITfThreadMgr2_CreateDocumentMgr failed: %#x.\n", hr); + + hr = ITfThreadMgr2_Deactivate(thmgr2); + ok(hr == S_OK, "ITfThreadMgr2_Deactivate failed: %#x.\n", hr); + hr = ITfThreadMgr2_Deactivate(thmgr2); + ok(hr == S_OK, "ITfThreadMgr2_Deactivate failed: %#x.\n", hr); + hr = ITfThreadMgr2_Deactivate(thmgr2); + ok(hr == S_OK, "ITfThreadMgr2_Deactivate failed: %#x.\n", hr); + + ITfDocumentMgr_Release(docmgr); + ITfThreadMgr2_Release(thmgr2); +} + START_TEST(inputprocessor) { if (SUCCEEDED(initialize())) @@ -2588,6 +2636,7 @@ START_TEST(inputprocessor) test_Unregister(); test_profile_mgr(); test_MultiThreadApartment(); + test_thread_mgr2();
ITextStoreACPSink_Release(ACPSink); ITfDocumentMgr_Release(g_dm); diff --git a/dlls/msctf/threadmgr.c b/dlls/msctf/threadmgr.c index 2c208fbc04..2e5deb62ee 100644 --- a/dlls/msctf/threadmgr.c +++ b/dlls/msctf/threadmgr.c @@ -61,6 +61,7 @@ typedef struct tagAssociatedWindow
typedef struct tagACLMulti { ITfThreadMgrEx ITfThreadMgrEx_iface; + ITfThreadMgr2 ITfThreadMgr2_iface; ITfSource ITfSource_iface; ITfKeystrokeMgr ITfKeystrokeMgr_iface; ITfMessagePump ITfMessagePump_iface; @@ -115,6 +116,11 @@ static inline ThreadMgr *impl_from_ITfThreadMgrEx(ITfThreadMgrEx *iface) return CONTAINING_RECORD(iface, ThreadMgr, ITfThreadMgrEx_iface); }
+static inline ThreadMgr *impl_from_ITfThreadMgr2(ITfThreadMgr2 *iface) +{ + return CONTAINING_RECORD(iface, ThreadMgr, ITfThreadMgr2_iface); +} + static inline ThreadMgr *impl_from_ITfSource(ITfSource *iface) { return CONTAINING_RECORD(iface, ThreadMgr, ITfSource_iface); @@ -215,6 +221,10 @@ static HRESULT WINAPI ThreadMgr_QueryInterface(ITfThreadMgrEx *iface, REFIID iid { *ppvOut = &This->ITfThreadMgrEx_iface; } + else if (IsEqualIID(iid, &IID_ITfThreadMgr2)) + { + *ppvOut = &This->ITfThreadMgr2_iface; + } else if (IsEqualIID(iid, &IID_ITfSource)) { *ppvOut = &This->ITfSource_iface; @@ -581,6 +591,171 @@ static const ITfThreadMgrExVtbl ThreadMgrExVtbl = ThreadMgr_GetActiveFlags };
+static HRESULT WINAPI ThreadMgr2_QueryInterface(ITfThreadMgr2 *iface, REFIID iid, LPVOID *out) +{ + ThreadMgr *This = impl_from_ITfThreadMgr2(iface); + return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, out); +} + +static ULONG WINAPI ThreadMgr2_AddRef(ITfThreadMgr2 *iface) +{ + ThreadMgr *This = impl_from_ITfThreadMgr2(iface); + return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface); +} + +static ULONG WINAPI ThreadMgr2_Release(ITfThreadMgr2 *iface) +{ + ThreadMgr *This = impl_from_ITfThreadMgr2(iface); + return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface); +} + +static HRESULT WINAPI ThreadMgr2_Activate(ITfThreadMgr2 *iface, TfClientId *id) +{ + ThreadMgr *This = impl_from_ITfThreadMgr2(iface); + + TRACE("(%p, %p).\n", This, id); + + return ITfThreadMgrEx_Activate(&This->ITfThreadMgrEx_iface, id); +} + +static HRESULT WINAPI ThreadMgr2_Deactivate(ITfThreadMgr2 *iface) +{ + ThreadMgr *This = impl_from_ITfThreadMgr2(iface); + + TRACE("(%p).\n", This); + + return ITfThreadMgrEx_Deactivate(&This->ITfThreadMgrEx_iface); +} + +static HRESULT WINAPI ThreadMgr2_CreateDocumentMgr(ITfThreadMgr2 *iface, ITfDocumentMgr **manager) +{ + ThreadMgr *This = impl_from_ITfThreadMgr2(iface); + + TRACE("(%p, %p).\n", This, manager); + + return ITfThreadMgrEx_CreateDocumentMgr(&This->ITfThreadMgrEx_iface, manager); +} + +static HRESULT WINAPI ThreadMgr2_EnumDocumentMgrs(ITfThreadMgr2 *iface, IEnumTfDocumentMgrs **managers) +{ + ThreadMgr *This = impl_from_ITfThreadMgr2(iface); + + FIXME("(%p, %p): stub.\n", This, managers); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ThreadMgr2_GetFocus(ITfThreadMgr2 *iface, ITfDocumentMgr **focus) +{ + ThreadMgr *This = impl_from_ITfThreadMgr2(iface); + + FIXME("(%p, %p): stub.\n", This, focus); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ThreadMgr2_SetFocus(ITfThreadMgr2 *iface, ITfDocumentMgr *focus) +{ + ThreadMgr *This = impl_from_ITfThreadMgr2(iface); + + FIXME("(%p, %p): stub.\n", This, focus); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ThreadMgr2_IsThreadFocus(ITfThreadMgr2 *iface, BOOL *focus) +{ + ThreadMgr *This = impl_from_ITfThreadMgr2(iface); + + FIXME("(%p, %p): stub.\n", This, focus); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ThreadMgr2_GetFunctionProvider(ITfThreadMgr2 *iface, REFCLSID clsid, ITfFunctionProvider **provider) +{ + ThreadMgr *This = impl_from_ITfThreadMgr2(iface); + + FIXME("(%p, %p): stub.\n", This, provider); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ThreadMgr2_EnumFunctionProviders(ITfThreadMgr2 *iface, IEnumTfFunctionProviders **providers) +{ + ThreadMgr *This = impl_from_ITfThreadMgr2(iface); + + FIXME("(%p, %p): stub.\n", This, providers); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ThreadMgr2_GetGlobalCompartment(ITfThreadMgr2 *iface, ITfCompartmentMgr **compartment) +{ + ThreadMgr *This = impl_from_ITfThreadMgr2(iface); + + FIXME("(%p, %p): stub.\n", This, compartment); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ThreadMgr2_ActivateEx(ITfThreadMgr2 *iface, TfClientId *id, DWORD flags) +{ + ThreadMgr *This = impl_from_ITfThreadMgr2(iface); + + TRACE("(%p, %p, %x).\n", This, id, flags); + + return ITfThreadMgrEx_ActivateEx(&This->ITfThreadMgrEx_iface, id, flags); +} + +static HRESULT WINAPI ThreadMgr2_GetActiveFlags(ITfThreadMgr2 *iface, DWORD *flags) +{ + ThreadMgr *This = impl_from_ITfThreadMgr2(iface); + + FIXME("(%p, %p): stub.\n", This, flags); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ThreadMgr2_SuspendKeystrokeHandling(ITfThreadMgr2 *iface) +{ + ThreadMgr *This = impl_from_ITfThreadMgr2(iface); + + FIXME("(%p): stub.\n", This); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ThreadMgr2_ResumeKeystrokeHandling(ITfThreadMgr2 *iface) +{ + ThreadMgr *This = impl_from_ITfThreadMgr2(iface); + + FIXME("(%p): stub.\n", This); + + return E_NOTIMPL; +} + +static const ITfThreadMgr2Vtbl ThreadMgr2Vtbl = +{ + ThreadMgr2_QueryInterface, + ThreadMgr2_AddRef, + ThreadMgr2_Release, + ThreadMgr2_Activate, + ThreadMgr2_Deactivate, + ThreadMgr2_CreateDocumentMgr, + ThreadMgr2_EnumDocumentMgrs, + ThreadMgr2_GetFocus, + ThreadMgr2_SetFocus, + ThreadMgr2_IsThreadFocus, + ThreadMgr2_GetFunctionProvider, + ThreadMgr2_EnumFunctionProviders, + ThreadMgr2_GetGlobalCompartment, + ThreadMgr2_ActivateEx, + ThreadMgr2_GetActiveFlags, + ThreadMgr2_SuspendKeystrokeHandling, + ThreadMgr2_ResumeKeystrokeHandling, +}; + static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut) { ThreadMgr *This = impl_from_ITfSource(iface); @@ -1351,6 +1526,7 @@ HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) return E_OUTOFMEMORY;
This->ITfThreadMgrEx_iface.lpVtbl = &ThreadMgrExVtbl; + This->ITfThreadMgr2_iface.lpVtbl = &ThreadMgr2Vtbl; This->ITfSource_iface.lpVtbl = &ThreadMgrSourceVtbl; This->ITfKeystrokeMgr_iface.lpVtbl = &KeystrokeMgrVtbl; This->ITfMessagePump_iface.lpVtbl = &MessagePumpVtbl; diff --git a/include/msctf.idl b/include/msctf.idl index 5ef33119fd..8de62d0add 100644 --- a/include/msctf.idl +++ b/include/msctf.idl @@ -228,6 +228,29 @@ interface ITfThreadMgrEx : ITfThreadMgr [out] DWORD *flags); }
+[ + object, + uuid(0ab198ef-6477-4ee8-8812-6780edb82d5e), + pointer_default(unique) +] +interface ITfThreadMgr2 : IUnknown +{ + HRESULT Activate([out] TfClientId *id); + HRESULT Deactivate(); + HRESULT CreateDocumentMgr([out] ITfDocumentMgr **manager); + HRESULT EnumDocumentMgrs([out] IEnumTfDocumentMgrs **managers); + HRESULT GetFocus([out] ITfDocumentMgr **focus); + HRESULT SetFocus([in] ITfDocumentMgr *focus); + HRESULT IsThreadFocus([out] BOOL *focus); + HRESULT GetFunctionProvider([in] REFCLSID clsid, [out] ITfFunctionProvider **provider); + HRESULT EnumFunctionProviders([out] IEnumTfFunctionProviders **providers); + HRESULT GetGlobalCompartment([out] ITfCompartmentMgr **compartment); + HRESULT ActivateEx([out] TfClientId *id, [in] DWORD flags); + HRESULT GetActiveFlags([out] DWORD *flags); + HRESULT SuspendKeystrokeHandling(); + HRESULT ResumeKeystrokeHandling(); +} + [ object, uuid(d7540241-f9a1-4364-befc-dbcd2c4395b7),