mshtml: Added IEventTarget stub implementation.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
632d897c10
commit
455d684671
|
@ -1346,6 +1346,11 @@ HRESULT remove_attribute(DispatchEx *This, DISPID id, VARIANT_BOOL *success)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compat_mode_t dispex_compat_mode(DispatchEx *dispex)
|
||||||
|
{
|
||||||
|
return dispex->info->desc->vtbl->get_compat_mode(dispex);
|
||||||
|
}
|
||||||
|
|
||||||
static dispex_data_t *ensure_dispex_info(dispex_static_data_t *desc, compat_mode_t compat_mode)
|
static dispex_data_t *ensure_dispex_info(dispex_static_data_t *desc, compat_mode_t compat_mode)
|
||||||
{
|
{
|
||||||
if(!desc->info_cache[compat_mode]) {
|
if(!desc->info_cache[compat_mode]) {
|
||||||
|
@ -1362,8 +1367,7 @@ static BOOL ensure_real_info(DispatchEx *dispex)
|
||||||
if(dispex->info != dispex->info->desc->delayed_init_info)
|
if(dispex->info != dispex->info->desc->delayed_init_info)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
dispex->info = ensure_dispex_info(dispex->info->desc,
|
dispex->info = ensure_dispex_info(dispex->info->desc, dispex_compat_mode(dispex));
|
||||||
dispex->info->desc->vtbl->get_compat_mode(dispex));
|
|
||||||
return dispex->info != NULL;
|
return dispex->info != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1638,8 +1638,120 @@ HRESULT doc_init_events(HTMLDocumentNode *doc)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline EventTarget *impl_from_IEventTarget(IEventTarget *iface)
|
||||||
|
{
|
||||||
|
return CONTAINING_RECORD(iface, EventTarget, IEventTarget_iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI EventTarget_QueryInterface(IEventTarget *iface, REFIID riid, void **ppv)
|
||||||
|
{
|
||||||
|
EventTarget *This = impl_from_IEventTarget(iface);
|
||||||
|
return IDispatchEx_QueryInterface(&This->dispex.IDispatchEx_iface, riid, ppv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI EventTarget_AddRef(IEventTarget *iface)
|
||||||
|
{
|
||||||
|
EventTarget *This = impl_from_IEventTarget(iface);
|
||||||
|
return IDispatchEx_AddRef(&This->dispex.IDispatchEx_iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI EventTarget_Release(IEventTarget *iface)
|
||||||
|
{
|
||||||
|
EventTarget *This = impl_from_IEventTarget(iface);
|
||||||
|
return IDispatchEx_Release(&This->dispex.IDispatchEx_iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI EventTarget_GetTypeInfoCount(IEventTarget *iface, UINT *pctinfo)
|
||||||
|
{
|
||||||
|
EventTarget *This = impl_from_IEventTarget(iface);
|
||||||
|
return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI EventTarget_GetTypeInfo(IEventTarget *iface, UINT iTInfo,
|
||||||
|
LCID lcid, ITypeInfo **ppTInfo)
|
||||||
|
{
|
||||||
|
EventTarget *This = impl_from_IEventTarget(iface);
|
||||||
|
return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI EventTarget_GetIDsOfNames(IEventTarget *iface, REFIID riid, LPOLESTR *rgszNames,
|
||||||
|
UINT cNames, LCID lcid, DISPID *rgDispId)
|
||||||
|
{
|
||||||
|
EventTarget *This = impl_from_IEventTarget(iface);
|
||||||
|
return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid,
|
||||||
|
rgszNames, cNames, lcid, rgDispId);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI EventTarget_Invoke(IEventTarget *iface, DISPID dispIdMember,
|
||||||
|
REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
|
||||||
|
VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
|
||||||
|
{
|
||||||
|
EventTarget *This = impl_from_IEventTarget(iface);
|
||||||
|
return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember,
|
||||||
|
riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI EventTarget_addEventListener(IEventTarget *iface, BSTR type,
|
||||||
|
IDispatch *listener, VARIANT_BOOL capture)
|
||||||
|
{
|
||||||
|
EventTarget *This = impl_from_IEventTarget(iface);
|
||||||
|
FIXME("(%p)->(%s %p %x)\n", This, debugstr_w(type), listener, capture);
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI EventTarget_removeEventListener(IEventTarget *iface, BSTR type,
|
||||||
|
IDispatch *listener, VARIANT_BOOL capture)
|
||||||
|
{
|
||||||
|
EventTarget *This = impl_from_IEventTarget(iface);
|
||||||
|
FIXME("(%p)->(%s %p %x)\n", This, debugstr_w(type), listener, capture);
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI EventTarget_dispatchEvent(IEventTarget *iface, IDOMEvent *event, VARIANT_BOOL *result)
|
||||||
|
{
|
||||||
|
EventTarget *This = impl_from_IEventTarget(iface);
|
||||||
|
FIXME("(%p)->(%p %p)\n", This, event, result);
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const IEventTargetVtbl EventTargetVtbl = {
|
||||||
|
EventTarget_QueryInterface,
|
||||||
|
EventTarget_AddRef,
|
||||||
|
EventTarget_Release,
|
||||||
|
EventTarget_GetTypeInfoCount,
|
||||||
|
EventTarget_GetTypeInfo,
|
||||||
|
EventTarget_GetIDsOfNames,
|
||||||
|
EventTarget_Invoke,
|
||||||
|
EventTarget_addEventListener,
|
||||||
|
EventTarget_removeEventListener,
|
||||||
|
EventTarget_dispatchEvent
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DELAY_INIT_VTBL ((const IEventTargetVtbl*)1)
|
||||||
|
|
||||||
|
static BOOL use_event_quirks(EventTarget *event_target)
|
||||||
|
{
|
||||||
|
if(event_target->IEventTarget_iface.lpVtbl == DELAY_INIT_VTBL) {
|
||||||
|
event_target->IEventTarget_iface.lpVtbl =
|
||||||
|
dispex_compat_mode(&event_target->dispex) >= COMPAT_MODE_IE9
|
||||||
|
? &EventTargetVtbl : NULL;
|
||||||
|
}
|
||||||
|
return !event_target->IEventTarget_iface.lpVtbl;
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT EventTarget_QI(EventTarget *event_target, REFIID riid, void **ppv)
|
HRESULT EventTarget_QI(EventTarget *event_target, REFIID riid, void **ppv)
|
||||||
{
|
{
|
||||||
|
if(IsEqualGUID(riid, &IID_IEventTarget)) {
|
||||||
|
if(use_event_quirks(event_target)) {
|
||||||
|
WARN("IEventTarget queried, but not supported by in document mode\n");
|
||||||
|
*ppv = NULL;
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
IEventTarget_AddRef(&event_target->IEventTarget_iface);
|
||||||
|
*ppv = &event_target->IEventTarget_iface;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if(dispex_query_interface(&event_target->dispex, riid, ppv))
|
if(dispex_query_interface(&event_target->dispex, riid, ppv))
|
||||||
return *ppv ? S_OK : E_NOINTERFACE;
|
return *ppv ? S_OK : E_NOINTERFACE;
|
||||||
|
|
||||||
|
@ -1658,6 +1770,20 @@ void EventTarget_Init(EventTarget *event_target, IUnknown *outer, dispex_static_
|
||||||
{
|
{
|
||||||
init_dispex_with_compat_mode(&event_target->dispex, outer, dispex_data, compat_mode);
|
init_dispex_with_compat_mode(&event_target->dispex, outer, dispex_data, compat_mode);
|
||||||
wine_rb_init(&event_target->handler_map, event_id_cmp);
|
wine_rb_init(&event_target->handler_map, event_id_cmp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IEventTarget is supported by the object or not depending on compatibility mode.
|
||||||
|
* We use NULL vtbl for objects in compatibility mode not supporting the interface.
|
||||||
|
* For targets that don't know compatibility mode at creation time, we set vtbl
|
||||||
|
* to special DELAY_INIT_VTBL value so that vtbl will be set to proper value
|
||||||
|
* when it's needed.
|
||||||
|
*/
|
||||||
|
if(compat_mode == COMPAT_MODE_QUIRKS && dispex_data->vtbl && dispex_data->vtbl->get_compat_mode)
|
||||||
|
event_target->IEventTarget_iface.lpVtbl = DELAY_INIT_VTBL;
|
||||||
|
else if(compat_mode < COMPAT_MODE_IE9)
|
||||||
|
event_target->IEventTarget_iface.lpVtbl = NULL;
|
||||||
|
else
|
||||||
|
event_target->IEventTarget_iface.lpVtbl = &EventTargetVtbl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void release_event_target(EventTarget *event_target)
|
void release_event_target(EventTarget *event_target)
|
||||||
|
|
|
@ -333,6 +333,7 @@ void release_typelib(void) DECLSPEC_HIDDEN;
|
||||||
HRESULT get_class_typeinfo(const CLSID*,ITypeInfo**) DECLSPEC_HIDDEN;
|
HRESULT get_class_typeinfo(const CLSID*,ITypeInfo**) DECLSPEC_HIDDEN;
|
||||||
const dispex_static_data_vtbl_t *dispex_get_vtbl(DispatchEx*) DECLSPEC_HIDDEN;
|
const dispex_static_data_vtbl_t *dispex_get_vtbl(DispatchEx*) DECLSPEC_HIDDEN;
|
||||||
void dispex_info_add_interface(dispex_data_t*,tid_t,const DISPID*) DECLSPEC_HIDDEN;
|
void dispex_info_add_interface(dispex_data_t*,tid_t,const DISPID*) DECLSPEC_HIDDEN;
|
||||||
|
compat_mode_t dispex_compat_mode(DispatchEx*) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
static inline void init_dispex(DispatchEx *dispex, IUnknown *outer, dispex_static_data_t *desc)
|
static inline void init_dispex(DispatchEx *dispex, IUnknown *outer, dispex_static_data_t *desc)
|
||||||
{
|
{
|
||||||
|
@ -379,6 +380,7 @@ typedef struct {
|
||||||
|
|
||||||
struct EventTarget {
|
struct EventTarget {
|
||||||
DispatchEx dispex;
|
DispatchEx dispex;
|
||||||
|
IEventTarget IEventTarget_iface;
|
||||||
struct wine_rb_tree handler_map;
|
struct wine_rb_tree handler_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10582,7 +10582,10 @@ static float expected_document_mode;
|
||||||
|
|
||||||
static void test_document_mode(IHTMLDocument2 *doc2)
|
static void test_document_mode(IHTMLDocument2 *doc2)
|
||||||
{
|
{
|
||||||
|
IEventTarget *event_target;
|
||||||
|
IHTMLDocument2 *doc_node;
|
||||||
IHTMLDocument6 *doc;
|
IHTMLDocument6 *doc;
|
||||||
|
IHTMLElement *body;
|
||||||
VARIANT v;
|
VARIANT v;
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
|
||||||
|
@ -10605,6 +10608,31 @@ static void test_document_mode(IHTMLDocument2 *doc2)
|
||||||
ok(V_VT(&v) == VT_R4, "V_VT(documentMode) = %u\n", V_VT(&v));
|
ok(V_VT(&v) == VT_R4, "V_VT(documentMode) = %u\n", V_VT(&v));
|
||||||
ok(V_R4(&v) == expected_document_mode, "documentMode = %f\n", V_R4(&v));
|
ok(V_R4(&v) == expected_document_mode, "documentMode = %f\n", V_R4(&v));
|
||||||
IHTMLDocument6_Release(doc);
|
IHTMLDocument6_Release(doc);
|
||||||
|
|
||||||
|
doc_node = get_doc_node(doc2);
|
||||||
|
|
||||||
|
hres = IHTMLDocument2_QueryInterface(doc_node, &IID_IEventTarget, (void**)&event_target);
|
||||||
|
if(expected_document_mode >= 9) {
|
||||||
|
ok(hres == S_OK, "Could not get IEventTarget interface: %08x\n", hres);
|
||||||
|
IEventTarget_Release(event_target);
|
||||||
|
}else {
|
||||||
|
ok(hres == E_NOINTERFACE, "QI(IEventTarget) returned %08x\n", hres);
|
||||||
|
}
|
||||||
|
|
||||||
|
IHTMLDocument2_Release(doc_node);
|
||||||
|
|
||||||
|
|
||||||
|
body = doc_get_body(doc2);
|
||||||
|
|
||||||
|
hres = IHTMLElement_QueryInterface(body, &IID_IEventTarget, (void**)&event_target);
|
||||||
|
if(expected_document_mode >= 9) {
|
||||||
|
ok(hres == S_OK, "Could not get IEventTarget interface: %08x\n", hres);
|
||||||
|
IEventTarget_Release(event_target);
|
||||||
|
}else {
|
||||||
|
ok(hres == E_NOINTERFACE, "QI(IEventTarget) returned %08x\n", hres);
|
||||||
|
}
|
||||||
|
|
||||||
|
IHTMLElement_Release(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_quirks_mode(void)
|
static void test_quirks_mode(void)
|
||||||
|
|
Loading…
Reference in New Issue