Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
32ce98e9
Commit
32ce98e9
authored
Sep 07, 2023
by
Gabriel Ivăncescu
Committed by
Alexandre Julliard
Sep 07, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mshtml: Expose an EventTarget interface on the outer window for events' target dispatch.
Signed-off-by:
Gabriel Ivăncescu
<
gabrielopcode@gmail.com
>
parent
04a74bdb
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
182 additions
and
7 deletions
+182
-7
htmlevent.c
dlls/mshtml/htmlevent.c
+30
-5
htmlevent.h
dlls/mshtml/htmlevent.h
+1
-0
htmlwindow.c
dlls/mshtml/htmlwindow.c
+114
-2
mshtml_private.h
dlls/mshtml/mshtml_private.h
+1
-0
events.c
dlls/mshtml/tests/events.c
+18
-0
script.c
dlls/mshtml/tests/script.c
+18
-0
No files found.
dlls/mshtml/htmlevent.c
View file @
32ce98e9
...
...
@@ -318,6 +318,21 @@ static void remove_event_listener(EventTarget *event_target, const WCHAR *type_n
}
}
static
IEventTarget
*
get_event_target_iface
(
EventTarget
*
event_target
)
{
const
event_target_vtbl_t
*
vtbl
=
dispex_get_vtbl
(
&
event_target
->
dispex
);
IEventTarget
*
ret
;
if
(
vtbl
->
get_dispatch_this
)
{
IDispatch
*
disp
=
vtbl
->
get_dispatch_this
(
&
event_target
->
dispex
);
IDispatch_QueryInterface
(
disp
,
&
IID_IEventTarget
,
(
void
**
)
&
ret
);
}
else
{
ret
=
&
event_target
->
IEventTarget_iface
;
IEventTarget_AddRef
(
ret
);
}
return
ret
;
}
static
HRESULT
get_gecko_target
(
IEventTarget
*
,
nsIDOMEventTarget
**
);
typedef
struct
{
...
...
@@ -1049,7 +1064,7 @@ static HRESULT WINAPI DOMEvent_get_currentTarget(IDOMEvent *iface, IEventTarget
TRACE
(
"(%p)->(%p)
\n
"
,
This
,
p
);
if
(
This
->
current_target
)
IEventTarget_AddRef
(
*
p
=
&
This
->
current_target
->
IEventTarget_iface
);
*
p
=
get_event_target_iface
(
This
->
current_target
);
else
*
p
=
NULL
;
return
S_OK
;
...
...
@@ -1082,7 +1097,7 @@ static HRESULT WINAPI DOMEvent_get_target(IDOMEvent *iface, IEventTarget **p)
TRACE
(
"(%p)->(%p)
\n
"
,
This
,
p
);
if
(
This
->
target
)
IEventTarget_AddRef
(
*
p
=
&
This
->
target
->
IEventTarget_iface
);
*
p
=
get_event_target_iface
(
This
->
target
);
else
*
p
=
NULL
;
return
S_OK
;
...
...
@@ -3573,10 +3588,10 @@ static BOOL is_cp_event(cp_static_data_t *data, DISPID dispid)
static
void
call_event_handlers
(
EventTarget
*
event_target
,
DOMEvent
*
event
,
dispatch_mode_t
dispatch_mode
)
{
const
listener_container_t
*
container
=
get_listener_container
(
event_target
,
event
->
type
,
FALSE
);
const
event_target_vtbl_t
*
vtbl
=
dispex_get_vtbl
(
&
event_target
->
dispex
);
event_listener_t
*
listener
,
listeners_buf
[
8
],
*
listeners
=
listeners_buf
;
unsigned
listeners_cnt
,
listeners_size
;
ConnectionPointContainer
*
cp_container
=
NULL
;
const
event_target_vtbl_t
*
vtbl
=
NULL
;
BOOL
skip_onevent_listener
=
FALSE
;
VARIANT
v
;
HRESULT
hres
;
...
...
@@ -3597,9 +3612,14 @@ static void call_event_handlers(EventTarget *event_target, DOMEvent *event, disp
V_VT
(
&
arg
)
=
VT_DISPATCH
;
V_DISPATCH
(
&
arg
)
=
(
IDispatch
*
)
&
event_target
->
dispex
.
IDispatchEx_iface
;
V_VT
(
&
v
)
=
VT_EMPTY
;
if
(
vtbl
->
get_dispatch_this
)
V_DISPATCH
(
&
arg
)
=
vtbl
->
get_dispatch_this
(
&
event_target
->
dispex
);
IDispatch_AddRef
(
V_DISPATCH
(
&
arg
));
TRACE
(
"%p %s >>>
\n
"
,
event_target
,
debugstr_w
(
event
->
type
));
hres
=
call_disp_func
(
listener
->
function
,
&
dp
,
&
v
);
IDispatch_Release
(
V_DISPATCH
(
&
arg
));
if
(
hres
==
S_OK
)
{
TRACE
(
"%p %s <<< %s
\n
"
,
event_target
,
debugstr_w
(
event
->
type
),
debugstr_variant
(
&
v
));
...
...
@@ -3673,6 +3693,10 @@ static void call_event_handlers(EventTarget *event_target, DOMEvent *event, disp
V_VT
(
args
)
=
VT_DISPATCH
;
V_DISPATCH
(
args
)
=
(
IDispatch
*
)
&
event_target
->
dispex
.
IDispatchEx_iface
;
if
(
vtbl
->
get_dispatch_this
)
V_DISPATCH
(
args
)
=
vtbl
->
get_dispatch_this
(
&
event_target
->
dispex
);
IDispatch_AddRef
(
V_DISPATCH
(
args
));
V_VT
(
args
+
1
)
=
VT_DISPATCH
;
V_DISPATCH
(
args
+
1
)
=
dispatch_mode
==
DISPATCH_LEGACY
?
(
IDispatch
*
)
event
->
event_obj
:
(
IDispatch
*
)
&
event
->
IDOMEvent_iface
;
...
...
@@ -3680,6 +3704,8 @@ static void call_event_handlers(EventTarget *event_target, DOMEvent *event, disp
TRACE
(
"%p %s >>>
\n
"
,
event_target
,
debugstr_w
(
event
->
type
));
hres
=
call_disp_func
(
listener
->
function
,
&
dp
,
&
v
);
IDispatch_Release
(
V_DISPATCH
(
args
));
if
(
hres
==
S_OK
)
{
TRACE
(
"%p %s <<< %s
\n
"
,
event_target
,
debugstr_w
(
event
->
type
),
debugstr_variant
(
&
v
));
...
...
@@ -3729,8 +3755,7 @@ static void call_event_handlers(EventTarget *event_target, DOMEvent *event, disp
if
(
listeners
!=
listeners_buf
)
free
(
listeners
);
if
(
event
->
phase
!=
DEP_CAPTURING_PHASE
&&
event_info
[
event
->
event_id
].
dispid
&&
(
vtbl
=
dispex_get_vtbl
(
&
event_target
->
dispex
))
->
get_cp_container
)
if
(
event
->
phase
!=
DEP_CAPTURING_PHASE
&&
event_info
[
event
->
event_id
].
dispid
&&
vtbl
->
get_cp_container
)
cp_container
=
vtbl
->
get_cp_container
(
&
event_target
->
dispex
);
if
(
cp_container
)
{
if
(
cp_container
->
cps
)
{
...
...
dlls/mshtml/htmlevent.h
View file @
32ce98e9
...
...
@@ -128,6 +128,7 @@ void detach_nsevent(HTMLDocumentNode*,const WCHAR*);
/* We extend dispex vtbl for EventTarget functions to avoid separated vtbl. */
typedef
struct
{
dispex_static_data_vtbl_t
dispex_vtbl
;
IDispatch
*
(
*
get_dispatch_this
)(
DispatchEx
*
);
nsISupports
*
(
*
get_gecko_target
)(
DispatchEx
*
);
void
(
*
bind_event
)(
DispatchEx
*
,
eventid_t
);
EventTarget
*
(
*
get_parent_event_target
)(
DispatchEx
*
);
...
...
dlls/mshtml/htmlwindow.c
View file @
32ce98e9
...
...
@@ -260,9 +260,19 @@ static HRESULT WINAPI outer_window_QueryInterface(IHTMLWindow2 *iface, REFIID ri
}
else
if
(
IsEqualGUID
(
&
IID_nsCycleCollectionISupports
,
riid
))
{
*
ppv
=
&
This
->
base
.
IHTMLWindow2_iface
;
return
S_OK
;
}
else
{
return
EventTarget_QI
(
&
This
->
base
.
inner_window
->
event_target
,
riid
,
ppv
);
}
else
if
(
IsEqualGUID
(
&
IID_IEventTarget
,
riid
))
{
if
(
!
This
->
base
.
inner_window
->
doc
||
This
->
base
.
inner_window
->
doc
->
document_mode
<
COMPAT_MODE_IE9
)
{
*
ppv
=
NULL
;
return
E_NOINTERFACE
;
}
*
ppv
=
&
This
->
IEventTarget_iface
;
IHTMLWindow2_AddRef
(
&
This
->
base
.
IHTMLWindow2_iface
);
return
S_OK
;
}
WARN
(
"(%p)->(%s %p)
\n
"
,
This
,
debugstr_mshtml_guid
(
riid
),
ppv
);
*
ppv
=
NULL
;
return
E_NOINTERFACE
;
}
static
ULONG
WINAPI
outer_window_AddRef
(
IHTMLWindow2
*
iface
)
...
...
@@ -3771,6 +3781,100 @@ static const IDispatchExVtbl WindowDispExVtbl = {
WindowDispEx_GetNameSpaceParent
};
static
inline
HTMLOuterWindow
*
impl_from_IEventTarget
(
IEventTarget
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
HTMLOuterWindow
,
IEventTarget_iface
);
}
static
HRESULT
WINAPI
WindowEventTarget_QueryInterface
(
IEventTarget
*
iface
,
REFIID
riid
,
void
**
ppv
)
{
HTMLOuterWindow
*
This
=
impl_from_IEventTarget
(
iface
);
return
IHTMLWindow2_QueryInterface
(
&
This
->
base
.
IHTMLWindow2_iface
,
riid
,
ppv
);
}
static
ULONG
WINAPI
WindowEventTarget_AddRef
(
IEventTarget
*
iface
)
{
HTMLOuterWindow
*
This
=
impl_from_IEventTarget
(
iface
);
return
IHTMLWindow2_AddRef
(
&
This
->
base
.
IHTMLWindow2_iface
);
}
static
ULONG
WINAPI
WindowEventTarget_Release
(
IEventTarget
*
iface
)
{
HTMLOuterWindow
*
This
=
impl_from_IEventTarget
(
iface
);
return
IHTMLWindow2_Release
(
&
This
->
base
.
IHTMLWindow2_iface
);
}
static
HRESULT
WINAPI
WindowEventTarget_GetTypeInfoCount
(
IEventTarget
*
iface
,
UINT
*
pctinfo
)
{
HTMLOuterWindow
*
This
=
impl_from_IEventTarget
(
iface
);
return
IDispatchEx_GetTypeInfoCount
(
&
This
->
base
.
IDispatchEx_iface
,
pctinfo
);
}
static
HRESULT
WINAPI
WindowEventTarget_GetTypeInfo
(
IEventTarget
*
iface
,
UINT
iTInfo
,
LCID
lcid
,
ITypeInfo
**
ppTInfo
)
{
HTMLOuterWindow
*
This
=
impl_from_IEventTarget
(
iface
);
return
IDispatchEx_GetTypeInfo
(
&
This
->
base
.
IDispatchEx_iface
,
iTInfo
,
lcid
,
ppTInfo
);
}
static
HRESULT
WINAPI
WindowEventTarget_GetIDsOfNames
(
IEventTarget
*
iface
,
REFIID
riid
,
LPOLESTR
*
rgszNames
,
UINT
cNames
,
LCID
lcid
,
DISPID
*
rgDispId
)
{
HTMLOuterWindow
*
This
=
impl_from_IEventTarget
(
iface
);
return
IDispatchEx_GetIDsOfNames
(
&
This
->
base
.
IDispatchEx_iface
,
riid
,
rgszNames
,
cNames
,
lcid
,
rgDispId
);
}
static
HRESULT
WINAPI
WindowEventTarget_Invoke
(
IEventTarget
*
iface
,
DISPID
dispIdMember
,
REFIID
riid
,
LCID
lcid
,
WORD
wFlags
,
DISPPARAMS
*
pDispParams
,
VARIANT
*
pVarResult
,
EXCEPINFO
*
pExcepInfo
,
UINT
*
puArgErr
)
{
HTMLOuterWindow
*
This
=
impl_from_IEventTarget
(
iface
);
return
IDispatchEx_Invoke
(
&
This
->
base
.
IDispatchEx_iface
,
dispIdMember
,
riid
,
lcid
,
wFlags
,
pDispParams
,
pVarResult
,
pExcepInfo
,
puArgErr
);
}
static
HRESULT
WINAPI
WindowEventTarget_addEventListener
(
IEventTarget
*
iface
,
BSTR
type
,
IDispatch
*
listener
,
VARIANT_BOOL
capture
)
{
HTMLOuterWindow
*
This
=
impl_from_IEventTarget
(
iface
);
return
IEventTarget_addEventListener
(
&
This
->
base
.
inner_window
->
event_target
.
IEventTarget_iface
,
type
,
listener
,
capture
);
}
static
HRESULT
WINAPI
WindowEventTarget_removeEventListener
(
IEventTarget
*
iface
,
BSTR
type
,
IDispatch
*
listener
,
VARIANT_BOOL
capture
)
{
HTMLOuterWindow
*
This
=
impl_from_IEventTarget
(
iface
);
return
IEventTarget_removeEventListener
(
&
This
->
base
.
inner_window
->
event_target
.
IEventTarget_iface
,
type
,
listener
,
capture
);
}
static
HRESULT
WINAPI
WindowEventTarget_dispatchEvent
(
IEventTarget
*
iface
,
IDOMEvent
*
event_iface
,
VARIANT_BOOL
*
result
)
{
HTMLOuterWindow
*
This
=
impl_from_IEventTarget
(
iface
);
return
IEventTarget_dispatchEvent
(
&
This
->
base
.
inner_window
->
event_target
.
IEventTarget_iface
,
event_iface
,
result
);
}
static
const
IEventTargetVtbl
EventTargetVtbl
=
{
WindowEventTarget_QueryInterface
,
WindowEventTarget_AddRef
,
WindowEventTarget_Release
,
WindowEventTarget_GetTypeInfoCount
,
WindowEventTarget_GetTypeInfo
,
WindowEventTarget_GetIDsOfNames
,
WindowEventTarget_Invoke
,
WindowEventTarget_addEventListener
,
WindowEventTarget_removeEventListener
,
WindowEventTarget_dispatchEvent
};
static
inline
HTMLWindow
*
impl_from_IServiceProvider
(
IServiceProvider
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
HTMLWindow
,
IServiceProvider_iface
);
...
...
@@ -4075,6 +4179,12 @@ static compat_mode_t HTMLWindow_get_compat_mode(DispatchEx *dispex)
return
lock_document_mode
(
This
->
doc
);
}
static
IDispatch
*
HTMLWindow_get_dispatch_this
(
DispatchEx
*
dispex
)
{
HTMLInnerWindow
*
This
=
impl_from_DispatchEx
(
dispex
);
return
(
IDispatch
*
)
&
This
->
base
.
outer_window
->
base
.
IHTMLWindow2_iface
;
}
static
nsISupports
*
HTMLWindow_get_gecko_target
(
DispatchEx
*
dispex
)
{
HTMLInnerWindow
*
This
=
impl_from_DispatchEx
(
dispex
);
...
...
@@ -4193,6 +4303,7 @@ static const event_target_vtbl_t HTMLWindow_event_target_vtbl = {
.
next_dispid
=
HTMLWindow_next_dispid
,
.
get_compat_mode
=
HTMLWindow_get_compat_mode
,
},
.
get_dispatch_this
=
HTMLWindow_get_dispatch_this
,
.
get_gecko_target
=
HTMLWindow_get_gecko_target
,
.
bind_event
=
HTMLWindow_bind_event
,
.
set_current_event
=
HTMLWindow_set_current_event
...
...
@@ -4351,6 +4462,7 @@ HRESULT create_outer_window(GeckoBrowser *browser, mozIDOMWindowProxy *mozwindow
if
(
!
window
)
return
E_OUTOFMEMORY
;
window
->
base
.
IHTMLWindow2_iface
.
lpVtbl
=
&
outer_window_HTMLWindow2Vtbl
;
window
->
IEventTarget_iface
.
lpVtbl
=
&
EventTargetVtbl
;
window
->
base
.
outer_window
=
window
;
window
->
base
.
inner_window
=
NULL
;
...
...
dlls/mshtml/mshtml_private.h
View file @
32ce98e9
...
...
@@ -551,6 +551,7 @@ struct HTMLWindow {
struct
HTMLOuterWindow
{
HTMLWindow
base
;
IEventTarget
IEventTarget_iface
;
nsCycleCollectingAutoRefCnt
ccref
;
LONG
task_magic
;
...
...
dlls/mshtml/tests/events.c
View file @
32ce98e9
...
...
@@ -1469,8 +1469,26 @@ EVENT_HANDLER_FUNC_OBJ(onvisibilitychange);
static
HRESULT
WINAPI
onbeforeunload
(
IDispatchEx
*
iface
,
DISPID
id
,
LCID
lcid
,
WORD
wFlags
,
DISPPARAMS
*
pdp
,
VARIANT
*
pvarRes
,
EXCEPINFO
*
pei
,
IServiceProvider
*
pspCaller
)
{
IEventTarget
*
event_target
;
IHTMLWindow2
*
window2
;
IDOMEvent
*
event
;
HRESULT
hres
;
CHECK_EXPECT
(
onbeforeunload
);
test_event_args
(
NULL
,
id
,
wFlags
,
pdp
,
pvarRes
,
pei
,
pspCaller
);
hres
=
IDispatch_QueryInterface
(
V_DISPATCH
(
&
pdp
->
rgvarg
[
1
]),
&
IID_IDOMEvent
,
(
void
**
)
&
event
);
ok
(
hres
==
S_OK
,
"Could not get IDOMEvent iface: %08lx
\n
"
,
hres
);
hres
=
IDOMEvent_get_target
(
event
,
&
event_target
);
ok
(
hres
==
S_OK
,
"get_target failed: %08lx
\n
"
,
hres
);
IDOMEvent_Release
(
event
);
hres
=
IEventTarget_QueryInterface
(
event_target
,
&
IID_IHTMLWindow2
,
(
void
**
)
&
window2
);
ok
(
hres
==
S_OK
,
"Could not get IHTMLWindow2 iface: %08lx
\n
"
,
hres
);
ok
(
window2
==
window
,
"event_target's window iface != window
\n
"
);
IHTMLWindow2_Release
(
window2
);
IEventTarget_Release
(
event_target
);
return
S_OK
;
}
...
...
dlls/mshtml/tests/script.c
View file @
32ce98e9
...
...
@@ -197,6 +197,21 @@ static BOOL skip_loadobject_tests;
static
IActiveScriptSite
*
site
,
*
site2
;
static
SCRIPTSTATE
state
,
state2
;
static
BOOL
iface_cmp
(
IUnknown
*
iface1
,
IUnknown
*
iface2
)
{
IUnknown
*
unk1
,
*
unk2
;
if
(
iface1
==
iface2
)
return
TRUE
;
IUnknown_QueryInterface
(
iface1
,
&
IID_IHTMLWindow2
,
(
void
**
)
&
unk1
);
IUnknown_Release
(
unk1
);
IUnknown_QueryInterface
(
iface2
,
&
IID_IHTMLWindow2
,
(
void
**
)
&
unk2
);
IUnknown_Release
(
unk2
);
return
unk1
==
unk2
;
}
static
BOOL
init_key
(
const
WCHAR
*
key_name
,
const
WCHAR
*
def_value
,
BOOL
init
)
{
HKEY
hkey
;
...
...
@@ -4483,6 +4498,9 @@ static void test_exec_script(IHTMLDocument2 *doc, const WCHAR *codew, const WCHA
hres
=
IHTMLDocument2_get_parentWindow
(
doc
,
&
window
);
ok
(
hres
==
S_OK
,
"get_parentWindow failed: %08lx
\n
"
,
hres
);
todo_wine
ok
(
iface_cmp
((
IUnknown
*
)
window
,
(
IUnknown
*
)
window_dispex
),
"window != dispex_window
\n
"
);
code
=
SysAllocString
(
codew
);
lang
=
SysAllocString
(
langw
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment