##// END OF EJS Templates
Factorized glut code into glut_support.py
Nicolas Rougier -
Show More
@@ -0,0 +1,124 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 a default timer to
21 # ensure we got at least one event that will unblock the function. We set
22 # a default timer of 60fps.
23 #
24 # Furthermore, it is not possible to install these handlers without a
25 # window being first created. We choose to make this window invisible and
26 # the user is supposed to make it visible when needed (see gui-glut.py in
27 # the docs/examples/lib directory). This means that display mode options
28 # are set at this level and user won't be able to change them later
29 # without modifying the code. This should probably be made available via
30 # IPython options system.
31
32 #-----------------------------------------------------------------------------
33 # Imports
34 #-----------------------------------------------------------------------------
35
36 import sys
37 import time
38 import signal
39 import OpenGL
40 OpenGL.ERROR_CHECKING = False
41 import OpenGL.GLUT as glut
42 import OpenGL.platform as platform
43
44 #-----------------------------------------------------------------------------
45 # Constants
46 #-----------------------------------------------------------------------------
47
48 # Frame per second : 60
49 # Should probably be an IPython option
50 glut_fps = 60
51
52
53 # Display mode : double buffeed + rgba + depth
54 # Should probably be an IPython option
55 glut_display_mode = (glut.GLUT_DOUBLE |
56 glut.GLUT_RGBA |
57 glut.GLUT_DEPTH)
58
59 glutMainLoopEvent = None
60 if sys.platform == 'darwin':
61 try:
62 glutCheckLoop = platform.createBaseFunction(
63 'glutCheckLoop', dll=platform.GLUT, resultType=None,
64 argTypes=[],
65 doc='glutCheckLoop( ) -> None',
66 argNames=(),
67 )
68 except AttributeError:
69 raise RuntimeError(
70 '''Your glut implementation does not allow interactive sessions'''
71 '''Consider installing freeglut.''')
72 glutMainLoopEvent = glutCheckLoop
73 elif glut.HAVE_FREEGLUT:
74 glutMainLoopEvent = glut.glutMainLoopEvent
75 else:
76 raise RuntimeError(
77 '''Your glut implementation does not allow interactive sessions. '''
78 '''Consider installing freeglut.''')
79
80
81 #-----------------------------------------------------------------------------
82 # Callback functions
83 #-----------------------------------------------------------------------------
84
85 def glut_display():
86 # Dummy display function
87 pass
88
89 def glut_timer(fps):
90 # We should normally set the active window to 1 and post a
91 # redisplay for each window. The problem is that we do not know
92 # how much active windows we have and there is no function in glut
93 # to get that number.
94 # glut.glutSetWindow(1)
95 glut.glutTimerFunc( int(1000.0/fps), glut_timer, fps)
96 glut.glutPostRedisplay()
97
98 def glut_close():
99 glut.glutHideWindow()
100
101
102 def glut_int_handler(signum, frame):
103 signal.signal(signal.SIGINT, signal.default_int_handler)
104 print '\nKeyboardInterrupt'
105 # Need to reprint the prompt at this stage
106
107
108
109 def inputhook_glut():
110 """ Process pending GLUT events only. """
111
112 # We need to protect against a user pressing Control-C when IPython
113 # is idle and this is running. We should trap KeyboardInterrupt and
114 # pass but it does not seem to work with glutMainLoopEvent.
115 # Instead, we setup a signal handler on SIGINT and returns after
116 # having restored the default python SIGINT handler.
117 signal.signal(signal.SIGINT, glut_int_handler)
118 try:
119 glutMainLoopEvent()
120 except KeyboardInterrupt: # this catch doesn't work for some reasons...
121 pass
122 return 0
123
124
@@ -1,585 +1,441 b''
1 1 # coding: utf-8
2 2 """
3 3 Inputhook management for GUI event loop integration.
4 4 """
5 5
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (C) 2008-2009 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 17 import ctypes
18 18 import sys
19 19 import warnings
20 20
21 21 #-----------------------------------------------------------------------------
22 22 # Constants
23 23 #-----------------------------------------------------------------------------
24 24
25 25 # Constants for identifying the GUI toolkits.
26 26 GUI_WX = 'wx'
27 27 GUI_QT = 'qt'
28 28 GUI_QT4 = 'qt4'
29 29 GUI_GTK = 'gtk'
30 30 GUI_TK = 'tk'
31 31 GUI_OSX = 'osx'
32 32 GUI_GLUT = 'glut'
33 33 GUI_PYGLET = 'pyglet'
34 34
35 35 #-----------------------------------------------------------------------------
36 36 # Utility classes
37 37 #-----------------------------------------------------------------------------
38 38
39 39
40 40 #-----------------------------------------------------------------------------
41 41 # Main InputHookManager class
42 42 #-----------------------------------------------------------------------------
43 43
44 44
45 45 class InputHookManager(object):
46 46 """Manage PyOS_InputHook for different GUI toolkits.
47 47
48 48 This class installs various hooks under ``PyOSInputHook`` to handle
49 49 GUI event loop integration.
50 50 """
51 51
52 52 def __init__(self):
53 53 self.PYFUNC = ctypes.PYFUNCTYPE(ctypes.c_int)
54 54 self._apps = {}
55 55 self._reset()
56 56
57 57 def _reset(self):
58 58 self._callback_pyfunctype = None
59 59 self._callback = None
60 60 self._installed = False
61 61 self._current_gui = None
62 62
63 63 def get_pyos_inputhook(self):
64 64 """Return the current PyOS_InputHook as a ctypes.c_void_p."""
65 65 return ctypes.c_void_p.in_dll(ctypes.pythonapi,"PyOS_InputHook")
66 66
67 67 def get_pyos_inputhook_as_func(self):
68 68 """Return the current PyOS_InputHook as a ctypes.PYFUNCYPE."""
69 69 return self.PYFUNC.in_dll(ctypes.pythonapi,"PyOS_InputHook")
70 70
71 71 def set_inputhook(self, callback):
72 72 """Set PyOS_InputHook to callback and return the previous one."""
73 73 self._callback = callback
74 74 self._callback_pyfunctype = self.PYFUNC(callback)
75 75 pyos_inputhook_ptr = self.get_pyos_inputhook()
76 76 original = self.get_pyos_inputhook_as_func()
77 77 pyos_inputhook_ptr.value = \
78 78 ctypes.cast(self._callback_pyfunctype, ctypes.c_void_p).value
79 79 self._installed = True
80 80 return original
81 81
82 82 def clear_inputhook(self, app=None):
83 83 """Set PyOS_InputHook to NULL and return the previous one.
84 84
85 85 Parameters
86 86 ----------
87 87 app : optional, ignored
88 88 This parameter is allowed only so that clear_inputhook() can be
89 89 called with a similar interface as all the ``enable_*`` methods. But
90 90 the actual value of the parameter is ignored. This uniform interface
91 91 makes it easier to have user-level entry points in the main IPython
92 92 app like :meth:`enable_gui`."""
93 93 pyos_inputhook_ptr = self.get_pyos_inputhook()
94 94 original = self.get_pyos_inputhook_as_func()
95 95 pyos_inputhook_ptr.value = ctypes.c_void_p(None).value
96 96 self._reset()
97 97 return original
98 98
99 99 def clear_app_refs(self, gui=None):
100 100 """Clear IPython's internal reference to an application instance.
101 101
102 102 Whenever we create an app for a user on qt4 or wx, we hold a
103 103 reference to the app. This is needed because in some cases bad things
104 104 can happen if a user doesn't hold a reference themselves. This
105 105 method is provided to clear the references we are holding.
106 106
107 107 Parameters
108 108 ----------
109 109 gui : None or str
110 110 If None, clear all app references. If ('wx', 'qt4') clear
111 111 the app for that toolkit. References are not held for gtk or tk
112 112 as those toolkits don't have the notion of an app.
113 113 """
114 114 if gui is None:
115 115 self._apps = {}
116 116 elif self._apps.has_key(gui):
117 117 del self._apps[gui]
118 118
119 119 def enable_wx(self, app=None):
120 120 """Enable event loop integration with wxPython.
121 121
122 122 Parameters
123 123 ----------
124 124 app : WX Application, optional.
125 125 Running application to use. If not given, we probe WX for an
126 126 existing application object, and create a new one if none is found.
127 127
128 128 Notes
129 129 -----
130 130 This methods sets the ``PyOS_InputHook`` for wxPython, which allows
131 131 the wxPython to integrate with terminal based applications like
132 132 IPython.
133 133
134 134 If ``app`` is not given we probe for an existing one, and return it if
135 135 found. If no existing app is found, we create an :class:`wx.App` as
136 136 follows::
137 137
138 138 import wx
139 139 app = wx.App(redirect=False, clearSigInt=False)
140 140 """
141 141 from IPython.lib.inputhookwx import inputhook_wx
142 142 self.set_inputhook(inputhook_wx)
143 143 self._current_gui = GUI_WX
144 144 import wx
145 145 if app is None:
146 146 app = wx.GetApp()
147 147 if app is None:
148 148 app = wx.App(redirect=False, clearSigInt=False)
149 149 app._in_event_loop = True
150 150 self._apps[GUI_WX] = app
151 151 return app
152 152
153 153 def disable_wx(self):
154 154 """Disable event loop integration with wxPython.
155 155
156 156 This merely sets PyOS_InputHook to NULL.
157 157 """
158 158 if self._apps.has_key(GUI_WX):
159 159 self._apps[GUI_WX]._in_event_loop = False
160 160 self.clear_inputhook()
161 161
162 162 def enable_qt4(self, app=None):
163 163 """Enable event loop integration with PyQt4.
164 164
165 165 Parameters
166 166 ----------
167 167 app : Qt Application, optional.
168 168 Running application to use. If not given, we probe Qt for an
169 169 existing application object, and create a new one if none is found.
170 170
171 171 Notes
172 172 -----
173 173 This methods sets the PyOS_InputHook for PyQt4, which allows
174 174 the PyQt4 to integrate with terminal based applications like
175 175 IPython.
176 176
177 177 If ``app`` is not given we probe for an existing one, and return it if
178 178 found. If no existing app is found, we create an :class:`QApplication`
179 179 as follows::
180 180
181 181 from PyQt4 import QtCore
182 182 app = QtGui.QApplication(sys.argv)
183 183 """
184 184 from IPython.external.qt_for_kernel import QtCore, QtGui
185 185
186 186 if 'pyreadline' in sys.modules:
187 187 # see IPython GitHub Issue #281 for more info on this issue
188 188 # Similar intermittent behavior has been reported on OSX,
189 189 # but not consistently reproducible
190 190 warnings.warn("""PyReadline's inputhook can conflict with Qt, causing delays
191 191 in interactive input. If you do see this issue, we recommend using another GUI
192 192 toolkit if you can, or disable readline with the configuration option
193 193 'TerminalInteractiveShell.readline_use=False', specified in a config file or
194 194 at the command-line""",
195 195 RuntimeWarning)
196 196
197 197 # PyQt4 has had this since 4.3.1. In version 4.2, PyOS_InputHook
198 198 # was set when QtCore was imported, but if it ever got removed,
199 199 # you couldn't reset it. For earlier versions we can
200 200 # probably implement a ctypes version.
201 201 try:
202 202 QtCore.pyqtRestoreInputHook()
203 203 except AttributeError:
204 204 pass
205 205
206 206 self._current_gui = GUI_QT4
207 207 if app is None:
208 208 app = QtCore.QCoreApplication.instance()
209 209 if app is None:
210 210 app = QtGui.QApplication([" "])
211 211 app._in_event_loop = True
212 212 self._apps[GUI_QT4] = app
213 213 return app
214 214
215 215 def disable_qt4(self):
216 216 """Disable event loop integration with PyQt4.
217 217
218 218 This merely sets PyOS_InputHook to NULL.
219 219 """
220 220 if self._apps.has_key(GUI_QT4):
221 221 self._apps[GUI_QT4]._in_event_loop = False
222 222 self.clear_inputhook()
223 223
224 224 def enable_gtk(self, app=None):
225 225 """Enable event loop integration with PyGTK.
226 226
227 227 Parameters
228 228 ----------
229 229 app : ignored
230 230 Ignored, it's only a placeholder to keep the call signature of all
231 231 gui activation methods consistent, which simplifies the logic of
232 232 supporting magics.
233 233
234 234 Notes
235 235 -----
236 236 This methods sets the PyOS_InputHook for PyGTK, which allows
237 237 the PyGTK to integrate with terminal based applications like
238 238 IPython.
239 239 """
240 240 import gtk
241 241 try:
242 242 gtk.set_interactive(True)
243 243 self._current_gui = GUI_GTK
244 244 except AttributeError:
245 245 # For older versions of gtk, use our own ctypes version
246 246 from IPython.lib.inputhookgtk import inputhook_gtk
247 247 self.set_inputhook(inputhook_gtk)
248 248 self._current_gui = GUI_GTK
249 249
250 250 def disable_gtk(self):
251 251 """Disable event loop integration with PyGTK.
252 252
253 253 This merely sets PyOS_InputHook to NULL.
254 254 """
255 255 self.clear_inputhook()
256 256
257 257 def enable_tk(self, app=None):
258 258 """Enable event loop integration with Tk.
259 259
260 260 Parameters
261 261 ----------
262 262 app : toplevel :class:`Tkinter.Tk` widget, optional.
263 263 Running toplevel widget to use. If not given, we probe Tk for an
264 264 existing one, and create a new one if none is found.
265 265
266 266 Notes
267 267 -----
268 268 If you have already created a :class:`Tkinter.Tk` object, the only
269 269 thing done by this method is to register with the
270 270 :class:`InputHookManager`, since creating that object automatically
271 271 sets ``PyOS_InputHook``.
272 272 """
273 273 self._current_gui = GUI_TK
274 274 if app is None:
275 275 import Tkinter
276 276 app = Tkinter.Tk()
277 277 app.withdraw()
278 278 self._apps[GUI_TK] = app
279 279 return app
280 280
281 281 def disable_tk(self):
282 282 """Disable event loop integration with Tkinter.
283 283
284 284 This merely sets PyOS_InputHook to NULL.
285 285 """
286 286 self.clear_inputhook()
287 287
288
288 289 def enable_glut(self, app=None):
289 290 """Enable event loop integration with GLUT.
290 291
291 292 Parameters
292 293 ----------
294
293 295 app : ignored
294 296 Ignored, it's only a placeholder to keep the call signature of all
295 297 gui activation methods consistent, which simplifies the logic of
296 298 supporting magics.
297 299
298 300 Notes
299 301 -----
300 302
301 303 This methods sets the PyOS_InputHook for GLUT, which allows the GLUT to
302 304 integrate with terminal based applications like IPython. Due to GLUT
303 305 limitations, it is currently not possible to start the event loop
304 306 without first creating a window. You should thus not create another
305 307 window but use instead the created one. See 'gui-glut.py' in the
306 308 docs/examples/lib directory.
307 309
308 310 The default screen mode is set to:
309
310 311 glut.GLUT_DOUBLE | glut.GLUT_RGBA | glut.GLUT_DEPTH
311
312 Script integration
313 ------------------
314
315 if glut.glutGetWindow() > 0:
316 interactive = True
317 glut.glutShowWindow()
318 else:
319 interactive = False
320 glut.glutInit(sys.argv)
321 glut.glutInitDisplayMode( glut.GLUT_DOUBLE |
322 glut.GLUT_RGBA |
323 glut.GLUT_DEPTH )
324 ...
325 if not interactive:
326 glut.glutMainLoop()
327 312 """
328 # GLUT is quite an old library and it is difficult to ensure proper
329 # integration within IPython since original GLUT does not allow to handle
330 # events one by one. Instead, it requires for the mainloop to be entered
331 # and never returned (there is not even a function to exit he
332 # mainloop). Fortunately, there are alternatives such as freeglut
333 # (available for linux and windows) and the OSX implementation gives
334 # access to a glutCheckLoop() function that blocks itself until a new
335 # event is received. This means we have to setup a default timer to
336 # ensure we got at least one event that will unblock the function. We set
337 # a default timer of 60fps.
338 #
339 # Furthermore, it is not possible to install these handlers without a
340 # window being first created. We choose to make this window invisible and
341 # the user is supposed to make it visible when needed (see gui-glut.py in
342 # the docs/examples/lib directory). This means that display mode options
343 # are set at this level and user won't be able to change them later
344 # without modifying the code. This should probably be made available via
345 # IPython options system.
346
347 import OpenGL
348 OpenGL.ERROR_CHECKING = False
349 import OpenGL.GLUT as glut
350 import OpenGL.platform as platform
351 import time
352
353
354 # Frame per second : 60
355 # Should probably be an IPython option
356 glut_fps = 60
357
358
359 # Display mode : double buffeed + rgba + depth
360 # Should probably be an IPython option
361 glut_display_mode = (glut.GLUT_DOUBLE |
362 glut.GLUT_RGBA |
363 glut.GLUT_DEPTH)
364
365 glut_interrupted = False
366
367 def display():
368 ''' Dummy display function '''
369 pass
370
371 def timer(fps):
372 # We should normally set the active window to 1 and post a
373 # redisplay for each window. The problem is that we do not know
374 # how much active windows we have and there is no function in glut
375 # to get that number.
376 # glut.glutSetWindow(1)
377 glut.glutTimerFunc( int(1000.0/fps), timer, fps)
378 glut.glutPostRedisplay()
379 313
380 def close():
381 glut.glutHideWindow()
382
383 glutMainLoopEvent = None
384 if sys.platform == 'darwin':
385 try:
386 glutCheckLoop = platform.createBaseFunction(
387 'glutCheckLoop', dll=platform.GLUT, resultType=None,
388 argTypes=[],
389 doc='glutCheckLoop( ) -> None',
390 argNames=(),
391 )
392 except AttributeError:
393 raise RuntimeError(
394 '''Your glut implementation does not allow interactive sessions'''
395 '''Consider installing freeglut.''')
396 glutMainLoopEvent = glutCheckLoop
397 elif glut.HAVE_FREEGLUT:
398 glutMainLoopEvent = glut.glutMainLoopEvent
399 else:
400 raise RuntimeError(
401 '''Your glut implementation does not allow interactive sessions. '''
402 '''Consider installing freeglut.''')
403
404 def inputhook_glut():
405 """ Process pending GLUT events only. """
406
407 # We need to protect against a user pressing Control-C when IPython
408 # is idle and this is running. We should trap KeyboardInterrupt and
409 # pass but it does not seem to work with glutMainLoopEvent.
410 # Instead, we setup a signal handler on SIGINT and returns after
411 # having restored the default python SIGINT handler.
412 import signal
413 def handler(signum, frame):
414 signal.signal(signal.SIGINT, signal.default_int_handler)
415 print '\nKeyboardInterrupt'
416 # Need to reprint the prompt at this stage
417
418 signal.signal(signal.SIGINT, handler)
419
420 try:
421 glutMainLoopEvent()
422 except KeyboardInterrupt: # this catch doesn't work for some reasons...
423 pass
424
425 return 0
314 from glut_support import *
426 315
427 316 if not self._apps.has_key(GUI_GLUT):
428 317 glut.glutInit(sys.argv)
429 # Display mode should be also an Ipython option since user won't be able
430 # to change it later
431 318 glut.glutInitDisplayMode(glut_display_mode)
432 319 glut.glutCreateWindow(sys.argv[0])
433 320 glut.glutHideWindow()
434 glut.glutWMCloseFunc(close)
435 glut.glutDisplayFunc(display)
436 glut.glutTimerFunc( int(1000.0/glut_fps), timer, glut_fps)
321 glut.glutWMCloseFunc(glut_close)
322 glut.glutDisplayFunc(glut_display)
323 glut.glutTimerFunc( int(1000.0/glut_fps), glut_timer, glut_fps)
437 324 else:
438 glut.glutWMCloseFunc(close)
439 glut.glutDisplayFunc(display)
440 glut.glutTimerFunc( int(1000.0/glut_fps), timer, glut_fps)
441
325 glut.glutWMCloseFunc(glut_close)
326 glut.glutDisplayFunc(glut_display)
327 glut.glutTimerFunc( int(1000.0/glut_fps), glut_timer, glut_fps)
442 328 self.set_inputhook(inputhook_glut)
443 329 self._current_gui = GUI_GLUT
444 330 self._apps[GUI_GLUT] = True
445 331
332
446 333 def disable_glut(self):
447 334 """Disable event loop integration with glut.
448 335
449 336 This sets PyOS_InputHook to NULL and set the display function to a
450 337 dummy one and set the timer to a dummy timer that will be triggered
451 338 very far in the future.
452 339 """
453 import signal
454 import OpenGL
455 OpenGL.ERROR_CHECKING = False
456 import OpenGL.GLUT as glut
457 import OpenGL.platform as platform
458
459 def timer_none(fps):
460 ''' Dummy timer function '''
461 pass
462
463 glutMainLoopEvent = None
464 if sys.platform == 'darwin':
465 try:
466 glutCheckLoop = platform.createBaseFunction(
467 'glutCheckLoop', dll=platform.GLUT, resultType=None,
468 argTypes=[],
469 doc='glutCheckLoop( ) -> None',
470 argNames=(),
471 )
472 except AttributeError:
473 raise RuntimeError(
474 '''Your glut implementation does not allow interactive sessions'''
475 '''Consider installing freeglut.''')
476 glutMainLoopEvent = glutCheckLoop
477 elif glut.HAVE_FREEGLUT:
478 glutMainLoopEvent = glut.glutMainLoopEvent
479 else:
480 raise RuntimeError(
481 '''Your glut implementation does not allow interactive sessions. '''
482 '''Consider installing freeglut.''')
340 from glut_support import *
483 341
484 342 glut.glutHideWindow() # This is an event to be processed below
485 343 glutMainLoopEvent()
486 #glut.glutTimerFunc( sys.maxint-1, timer_none, 0)
487 344 self.clear_inputhook()
488 #signal.signal(signal.SIGINT, signal.default_int_handler)
489 345
490 346 def enable_pyglet(self, app=None):
491 347 """Enable event loop integration with pyglet.
492 348
493 349 Parameters
494 350 ----------
495 351 app : ignored
496 352 Ignored, it's only a placeholder to keep the call signature of all
497 353 gui activation methods consistent, which simplifies the logic of
498 354 supporting magics.
499 355
500 356 Notes
501 357 -----
502 358 This methods sets the ``PyOS_InputHook`` for pyglet, which allows
503 359 pyglet to integrate with terminal based applications like
504 360 IPython.
505 361
506 362 """
507 363 import pyglet
508 364 from IPython.lib.inputhookpyglet import inputhook_pyglet
509 365 self.set_inputhook(inputhook_pyglet)
510 366 self._current_gui = GUI_PYGLET
511 367 return app
512 368
513 369 def disable_pyglet(self):
514 370 """Disable event loop integration with pyglet.
515 371
516 372 This merely sets PyOS_InputHook to NULL.
517 373 """
518 374 self.clear_inputhook()
519 375
520 376 def current_gui(self):
521 377 """Return a string indicating the currently active GUI or None."""
522 378 return self._current_gui
523 379
524 380 inputhook_manager = InputHookManager()
525 381
526 382 enable_wx = inputhook_manager.enable_wx
527 383 disable_wx = inputhook_manager.disable_wx
528 384 enable_qt4 = inputhook_manager.enable_qt4
529 385 disable_qt4 = inputhook_manager.disable_qt4
530 386 enable_gtk = inputhook_manager.enable_gtk
531 387 disable_gtk = inputhook_manager.disable_gtk
532 388 enable_tk = inputhook_manager.enable_tk
533 389 disable_tk = inputhook_manager.disable_tk
534 390 enable_glut = inputhook_manager.enable_glut
535 391 disable_glut = inputhook_manager.disable_glut
536 392 enable_pyglet = inputhook_manager.enable_pyglet
537 393 disable_pyglet = inputhook_manager.disable_pyglet
538 394 clear_inputhook = inputhook_manager.clear_inputhook
539 395 set_inputhook = inputhook_manager.set_inputhook
540 396 current_gui = inputhook_manager.current_gui
541 397 clear_app_refs = inputhook_manager.clear_app_refs
542 398
543 399
544 400 # Convenience function to switch amongst them
545 401 def enable_gui(gui=None, app=None):
546 402 """Switch amongst GUI input hooks by name.
547 403
548 404 This is just a utility wrapper around the methods of the InputHookManager
549 405 object.
550 406
551 407 Parameters
552 408 ----------
553 409 gui : optional, string or None
554 410 If None, clears input hook, otherwise it must be one of the recognized
555 411 GUI names (see ``GUI_*`` constants in module).
556 412
557 413 app : optional, existing application object.
558 414 For toolkits that have the concept of a global app, you can supply an
559 415 existing one. If not given, the toolkit will be probed for one, and if
560 416 none is found, a new one will be created. Note that GTK does not have
561 417 this concept, and passing an app if `gui`=="GTK" will raise an error.
562 418
563 419 Returns
564 420 -------
565 421 The output of the underlying gui switch routine, typically the actual
566 422 PyOS_InputHook wrapper object or the GUI toolkit app created, if there was
567 423 one.
568 424 """
569 425 guis = {None: clear_inputhook,
570 426 GUI_OSX: lambda app=False: None,
571 427 GUI_TK: enable_tk,
572 428 GUI_GTK: enable_gtk,
573 429 GUI_WX: enable_wx,
574 430 GUI_QT: enable_qt4, # qt3 not supported
575 431 GUI_QT4: enable_qt4,
576 432 GUI_GLUT: enable_glut,
577 433 GUI_PYGLET: enable_pyglet,
578 434 }
579 435 try:
580 436 gui_hook = guis[gui]
581 437 except KeyError:
582 438 e = "Invalid GUI request %r, valid ones are:%s" % (gui, guis.keys())
583 439 raise ValueError(e)
584 440 return gui_hook(app)
585 441
General Comments 0
You need to be logged in to leave comments. Login now