Jacek Caban : mshtml: Added setTimeout implementation.
Alexandre Julliard
julliard at winehq.org
Tue Apr 22 06:46:59 CDT 2008
Module: wine
Branch: master
Commit: 788432af49d0ce9a63ab15397c5277c68ec574b2
URL: http://source.winehq.org/git/wine.git/?a=commit;h=788432af49d0ce9a63ab15397c5277c68ec574b2
Author: Jacek Caban <jacek at 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;
More information about the wine-cvs
mailing list