diff --git a/utils/config.h b/utils/config.h index b05785390..8b6ce900a 100644 --- a/utils/config.h +++ b/utils/config.h @@ -50,7 +50,7 @@ char *strchrnul(const char *s, int c); #define HAVE_INETATON #if (defined(_WIN32)) #undef HAVE_INETATON -#include +#include #define EAFNOSUPPORT WSAEAFNOSUPPORT int inet_aton(const char *cp, struct in_addr *inp); #else diff --git a/utils/utils.h b/utils/utils.h index 84322156e..079708843 100644 --- a/utils/utils.h +++ b/utils/utils.h @@ -91,6 +91,31 @@ typedef struct #define nsmkdir(dir, mode) mkdir((dir)) #endif +#ifndef timeradd +#define timeradd(a, aa, result) \ + do { \ + (result)->tv_sec = (a)->tv_sec + (aa)->tv_sec; \ + (result)->tv_usec = (a)->tv_usec + (aa)->tv_usec; \ + if ((result)->tv_usec >= 1000000) { \ + ++(result)->tv_sec; \ + (result)->tv_usec -= 1000000; \ + } \ + } while (0) +#endif + +#ifndef timersub +#define timersub(a, aa, result) \ + do { \ + (result)->tv_sec = (a)->tv_sec - (aa)->tv_sec; \ + (result)->tv_usec = (a)->tv_usec - (aa)->tv_usec; \ + if ((result)->tv_usec < 0) { \ + --(result)->tv_sec; \ + (result)->tv_usec += 1000000; \ + } \ + } while (0) +#endif + + /** * Private-word-capable realloc() implementation which * behaves as most NS libraries expect in the face of diff --git a/windows/gui.c b/windows/gui.c index 18a67d355..35ab01b72 100644 --- a/windows/gui.c +++ b/windows/gui.c @@ -143,20 +143,40 @@ void gui_multitask(void) void gui_poll(bool active) { - MSG Msg; - if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE) != 0) { -/* if (!((current_gui == NULL) || - (TranslateAccelerator(current_gui->main, - current_gui->acceltable, &Msg)))) { - TranslateMessage(&Msg); - } -*/ - TranslateMessage(&Msg); - DispatchMessage(&Msg); + MSG Msg; /* message from system */ + BOOL bRet; /* message fetch result */ + int timeout; /* timeout in miliseconds */ + UINT timer_id = 0; + + /* run the scheduler and discover how long to wait for the next event */ + timeout = schedule_run(); + + /* if active set timeout so message is not waited for */ + if (active) + timeout = 0; + + if (timeout == 0) { + bRet = PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE); + } else { + if (timeout > 0) { + /* set up a timer to ensure we get woken */ + timer_id = SetTimer(NULL, 0, timeout, NULL); + } + + /* wait for a message */ + bRet = GetMessage(&Msg, NULL, 0, 0); + + /* if a timer was sucessfully created remove it */ + if (timer_id != 0) { + KillTimer(NULL, timer_id); + } } - schedule_run(); + if (bRet > 0) { + TranslateMessage(&Msg); + DispatchMessage(&Msg); + } } /* obtain gui window structure from windows window handle */ diff --git a/windows/schedule.c b/windows/schedule.c index 5414f6d56..a37a0e051 100644 --- a/windows/schedule.c +++ b/windows/schedule.c @@ -20,32 +20,20 @@ #include #include "desktop/browser.h" -#include "windows/schedule.h" +#include "framebuffer/schedule.h" #include "utils/log.h" +#include "utils/utils.h" /* linked list of scheduled callbacks */ static struct nscallback *schedule_list = NULL; -#ifndef timeradd -#define timeradd(a, aa, result) \ - do {\ - (result)->tv_sec = (a)->tv_sec + (aa)->tv_sec;\ - (result)->tv_usec = (a)->tv_usec + (aa)->tv_usec;\ - if ((result)->tv_usec >= 1000000)\ - {\ - ++(result)->tv_sec;\ - (result)->tv_usec -= 1000000;\ - }\ - } while (0) -#endif - /** * scheduled callback. */ struct nscallback { - struct nscallback *next; + struct nscallback *next; struct timeval tv; void (*callback)(void *p); void *p; @@ -57,7 +45,7 @@ struct nscallback * * \param tival interval before the callback should be made / cs * \param callback callback function - * \param p user parameter, passed to callback function + * \param p user parameter, passed to callback function * * The callback function will be called as soon as possible after t cs have * passed. @@ -68,8 +56,8 @@ void schedule(int cs_ival, void (*callback)(void *p), void *p) struct nscallback *nscb; struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = cs_ival * 10000; + tv.tv_sec = cs_ival / 100; /* cs to seconds */ + tv.tv_usec = (cs_ival % 100) * 10000; /* remainder to microseconds */ nscb = calloc(1, sizeof(struct nscallback)); @@ -81,128 +69,158 @@ void schedule(int cs_ival, void (*callback)(void *p), void *p) nscb->callback = callback; nscb->p = p; - /* add to list front */ - nscb->next = schedule_list; - schedule_list = nscb; + /* add to list front */ + nscb->next = schedule_list; + schedule_list = nscb; } /** * Unschedule a callback. * * \param callback callback function - * \param p user parameter, passed to callback function + * \param p user parameter, passed to callback function * * All scheduled callbacks matching both callback and p are removed. */ void schedule_remove(void (*callback)(void *p), void *p) { - struct nscallback *cur_nscb; - struct nscallback *prev_nscb; - struct nscallback *unlnk_nscb; + struct nscallback *cur_nscb; + struct nscallback *prev_nscb; + struct nscallback *unlnk_nscb; - if (schedule_list == NULL) - return; + if (schedule_list == NULL) + return; LOG(("removing %p, %p", callback, p)); - cur_nscb = schedule_list; - prev_nscb = NULL; + cur_nscb = schedule_list; + prev_nscb = NULL; - while (cur_nscb != NULL) { - if ((cur_nscb->callback == callback) && - (cur_nscb->p == p)) { - /* item to remove */ - - LOG(("callback entry %p removing %p(%p)", - cur_nscb, cur_nscb->callback, cur_nscb->p)); + while (cur_nscb != NULL) { + if ((cur_nscb->callback == callback) && + (cur_nscb->p == p)) { + /* item to remove */ - /* remove callback */ - unlnk_nscb = cur_nscb; - cur_nscb = unlnk_nscb->next; + LOG(("callback entry %p removing %p(%p)", + cur_nscb, cur_nscb->callback, cur_nscb->p)); - if (prev_nscb == NULL) { - schedule_list = cur_nscb; - } else { - prev_nscb->next = cur_nscb; - } - free (unlnk_nscb); - } else { - /* move to next element */ - prev_nscb = cur_nscb; - cur_nscb = prev_nscb->next; - } - } + /* remove callback */ + unlnk_nscb = cur_nscb; + cur_nscb = unlnk_nscb->next; + + if (prev_nscb == NULL) { + schedule_list = cur_nscb; + } else { + prev_nscb->next = cur_nscb; + } + free (unlnk_nscb); + } else { + /* move to next element */ + prev_nscb = cur_nscb; + cur_nscb = prev_nscb->next; + } + } } /** - * Process events up to current time. + * Process scheduled callbacks up to current time. + * + * @return The number of milliseconds untill the next scheduled event + * or -1 for no event. */ - -bool schedule_run(void) +int +schedule_run(void) { struct timeval tv; - struct nscallback *cur_nscb; - struct nscallback *prev_nscb; - struct nscallback *unlnk_nscb; + struct timeval nexttime; + struct timeval rettime; + struct nscallback *cur_nscb; + struct nscallback *prev_nscb; + struct nscallback *unlnk_nscb; - if (schedule_list == NULL) - return false; + if (schedule_list == NULL) + return -1; - cur_nscb = schedule_list; - prev_nscb = NULL; + /* reset enumeration to the start of the list */ + cur_nscb = schedule_list; + prev_nscb = NULL; + nexttime = cur_nscb->tv; gettimeofday(&tv, NULL); - while (cur_nscb != NULL) { - if (timercmp(&tv, &cur_nscb->tv, >)) { - /* scheduled time */ + while (cur_nscb != NULL) { + if (timercmp(&tv, &cur_nscb->tv, >)) { + /* scheduled time */ + + /* remove callback */ + unlnk_nscb = cur_nscb; + + if (prev_nscb == NULL) { + schedule_list = unlnk_nscb->next; + } else { + prev_nscb->next = unlnk_nscb->next; + } + + LOG(("callback entry %p running %p(%p)", + unlnk_nscb, unlnk_nscb->callback, unlnk_nscb->p)); + /* call callback */ + unlnk_nscb->callback(unlnk_nscb->p); + + free(unlnk_nscb); + + /* need to deal with callback modifying the list. */ + if (schedule_list == NULL) + return -1; /* no more callbacks scheduled */ - /* remove callback */ - unlnk_nscb = cur_nscb; - - if (prev_nscb == NULL) { - schedule_list = unlnk_nscb->next; - } else { - prev_nscb->next = unlnk_nscb->next; - } - - LOG(("callback entry %p running %p(%p)", - unlnk_nscb, unlnk_nscb->callback, unlnk_nscb->p)); - /* call callback */ - unlnk_nscb->callback(unlnk_nscb->p); - - free (unlnk_nscb); - - /* the callback might have modded the list, so start - * again + /* reset enumeration to the start of the list */ + cur_nscb = schedule_list; + prev_nscb = NULL; + nexttime = cur_nscb->tv; + } else { + /* if the time to the event is sooner than the + * currently recorded soonest event record it */ - cur_nscb = schedule_list; - prev_nscb = NULL; + if (timercmp(&nexttime, &cur_nscb->tv, >)) { + nexttime = cur_nscb->tv; + } + /* move to next element */ + prev_nscb = cur_nscb; + cur_nscb = prev_nscb->next; + } + } - } else { - /* move to next element */ - prev_nscb = cur_nscb; - cur_nscb = prev_nscb->next; - } - } - return true; + /* make rettime relative to now */ + timersub(&nexttime, &tv, &rettime); + +#if DEBUG_SCHEDULER + LOG(("returning time to next event as %ldms",(rettime.tv_sec * 1000) + (rettime.tv_usec / 1000))); +#endif + /* return next event time in milliseconds (24days max wait) */ + return (rettime.tv_sec * 1000) + (rettime.tv_usec / 1000); } void list_schedule(void) { struct timeval tv; - struct nscallback *cur_nscb; + struct nscallback *cur_nscb; gettimeofday(&tv, NULL); - LOG(("schedule list at %ld:%ld", tv.tv_sec, tv.tv_usec)); + LOG(("schedule list at %ld:%ld", tv.tv_sec, tv.tv_usec)); - cur_nscb = schedule_list; + cur_nscb = schedule_list; - while (cur_nscb != NULL) { - LOG(("Schedule %p at %ld:%ld", - cur_nscb, cur_nscb->tv.tv_sec, cur_nscb->tv.tv_usec)); - cur_nscb = cur_nscb->next; - } + while (cur_nscb != NULL) { + LOG(("Schedule %p at %ld:%ld", + cur_nscb, cur_nscb->tv.tv_sec, cur_nscb->tv.tv_usec)); + cur_nscb = cur_nscb->next; + } } + + +/* + * Local Variables: + * c-basic-offset:8 + * End: + */ diff --git a/windows/schedule.h b/windows/schedule.h index 77fb24283..2c9b55f82 100644 --- a/windows/schedule.h +++ b/windows/schedule.h @@ -1,6 +1,5 @@ /* * Copyright 2008 Vincent Sanders - * Copyright 2009 Mark Benjamin * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -17,10 +16,10 @@ * along with this program. If not, see . */ -#ifndef _NETSURF_WINDOWS_SCHEDULE_H_ -#define _NETSURF_WINDOWS_SCHEDULE_H_ +#ifndef FRAMEBUFFER_SCHEDULE_H +#define FRAMEBUFFER_SCHEDULE_H +int schedule_run(void); void list_schedule(void); -bool schedule_run(void); #endif