18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SharedTimer.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Page.h"
30231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "Settings.h"
31dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "WebCoreInstanceHandle.h"
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Widget.h"
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/Assertions.h>
34635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <wtf/CurrentTime.h>
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Note: wx headers set defines that affect the configuration of windows.h
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// so we must include the wx header first to get unicode versions of functions,
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// etc.
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if PLATFORM(WX)
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wx/wx.h>
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <windows.h>
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <mmsystem.h>
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
46635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#if PLATFORM(WIN)
47635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "PluginView.h"
48635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif
49635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// These aren't in winuser.h with the MSVS 2003 Platform SDK,
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// so use default values in that case.
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef USER_TIMER_MINIMUM
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define USER_TIMER_MINIMUM 0x0000000A
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef USER_TIMER_MAXIMUM
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define USER_TIMER_MAXIMUM 0x7FFFFFFF
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef QS_RAWINPUT
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QS_RAWINPUT         0x0400
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic UINT timerID;
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void (*sharedTimerFiredFunction)();
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic HWND timerWindowHandle = 0;
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic UINT timerFiredMessage = 0;
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic HANDLE timerQueue;
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic HANDLE timer;
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool highResTimerActive;
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool processingCustomTimerMessage = false;
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic LONG pendingTimers;
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst LPCWSTR kTimerWindowClassName = L"TimerWindowClass";
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst int timerResolution = 1; // To improve timer resolution, we call timeBeginPeriod/timeEndPeriod with this value to increase timer resolution to 1ms.
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst int highResolutionThresholdMsec = 16; // Only activate high-res timer for sub-16ms timers (Windows can fire timers at 16ms intervals without changing the system resolution).
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst int stopHighResTimerInMsec = 300; // Stop high-res timer after 0.3 seconds to lessen power consumption (we don't use a smaller time since oscillating between high and low resolution breaks timer accuracy on XP).
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectenum {
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    sharedTimerID = 1000,
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    endHighResTimerID = 1001,
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectLRESULT CALLBACK TimerWindowWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if PLATFORM(WIN)
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Windows Media Player has a modal message loop that will deliver messages
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // to us at inappropriate times and we will crash if we handle them when
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // they are delivered. We repost all messages so that we will get to handle
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // them once the modal loop exits.
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (PluginView::isCallingPlugin()) {
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        PostMessage(hWnd, message, wParam, lParam);
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (message == timerFiredMessage) {
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        InterlockedExchange(&pendingTimers, 0);
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        processingCustomTimerMessage = true;
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        sharedTimerFiredFunction();
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        processingCustomTimerMessage = false;
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else if (message == WM_TIMER) {
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (wParam == sharedTimerID) {
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            KillTimer(timerWindowHandle, sharedTimerID);
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            sharedTimerFiredFunction();
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else if (wParam == endHighResTimerID) {
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            KillTimer(timerWindowHandle, endHighResTimerID);
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            highResTimerActive = false;
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            timeEndPeriod(timerResolution);
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return DefWindowProc(hWnd, message, wParam, lParam);
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void initializeOffScreenTimerWindow()
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (timerWindowHandle)
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WNDCLASSEX wcex;
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(&wcex, 0, sizeof(WNDCLASSEX));
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    wcex.cbSize = sizeof(WNDCLASSEX);
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    wcex.lpfnWndProc    = TimerWindowWndProc;
129dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    wcex.hInstance      = WebCore::instanceHandle();
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    wcex.lpszClassName  = kTimerWindowClassName;
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RegisterClassEx(&wcex);
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    timerWindowHandle = CreateWindow(kTimerWindowClassName, 0, 0,
134dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, HWND_MESSAGE, 0, WebCore::instanceHandle(), 0);
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    timerFiredMessage = RegisterWindowMessage(L"com.apple.WebKit.TimerFired");
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid setSharedTimerFiredFunction(void (*f)())
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    sharedTimerFiredFunction = f;
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void NTAPI queueTimerProc(PVOID, BOOLEAN)
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (InterlockedIncrement(&pendingTimers) == 1)
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        PostMessage(timerWindowHandle, timerFiredMessage, 0, 0);
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid setSharedTimerFireTime(double fireTime)
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(sharedTimerFiredFunction);
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    double interval = fireTime - currentTime();
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned intervalInMS;
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (interval < 0)
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        intervalInMS = 0;
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else {
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        interval *= 1000;
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (interval > USER_TIMER_MAXIMUM)
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            intervalInMS = USER_TIMER_MAXIMUM;
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            intervalInMS = (unsigned)interval;
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    initializeOffScreenTimerWindow();
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool timerSet = false;
167231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
168231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (Settings::shouldUseHighResolutionTimers()) {
169231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (interval < highResolutionThresholdMsec) {
170231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (!highResTimerActive) {
171231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                highResTimerActive = true;
172231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                timeBeginPeriod(timerResolution);
173231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            }
174231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            SetTimer(timerWindowHandle, endHighResTimerID, stopHighResTimerInMsec, 0);
175231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
176231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
177231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        DWORD queueStatus = LOWORD(GetQueueStatus(QS_PAINT | QS_MOUSEBUTTON | QS_KEY | QS_RAWINPUT));
178231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
179231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // Win32 has a tri-level queue with application messages > user input > WM_PAINT/WM_TIMER.
180231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
181231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // If the queue doesn't contains input events, we use a higher priorty timer event posting mechanism.
182231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (!(queueStatus & (QS_MOUSEBUTTON | QS_KEY | QS_RAWINPUT))) {
183231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (intervalInMS < USER_TIMER_MINIMUM && !processingCustomTimerMessage && !(queueStatus & QS_PAINT)) {
184231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                // Call PostMessage immediately if the timer is already expired, unless a paint is pending.
185231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                // (we prioritize paints over timers)
186231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                if (InterlockedIncrement(&pendingTimers) == 1)
187231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                    PostMessage(timerWindowHandle, timerFiredMessage, 0, 0);
188231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                timerSet = true;
189231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            } else {
190231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                // Otherwise, delay the PostMessage via a CreateTimerQueueTimer
191231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                if (!timerQueue)
192231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                    timerQueue = CreateTimerQueue();
193231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                if (timer)
194231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                    DeleteTimerQueueTimer(timerQueue, timer, 0);
195231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                timerSet = CreateTimerQueueTimer(&timer, timerQueue, queueTimerProc, 0, intervalInMS, 0, WT_EXECUTEINTIMERTHREAD | WT_EXECUTEONLYONCE);
196231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            }
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (timerSet) {
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (timerID) {
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            KillTimer(timerWindowHandle, timerID);
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            timerID = 0;
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
205635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    } else {
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        timerID = SetTimer(timerWindowHandle, sharedTimerID, intervalInMS, 0);
207635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        timer = 0;
208635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid stopSharedTimer()
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
213635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (timerQueue && timer) {
214635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        DeleteTimerQueueTimer(timerQueue, timer, 0);
215635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        timer = 0;
216635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
217635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (timerID) {
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        KillTimer(timerWindowHandle, timerID);
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        timerID = 0;
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
225