diff --git a/dlls/msctf/msctf_internal.h b/dlls/msctf/msctf_internal.h index 9d375483616..71ed10bb8dd 100644 --- a/dlls/msctf/msctf_internal.h +++ b/dlls/msctf/msctf_internal.h @@ -32,6 +32,7 @@ #define COOKIE_MAGIC_DMSINK 0x0070 #define COOKIE_MAGIC_THREADFOCUSSINK 0x0080 #define COOKIE_MAGIC_KEYTRACESINK 0x0090 +#define COOKIE_MAGIC_UIELEMENTSINK 0x00a0 extern DWORD tlsIndex DECLSPEC_HIDDEN; extern TfClientId processId DECLSPEC_HIDDEN; diff --git a/dlls/msctf/tests/inputprocessor.c b/dlls/msctf/tests/inputprocessor.c index 0d03ce3a8a1..d440b536764 100644 --- a/dlls/msctf/tests/inputprocessor.c +++ b/dlls/msctf/tests/inputprocessor.c @@ -64,7 +64,7 @@ static DWORD tmSinkCookie; static DWORD tmSinkRefCount; static DWORD dmSinkCookie; static DWORD documentStatus; -static DWORD key_trace_sink_cookie; +static DWORD key_trace_sink_cookie, ui_element_sink_cookie; static ITfDocumentMgr *test_CurrentFocus = NULL; static ITfDocumentMgr *test_PrevFocus = NULL; static ITfDocumentMgr *test_LastCurrentFocus = FOCUS_SAVE; @@ -671,6 +671,60 @@ static const ITfKeyTraceEventSinkVtbl TfKeyTraceEventSinkVtbl = { static ITfKeyTraceEventSink TfKeyTraceEventSink = { &TfKeyTraceEventSinkVtbl }; +static HRESULT WINAPI TfUIElementSink_QueryInterface(ITfUIElementSink *iface, + REFIID riid, void **ppvObject) +{ + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_ITfUIElementSink, riid)){ + *ppvObject = iface; + return S_OK; + } + + *ppvObject = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI TfUIElementSink_AddRef(ITfUIElementSink *iface) +{ + return 2; +} + +static ULONG WINAPI TfUIElementSink_Release(ITfUIElementSink *iface) +{ + return 1; +} + +static HRESULT WINAPI TfUIElementSink_BeginUIElement(ITfUIElementSink *iface, + DWORD id, BOOL *show) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TfUIElementSink_UpdateUIElement(ITfUIElementSink *iface, + DWORD id) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TfUIElementSink_EndUIElement(ITfUIElementSink *iface, + DWORD id) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const ITfUIElementSinkVtbl TfUIElementSinkVtbl = { + TfUIElementSink_QueryInterface, + TfUIElementSink_AddRef, + TfUIElementSink_Release, + TfUIElementSink_BeginUIElement, + TfUIElementSink_UpdateUIElement, + TfUIElementSink_EndUIElement +}; + +static ITfUIElementSink TfUIElementSink = { &TfUIElementSinkVtbl }; + static HRESULT WINAPI TfTransitoryExtensionSink_QueryInterface(ITfTransitoryExtensionSink *iface, REFIID riid, void **ppv) { if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_ITfTransitoryExtensionSink, riid)) { @@ -1128,7 +1182,7 @@ static void test_ThreadMgrAdviseSinks(void) tmSinkRefCount = 1; tmSinkCookie = 0; hr = ITfSource_AdviseSink(source,&IID_ITfThreadMgrEventSink, sink, &tmSinkCookie); - ok(hr == S_OK, "Failed to Advise Sink\n"); + ok(hr == S_OK, "Failed to Advise ITfThreadMgrEventSink\n"); ok(tmSinkCookie!=0,"Failed to get sink cookie\n"); /* Advising the sink adds a ref, Releasing here lets the object be deleted @@ -1138,7 +1192,11 @@ static void test_ThreadMgrAdviseSinks(void) hr = ITfSource_AdviseSink(source, &IID_ITfKeyTraceEventSink, (IUnknown*)&TfKeyTraceEventSink, &key_trace_sink_cookie); - ok(hr == S_OK, "Failed to Advise Sink\n"); + ok(hr == S_OK, "Failed to Advise ITfKeyTraceEventSink\n"); + + hr = ITfSource_AdviseSink(source, &IID_ITfUIElementSink, (IUnknown*)&TfUIElementSink, + &ui_element_sink_cookie); + ok(hr == S_OK, "Failed to Advise ITfUIElementSink\n"); ITfSource_Release(source); } @@ -1155,10 +1213,13 @@ static void test_ThreadMgrUnadviseSinks(void) tmSinkRefCount = 1; hr = ITfSource_UnadviseSink(source, tmSinkCookie); - ok(hr == S_OK, "Failed to unadvise Sink\n"); + ok(hr == S_OK, "Failed to unadvise ITfThreadMgrEventSink\n"); hr = ITfSource_UnadviseSink(source, key_trace_sink_cookie); - ok(hr == S_OK, "Failed to unadvise Sink\n"); + ok(hr == S_OK, "Failed to unadvise ITfKeyTraceEventSink\n"); + + hr = ITfSource_UnadviseSink(source, ui_element_sink_cookie); + ok(hr == S_OK, "Failed to unadvise ITfUIElementSink\n"); ITfSource_Release(source); } diff --git a/dlls/msctf/threadmgr.c b/dlls/msctf/threadmgr.c index a9fcb5cd15c..7afef3cdd53 100644 --- a/dlls/msctf/threadmgr.c +++ b/dlls/msctf/threadmgr.c @@ -96,6 +96,7 @@ typedef struct tagACLMulti { struct list PreservedKeyNotifySink; struct list ThreadFocusSink; struct list ThreadMgrEventSink; + struct list UIElementSink; } ThreadMgr; typedef struct tagEnumTfDocumentMgr { @@ -172,6 +173,7 @@ static void ThreadMgr_Destructor(ThreadMgr *This) free_sinks(&This->PreservedKeyNotifySink); free_sinks(&This->ThreadFocusSink); free_sinks(&This->ThreadMgrEventSink); + free_sinks(&This->UIElementSink); LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CurrentPreservedKeys) { @@ -624,6 +626,13 @@ static HRESULT WINAPI ThreadMgrSource_AdviseSink(ITfSource *iface, COOKIE_MAGIC_KEYTRACESINK, punk, pdwCookie); } + if (IsEqualIID(riid, &IID_ITfUIElementSink)) + { + WARN("semi-stub for ITfUIElementSink: sink won't be used.\n"); + return advise_sink(&This->UIElementSink, &IID_ITfUIElementSink, + COOKIE_MAGIC_UIELEMENTSINK, punk, pdwCookie); + } + FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid)); return E_NOTIMPL; } @@ -637,7 +646,7 @@ static HRESULT WINAPI ThreadMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCo magic = get_Cookie_magic(pdwCookie); if (magic != COOKIE_MAGIC_TMSINK && magic != COOKIE_MAGIC_THREADFOCUSSINK - && magic != COOKIE_MAGIC_KEYTRACESINK) + && magic != COOKIE_MAGIC_KEYTRACESINK && magic != COOKIE_MAGIC_UIELEMENTSINK) return E_INVALIDARG; return unadvise_sink(pdwCookie); @@ -1354,6 +1363,7 @@ HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) list_init(&This->PreservedKeyNotifySink); list_init(&This->ThreadFocusSink); list_init(&This->ThreadMgrEventSink); + list_init(&This->UIElementSink); TRACE("returning %p\n", This); *ppOut = (IUnknown *)&This->ITfThreadMgrEx_iface; diff --git a/include/msctf.idl b/include/msctf.idl index 01e944cf5df..5ef33119fd8 100644 --- a/include/msctf.idl +++ b/include/msctf.idl @@ -1136,6 +1136,25 @@ interface ITfKeyTraceEventSink : IUnknown [in] LPARAM lParam); } +[ + object, + local, + uuid(ea1ea136-19df-11d7-a6d2-00065b84435c), + pointer_default(unique) +] +interface ITfUIElementSink : IUnknown +{ + HRESULT BeginUIElement( + [in] DWORD id, + [in, out] BOOL *show); + + HRESULT UpdateUIElement( + [in] DWORD id); + + HRESULT EndUIElement( + [in] DWORD id); +} + [ object, local,