107 lines
4.3 KiB
Python
107 lines
4.3 KiB
Python
|
# ----------------------------------------------------------------------------
|
||
|
# pyglet
|
||
|
# Copyright (c) 2006-2008 Alex Holkner
|
||
|
# All rights reserved.
|
||
|
#
|
||
|
# Redistribution and use in source and binary forms, with or without
|
||
|
# modification, are permitted provided that the following conditions
|
||
|
# are met:
|
||
|
#
|
||
|
# * Redistributions of source code must retain the above copyright
|
||
|
# notice, this list of conditions and the following disclaimer.
|
||
|
# * Redistributions in binary form must reproduce the above copyright
|
||
|
# notice, this list of conditions and the following disclaimer in
|
||
|
# the documentation and/or other materials provided with the
|
||
|
# distribution.
|
||
|
# * Neither the name of pyglet nor the names of its
|
||
|
# contributors may be used to endorse or promote products
|
||
|
# derived from this software without specific prior written
|
||
|
# permission.
|
||
|
#
|
||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||
|
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||
|
# ----------------------------------------------------------------------------
|
||
|
# $Id:$
|
||
|
|
||
|
__docformat__ = 'restructuredtext'
|
||
|
__version__ = '$Id: $'
|
||
|
|
||
|
import ctypes
|
||
|
import time
|
||
|
|
||
|
from pyglet.app import windows, BaseEventLoop
|
||
|
from pyglet.window.win32 import _user32, types, constants
|
||
|
|
||
|
class Win32EventLoop(BaseEventLoop):
|
||
|
def run(self):
|
||
|
self._setup()
|
||
|
|
||
|
self._timer_proc = types.TIMERPROC(self._timer_func)
|
||
|
self._timer = timer = _user32.SetTimer(0, 0, 0, self._timer_proc)
|
||
|
self._polling = False
|
||
|
self._allow_polling = True
|
||
|
msg = types.MSG()
|
||
|
|
||
|
self.dispatch_event('on_enter')
|
||
|
|
||
|
while not self.has_exit:
|
||
|
if self._polling:
|
||
|
while _user32.PeekMessageW(ctypes.byref(msg),
|
||
|
0, 0, 0, constants.PM_REMOVE):
|
||
|
_user32.TranslateMessage(ctypes.byref(msg))
|
||
|
_user32.DispatchMessageW(ctypes.byref(msg))
|
||
|
self._timer_func(0, 0, timer, 0)
|
||
|
else:
|
||
|
_user32.GetMessageW(ctypes.byref(msg), 0, 0, 0)
|
||
|
_user32.TranslateMessage(ctypes.byref(msg))
|
||
|
_user32.DispatchMessageW(ctypes.byref(msg))
|
||
|
|
||
|
# Manual idle event
|
||
|
msg_types = \
|
||
|
_user32.GetQueueStatus(constants.QS_ALLINPUT) & 0xffff0000
|
||
|
if (msg.message != constants.WM_TIMER and
|
||
|
not msg_types & ~(constants.QS_TIMER<<16)):
|
||
|
self._timer_func(0, 0, timer, 0)
|
||
|
|
||
|
self.dispatch_event('on_exit')
|
||
|
|
||
|
def _idle_chance(self):
|
||
|
if (self._next_idle_time is not None and
|
||
|
self._next_idle_time <= time.time()):
|
||
|
self._timer_func(0, 0, self._timer, 0)
|
||
|
|
||
|
def _timer_func(self, hwnd, msg, timer, t):
|
||
|
sleep_time = self.idle()
|
||
|
|
||
|
if sleep_time is None:
|
||
|
# Block indefinitely
|
||
|
millis = constants.USER_TIMER_MAXIMUM
|
||
|
self._next_idle_time = None
|
||
|
self._polling = False
|
||
|
_user32.SetTimer(0, timer, millis, self._timer_proc)
|
||
|
elif sleep_time < 0.01 and self._allow_polling:
|
||
|
# Degenerate to polling
|
||
|
millis = constants.USER_TIMER_MAXIMUM
|
||
|
self._next_idle_time = 0.
|
||
|
if not self._polling:
|
||
|
self._polling = True
|
||
|
_user32.SetTimer(0, timer, millis, self._timer_proc)
|
||
|
else:
|
||
|
# Block until timer
|
||
|
# XXX hack to avoid oversleep; needs to be api
|
||
|
sleep_time = max(sleep_time - 0.01, 0)
|
||
|
millis = int(sleep_time * 1000)
|
||
|
self._next_idle_time = time.time() + sleep_time
|
||
|
self._polling = False
|
||
|
_user32.SetTimer(0, timer, millis, self._timer_proc)
|