##// END OF EJS Templates
Removed the timer callback in favor of the idle one and re-use wx waiting time after an event is processed. This make things more reactive. Also, the created window is now made insivisible and is not supposed to be ever show or detroyed. Finally, fixed the bug in window closing for linux platform using the glutSetOption available on Freeglut.
Nicolas Rougier -
Show More
@@ -0,0 +1,176 b''
1 # coding: utf-8
2 """
3 GLUT Inputhook support functions
4 """
5
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2009 The IPython Development Team
8 #
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
12
13 # GLUT is quite an old library and it is difficult to ensure proper
14 # integration within IPython since original GLUT does not allow to handle
15 # events one by one. Instead, it requires for the mainloop to be entered
16 # and never returned (there is not even a function to exit he
17 # mainloop). Fortunately, there are alternatives such as freeglut
18 # (available for linux and windows) and the OSX implementation gives
19 # access to a glutCheckLoop() function that blocks itself until a new
20 # event is received. This means we have to setup the idle callback to
21 # ensure we got at least one event that will unblock the function.
22 #
23 # Furthermore, it is not possible to install these handlers without a window
24 # being first created. We choose to make this window invisible. This means that
25 # display mode options are set at this level and user won't be able to change
26 # them later without modifying the code. This should probably be made available
27 # via IPython options system.
28
29 #-----------------------------------------------------------------------------
30 # Imports
31 #-----------------------------------------------------------------------------
32 import os
33 import sys
34 import time
35 import signal
36 import OpenGL
37 import OpenGL.GLUT as glut
38 import OpenGL.platform as platform
39 from timeit import default_timer as clock
40
41 #-----------------------------------------------------------------------------
42 # Constants
43 #-----------------------------------------------------------------------------
44
45 # Frame per second : 60
46 # Should probably be an IPython option
47 glut_fps = 60
48
49
50 # Display mode : double buffeed + rgba + depth
51 # Should probably be an IPython option
52 glut_display_mode = (glut.GLUT_DOUBLE |
53 glut.GLUT_RGBA |
54 glut.GLUT_DEPTH)
55
56 glutMainLoopEvent = None
57 if sys.platform == 'darwin':
58 try:
59 glutCheckLoop = platform.createBaseFunction(
60 'glutCheckLoop', dll=platform.GLUT, resultType=None,
61 argTypes=[],
62 doc='glutCheckLoop( ) -> None',
63 argNames=(),
64 )
65 except AttributeError:
66 raise RuntimeError(
67 '''Your glut implementation does not allow interactive sessions'''
68 '''Consider installing freeglut.''')
69 glutMainLoopEvent = glutCheckLoop
70 elif glut.HAVE_FREEGLUT:
71 glutMainLoopEvent = glut.glutMainLoopEvent
72 else:
73 raise RuntimeError(
74 '''Your glut implementation does not allow interactive sessions. '''
75 '''Consider installing freeglut.''')
76
77
78 #-----------------------------------------------------------------------------
79 # Platform-dependent imports and functions
80 #-----------------------------------------------------------------------------
81
82 if os.name == 'posix':
83 import select
84
85 def stdin_ready():
86 infds, outfds, erfds = select.select([sys.stdin],[],[],0)
87 if infds:
88 return True
89 else:
90 return False
91
92 elif sys.platform == 'win32':
93 import msvcrt
94
95 def stdin_ready():
96 return msvcrt.kbhit()
97
98 #-----------------------------------------------------------------------------
99 # Callback functions
100 #-----------------------------------------------------------------------------
101
102 def glut_display():
103 # Dummy display function
104 pass
105
106 def glut_idle():
107 # Dummy idle function
108 pass
109
110 def glut_close():
111 # Close function only hides the current window
112 glut.glutHideWindow()
113 glutMainLoopEvent()
114
115 def glut_int_handler(signum, frame):
116 # Catch sigint and print the defautl message
117 signal.signal(signal.SIGINT, signal.default_int_handler)
118 print '\nKeyboardInterrupt'
119 # Need to reprint the prompt at this stage
120
121
122
123 #-----------------------------------------------------------------------------
124 # Code
125 #-----------------------------------------------------------------------------
126 def inputhook_glut():
127 """Run the pyglet event loop by processing pending events only.
128
129 This keeps processing pending events until stdin is ready. After
130 processing all pending events, a call to time.sleep is inserted. This is
131 needed, otherwise, CPU usage is at 100%. This sleep time should be tuned
132 though for best performance.
133 """
134 # We need to protect against a user pressing Control-C when IPython is
135 # idle and this is running. We trap KeyboardInterrupt and pass.
136
137 signal.signal(signal.SIGINT, glut_int_handler)
138
139 try:
140 t = clock()
141
142 # Make sure the default window is set after a window has been closed
143 if glut.glutGetWindow() == 0:
144 glut.glutSetWindow( 1 )
145 glutMainLoopEvent()
146 return 0
147
148 while not stdin_ready():
149 glutMainLoopEvent()
150 # We need to sleep at this point to keep the idle CPU load
151 # low. However, if sleep to long, GUI response is poor. As
152 # a compromise, we watch how often GUI events are being processed
153 # and switch between a short and long sleep time. Here are some
154 # stats useful in helping to tune this.
155 # time CPU load
156 # 0.001 13%
157 # 0.005 3%
158 # 0.01 1.5%
159 # 0.05 0.5%
160 used_time = clock() - t
161 if used_time > 5*60.0:
162 # print 'Sleep for 5 s' # dbg
163 time.sleep(5.0)
164 elif used_time > 10.0:
165 # print 'Sleep for 1 s' # dbg
166 time.sleep(1.0)
167 elif used_time > 0.1:
168 # Few GUI events coming in, so we can sleep longer
169 # print 'Sleep for 0.05 s' # dbg
170 time.sleep(0.05)
171 else:
172 # Many GUI events coming in, so sleep only very little
173 time.sleep(0.001)
174 except KeyboardInterrupt:
175 pass
176 return 0
@@ -311,20 +311,26 b' class InputHookManager(object):'
311 glut.GLUT_DOUBLE | glut.GLUT_RGBA | glut.GLUT_DEPTH
311 glut.GLUT_DOUBLE | glut.GLUT_RGBA | glut.GLUT_DEPTH
312 """
312 """
313
313
314 from glut_support import *
314 import OpenGL.GLUT as glut
315 from IPython.lib.inputhookglut import *
315
316
316 if not self._apps.has_key(GUI_GLUT):
317 if not self._apps.has_key(GUI_GLUT):
317 glut.glutInit(sys.argv)
318 glut.glutInit(sys.argv)
318 glut.glutInitDisplayMode(glut_display_mode)
319 glut.glutInitDisplayMode(glut_display_mode)
320 # This is specific to freeglut
321 if bool(glut.glutSetOption):
322 glut.glutSetOption(glut.GLUT_ACTION_ON_WINDOW_CLOSE,
323 glut.GLUT_ACTION_GLUTMAINLOOP_RETURNS)
319 glut.glutCreateWindow(sys.argv[0])
324 glut.glutCreateWindow(sys.argv[0])
325 glut.glutReshapeWindow( 1, 1 )
320 glut.glutHideWindow()
326 glut.glutHideWindow()
321 glut.glutWMCloseFunc(glut_close)
327 glut.glutWMCloseFunc(glut_close)
322 glut.glutDisplayFunc(glut_display)
328 glut.glutDisplayFunc(glut_display)
323 glut.glutTimerFunc( int(1000.0/glut_fps), glut_timer, glut_fps)
329 glut.glutIdleFunc( glut_idle)
324 else:
330 else:
325 glut.glutWMCloseFunc(glut_close)
331 glut.glutWMCloseFunc(glut_close)
326 glut.glutDisplayFunc(glut_display)
332 glut.glutDisplayFunc(glut_display)
327 glut.glutTimerFunc( int(1000.0/glut_fps), glut_timer, glut_fps)
333 glut.glutIdleFunc( glut_idle)
328 self.set_inputhook(inputhook_glut)
334 self.set_inputhook(inputhook_glut)
329 self._current_gui = GUI_GLUT
335 self._current_gui = GUI_GLUT
330 self._apps[GUI_GLUT] = True
336 self._apps[GUI_GLUT] = True
@@ -15,6 +15,9 b' import sys'
15 import OpenGL.GL as gl
15 import OpenGL.GL as gl
16 import OpenGL.GLUT as glut
16 import OpenGL.GLUT as glut
17
17
18 def close():
19 glut.glutDestroyWindow(glut.glutGetWindow())
20
18 def display():
21 def display():
19 gl.glClear (gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
22 gl.glClear (gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
20 glut.glutSwapBuffers()
23 glut.glutSwapBuffers()
@@ -26,20 +29,22 b' def resize(width,height):'
26 gl.glOrtho(0, width, 0, height+4, -1, 1)
29 gl.glOrtho(0, width, 0, height+4, -1, 1)
27 gl.glMatrixMode(gl.GL_MODELVIEW)
30 gl.glMatrixMode(gl.GL_MODELVIEW)
28
31
29
30 if glut.glutGetWindow() > 0:
32 if glut.glutGetWindow() > 0:
31 interactive = True
33 interactive = True
32 glut.glutInit(sys.argv)
34 glut.glutInit(sys.argv)
33 glut.glutInitDisplayMode(glut.GLUT_DOUBLE |
35 glut.glutInitDisplayMode(glut.GLUT_DOUBLE |
34 glut.GLUT_RGBA |
36 glut.GLUT_RGBA |
35 glut.GLUT_DEPTH)
37 glut.GLUT_DEPTH)
36 glut.glutShowWindow()
37 else:
38 else:
38 glut.glutCreateWindow('gui-glut')
39 interactive = False
39 interactive = False
40
40
41 glut.glutCreateWindow('gui-glut')
41 glut.glutDisplayFunc(display)
42 glut.glutDisplayFunc(display)
42 glut.glutReshapeFunc(resize)
43 glut.glutReshapeFunc(resize)
44 # This is necessary on osx to be able to close the window
45 # (else the close button is disabled)
46 if sys.platform == 'darwin' and not bool(glut.HAVE_FREEGLUT):
47 glut.glutWMCloseFunc(close)
43 gl.glClearColor(0,0,0,1)
48 gl.glClearColor(0,0,0,1)
44
49
45 if not interactive:
50 if not interactive:
General Comments 0
You need to be logged in to leave comments. Login now