1 /* 2 * Copyright (C) 2006, 2007, 2009 Apple Computer, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 #include "config.h" 26 27 #include <windows.h> 28 29 #include "QTMovieWinTimer.h" 30 31 #include <wtf/Assertions.h> 32 33 // This file is used by the QuickTime access DLL. It copies some WebCore code 34 // which can't be used directly due to dependency issues. 35 36 // FIXME: Find a way to do timers that can manage <10ms resolution properly too. 37 38 static UINT_PTR timerID; 39 static void (*sharedTimerFiredFunction)(); 40 41 static HINSTANCE instanceHandle = 0; 42 43 static HWND timerWindowHandle = 0; 44 static UINT timerFiredMessage = 0; 45 static const LPCWSTR kTimerWindowClassName = L"TimerWindowClass"; 46 static bool processingCustomTimerMessage = false; 47 48 static LRESULT CALLBACK TimerWindowWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 49 { 50 if (message == timerFiredMessage) { 51 processingCustomTimerMessage = true; 52 sharedTimerFiredFunction(); 53 processingCustomTimerMessage = false; 54 } else if (message == WM_TIMER && wParam == timerID) { 55 stopSharedTimer(); 56 sharedTimerFiredFunction(); 57 } else 58 return DefWindowProc(hWnd, message, wParam, lParam); 59 return 0; 60 } 61 62 static void initializeOffScreenTimerWindow() 63 { 64 if (timerWindowHandle) 65 return; 66 67 WNDCLASSEX wcex; 68 memset(&wcex, 0, sizeof(WNDCLASSEX)); 69 wcex.cbSize = sizeof(WNDCLASSEX); 70 wcex.lpfnWndProc = TimerWindowWndProc; 71 wcex.hInstance = instanceHandle; 72 wcex.lpszClassName = kTimerWindowClassName; 73 RegisterClassEx(&wcex); 74 75 timerWindowHandle = CreateWindow(kTimerWindowClassName, 0, 0, 76 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, HWND_MESSAGE, 0, instanceHandle, 0); 77 timerFiredMessage = RegisterWindowMessage(L"com.apple.WebKit.TimerFired"); 78 } 79 80 void setSharedTimerFiredFunction(void (*f)()) 81 { 82 sharedTimerFiredFunction = f; 83 } 84 85 void setSharedTimerFireDelay(double interval) 86 { 87 ASSERT(sharedTimerFiredFunction); 88 89 unsigned intervalInMS; 90 if (interval < 0) 91 intervalInMS = 0; 92 else { 93 interval *= 1000; 94 if (interval > USER_TIMER_MAXIMUM) 95 intervalInMS = USER_TIMER_MAXIMUM; 96 else 97 intervalInMS = (unsigned)interval; 98 } 99 100 stopSharedTimer(); 101 initializeOffScreenTimerWindow(); 102 103 // We don't allow nested PostMessages, since the custom messages will effectively starve 104 // painting and user input. (Win32 has a tri-level queue with application messages > 105 // user input > WM_PAINT/WM_TIMER.) 106 // In addition, if the queue contains input events that have been there since the last call to 107 // GetQueueStatus, PeekMessage or GetMessage we favor timers. 108 if (intervalInMS < USER_TIMER_MINIMUM 109 && !processingCustomTimerMessage 110 && !LOWORD(::GetQueueStatus(QS_ALLINPUT))) { 111 // Windows SetTimer does not allow timeouts smaller than 10ms (USER_TIMER_MINIMUM) 112 PostMessage(timerWindowHandle, timerFiredMessage, 0, 0); 113 } else 114 timerID = SetTimer(timerWindowHandle, timerFiredMessage, intervalInMS, 0); 115 } 116 117 void stopSharedTimer() 118 { 119 if (timerID) { 120 KillTimer(timerWindowHandle, timerID); 121 timerID = 0; 122 } 123 } 124 125 void setSharedTimerInstanceHandle(HINSTANCE handle) 126 { 127 instanceHandle = handle; 128 } 129 130 double systemTime() 131 { 132 FILETIME ft; 133 GetSystemTimeAsFileTime(&ft); 134 ULARGE_INTEGER t; 135 memcpy(&t, &ft, sizeof(t)); 136 return t.QuadPart * 0.0000001 - 11644473600.0; 137 } 138