[PATCH 3/5] mshtml: Implement window.cancelAnimationFrame.

Gabriel Ivăncescu gabrielopcode at gmail.com
Thu May 19 13:06:37 CDT 2022


Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
 dlls/mshtml/htmlwindow.c             | 15 +++++++++++++++
 dlls/mshtml/mshtml_private.h         |  1 +
 dlls/mshtml/mshtml_private_iface.idl |  4 +++-
 dlls/mshtml/task.c                   | 23 ++++++++++++++++++++++-
 dlls/mshtml/tests/documentmode.js    |  1 +
 dlls/mshtml/tests/dom.js             | 10 +++++++++-
 6 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c
index ecd530d..235e29a 100644
--- a/dlls/mshtml/htmlwindow.c
+++ b/dlls/mshtml/htmlwindow.c
@@ -3152,6 +3152,20 @@ static HRESULT WINAPI window_private_requestAnimationFrame(IWineHTMLWindowPrivat
     return hres;
 }
 
+static HRESULT WINAPI window_private_cancelAnimationFrame(IWineHTMLWindowPrivate *iface, VARIANT timer_id)
+{
+    HTMLWindow *This = impl_from_IWineHTMLWindowPrivateVtbl(iface);
+    HRESULT hres;
+
+    TRACE("iface %p, timer_id %s\n", iface, debugstr_variant(&timer_id));
+
+    hres = VariantChangeType(&timer_id, &timer_id, 0, VT_I4);
+    if(SUCCEEDED(hres))
+        clear_animation_timer(This->inner_window, V_I4(&timer_id));
+
+    return S_OK;
+}
+
 static HRESULT WINAPI window_private_get_console(IWineHTMLWindowPrivate *iface, IDispatch **console)
 {
     HTMLWindow *This = impl_from_IWineHTMLWindowPrivateVtbl(iface);
@@ -3176,6 +3190,7 @@ static const IWineHTMLWindowPrivateVtbl WineHTMLWindowPrivateVtbl = {
     window_private_GetIDsOfNames,
     window_private_Invoke,
     window_private_requestAnimationFrame,
+    window_private_cancelAnimationFrame,
     window_private_get_console,
 };
 
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index a94f1be..930ab3b 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -1247,6 +1247,7 @@ enum timer_type {
 
 HRESULT set_task_timer(HTMLInnerWindow*,LONG,enum timer_type,IDispatch*,LONG*) DECLSPEC_HIDDEN;
 HRESULT clear_task_timer(HTMLInnerWindow*,DWORD) DECLSPEC_HIDDEN;
+HRESULT clear_animation_timer(HTMLInnerWindow*,DWORD) DECLSPEC_HIDDEN;
 
 BOOL parse_compat_version(const WCHAR*,compat_mode_t*) DECLSPEC_HIDDEN;
 
diff --git a/dlls/mshtml/mshtml_private_iface.idl b/dlls/mshtml/mshtml_private_iface.idl
index b9039c9..a273e33 100644
--- a/dlls/mshtml/mshtml_private_iface.idl
+++ b/dlls/mshtml/mshtml_private_iface.idl
@@ -87,7 +87,9 @@ interface IWineHTMLWindowPrivate : IDispatch
 {
     [id(50)]
     HRESULT requestAnimationFrame([in] VARIANT *expr, [retval, out] VARIANT *timer_id);
-    [propget, id(51)]
+    [id(51)]
+    HRESULT cancelAnimationFrame([in] VARIANT timer_id);
+    [propget, id(52)]
     HRESULT console([retval, out] IDispatch **console);
 }
 
diff --git a/dlls/mshtml/task.c b/dlls/mshtml/task.c
index 088742e..1bb761e 100644
--- a/dlls/mshtml/task.c
+++ b/dlls/mshtml/task.c
@@ -208,7 +208,8 @@ HRESULT clear_task_timer(HTMLInnerWindow *window, DWORD id)
 
     LIST_FOR_EACH_ENTRY(iter, &thread_data->timer_list, task_timer_t, entry) {
         if(iter->id == id && iter->window == window) {
-            release_task_timer(thread_data->thread_hwnd, iter);
+            if(iter->type != TIMER_ANIMATION_FRAME)
+                release_task_timer(thread_data->thread_hwnd, iter);
             return S_OK;
         }
     }
@@ -217,6 +218,26 @@ HRESULT clear_task_timer(HTMLInnerWindow *window, DWORD id)
     return S_OK;
 }
 
+HRESULT clear_animation_timer(HTMLInnerWindow *window, DWORD id)
+{
+    thread_data_t *thread_data = get_thread_data(FALSE);
+    task_timer_t *iter;
+
+    if(!thread_data)
+        return S_OK;
+
+    LIST_FOR_EACH_ENTRY(iter, &thread_data->timer_list, task_timer_t, entry) {
+        if(iter->id == id && iter->window == window) {
+            if(iter->type == TIMER_ANIMATION_FRAME)
+                release_task_timer(thread_data->thread_hwnd, iter);
+            return S_OK;
+        }
+    }
+
+    WARN("timer not found\n");
+    return S_OK;
+}
+
 static const char *debugstr_timer_type(enum timer_type type)
 {
     switch(type) {
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js
index eeeb1c8..5f10447 100644
--- a/dlls/mshtml/tests/documentmode.js
+++ b/dlls/mshtml/tests/documentmode.js
@@ -357,6 +357,7 @@ sync_test("window_props", function() {
     test_exposed("getSelection", v >= 9);
     test_exposed("onfocusout", v >= 9);
     test_exposed("getComputedStyle", v >= 9);
+    test_exposed("cancelAnimationFrame", v >= 10);
     test_exposed("requestAnimationFrame", v >= 10);
     test_exposed("Map", v >= 11);
     test_exposed("Set", v >= 11);
diff --git a/dlls/mshtml/tests/dom.js b/dlls/mshtml/tests/dom.js
index ed5f72c..3939dd9 100644
--- a/dlls/mshtml/tests/dom.js
+++ b/dlls/mshtml/tests/dom.js
@@ -494,13 +494,21 @@ sync_test("elem_props", function() {
 });
 
 async_test("animation_frame", function() {
-    var id = requestAnimationFrame(function(x) {
+    var id = requestAnimationFrame(function(x) { ok(false, "request was supposed to be cancelled"); });
+    id = cancelAnimationFrame(id);
+    ok(id === undefined, "cancelAnimationFrame returned " + id);
+
+    id = requestAnimationFrame(function(x) {
         ok(this === window, "this != window");
         ok(typeof(x) === "number", "x = " + x);
         ok(arguments.length === 1, "arguments.length = " + arguments.length);
         next_test();
     });
+    cancelAnimationFrame(0);
+    clearInterval(id);
+    clearTimeout(id);
     ok(typeof(id) === "number", "id = " + id);
+    ok(id !== 0, "id = 0");
 });
 
 sync_test("title", function() {
-- 
2.34.1




More information about the wine-devel mailing list