##// END OF EJS Templates
Work on inputhook....
Brian Granger -
Show More
@@ -22,6 +22,9 b' import sys'
22 # Code
22 # Code
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25 def _dummy_mainloop(*args, **kw):
26 pass
27
25
28
26 class InputHookManager(object):
29 class InputHookManager(object):
27 """Manage PyOS_InputHook for different GUI toolkits.
30 """Manage PyOS_InputHook for different GUI toolkits.
@@ -32,6 +35,7 b' class InputHookManager(object):'
32
35
33 def __init__(self):
36 def __init__(self):
34 self.PYFUNC = ctypes.PYFUNCTYPE(ctypes.c_int)
37 self.PYFUNC = ctypes.PYFUNCTYPE(ctypes.c_int)
38 self._apps = {}
35 self._reset()
39 self._reset()
36
40
37 def _reset(self):
41 def _reset(self):
@@ -40,6 +44,35 b' class InputHookManager(object):'
40 self._installed = False
44 self._installed = False
41 self._current_gui = None
45 self._current_gui = None
42
46
47 def _hijack_wx(self):
48 import wx
49 if hasattr(wx, '_core_'): core = getattr(wx, '_core_')
50 elif hasattr(wx, '_core'): core = getattr(wx, '_core')
51 else: raise AttributeError('Could not find wx core module')
52 orig_mainloop = core.PyApp_MainLoop
53 core.PyApp_MainLoop = _dummy_mainloop
54 return orig_mainloop
55
56 def _hijack_qt4(self):
57 from PyQt4 import QtGui, QtCore
58 orig_mainloop = QtGui.qApp.exec_
59 QtGui.qApp.exec_ = _dummy_mainloop
60 QtGui.QApplication.exec_ = _dummy_mainloop
61 QtCore.QCoreApplication.exec_ = _dummy_mainloop
62 return orig_mainloop
63
64 def _hijack_gtk(self):
65 import gtk
66 orig_mainloop = gtk.main
67 gtk.mainloop = _dummy_mainloop
68 gtk.main = _dummy_mainloop
69 return orig_mainloop
70
71 def _hijack_tk(self):
72 import Tkinter
73 Tkinter.Misc.mainloop = _dummy_mainloop
74 Tkinter.mainloop = _dummy_mainloop
75
43 def get_pyos_inputhook(self):
76 def get_pyos_inputhook(self):
44 """Return the current PyOS_InputHook as a ctypes.c_void_p.
77 """Return the current PyOS_InputHook as a ctypes.c_void_p.
45 """
78 """
@@ -71,6 +104,21 b' class InputHookManager(object):'
71 self._reset()
104 self._reset()
72 return original
105 return original
73
106
107 def clear_app_refs(self, gui=None):
108 """Clear IPython's internal reference to an application instance.
109
110 Parameters
111 ----------
112 gui : None or str
113 If None, clear all app references. If ('wx', 'qt4') clear
114 the app for that toolkit. References are not held for gtk or tk
115 as those toolkits don't have the notion of an app.
116 """
117 if gui is None:
118 self._apps = {}
119 elif self._apps.has_key(gui):
120 del self._apps[gui]
121
74 def enable_wx(self, app=False):
122 def enable_wx(self, app=False):
75 """Enable event loop integration with wxPython.
123 """Enable event loop integration with wxPython.
76
124
@@ -99,15 +147,13 b' class InputHookManager(object):'
99 from IPython.lib.inputhookwx import inputhook_wx
147 from IPython.lib.inputhookwx import inputhook_wx
100 self.set_inputhook(inputhook_wx)
148 self.set_inputhook(inputhook_wx)
101 self._current_gui = 'wx'
149 self._current_gui = 'wx'
150 self._hijack_wx()
102 if app:
151 if app:
103 import wx
152 import wx
104 app = wx.App(redirect=False, clearSigInt=False)
153 app = wx.GetApp()
105 # The import of wx on Linux sets the handler for signal.SIGINT
154 if app is None:
106 # to 0. This is a bug in wx or gtk. We fix by just setting it
155 app = wx.App(redirect=False, clearSigInt=False)
107 # back to the Python default.
156 self._apps['wx'] = app
108 import signal
109 if not callable(signal.getsignal(signal.SIGINT)):
110 signal.signal(signal.SIGINT, signal.default_int_handler)
111 return app
157 return app
112
158
113 def disable_wx(self):
159 def disable_wx(self):
@@ -145,9 +191,13 b' class InputHookManager(object):'
145 except AttributeError:
191 except AttributeError:
146 pass
192 pass
147 self._current_gui = 'qt4'
193 self._current_gui = 'qt4'
194 self._hijack_qt4()
148 if app:
195 if app:
149 from PyQt4 import QtGui
196 from PyQt4 import QtGui
150 app = QtGui.QApplication(sys.argv)
197 app = QtGui.QApplication.instance()
198 if app is None:
199 app = QtGui.QApplication(sys.argv)
200 self._apps['qt4'] = app
151 return app
201 return app
152
202
153 def disable_qt4(self):
203 def disable_qt4(self):
@@ -184,6 +234,7 b' class InputHookManager(object):'
184 from IPython.lib.inputhookgtk import inputhook_gtk
234 from IPython.lib.inputhookgtk import inputhook_gtk
185 self.set_inputhook(inputhook_gtk)
235 self.set_inputhook(inputhook_gtk)
186 self._current_gui = 'gtk'
236 self._current_gui = 'gtk'
237 self._hijack_gtk()
187
238
188 def disable_gtk(self):
239 def disable_gtk(self):
189 """Disable event loop integration with PyGTK.
240 """Disable event loop integration with PyGTK.
@@ -206,6 +257,7 b' class InputHookManager(object):'
206 sets ``PyOS_InputHook``.
257 sets ``PyOS_InputHook``.
207 """
258 """
208 self._current_gui = 'tk'
259 self._current_gui = 'tk'
260 self._hijack_tk()
209
261
210 def disable_tk(self):
262 def disable_tk(self):
211 """Disable event loop integration with Tkinter.
263 """Disable event loop integration with Tkinter.
@@ -230,4 +282,5 b' enable_tk = inputhook_manager.enable_tk'
230 disable_tk = inputhook_manager.disable_tk
282 disable_tk = inputhook_manager.disable_tk
231 clear_inputhook = inputhook_manager.clear_inputhook
283 clear_inputhook = inputhook_manager.clear_inputhook
232 set_inputhook = inputhook_manager.set_inputhook
284 set_inputhook = inputhook_manager.set_inputhook
233 current_gui = inputhook_manager.current_gui No newline at end of file
285 current_gui = inputhook_manager.current_gui
286 clear_app_refs = inputhook_manager.clear_app_refs
@@ -19,6 +19,7 b' Authors: Robin Dunn, Brian Granger, Ondrej Certik'
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 import os
21 import os
22 import signal
22 import sys
23 import sys
23 import time
24 import time
24 from timeit import default_timer as clock
25 from timeit import default_timer as clock
@@ -122,6 +123,12 b' def inputhook_wx3():'
122 if app is not None:
123 if app is not None:
123 assert wx.Thread_IsMain()
124 assert wx.Thread_IsMain()
124
125
126 # The import of wx on Linux sets the handler for signal.SIGINT
127 # to 0. This is a bug in wx or gtk. We fix by just setting it
128 # back to the Python default.
129 if not callable(signal.getsignal(signal.SIGINT)):
130 signal.signal(signal.SIGINT, signal.default_int_handler)
131
125 evtloop = wx.EventLoop()
132 evtloop = wx.EventLoop()
126 ea = wx.EventLoopActivator(evtloop)
133 ea = wx.EventLoopActivator(evtloop)
127 t = clock()
134 t = clock()
@@ -139,7 +146,9 b' def inputhook_wx3():'
139 # 0.001 13%
146 # 0.001 13%
140 # 0.005 3%
147 # 0.005 3%
141 # 0.01 1.5%
148 # 0.01 1.5%
142 # 0.05 0.5%
149 # 0.05 0.5%
150 if clock()-t > 1.0:
151 time.sleep(1.0)
143 if clock()-t > 0.1:
152 if clock()-t > 0.1:
144 # Few GUI events coming in, so we can sleep longer
153 # Few GUI events coming in, so we can sleep longer
145 time.sleep(0.05)
154 time.sleep(0.05)
General Comments 0
You need to be logged in to leave comments. Login now