Module: wine Branch: master Commit: 788432af49d0ce9a63ab15397c5277c68ec574b2 URL: http://source.winehq.org/git/wine.git/?a=commit;h=788432af49d0ce9a63ab15397c...
Author: Jacek Caban jacek@codeweavers.com Date: Mon Apr 21 18:21:19 2008 +0200
mshtml: Added setTimeout implementation.
---
dlls/mshtml/htmlwindow.c | 15 ++++++- dlls/mshtml/mshtml_private.h | 2 + dlls/mshtml/task.c | 95 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index ce98f38..82b03e6 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -845,8 +845,19 @@ static HRESULT WINAPI HTMLWindow3_setTimeout(IHTMLWindow3 *iface, VARIANT *expre VARIANT *language, long *timerID) { HTMLWindow *This = HTMLWINDOW3_THIS(iface); - FIXME("(%p)->(%p(%d) %ld %p %p)\n", This, expression, V_VT(expression), msec, language, timerID); - return E_NOTIMPL; + + TRACE("(%p)->(%p(%d) %ld %p %p)\n", This, expression, V_VT(expression), msec, language, timerID); + + switch(V_VT(expression)) { + case VT_DISPATCH: + *timerID = set_task_timer(This->doc, msec, V_DISPATCH(expression)); + break; + + default: + FIXME("unimplemented vt=%d\n", V_VT(expression)); + } + + return S_OK; }
static HRESULT WINAPI HTMLWindow3_setInterval(IHTMLWindow3 *iface, VARIANT *expression, long msec, diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 8bca848..15320be 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -555,12 +555,14 @@ typedef struct { HWND thread_hwnd; task_t *task_queue_head; task_t *task_queue_tail; + struct list timer_list; } thread_data_t;
thread_data_t *get_thread_data(BOOL); HWND get_thread_hwnd(void); void push_task(task_t*); void remove_doc_tasks(const HTMLDocument*); +DWORD set_task_timer(HTMLDocument*,DWORD,IDispatch*);
HRESULT get_typeinfo(tid_t,ITypeInfo**); void release_typelib(void); diff --git a/dlls/mshtml/task.c b/dlls/mshtml/task.c index 3bb99cc..99e2573 100644 --- a/dlls/mshtml/task.c +++ b/dlls/mshtml/task.c @@ -36,6 +36,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
#define WM_PROCESSTASK 0x8008 +#define TIMER_ID 0x3000 + +typedef struct { + HTMLDocument *doc; + DWORD id; + DWORD time; + IDispatch *disp; + + struct list entry; +} task_timer_t;
void push_task(task_t *task) { @@ -66,11 +76,34 @@ static task_t *pop_task(void) return task; }
+static void release_task_timer(HWND thread_hwnd, task_timer_t *timer) +{ + list_remove(&timer->entry); + + KillTimer(thread_hwnd, timer->id); + IDispatch_Release(timer->disp); + + heap_free(timer); +} + void remove_doc_tasks(const HTMLDocument *doc) { thread_data_t *thread_data = get_thread_data(FALSE); + struct list *liter, *ltmp; + task_timer_t *timer; task_t *iter, *tmp;
+ LIST_FOR_EACH_SAFE(liter, ltmp, &thread_data->timer_list) { + timer = LIST_ENTRY(liter, task_timer_t, entry); + if(timer->doc == doc) + release_task_timer(thread_data->thread_hwnd, timer); + } + + if(!list_empty(&thread_data->timer_list)) { + timer = LIST_ENTRY(list_head(&thread_data->timer_list), task_timer_t, entry); + SetTimer(thread_data->thread_hwnd, TIMER_ID, timer->time - GetTickCount(), NULL); + } + if(!thread_data) return;
@@ -90,6 +123,43 @@ void remove_doc_tasks(const HTMLDocument *doc) } }
+DWORD set_task_timer(HTMLDocument *doc, DWORD msec, IDispatch *disp) +{ + thread_data_t *thread_data = get_thread_data(TRUE); + task_timer_t *timer; + DWORD tc = GetTickCount(); + + static DWORD id_cnt = 0x20000000; + + timer = heap_alloc(sizeof(task_timer_t)); + timer->id = id_cnt++; + timer->doc = doc; + timer->time = tc + msec; + + IDispatch_AddRef(disp); + timer->disp = disp; + + if(list_empty(&thread_data->timer_list) + || LIST_ENTRY(list_head(&thread_data->timer_list), task_timer_t, entry)->time > timer->time) { + + list_add_head(&thread_data->timer_list, &timer->entry); + SetTimer(thread_data->thread_hwnd, TIMER_ID, msec, NULL); + }else { + task_timer_t *iter; + + LIST_FOR_EACH_ENTRY(iter, &thread_data->timer_list, task_timer_t, entry) { + if(iter->time > timer->time) { + list_add_tail(&iter->entry, &timer->entry); + return timer->id; + } + } + + list_add_tail(&thread_data->timer_list, &timer->entry); + } + + return timer->id; +} + static void set_downloading(HTMLDocument *doc) { IOleCommandTarget *olecmd; @@ -238,6 +308,28 @@ static void process_task(task_t *task) } }
+static LRESULT process_timer(void) +{ + thread_data_t *thread_data = get_thread_data(TRUE); + DWORD tc = GetTickCount(); + task_timer_t *timer; + + while(!list_empty(&thread_data->timer_list)) { + timer = LIST_ENTRY(list_head(&thread_data->timer_list), task_timer_t, entry); + if(timer->time > tc) { + SetTimer(thread_data->thread_hwnd, TIMER_ID, timer->time-tc, NULL); + return 0; + } + + list_remove(&timer->entry); + call_disp_func(timer->doc, timer->disp); + release_task_timer(thread_data->thread_hwnd, timer); + } + + KillTimer(thread_data->thread_hwnd, TIMER_ID); + return 0; +} + static LRESULT WINAPI hidden_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { @@ -252,6 +344,8 @@ static LRESULT WINAPI hidden_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa }
return 0; + case WM_TIMER: + return process_timer(); }
if(msg > WM_USER) @@ -307,6 +401,7 @@ thread_data_t *get_thread_data(BOOL create) if(!thread_data && create) { thread_data = heap_alloc_zero(sizeof(thread_data_t)); TlsSetValue(mshtml_tls, thread_data); + list_init(&thread_data->timer_list); }
return thread_data;