You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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)