##// END OF EJS Templates
Merge branch 'pyglet' by Nicolas Rougier, with minor fixes....
Fernando Perez -
r4805:7511bc62 merge
parent child Browse files
Show More
@@ -0,0 +1,115 b''
1 # encoding: utf-8
2 """
3 Enable pyglet to be used interacive by setting PyOS_InputHook.
4
5 Authors
6 -------
7
8 * Nicolas P. Rougier
9 * Fernando Perez
10 """
11
12 #-----------------------------------------------------------------------------
13 # Copyright (C) 2008-2009 The IPython Development Team
14 #
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
18
19 #-----------------------------------------------------------------------------
20 # Imports
21 #-----------------------------------------------------------------------------
22
23 import os
24 import signal
25 import sys
26 import time
27 from timeit import default_timer as clock
28 import pyglet
29
30 #-----------------------------------------------------------------------------
31 # Platform-dependent imports and functions
32 #-----------------------------------------------------------------------------
33
34 if os.name == 'posix':
35 import select
36
37 def stdin_ready():
38 infds, outfds, erfds = select.select([sys.stdin],[],[],0)
39 if infds:
40 return True
41 else:
42 return False
43
44 elif sys.platform == 'win32':
45 import msvcrt
46
47 def stdin_ready():
48 return msvcrt.kbhit()
49
50
51 # On linux only, window.flip() has a bug that causes an AttributeError on
52 # window close. For details, see:
53 # http://groups.google.com/group/pyglet-users/browse_thread/thread/47c1aab9aa4a3d23/c22f9e819826799e?#c22f9e819826799e
54
55 if sys.platform.startswith('linux'):
56 def flip(window):
57 try:
58 window.flip()
59 except AttributeError:
60 pass
61 else:
62 def flip(window):
63 window.flip()
64
65 #-----------------------------------------------------------------------------
66 # Code
67 #-----------------------------------------------------------------------------
68
69 def inputhook_pyglet():
70 """Run the pyglet event loop by processing pending events only.
71
72 This keeps processing pending events until stdin is ready. After
73 processing all pending events, a call to time.sleep is inserted. This is
74 needed, otherwise, CPU usage is at 100%. This sleep time should be tuned
75 though for best performance.
76 """
77 # We need to protect against a user pressing Control-C when IPython is
78 # idle and this is running. We trap KeyboardInterrupt and pass.
79 try:
80 t = clock()
81 while not stdin_ready():
82 pyglet.clock.tick()
83 for window in pyglet.app.windows:
84 window.switch_to()
85 window.dispatch_events()
86 window.dispatch_event('on_draw')
87 flip(window)
88
89 # We need to sleep at this point to keep the idle CPU load
90 # low. However, if sleep to long, GUI response is poor. As
91 # a compromise, we watch how often GUI events are being processed
92 # and switch between a short and long sleep time. Here are some
93 # stats useful in helping to tune this.
94 # time CPU load
95 # 0.001 13%
96 # 0.005 3%
97 # 0.01 1.5%
98 # 0.05 0.5%
99 used_time = clock() - t
100 if used_time > 5*60.0:
101 # print 'Sleep for 5 s' # dbg
102 time.sleep(5.0)
103 elif used_time > 10.0:
104 # print 'Sleep for 1 s' # dbg
105 time.sleep(1.0)
106 elif used_time > 0.1:
107 # Few GUI events coming in, so we can sleep longer
108 # print 'Sleep for 0.05 s' # dbg
109 time.sleep(0.05)
110 else:
111 # Many GUI events coming in, so sleep only very little
112 time.sleep(0.001)
113 except KeyboardInterrupt:
114 pass
115 return 0
@@ -0,0 +1,33 b''
1 #!/usr/bin/env python
2 """Simple pyglet example to manually test event loop integration.
3
4 This is meant to run tests manually in ipython as:
5
6 In [5]: %gui pyglet
7
8 In [6]: %run gui-pyglet.py
9 """
10
11 import pyglet
12
13
14 window = pyglet.window.Window()
15 label = pyglet.text.Label('Hello, world',
16 font_name='Times New Roman',
17 font_size=36,
18 x=window.width//2, y=window.height//2,
19 anchor_x='center', anchor_y='center')
20 @window.event
21 def on_close():
22 window.close()
23
24 @window.event
25 def on_draw():
26 window.clear()
27 label.draw()
28
29 try:
30 from IPython.lib.inputhook import enable_pyglet
31 enable_pyglet()
32 except ImportError:
33 pyglet.app.run()
@@ -229,8 +229,8 b' class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):'
229 229 self.load_config_file = lambda *a, **kw: None
230 230 self.ignore_old_config=True
231 231
232 gui = CaselessStrEnum(('qt','wx','gtk'), config=True,
233 help="Enable GUI event loop integration ('qt', 'wx', 'gtk')."
232 gui = CaselessStrEnum(('qt','wx','gtk', 'pyglet'), config=True,
233 help="Enable GUI event loop integration ('qt', 'wx', 'gtk', 'pyglet')."
234 234 )
235 235 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'auto'],
236 236 config=True,
@@ -19,6 +19,7 b' from IPython.lib.inputhook import ('
19 19 enable_gtk, disable_gtk,
20 20 enable_qt4, disable_qt4,
21 21 enable_tk, disable_tk,
22 enable_pyglet, disable_pyglet,
22 23 set_inputhook, clear_inputhook,
23 24 current_gui
24 25 )
@@ -29,6 +29,7 b" GUI_QT4 = 'qt4'"
29 29 GUI_GTK = 'gtk'
30 30 GUI_TK = 'tk'
31 31 GUI_OSX = 'osx'
32 GUI_PYGLET = 'pyglet'
32 33
33 34 #-----------------------------------------------------------------------------
34 35 # Utility classes
@@ -283,6 +284,39 b' class InputHookManager(object):'
283 284 """
284 285 self.clear_inputhook()
285 286
287
288
289 def enable_pyglet(self, app=None):
290 """Enable event loop integration with pyglet.
291
292 Parameters
293 ----------
294 app : ignored
295 Ignored, it's only a placeholder to keep the call signature of all
296 gui activation methods consistent, which simplifies the logic of
297 supporting magics.
298
299 Notes
300 -----
301 This methods sets the ``PyOS_InputHook`` for pyglet, which allows
302 pyglet to integrate with terminal based applications like
303 IPython.
304
305 """
306 import pyglet
307 from IPython.lib.inputhookpyglet import inputhook_pyglet
308 self.set_inputhook(inputhook_pyglet)
309 self._current_gui = GUI_PYGLET
310 return app
311
312 def disable_pyglet(self):
313 """Disable event loop integration with pyglet.
314
315 This merely sets PyOS_InputHook to NULL.
316 """
317 self.clear_inputhook()
318
319
286 320 def current_gui(self):
287 321 """Return a string indicating the currently active GUI or None."""
288 322 return self._current_gui
@@ -297,6 +331,8 b' enable_gtk = inputhook_manager.enable_gtk'
297 331 disable_gtk = inputhook_manager.disable_gtk
298 332 enable_tk = inputhook_manager.enable_tk
299 333 disable_tk = inputhook_manager.disable_tk
334 enable_pyglet = inputhook_manager.enable_pyglet
335 disable_pyglet = inputhook_manager.disable_pyglet
300 336 clear_inputhook = inputhook_manager.clear_inputhook
301 337 set_inputhook = inputhook_manager.set_inputhook
302 338 current_gui = inputhook_manager.current_gui
@@ -334,7 +370,9 b' def enable_gui(gui=None, app=None):'
334 370 GUI_GTK: enable_gtk,
335 371 GUI_WX: enable_wx,
336 372 GUI_QT: enable_qt4, # qt3 not supported
337 GUI_QT4: enable_qt4 }
373 GUI_QT4: enable_qt4,
374 GUI_PYGLET: enable_pyglet,
375 }
338 376 try:
339 377 gui_hook = guis[gui]
340 378 except KeyError:
General Comments 0
You need to be logged in to leave comments. Login now