2 * ITfThreadMgr implementation
4 * Copyright 2008 Aric Stewart, CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/debug.h"
37 #include "wine/unicode.h"
38 #include "wine/list.h"
41 #include "msctf_internal.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(msctf
);
45 typedef struct tagThreadMgrSink
{
50 /* ITfActiveLanguageProfileNotifySink *pITfActiveLanguageProfileNotifySink; */
51 /* ITfDisplayAttributeNotifySink *pITfDisplayAttributeNotifySink; */
52 /* ITfKeyTraceEventSink *pITfKeyTraceEventSink; */
53 /* ITfPreservedKeyNotifySink *pITfPreservedKeyNotifySink; */
54 /* ITfThreadFocusSink *pITfThreadFocusSink; */
55 ITfThreadMgrEventSink
*pITfThreadMgrEventSink
;
59 typedef struct tagACLMulti
{
60 const ITfThreadMgrVtbl
*ThreadMgrVtbl
;
61 const ITfSourceVtbl
*SourceVtbl
;
64 const ITfThreadMgrEventSinkVtbl
*ThreadMgrEventSinkVtbl
; /* internal */
66 ITfDocumentMgr
*focus
;
68 /* kept as separate lists to reduce unnecessary iterations */
69 struct list ActiveLanguageProfileNotifySink
;
70 struct list DisplayAttributeNotifySink
;
71 struct list KeyTraceEventSink
;
72 struct list PreservedKeyNotifySink
;
73 struct list ThreadFocusSink
;
74 struct list ThreadMgrEventSink
;
77 static inline ThreadMgr
*impl_from_ITfSourceVtbl(ITfSource
*iface
)
79 return (ThreadMgr
*)((char *)iface
- FIELD_OFFSET(ThreadMgr
,SourceVtbl
));
82 static inline ThreadMgr
*impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink
*iface
)
84 return (ThreadMgr
*)((char *)iface
- FIELD_OFFSET(ThreadMgr
,ThreadMgrEventSinkVtbl
));
87 static void free_sink(ThreadMgrSink
*sink
)
89 IUnknown_Release(sink
->interfaces
.pIUnknown
);
90 HeapFree(GetProcessHeap(),0,sink
);
93 static void ThreadMgr_Destructor(ThreadMgr
*This
)
95 struct list
*cursor
, *cursor2
;
97 TlsSetValue(tlsIndex
,NULL
);
98 TRACE("destroying %p\n", This
);
100 ITfDocumentMgr_Release(This
->focus
);
103 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->ActiveLanguageProfileNotifySink
)
105 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
109 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->DisplayAttributeNotifySink
)
111 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
115 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->KeyTraceEventSink
)
117 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
121 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->PreservedKeyNotifySink
)
123 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
127 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->ThreadFocusSink
)
129 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
133 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->ThreadMgrEventSink
)
135 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
140 HeapFree(GetProcessHeap(),0,This
);
143 static HRESULT WINAPI
ThreadMgr_QueryInterface(ITfThreadMgr
*iface
, REFIID iid
, LPVOID
*ppvOut
)
145 ThreadMgr
*This
= (ThreadMgr
*)iface
;
148 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_ITfThreadMgr
))
152 else if (IsEqualIID(iid
, &IID_ITfSource
))
154 *ppvOut
= &This
->SourceVtbl
;
159 IUnknown_AddRef(iface
);
163 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
164 return E_NOINTERFACE
;
167 static ULONG WINAPI
ThreadMgr_AddRef(ITfThreadMgr
*iface
)
169 ThreadMgr
*This
= (ThreadMgr
*)iface
;
170 return InterlockedIncrement(&This
->refCount
);
173 static ULONG WINAPI
ThreadMgr_Release(ITfThreadMgr
*iface
)
175 ThreadMgr
*This
= (ThreadMgr
*)iface
;
178 ret
= InterlockedDecrement(&This
->refCount
);
180 ThreadMgr_Destructor(This
);
184 /*****************************************************
185 * ITfThreadMgr functions
186 *****************************************************/
188 static HRESULT WINAPI
ThreadMgr_fnActivate( ITfThreadMgr
* iface
, TfClientId
*ptid
)
190 ThreadMgr
*This
= (ThreadMgr
*)iface
;
191 FIXME("STUB:(%p)\n",This
);
195 static HRESULT WINAPI
ThreadMgr_fnDeactivate( ITfThreadMgr
* iface
)
197 ThreadMgr
*This
= (ThreadMgr
*)iface
;
198 FIXME("STUB:(%p)\n",This
);
202 ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink
*)&This
->ThreadMgrEventSinkVtbl
, 0, This
->focus
);
203 ITfDocumentMgr_Release(This
->focus
);
210 static HRESULT WINAPI
ThreadMgr_CreateDocumentMgr( ITfThreadMgr
* iface
, ITfDocumentMgr
213 ThreadMgr
*This
= (ThreadMgr
*)iface
;
214 TRACE("(%p)\n",iface
);
215 return DocumentMgr_Constructor((ITfThreadMgrEventSink
*)&This
->ThreadMgrEventSinkVtbl
, ppdim
);
218 static HRESULT WINAPI
ThreadMgr_EnumDocumentMgrs( ITfThreadMgr
* iface
, IEnumTfDocumentMgrs
221 ThreadMgr
*This
= (ThreadMgr
*)iface
;
222 FIXME("STUB:(%p)\n",This
);
226 static HRESULT WINAPI
ThreadMgr_GetFocus( ITfThreadMgr
* iface
, ITfDocumentMgr
229 ThreadMgr
*This
= (ThreadMgr
*)iface
;
230 TRACE("(%p)\n",This
);
235 *ppdimFocus
= This
->focus
;
237 TRACE("->%p\n",This
->focus
);
239 if (This
->focus
== NULL
)
242 ITfDocumentMgr_AddRef(This
->focus
);
247 static HRESULT WINAPI
ThreadMgr_SetFocus( ITfThreadMgr
* iface
, ITfDocumentMgr
*pdimFocus
)
249 ITfDocumentMgr
*check
;
250 ThreadMgr
*This
= (ThreadMgr
*)iface
;
252 TRACE("(%p) %p\n",This
,pdimFocus
);
254 if (!pdimFocus
|| FAILED(IUnknown_QueryInterface(pdimFocus
,&IID_ITfDocumentMgr
,(LPVOID
*) &check
)))
257 ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink
*)&This
->ThreadMgrEventSinkVtbl
, check
, This
->focus
);
260 ITfDocumentMgr_Release(This
->focus
);
266 static HRESULT WINAPI
ThreadMgr_AssociateFocus( ITfThreadMgr
* iface
, HWND hwnd
,
267 ITfDocumentMgr
*pdimNew
, ITfDocumentMgr
**ppdimPrev
)
269 ThreadMgr
*This
= (ThreadMgr
*)iface
;
270 FIXME("STUB:(%p)\n",This
);
274 static HRESULT WINAPI
ThreadMgr_IsThreadFocus( ITfThreadMgr
* iface
, BOOL
*pfThreadFocus
)
276 ThreadMgr
*This
= (ThreadMgr
*)iface
;
277 FIXME("STUB:(%p)\n",This
);
281 static HRESULT WINAPI
ThreadMgr_GetFunctionProvider( ITfThreadMgr
* iface
, REFCLSID clsid
,
282 ITfFunctionProvider
**ppFuncProv
)
284 ThreadMgr
*This
= (ThreadMgr
*)iface
;
285 FIXME("STUB:(%p)\n",This
);
289 static HRESULT WINAPI
ThreadMgr_EnumFunctionProviders( ITfThreadMgr
* iface
,
290 IEnumTfFunctionProviders
**ppEnum
)
292 ThreadMgr
*This
= (ThreadMgr
*)iface
;
293 FIXME("STUB:(%p)\n",This
);
297 static HRESULT WINAPI
ThreadMgr_GetGlobalCompartment( ITfThreadMgr
* iface
,
298 ITfCompartmentMgr
**ppCompMgr
)
300 ThreadMgr
*This
= (ThreadMgr
*)iface
;
301 FIXME("STUB:(%p)\n",This
);
305 static const ITfThreadMgrVtbl ThreadMgr_ThreadMgrVtbl
=
307 ThreadMgr_QueryInterface
,
311 ThreadMgr_fnActivate
,
312 ThreadMgr_fnDeactivate
,
313 ThreadMgr_CreateDocumentMgr
,
314 ThreadMgr_EnumDocumentMgrs
,
317 ThreadMgr_AssociateFocus
,
318 ThreadMgr_IsThreadFocus
,
319 ThreadMgr_GetFunctionProvider
,
320 ThreadMgr_EnumFunctionProviders
,
321 ThreadMgr_GetGlobalCompartment
325 static HRESULT WINAPI
Source_QueryInterface(ITfSource
*iface
, REFIID iid
, LPVOID
*ppvOut
)
327 ThreadMgr
*This
= impl_from_ITfSourceVtbl(iface
);
328 return ThreadMgr_QueryInterface((ITfThreadMgr
*)This
, iid
, *ppvOut
);
331 static ULONG WINAPI
Source_AddRef(ITfSource
*iface
)
333 ThreadMgr
*This
= impl_from_ITfSourceVtbl(iface
);
334 return ThreadMgr_AddRef((ITfThreadMgr
*)This
);
337 static ULONG WINAPI
Source_Release(ITfSource
*iface
)
339 ThreadMgr
*This
= impl_from_ITfSourceVtbl(iface
);
340 return ThreadMgr_Release((ITfThreadMgr
*)This
);
343 /*****************************************************
344 * ITfSource functions
345 *****************************************************/
346 static WINAPI HRESULT
ThreadMgrSource_AdviseSink(ITfSource
*iface
,
347 REFIID riid
, IUnknown
*punk
, DWORD
*pdwCookie
)
350 ThreadMgr
*This
= impl_from_ITfSourceVtbl(iface
);
352 TRACE("(%p) %s %p %p\n",This
,debugstr_guid(riid
),punk
,pdwCookie
);
354 if (!riid
|| !punk
|| !pdwCookie
)
357 if (IsEqualIID(riid
, &IID_ITfThreadMgrEventSink
))
359 tms
= HeapAlloc(GetProcessHeap(),0,sizeof(ThreadMgrSink
));
361 return E_OUTOFMEMORY
;
362 if (!SUCCEEDED(IUnknown_QueryInterface(punk
, riid
, (LPVOID
*)&tms
->interfaces
.pITfThreadMgrEventSink
)))
364 HeapFree(GetProcessHeap(),0,tms
);
365 return CONNECT_E_CANNOTCONNECT
;
367 list_add_head(&This
->ThreadMgrEventSink
,&tms
->entry
);
368 *pdwCookie
= generate_Cookie(COOKIE_MAGIC_TMSINK
, tms
);
372 FIXME("(%p) Unhandled Sink: %s\n",This
,debugstr_guid(riid
));
376 TRACE("cookie %x\n",*pdwCookie
);
381 static WINAPI HRESULT
ThreadMgrSource_UnadviseSink(ITfSource
*iface
, DWORD pdwCookie
)
384 ThreadMgr
*This
= impl_from_ITfSourceVtbl(iface
);
386 TRACE("(%p) %x\n",This
,pdwCookie
);
388 if (get_Cookie_magic(pdwCookie
)!=COOKIE_MAGIC_TMSINK
)
391 sink
= (ThreadMgrSink
*)remove_Cookie(pdwCookie
);
393 return CONNECT_E_NOCONNECTION
;
395 list_remove(&sink
->entry
);
401 static const ITfSourceVtbl ThreadMgr_SourceVtbl
=
403 Source_QueryInterface
,
407 ThreadMgrSource_AdviseSink
,
408 ThreadMgrSource_UnadviseSink
,
411 /*****************************************************
412 * ITfThreadMgrEventSink functions (internal)
413 *****************************************************/
414 static HRESULT WINAPI
ThreadMgrEventSink_QueryInterface(ITfThreadMgrEventSink
*iface
, REFIID iid
, LPVOID
*ppvOut
)
416 ThreadMgr
*This
= impl_from_ITfThreadMgrEventSink(iface
);
417 return ThreadMgr_QueryInterface((ITfThreadMgr
*)This
, iid
, *ppvOut
);
420 static ULONG WINAPI
ThreadMgrEventSink_AddRef(ITfThreadMgrEventSink
*iface
)
422 ThreadMgr
*This
= impl_from_ITfThreadMgrEventSink(iface
);
423 return ThreadMgr_AddRef((ITfThreadMgr
*)This
);
426 static ULONG WINAPI
ThreadMgrEventSink_Release(ITfThreadMgrEventSink
*iface
)
428 ThreadMgr
*This
= impl_from_ITfThreadMgrEventSink(iface
);
429 return ThreadMgr_Release((ITfThreadMgr
*)This
);
433 static WINAPI HRESULT
ThreadMgrEventSink_OnInitDocumentMgr(
434 ITfThreadMgrEventSink
*iface
,ITfDocumentMgr
*pdim
)
437 ThreadMgr
*This
= impl_from_ITfThreadMgrEventSink(iface
);
439 TRACE("(%p) %p\n",This
,pdim
);
441 LIST_FOR_EACH(cursor
, &This
->ThreadMgrEventSink
)
443 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
444 ITfThreadMgrEventSink_OnInitDocumentMgr(sink
->interfaces
.pITfThreadMgrEventSink
,pdim
);
450 static WINAPI HRESULT
ThreadMgrEventSink_OnUninitDocumentMgr(
451 ITfThreadMgrEventSink
*iface
, ITfDocumentMgr
*pdim
)
454 ThreadMgr
*This
= impl_from_ITfThreadMgrEventSink(iface
);
456 TRACE("(%p) %p\n",This
,pdim
);
458 LIST_FOR_EACH(cursor
, &This
->ThreadMgrEventSink
)
460 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
461 ITfThreadMgrEventSink_OnUninitDocumentMgr(sink
->interfaces
.pITfThreadMgrEventSink
,pdim
);
467 static WINAPI HRESULT
ThreadMgrEventSink_OnSetFocus(
468 ITfThreadMgrEventSink
*iface
, ITfDocumentMgr
*pdimFocus
,
469 ITfDocumentMgr
*pdimPrevFocus
)
472 ThreadMgr
*This
= impl_from_ITfThreadMgrEventSink(iface
);
474 TRACE("(%p) %p %p\n",This
,pdimFocus
, pdimPrevFocus
);
476 LIST_FOR_EACH(cursor
, &This
->ThreadMgrEventSink
)
478 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
479 ITfThreadMgrEventSink_OnSetFocus(sink
->interfaces
.pITfThreadMgrEventSink
, pdimFocus
, pdimPrevFocus
);
485 static WINAPI HRESULT
ThreadMgrEventSink_OnPushContext(
486 ITfThreadMgrEventSink
*iface
, ITfContext
*pic
)
489 ThreadMgr
*This
= impl_from_ITfThreadMgrEventSink(iface
);
491 TRACE("(%p) %p\n",This
,pic
);
493 LIST_FOR_EACH(cursor
, &This
->ThreadMgrEventSink
)
495 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
496 ITfThreadMgrEventSink_OnPushContext(sink
->interfaces
.pITfThreadMgrEventSink
,pic
);
502 static WINAPI HRESULT
ThreadMgrEventSink_OnPopContext(
503 ITfThreadMgrEventSink
*iface
, ITfContext
*pic
)
506 ThreadMgr
*This
= impl_from_ITfThreadMgrEventSink(iface
);
508 TRACE("(%p) %p\n",This
,pic
);
510 LIST_FOR_EACH(cursor
, &This
->ThreadMgrEventSink
)
512 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
513 ITfThreadMgrEventSink_OnPopContext(sink
->interfaces
.pITfThreadMgrEventSink
,pic
);
519 static const ITfThreadMgrEventSinkVtbl ThreadMgr_ThreadMgrEventSinkVtbl
=
521 ThreadMgrEventSink_QueryInterface
,
522 ThreadMgrEventSink_AddRef
,
523 ThreadMgrEventSink_Release
,
525 ThreadMgrEventSink_OnInitDocumentMgr
,
526 ThreadMgrEventSink_OnUninitDocumentMgr
,
527 ThreadMgrEventSink_OnSetFocus
,
528 ThreadMgrEventSink_OnPushContext
,
529 ThreadMgrEventSink_OnPopContext
532 HRESULT
ThreadMgr_Constructor(IUnknown
*pUnkOuter
, IUnknown
**ppOut
)
536 return CLASS_E_NOAGGREGATION
;
538 /* Only 1 ThreadMgr is created per thread */
539 This
= TlsGetValue(tlsIndex
);
542 ThreadMgr_AddRef((ITfThreadMgr
*)This
);
543 *ppOut
= (IUnknown
*)This
;
547 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ThreadMgr
));
549 return E_OUTOFMEMORY
;
551 This
->ThreadMgrVtbl
= &ThreadMgr_ThreadMgrVtbl
;
552 This
->SourceVtbl
= &ThreadMgr_SourceVtbl
;
553 This
->ThreadMgrEventSinkVtbl
= &ThreadMgr_ThreadMgrEventSinkVtbl
;
555 TlsSetValue(tlsIndex
,This
);
557 list_init(&This
->ActiveLanguageProfileNotifySink
);
558 list_init(&This
->DisplayAttributeNotifySink
);
559 list_init(&This
->KeyTraceEventSink
);
560 list_init(&This
->PreservedKeyNotifySink
);
561 list_init(&This
->ThreadFocusSink
);
562 list_init(&This
->ThreadMgrEventSink
);
564 TRACE("returning %p\n", This
);
565 *ppOut
= (IUnknown
*)This
;