From 101822c04b4f3f5e22cc6cb4655df64a70e13505 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Thu, 22 Apr 2021 01:52:53 +0200 Subject: [PATCH] mshtml: Add window.requestAnimationFrame semi-stub implementation. Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- dlls/mshtml/htmlwindow.c | 29 +++++++++++++++++++++++++++++ dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/task.c | 30 +++++++++++++++++++++++++----- dlls/mshtml/tests/documentmode.js | 1 + dlls/mshtml/tests/dom.js | 10 ++++++++++ 5 files changed, 66 insertions(+), 5 deletions(-) diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index e535cd54bd6..4c57d457e41 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -3170,6 +3170,9 @@ HRESULT search_window_props(HTMLInnerWindow *This, BSTR bstrName, DWORD grfdex, return DISP_E_UNKNOWNNAME; } +/* DISPIDs not exposed by interfaces */ +#define DISPID_IHTMLWINDOW_IE10_REQUESTANIMATIONFRAME 1300 + static HRESULT WINAPI WindowDispEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) { HTMLWindow *This = impl_from_IDispatchEx(iface); @@ -3186,6 +3189,13 @@ static HRESULT WINAPI WindowDispEx_GetDispID(IDispatchEx *iface, BSTR bstrName, if(hres != DISP_E_UNKNOWNNAME) return hres; + if(dispex_compat_mode(&window->event_target.dispex) >= COMPAT_MODE_IE10 && + !wcscmp(bstrName, L"requestAnimationFrame")) { + TRACE("requestAnimationFrame\n"); + *pid = DISPID_IHTMLWINDOW_IE10_REQUESTANIMATIONFRAME; + return S_OK; + } + if(This->outer_window) { HTMLOuterWindow *frame; @@ -3272,6 +3282,25 @@ static HRESULT WINAPI WindowDispEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID return IDispatchEx_InvokeEx(&window->event_target.dispex.IDispatchEx_iface, id, lcid, wFlags, &dp, pvarRes, pei, pspCaller); } + case DISPID_IHTMLWINDOW_IE10_REQUESTANIMATIONFRAME: { + HRESULT hres; + LONG r; + + FIXME("requestAnimationFrame: semi-stub\n"); + + if(!(wFlags & DISPATCH_METHOD) || pdp->cArgs != 1 || pdp->cNamedArgs) { + FIXME("unsupported args\n"); + return E_INVALIDARG; + } + + hres = window_set_timer(window, pdp->rgvarg, 50, NULL, TIMER_ANIMATION_FRAME, &r); + if(SUCCEEDED(hres) && pvarRes) { + V_VT(pvarRes) = VT_I4; + V_I4(pvarRes) = r; + } + + return hres; + } } return IDispatchEx_InvokeEx(&window->event_target.dispex.IDispatchEx_iface, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 9d1737cc81f..7bc645e549f 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -1217,6 +1217,7 @@ ULONGLONG get_time_stamp(void) DECLSPEC_HIDDEN; enum timer_type { TIMER_TIMEOUT, TIMER_INTERVAL, + TIMER_ANIMATION_FRAME, }; HRESULT set_task_timer(HTMLInnerWindow*,LONG,enum timer_type,IDispatch*,LONG*) DECLSPEC_HIDDEN; diff --git a/dlls/mshtml/task.c b/dlls/mshtml/task.c index b7616058461..28cb88ab5f1 100644 --- a/dlls/mshtml/task.c +++ b/dlls/mshtml/task.c @@ -218,9 +218,20 @@ HRESULT clear_task_timer(HTMLInnerWindow *window, DWORD id) return S_OK; } -static void call_timer_disp(IDispatch *disp) +static const char *debugstr_timer_type(enum timer_type type) +{ + switch(type) { + case TIMER_TIMEOUT: return "timeout"; + case TIMER_INTERVAL: return "interval"; + case TIMER_ANIMATION_FRAME: return "animation-frame"; + DEFAULT_UNREACHABLE; + } +} + +static void call_timer_disp(IDispatch *disp, enum timer_type timer_type) { DISPPARAMS dp = {NULL, NULL, 0, 0}; + VARIANT timestamp; EXCEPINFO ei; VARIANT res; HRESULT hres; @@ -228,12 +239,19 @@ static void call_timer_disp(IDispatch *disp) V_VT(&res) = VT_EMPTY; memset(&ei, 0, sizeof(ei)); - TRACE(">>>\n"); + if(timer_type == TIMER_ANIMATION_FRAME) { + dp.cArgs = 1; + dp.rgvarg = ×tamp; + V_VT(×tamp) = VT_R8; + V_R8(×tamp) = get_time_stamp(); + } + + TRACE("%p %s >>>\n", disp, debugstr_timer_type(timer_type)); hres = IDispatch_Invoke(disp, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dp, &res, &ei, NULL); if(hres == S_OK) - TRACE("<<<\n"); + TRACE("%p %s <<<\n", disp, debugstr_timer_type(timer_type)); else - WARN("<<< %08x\n", hres); + WARN("%p %s <<< %08x\n", disp, debugstr_timer_type(timer_type), hres); VariantClear(&res); } @@ -241,6 +259,7 @@ static void call_timer_disp(IDispatch *disp) static LRESULT process_timer(void) { thread_data_t *thread_data; + enum timer_type timer_type; IDispatch *disp; DWORD tc; task_timer_t *timer=NULL, *last_timer; @@ -273,6 +292,7 @@ static LRESULT process_timer(void) disp = timer->disp; IDispatch_AddRef(disp); + timer_type = timer->type; if(timer->interval) { timer->time += timer->interval; @@ -281,7 +301,7 @@ static LRESULT process_timer(void) release_task_timer(thread_data->thread_hwnd, timer); } - call_timer_disp(disp); + call_timer_disp(disp, timer_type); IDispatch_Release(disp); }while(!list_empty(&thread_data->timer_list)); diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 35b4a001fed..7074b1f62f2 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -115,6 +115,7 @@ sync_test("window_props", function() { test_exposed("getSelection", v >= 9); test_exposed("onfocusout", v >= 9); test_exposed("getComputedStyle", v >= 9); + test_exposed("requestAnimationFrame", v >= 10); test_exposed("Set", v >= 11); if(v >= 9) /* FIXME: native exposes it in all compat modes */ test_exposed("performance", true); diff --git a/dlls/mshtml/tests/dom.js b/dlls/mshtml/tests/dom.js index f5e4f393b58..b30d1a8fbed 100644 --- a/dlls/mshtml/tests/dom.js +++ b/dlls/mshtml/tests/dom.js @@ -448,3 +448,13 @@ sync_test("elem_props", function() { elem.accessKey = "q"; ok(elem.accessKey === "q", "accessKey = " + elem.accessKey + " expected q"); }); + +async_test("animation_frame", function() { + var id = requestAnimationFrame(function(x) { + ok(this === window, "this != window"); + ok(typeof(x) === "number", "x = " + x); + ok(arguments.length === 1, "arguments.lenght = " + arguments.length); + next_test(); + }); + ok(typeof(id) === "number", "id = " + id); +});