##// END OF EJS Templates
Reverting whitespace changes to inputhook.py.
Thomi Richards -
Show More
@@ -1,521 +1,521 b''
1 # coding: utf-8
1 # coding: utf-8
2 """
2 """
3 Inputhook management for GUI event loop integration.
3 Inputhook management for GUI event loop integration.
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 try:
17 try:
18 import ctypes
18 import ctypes
19 except ImportError:
19 except ImportError:
20 ctypes = None
20 ctypes = None
21 import os
21 import os
22 import sys
22 import sys
23
23
24 from IPython.utils.warn import warn
24 from IPython.utils.warn import warn
25
25
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27 # Constants
27 # Constants
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29
29
30 # Constants for identifying the GUI toolkits.
30 # Constants for identifying the GUI toolkits.
31 GUI_WX = 'wx'
31 GUI_WX = 'wx'
32 GUI_QT = 'qt'
32 GUI_QT = 'qt'
33 GUI_QT4 = 'qt4'
33 GUI_QT4 = 'qt4'
34 GUI_GTK = 'gtk'
34 GUI_GTK = 'gtk'
35 GUI_TK = 'tk'
35 GUI_TK = 'tk'
36 GUI_OSX = 'osx'
36 GUI_OSX = 'osx'
37 GUI_GLUT = 'glut'
37 GUI_GLUT = 'glut'
38 GUI_PYGLET = 'pyglet'
38 GUI_PYGLET = 'pyglet'
39 GUI_GTK3 = 'gtk3'
39 GUI_GTK3 = 'gtk3'
40 GUI_NONE = 'none' # i.e. disable
40 GUI_NONE = 'none' # i.e. disable
41
41
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43 # Utilities
43 # Utilities
44 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
45
45
46 def _stdin_ready_posix():
46 def _stdin_ready_posix():
47 """Return True if there's something to read on stdin (posix version)."""
47 """Return True if there's something to read on stdin (posix version)."""
48 infds, outfds, erfds = select.select([sys.stdin],[],[],0)
48 infds, outfds, erfds = select.select([sys.stdin],[],[],0)
49 return bool(infds)
49 return bool(infds)
50
50
51 def _stdin_ready_nt():
51 def _stdin_ready_nt():
52 """Return True if there's something to read on stdin (nt version)."""
52 """Return True if there's something to read on stdin (nt version)."""
53 return msvcrt.kbhit()
53 return msvcrt.kbhit()
54
54
55 def _stdin_ready_other():
55 def _stdin_ready_other():
56 """Return True, assuming there's something to read on stdin."""
56 """Return True, assuming there's something to read on stdin."""
57 return True #
57 return True #
58
58
59
59
60 def _ignore_CTRL_C_posix():
60 def _ignore_CTRL_C_posix():
61 """Ignore CTRL+C (SIGINT)."""
61 """Ignore CTRL+C (SIGINT)."""
62 signal.signal(signal.SIGINT, signal.SIG_IGN)
62 signal.signal(signal.SIGINT, signal.SIG_IGN)
63
63
64 def _allow_CTRL_C_posix():
64 def _allow_CTRL_C_posix():
65 """Take CTRL+C into account (SIGINT)."""
65 """Take CTRL+C into account (SIGINT)."""
66 signal.signal(signal.SIGINT, signal.default_int_handler)
66 signal.signal(signal.SIGINT, signal.default_int_handler)
67
67
68 def _ignore_CTRL_C_other():
68 def _ignore_CTRL_C_other():
69 """Ignore CTRL+C (not implemented)."""
69 """Ignore CTRL+C (not implemented)."""
70 pass
70 pass
71
71
72 def _allow_CTRL_C_other():
72 def _allow_CTRL_C_other():
73 """Take CTRL+C into account (not implemented)."""
73 """Take CTRL+C into account (not implemented)."""
74 pass
74 pass
75
75
76 if os.name == 'posix':
76 if os.name == 'posix':
77 import select
77 import select
78 import signal
78 import signal
79 stdin_ready = _stdin_ready_posix
79 stdin_ready = _stdin_ready_posix
80 ignore_CTRL_C = _ignore_CTRL_C_posix
80 ignore_CTRL_C = _ignore_CTRL_C_posix
81 allow_CTRL_C = _allow_CTRL_C_posix
81 allow_CTRL_C = _allow_CTRL_C_posix
82 elif os.name == 'nt':
82 elif os.name == 'nt':
83 import msvcrt
83 import msvcrt
84 stdin_ready = _stdin_ready_nt
84 stdin_ready = _stdin_ready_nt
85 ignore_CTRL_C = _ignore_CTRL_C_other
85 ignore_CTRL_C = _ignore_CTRL_C_other
86 allow_CTRL_C = _allow_CTRL_C_other
86 allow_CTRL_C = _allow_CTRL_C_other
87 else:
87 else:
88 stdin_ready = _stdin_ready_other
88 stdin_ready = _stdin_ready_other
89 ignore_CTRL_C = _ignore_CTRL_C_other
89 ignore_CTRL_C = _ignore_CTRL_C_other
90 allow_CTRL_C = _allow_CTRL_C_other
90 allow_CTRL_C = _allow_CTRL_C_other
91
91
92
92
93 #-----------------------------------------------------------------------------
93 #-----------------------------------------------------------------------------
94 # Main InputHookManager class
94 # Main InputHookManager class
95 #-----------------------------------------------------------------------------
95 #-----------------------------------------------------------------------------
96
96
97
97
98 class InputHookManager(object):
98 class InputHookManager(object):
99 """Manage PyOS_InputHook for different GUI toolkits.
99 """Manage PyOS_InputHook for different GUI toolkits.
100
100
101 This class installs various hooks under ``PyOSInputHook`` to handle
101 This class installs various hooks under ``PyOSInputHook`` to handle
102 GUI event loop integration.
102 GUI event loop integration.
103 """
103 """
104
104
105 def __init__(self):
105 def __init__(self):
106 if ctypes is None:
106 if ctypes is None:
107 warn("IPython GUI event loop requires ctypes, %gui will not be available\n")
107 warn("IPython GUI event loop requires ctypes, %gui will not be available\n")
108 return
108 return
109 self.PYFUNC = ctypes.PYFUNCTYPE(ctypes.c_int)
109 self.PYFUNC = ctypes.PYFUNCTYPE(ctypes.c_int)
110 self._apps = {}
110 self._apps = {}
111 self._reset()
111 self._reset()
112
112
113 def _reset(self):
113 def _reset(self):
114 self._callback_pyfunctype = None
114 self._callback_pyfunctype = None
115 self._callback = None
115 self._callback = None
116 self._installed = False
116 self._installed = False
117 self._current_gui = None
117 self._current_gui = None
118
118
119 def get_pyos_inputhook(self):
119 def get_pyos_inputhook(self):
120 """Return the current PyOS_InputHook as a ctypes.c_void_p."""
120 """Return the current PyOS_InputHook as a ctypes.c_void_p."""
121 return ctypes.c_void_p.in_dll(ctypes.pythonapi,"PyOS_InputHook")
121 return ctypes.c_void_p.in_dll(ctypes.pythonapi,"PyOS_InputHook")
122
122
123 def get_pyos_inputhook_as_func(self):
123 def get_pyos_inputhook_as_func(self):
124 """Return the current PyOS_InputHook as a ctypes.PYFUNCYPE."""
124 """Return the current PyOS_InputHook as a ctypes.PYFUNCYPE."""
125 return self.PYFUNC.in_dll(ctypes.pythonapi,"PyOS_InputHook")
125 return self.PYFUNC.in_dll(ctypes.pythonapi,"PyOS_InputHook")
126
126
127 def set_inputhook(self, callback):
127 def set_inputhook(self, callback):
128 """Set PyOS_InputHook to callback and return the previous one."""
128 """Set PyOS_InputHook to callback and return the previous one."""
129 # On platforms with 'readline' support, it's all too likely to
129 # On platforms with 'readline' support, it's all too likely to
130 # have a KeyboardInterrupt signal delivered *even before* an
130 # have a KeyboardInterrupt signal delivered *even before* an
131 # initial ``try:`` clause in the callback can be executed, so
131 # initial ``try:`` clause in the callback can be executed, so
132 # we need to disable CTRL+C in this situation.
132 # we need to disable CTRL+C in this situation.
133 ignore_CTRL_C()
133 ignore_CTRL_C()
134 self._callback = callback
134 self._callback = callback
135 self._callback_pyfunctype = self.PYFUNC(callback)
135 self._callback_pyfunctype = self.PYFUNC(callback)
136 pyos_inputhook_ptr = self.get_pyos_inputhook()
136 pyos_inputhook_ptr = self.get_pyos_inputhook()
137 original = self.get_pyos_inputhook_as_func()
137 original = self.get_pyos_inputhook_as_func()
138 pyos_inputhook_ptr.value = \
138 pyos_inputhook_ptr.value = \
139 ctypes.cast(self._callback_pyfunctype, ctypes.c_void_p).value
139 ctypes.cast(self._callback_pyfunctype, ctypes.c_void_p).value
140 self._installed = True
140 self._installed = True
141 return original
141 return original
142
142
143 def clear_inputhook(self, app=None):
143 def clear_inputhook(self, app=None):
144 """Set PyOS_InputHook to NULL and return the previous one.
144 """Set PyOS_InputHook to NULL and return the previous one.
145
145
146 Parameters
146 Parameters
147 ----------
147 ----------
148 app : optional, ignored
148 app : optional, ignored
149 This parameter is allowed only so that clear_inputhook() can be
149 This parameter is allowed only so that clear_inputhook() can be
150 called with a similar interface as all the ``enable_*`` methods. But
150 called with a similar interface as all the ``enable_*`` methods. But
151 the actual value of the parameter is ignored. This uniform interface
151 the actual value of the parameter is ignored. This uniform interface
152 makes it easier to have user-level entry points in the main IPython
152 makes it easier to have user-level entry points in the main IPython
153 app like :meth:`enable_gui`."""
153 app like :meth:`enable_gui`."""
154 pyos_inputhook_ptr = self.get_pyos_inputhook()
154 pyos_inputhook_ptr = self.get_pyos_inputhook()
155 original = self.get_pyos_inputhook_as_func()
155 original = self.get_pyos_inputhook_as_func()
156 pyos_inputhook_ptr.value = ctypes.c_void_p(None).value
156 pyos_inputhook_ptr.value = ctypes.c_void_p(None).value
157 allow_CTRL_C()
157 allow_CTRL_C()
158 self._reset()
158 self._reset()
159 return original
159 return original
160
160
161 def clear_app_refs(self, gui=None):
161 def clear_app_refs(self, gui=None):
162 """Clear IPython's internal reference to an application instance.
162 """Clear IPython's internal reference to an application instance.
163
163
164 Whenever we create an app for a user on qt4 or wx, we hold a
164 Whenever we create an app for a user on qt4 or wx, we hold a
165 reference to the app. This is needed because in some cases bad things
165 reference to the app. This is needed because in some cases bad things
166 can happen if a user doesn't hold a reference themselves. This
166 can happen if a user doesn't hold a reference themselves. This
167 method is provided to clear the references we are holding.
167 method is provided to clear the references we are holding.
168
168
169 Parameters
169 Parameters
170 ----------
170 ----------
171 gui : None or str
171 gui : None or str
172 If None, clear all app references. If ('wx', 'qt4') clear
172 If None, clear all app references. If ('wx', 'qt4') clear
173 the app for that toolkit. References are not held for gtk or tk
173 the app for that toolkit. References are not held for gtk or tk
174 as those toolkits don't have the notion of an app.
174 as those toolkits don't have the notion of an app.
175 """
175 """
176 if gui is None:
176 if gui is None:
177 self._apps = {}
177 self._apps = {}
178 elif self._apps.has_key(gui):
178 elif self._apps.has_key(gui):
179 del self._apps[gui]
179 del self._apps[gui]
180
180
181 def enable_wx(self, app=None):
181 def enable_wx(self, app=None):
182 """Enable event loop integration with wxPython.
182 """Enable event loop integration with wxPython.
183
183
184 Parameters
184 Parameters
185 ----------
185 ----------
186 app : WX Application, optional.
186 app : WX Application, optional.
187 Running application to use. If not given, we probe WX for an
187 Running application to use. If not given, we probe WX for an
188 existing application object, and create a new one if none is found.
188 existing application object, and create a new one if none is found.
189
189
190 Notes
190 Notes
191 -----
191 -----
192 This methods sets the ``PyOS_InputHook`` for wxPython, which allows
192 This methods sets the ``PyOS_InputHook`` for wxPython, which allows
193 the wxPython to integrate with terminal based applications like
193 the wxPython to integrate with terminal based applications like
194 IPython.
194 IPython.
195
195
196 If ``app`` is not given we probe for an existing one, and return it if
196 If ``app`` is not given we probe for an existing one, and return it if
197 found. If no existing app is found, we create an :class:`wx.App` as
197 found. If no existing app is found, we create an :class:`wx.App` as
198 follows::
198 follows::
199
199
200 import wx
200 import wx
201 app = wx.App(redirect=False, clearSigInt=False)
201 app = wx.App(redirect=False, clearSigInt=False)
202 """
202 """
203 from IPython.lib.inputhookwx import inputhook_wx
203 from IPython.lib.inputhookwx import inputhook_wx
204 self.set_inputhook(inputhook_wx)
204 self.set_inputhook(inputhook_wx)
205 self._current_gui = GUI_WX
205 self._current_gui = GUI_WX
206 import wx
206 import wx
207 if app is None:
207 if app is None:
208 app = wx.GetApp()
208 app = wx.GetApp()
209 if app is None:
209 if app is None:
210 app = wx.App(redirect=False, clearSigInt=False)
210 app = wx.App(redirect=False, clearSigInt=False)
211 app._in_event_loop = True
211 app._in_event_loop = True
212 self._apps[GUI_WX] = app
212 self._apps[GUI_WX] = app
213 return app
213 return app
214
214
215 def disable_wx(self):
215 def disable_wx(self):
216 """Disable event loop integration with wxPython.
216 """Disable event loop integration with wxPython.
217
217
218 This merely sets PyOS_InputHook to NULL.
218 This merely sets PyOS_InputHook to NULL.
219 """
219 """
220 if self._apps.has_key(GUI_WX):
220 if self._apps.has_key(GUI_WX):
221 self._apps[GUI_WX]._in_event_loop = False
221 self._apps[GUI_WX]._in_event_loop = False
222 self.clear_inputhook()
222 self.clear_inputhook()
223
223
224 def enable_qt4(self, app=None):
224 def enable_qt4(self, app=None):
225 """Enable event loop integration with PyQt4.
225 """Enable event loop integration with PyQt4.
226
226
227 Parameters
227 Parameters
228 ----------
228 ----------
229 app : Qt Application, optional.
229 app : Qt Application, optional.
230 Running application to use. If not given, we probe Qt for an
230 Running application to use. If not given, we probe Qt for an
231 existing application object, and create a new one if none is found.
231 existing application object, and create a new one if none is found.
232
232
233 Notes
233 Notes
234 -----
234 -----
235 This methods sets the PyOS_InputHook for PyQt4, which allows
235 This methods sets the PyOS_InputHook for PyQt4, which allows
236 the PyQt4 to integrate with terminal based applications like
236 the PyQt4 to integrate with terminal based applications like
237 IPython.
237 IPython.
238
238
239 If ``app`` is not given we probe for an existing one, and return it if
239 If ``app`` is not given we probe for an existing one, and return it if
240 found. If no existing app is found, we create an :class:`QApplication`
240 found. If no existing app is found, we create an :class:`QApplication`
241 as follows::
241 as follows::
242
242
243 from PyQt4 import QtCore
243 from PyQt4 import QtCore
244 app = QtGui.QApplication(sys.argv)
244 app = QtGui.QApplication(sys.argv)
245 """
245 """
246 from IPython.lib.inputhookqt4 import create_inputhook_qt4
246 from IPython.lib.inputhookqt4 import create_inputhook_qt4
247 app, inputhook_qt4 = create_inputhook_qt4(self, app)
247 app, inputhook_qt4 = create_inputhook_qt4(self, app)
248 self.set_inputhook(inputhook_qt4)
248 self.set_inputhook(inputhook_qt4)
249
249
250 self._current_gui = GUI_QT4
250 self._current_gui = GUI_QT4
251 app._in_event_loop = True
251 app._in_event_loop = True
252 self._apps[GUI_QT4] = app
252 self._apps[GUI_QT4] = app
253 return app
253 return app
254
254
255 def disable_qt4(self):
255 def disable_qt4(self):
256 """Disable event loop integration with PyQt4.
256 """Disable event loop integration with PyQt4.
257
257
258 This merely sets PyOS_InputHook to NULL.
258 This merely sets PyOS_InputHook to NULL.
259 """
259 """
260 if self._apps.has_key(GUI_QT4):
260 if self._apps.has_key(GUI_QT4):
261 self._apps[GUI_QT4]._in_event_loop = False
261 self._apps[GUI_QT4]._in_event_loop = False
262 self.clear_inputhook()
262 self.clear_inputhook()
263
263
264 def enable_gtk(self, app=None):
264 def enable_gtk(self, app=None):
265 """Enable event loop integration with PyGTK.
265 """Enable event loop integration with PyGTK.
266
266
267 Parameters
267 Parameters
268 ----------
268 ----------
269 app : ignored
269 app : ignored
270 Ignored, it's only a placeholder to keep the call signature of all
270 Ignored, it's only a placeholder to keep the call signature of all
271 gui activation methods consistent, which simplifies the logic of
271 gui activation methods consistent, which simplifies the logic of
272 supporting magics.
272 supporting magics.
273
273
274 Notes
274 Notes
275 -----
275 -----
276 This methods sets the PyOS_InputHook for PyGTK, which allows
276 This methods sets the PyOS_InputHook for PyGTK, which allows
277 the PyGTK to integrate with terminal based applications like
277 the PyGTK to integrate with terminal based applications like
278 IPython.
278 IPython.
279 """
279 """
280 import gtk
280 import gtk
281 try:
281 try:
282 gtk.set_interactive(True)
282 gtk.set_interactive(True)
283 self._current_gui = GUI_GTK
283 self._current_gui = GUI_GTK
284 except AttributeError:
284 except AttributeError:
285 # For older versions of gtk, use our own ctypes version
285 # For older versions of gtk, use our own ctypes version
286 from IPython.lib.inputhookgtk import inputhook_gtk
286 from IPython.lib.inputhookgtk import inputhook_gtk
287 self.set_inputhook(inputhook_gtk)
287 self.set_inputhook(inputhook_gtk)
288 self._current_gui = GUI_GTK
288 self._current_gui = GUI_GTK
289
289
290 def disable_gtk(self):
290 def disable_gtk(self):
291 """Disable event loop integration with PyGTK.
291 """Disable event loop integration with PyGTK.
292
292
293 This merely sets PyOS_InputHook to NULL.
293 This merely sets PyOS_InputHook to NULL.
294 """
294 """
295 self.clear_inputhook()
295 self.clear_inputhook()
296
296
297 def enable_tk(self, app=None):
297 def enable_tk(self, app=None):
298 """Enable event loop integration with Tk.
298 """Enable event loop integration with Tk.
299
299
300 Parameters
300 Parameters
301 ----------
301 ----------
302 app : toplevel :class:`Tkinter.Tk` widget, optional.
302 app : toplevel :class:`Tkinter.Tk` widget, optional.
303 Running toplevel widget to use. If not given, we probe Tk for an
303 Running toplevel widget to use. If not given, we probe Tk for an
304 existing one, and create a new one if none is found.
304 existing one, and create a new one if none is found.
305
305
306 Notes
306 Notes
307 -----
307 -----
308 If you have already created a :class:`Tkinter.Tk` object, the only
308 If you have already created a :class:`Tkinter.Tk` object, the only
309 thing done by this method is to register with the
309 thing done by this method is to register with the
310 :class:`InputHookManager`, since creating that object automatically
310 :class:`InputHookManager`, since creating that object automatically
311 sets ``PyOS_InputHook``.
311 sets ``PyOS_InputHook``.
312 """
312 """
313 self._current_gui = GUI_TK
313 self._current_gui = GUI_TK
314 if app is None:
314 if app is None:
315 import Tkinter
315 import Tkinter
316 app = Tkinter.Tk()
316 app = Tkinter.Tk()
317 app.withdraw()
317 app.withdraw()
318 self._apps[GUI_TK] = app
318 self._apps[GUI_TK] = app
319 return app
319 return app
320
320
321 def disable_tk(self):
321 def disable_tk(self):
322 """Disable event loop integration with Tkinter.
322 """Disable event loop integration with Tkinter.
323
323
324 This merely sets PyOS_InputHook to NULL.
324 This merely sets PyOS_InputHook to NULL.
325 """
325 """
326 self.clear_inputhook()
326 self.clear_inputhook()
327
327
328
328
329 def enable_glut(self, app=None):
329 def enable_glut(self, app=None):
330 """ Enable event loop integration with GLUT.
330 """ Enable event loop integration with GLUT.
331
331
332 Parameters
332 Parameters
333 ----------
333 ----------
334
334
335 app : ignored
335 app : ignored
336 Ignored, it's only a placeholder to keep the call signature of all
336 Ignored, it's only a placeholder to keep the call signature of all
337 gui activation methods consistent, which simplifies the logic of
337 gui activation methods consistent, which simplifies the logic of
338 supporting magics.
338 supporting magics.
339
339
340 Notes
340 Notes
341 -----
341 -----
342
342
343 This methods sets the PyOS_InputHook for GLUT, which allows the GLUT to
343 This methods sets the PyOS_InputHook for GLUT, which allows the GLUT to
344 integrate with terminal based applications like IPython. Due to GLUT
344 integrate with terminal based applications like IPython. Due to GLUT
345 limitations, it is currently not possible to start the event loop
345 limitations, it is currently not possible to start the event loop
346 without first creating a window. You should thus not create another
346 without first creating a window. You should thus not create another
347 window but use instead the created one. See 'gui-glut.py' in the
347 window but use instead the created one. See 'gui-glut.py' in the
348 docs/examples/lib directory.
348 docs/examples/lib directory.
349
349
350 The default screen mode is set to:
350 The default screen mode is set to:
351 glut.GLUT_DOUBLE | glut.GLUT_RGBA | glut.GLUT_DEPTH
351 glut.GLUT_DOUBLE | glut.GLUT_RGBA | glut.GLUT_DEPTH
352 """
352 """
353
353
354 import OpenGL.GLUT as glut
354 import OpenGL.GLUT as glut
355 from IPython.lib.inputhookglut import glut_display_mode, \
355 from IPython.lib.inputhookglut import glut_display_mode, \
356 glut_close, glut_display, \
356 glut_close, glut_display, \
357 glut_idle, inputhook_glut
357 glut_idle, inputhook_glut
358
358
359 if not self._apps.has_key( GUI_GLUT ):
359 if not self._apps.has_key( GUI_GLUT ):
360 glut.glutInit( sys.argv )
360 glut.glutInit( sys.argv )
361 glut.glutInitDisplayMode( glut_display_mode )
361 glut.glutInitDisplayMode( glut_display_mode )
362 # This is specific to freeglut
362 # This is specific to freeglut
363 if bool(glut.glutSetOption):
363 if bool(glut.glutSetOption):
364 glut.glutSetOption( glut.GLUT_ACTION_ON_WINDOW_CLOSE,
364 glut.glutSetOption( glut.GLUT_ACTION_ON_WINDOW_CLOSE,
365 glut.GLUT_ACTION_GLUTMAINLOOP_RETURNS )
365 glut.GLUT_ACTION_GLUTMAINLOOP_RETURNS )
366 glut.glutCreateWindow( sys.argv[0] )
366 glut.glutCreateWindow( sys.argv[0] )
367 glut.glutReshapeWindow( 1, 1 )
367 glut.glutReshapeWindow( 1, 1 )
368 glut.glutHideWindow( )
368 glut.glutHideWindow( )
369 glut.glutWMCloseFunc( glut_close )
369 glut.glutWMCloseFunc( glut_close )
370 glut.glutDisplayFunc( glut_display )
370 glut.glutDisplayFunc( glut_display )
371 glut.glutIdleFunc( glut_idle )
371 glut.glutIdleFunc( glut_idle )
372 else:
372 else:
373 glut.glutWMCloseFunc( glut_close )
373 glut.glutWMCloseFunc( glut_close )
374 glut.glutDisplayFunc( glut_display )
374 glut.glutDisplayFunc( glut_display )
375 glut.glutIdleFunc( glut_idle)
375 glut.glutIdleFunc( glut_idle)
376 self.set_inputhook( inputhook_glut )
376 self.set_inputhook( inputhook_glut )
377 self._current_gui = GUI_GLUT
377 self._current_gui = GUI_GLUT
378 self._apps[GUI_GLUT] = True
378 self._apps[GUI_GLUT] = True
379
379
380
380
381 def disable_glut(self):
381 def disable_glut(self):
382 """Disable event loop integration with glut.
382 """Disable event loop integration with glut.
383
383
384 This sets PyOS_InputHook to NULL and set the display function to a
384 This sets PyOS_InputHook to NULL and set the display function to a
385 dummy one and set the timer to a dummy timer that will be triggered
385 dummy one and set the timer to a dummy timer that will be triggered
386 very far in the future.
386 very far in the future.
387 """
387 """
388 import OpenGL.GLUT as glut
388 import OpenGL.GLUT as glut
389 from glut_support import glutMainLoopEvent
389 from glut_support import glutMainLoopEvent
390
390
391 glut.glutHideWindow() # This is an event to be processed below
391 glut.glutHideWindow() # This is an event to be processed below
392 glutMainLoopEvent()
392 glutMainLoopEvent()
393 self.clear_inputhook()
393 self.clear_inputhook()
394
394
395 def enable_pyglet(self, app=None):
395 def enable_pyglet(self, app=None):
396 """Enable event loop integration with pyglet.
396 """Enable event loop integration with pyglet.
397
397
398 Parameters
398 Parameters
399 ----------
399 ----------
400 app : ignored
400 app : ignored
401 Ignored, it's only a placeholder to keep the call signature of all
401 Ignored, it's only a placeholder to keep the call signature of all
402 gui activation methods consistent, which simplifies the logic of
402 gui activation methods consistent, which simplifies the logic of
403 supporting magics.
403 supporting magics.
404
404
405 Notes
405 Notes
406 -----
406 -----
407 This methods sets the ``PyOS_InputHook`` for pyglet, which allows
407 This methods sets the ``PyOS_InputHook`` for pyglet, which allows
408 pyglet to integrate with terminal based applications like
408 pyglet to integrate with terminal based applications like
409 IPython.
409 IPython.
410
410
411 """
411 """
412 import pyglet
412 import pyglet
413 from IPython.lib.inputhookpyglet import inputhook_pyglet
413 from IPython.lib.inputhookpyglet import inputhook_pyglet
414 self.set_inputhook(inputhook_pyglet)
414 self.set_inputhook(inputhook_pyglet)
415 self._current_gui = GUI_PYGLET
415 self._current_gui = GUI_PYGLET
416 return app
416 return app
417
417
418 def disable_pyglet(self):
418 def disable_pyglet(self):
419 """Disable event loop integration with pyglet.
419 """Disable event loop integration with pyglet.
420
420
421 This merely sets PyOS_InputHook to NULL.
421 This merely sets PyOS_InputHook to NULL.
422 """
422 """
423 self.clear_inputhook()
423 self.clear_inputhook()
424
424
425 def enable_gtk3(self, app=None):
425 def enable_gtk3(self, app=None):
426 """Enable event loop integration with Gtk3 (gir bindings).
426 """Enable event loop integration with Gtk3 (gir bindings).
427
427
428 Parameters
428 Parameters
429 ----------
429 ----------
430 app : ignored
430 app : ignored
431 Ignored, it's only a placeholder to keep the call signature of all
431 Ignored, it's only a placeholder to keep the call signature of all
432 gui activation methods consistent, which simplifies the logic of
432 gui activation methods consistent, which simplifies the logic of
433 supporting magics.
433 supporting magics.
434
434
435 Notes
435 Notes
436 -----
436 -----
437 This methods sets the PyOS_InputHook for Gtk3, which allows
437 This methods sets the PyOS_InputHook for Gtk3, which allows
438 the Gtk3 to integrate with terminal based applications like
438 the Gtk3 to integrate with terminal based applications like
439 IPython.
439 IPython.
440 """
440 """
441 from IPython.lib.inputhookgtk3 import inputhook_gtk3
441 from IPython.lib.inputhookgtk3 import inputhook_gtk3
442 self.set_inputhook(inputhook_gtk3)
442 self.set_inputhook(inputhook_gtk3)
443 self._current_gui = GUI_GTK
443 self._current_gui = GUI_GTK
444
444
445 def disable_gtk3(self):
445 def disable_gtk3(self):
446 """Disable event loop integration with PyGTK.
446 """Disable event loop integration with PyGTK.
447
447
448 This merely sets PyOS_InputHook to NULL.
448 This merely sets PyOS_InputHook to NULL.
449 """
449 """
450 self.clear_inputhook()
450 self.clear_inputhook()
451
451
452 def current_gui(self):
452 def current_gui(self):
453 """Return a string indicating the currently active GUI or None."""
453 """Return a string indicating the currently active GUI or None."""
454 return self._current_gui
454 return self._current_gui
455
455
456 inputhook_manager = InputHookManager()
456 inputhook_manager = InputHookManager()
457
457
458 enable_wx = inputhook_manager.enable_wx
458 enable_wx = inputhook_manager.enable_wx
459 disable_wx = inputhook_manager.disable_wx
459 disable_wx = inputhook_manager.disable_wx
460 enable_qt4 = inputhook_manager.enable_qt4
460 enable_qt4 = inputhook_manager.enable_qt4
461 disable_qt4 = inputhook_manager.disable_qt4
461 disable_qt4 = inputhook_manager.disable_qt4
462 enable_gtk = inputhook_manager.enable_gtk
462 enable_gtk = inputhook_manager.enable_gtk
463 disable_gtk = inputhook_manager.disable_gtk
463 disable_gtk = inputhook_manager.disable_gtk
464 enable_tk = inputhook_manager.enable_tk
464 enable_tk = inputhook_manager.enable_tk
465 disable_tk = inputhook_manager.disable_tk
465 disable_tk = inputhook_manager.disable_tk
466 enable_glut = inputhook_manager.enable_glut
466 enable_glut = inputhook_manager.enable_glut
467 disable_glut = inputhook_manager.disable_glut
467 disable_glut = inputhook_manager.disable_glut
468 enable_pyglet = inputhook_manager.enable_pyglet
468 enable_pyglet = inputhook_manager.enable_pyglet
469 disable_pyglet = inputhook_manager.disable_pyglet
469 disable_pyglet = inputhook_manager.disable_pyglet
470 enable_gtk3 = inputhook_manager.enable_gtk3
470 enable_gtk3 = inputhook_manager.enable_gtk3
471 disable_gtk3 = inputhook_manager.disable_gtk3
471 disable_gtk3 = inputhook_manager.disable_gtk3
472 clear_inputhook = inputhook_manager.clear_inputhook
472 clear_inputhook = inputhook_manager.clear_inputhook
473 set_inputhook = inputhook_manager.set_inputhook
473 set_inputhook = inputhook_manager.set_inputhook
474 current_gui = inputhook_manager.current_gui
474 current_gui = inputhook_manager.current_gui
475 clear_app_refs = inputhook_manager.clear_app_refs
475 clear_app_refs = inputhook_manager.clear_app_refs
476
476
477
477
478 # Convenience function to switch amongst them
478 # Convenience function to switch amongst them
479 def enable_gui(gui=None, app=None):
479 def enable_gui(gui=None, app=None):
480 """Switch amongst GUI input hooks by name.
480 """Switch amongst GUI input hooks by name.
481
481
482 This is just a utility wrapper around the methods of the InputHookManager
482 This is just a utility wrapper around the methods of the InputHookManager
483 object.
483 object.
484
484
485 Parameters
485 Parameters
486 ----------
486 ----------
487 gui : optional, string or None
487 gui : optional, string or None
488 If None (or 'none'), clears input hook, otherwise it must be one
488 If None (or 'none'), clears input hook, otherwise it must be one
489 of the recognized GUI names (see ``GUI_*`` constants in module).
489 of the recognized GUI names (see ``GUI_*`` constants in module).
490
490
491 app : optional, existing application object.
491 app : optional, existing application object.
492 For toolkits that have the concept of a global app, you can supply an
492 For toolkits that have the concept of a global app, you can supply an
493 existing one. If not given, the toolkit will be probed for one, and if
493 existing one. If not given, the toolkit will be probed for one, and if
494 none is found, a new one will be created. Note that GTK does not have
494 none is found, a new one will be created. Note that GTK does not have
495 this concept, and passing an app if `gui`=="GTK" will raise an error.
495 this concept, and passing an app if `gui`=="GTK" will raise an error.
496
496
497 Returns
497 Returns
498 -------
498 -------
499 The output of the underlying gui switch routine, typically the actual
499 The output of the underlying gui switch routine, typically the actual
500 PyOS_InputHook wrapper object or the GUI toolkit app created, if there was
500 PyOS_InputHook wrapper object or the GUI toolkit app created, if there was
501 one.
501 one.
502 """
502 """
503 guis = {None: clear_inputhook,
503 guis = {None: clear_inputhook,
504 GUI_NONE: clear_inputhook,
504 GUI_NONE: clear_inputhook,
505 GUI_OSX: lambda app=False: None,
505 GUI_OSX: lambda app=False: None,
506 GUI_TK: enable_tk,
506 GUI_TK: enable_tk,
507 GUI_GTK: enable_gtk,
507 GUI_GTK: enable_gtk,
508 GUI_WX: enable_wx,
508 GUI_WX: enable_wx,
509 GUI_QT: enable_qt4, # qt3 not supported
509 GUI_QT: enable_qt4, # qt3 not supported
510 GUI_QT4: enable_qt4,
510 GUI_QT4: enable_qt4,
511 GUI_GLUT: enable_glut,
511 GUI_GLUT: enable_glut,
512 GUI_PYGLET: enable_pyglet,
512 GUI_PYGLET: enable_pyglet,
513 GUI_GTK3: enable_gtk3,
513 GUI_GTK3: enable_gtk3,
514 }
514 }
515 try:
515 try:
516 gui_hook = guis[gui]
516 gui_hook = guis[gui]
517 except KeyError:
517 except KeyError:
518 e = "Invalid GUI request %r, valid ones are:%s" % (gui, guis.keys())
518 e = "Invalid GUI request %r, valid ones are:%s" % (gui, guis.keys())
519 raise ValueError(e)
519 raise ValueError(e)
520 return gui_hook(app)
520 return gui_hook(app)
521
521
General Comments 0
You need to be logged in to leave comments. Login now