1 '''
2 Defines a class that extends L{pyLinAcc.Event.Manager} to support L{AEEvent}s.
3
4 @var MAX_EVENT: Maximum number of raw or L{AEEvent}s to process in a single
5 callback from the main loop
6 @type MAX_EVENTS: integer
7 @var EVENT_INTERVAL: Number of ms between calls to pump the event queues
8 @type EVENT_INTERVAL: integer
9
10 @author: Peter Parente
11 @author: Pete Brunet
12 @organization: IBM Corporation
13 @copyright: Copyright (c) 2005, 2007 IBM Corporation
14 @license: The BSD License
15
16 All rights reserved. This program and the accompanying materials are made
17 available under the terms of the BSD license which accompanies
18 this distribution, and is available at
19 U{http://www.opensource.org/licenses/bsd-license.php}
20 '''
21 import pyLinAcc
22 import Queue, time, logging
23 import AEEvent, AEMonitor, UIRegistrar, AEConstants
24 from AEInterfaces import implements
25 from UIRegistrar import MONITOR
26 from i18n import _
27
28 log = logging.getLogger('Event')
29 EVENT_INTERVAL = 10
30 MAX_EVENTS = 10
31
33 '''
34 Watches for AT-SPI events and reports them to observers. Maintains a queue
35 of L{AEEvent} that are executed on a set interval.
36
37 @ivar acc_eng: Reference to the L{AccessEngine} object
38 @type acc_eng: L{AccessEngine}
39 @ivar view_manager: Reference to the L{ViewManager} object
40 @type view_manager: L{ViewManager}
41 @ivar tier_manager: Reference to the L{TierManager} object
42 @type tier_manager: L{TierManager}
43 @ivar raw_queue: FIFO queue of L{pyLinAcc.Event.Event}s to be dispatched
44 @type raw_queue: Queue.Queue
45 @ivar ae_queue: FIFO queue of L{AEEvent} to be executed
46 @type ae_queue: Queue.Queue
47 @ivar timer_id: ID of the timer pumping the event queue
48 @type timer_id: integer
49 @ivar last_event:
50 @type last_event: L{AEEvent}
51 '''
53 '''
54 Initializes the parent class. Creates an event queue. Asks the
55 L{AccessEngine} to schedule interval callbacks to the
56 L{EventManager.onPumpRawEvents} and L{EventManager.onPumpAEEvents} methods.
57
58 @param acc_eng: Reference to the L{AccessEngine} that created this manager
59 @type acc_eng: L{AccessEngine}
60 '''
61 pyLinAcc.Event.Manager.__init__(self)
62 self.acc_eng = acc_eng
63 self.ae_queue = Queue.Queue()
64 self.raw_queue = Queue.Queue()
65 self.monitors = AEMonitor.MonitorCollection()
66 self.last_event = None
67
68
69
70 self.acc_eng.addTimer(self.onPumpRawEvents, EVENT_INTERVAL)
71 self.acc_eng.addTimer(self.onPumpAEEvents, EVENT_INTERVAL)
72
73 - def init(self, view_man, tier_man, **kwargs):
74 '''
75 Stores references to the L{ViewManager} and L{TierManager}. Instantiates all
76 L{AEMonitor} UIEs registered with L{UIRegistrar} to be loaded at startup.
77 Called by L{AccessEngine} at startup.
78
79 @param tier_man: Reference to the L{TierManager}
80 @type tier_man: L{TierManager}
81 @param view_man: Reference to the L{ViewManager}
82 @type view_man: L{ViewManager}
83 @param kwargs: References to managers not of interest here
84 @type kwargs: dictionary
85 '''
86
87 self.view_manager = view_man
88 self.tier_manager = tier_man
89
90 reg = UIRegistrar
91 mons = reg.loadAssociated(MONITOR, self.acc_eng.getProfile())
92 self.addMonitors(*mons)
93
95 '''
96 Throws away all events in the L{raw_queue} and L{ae_queue}. Calls the parent
97 class close method.
98 '''
99 super(EventManager, self).close()
100 self.raw_queue = Queue.Queue()
101 self.ae_queue = Queue.Queue()
102 self.monitors.clear()
103
105 '''
106 Adds one or more L{AEMonitor}s to the list of monitors to be
107 notified about events.
108
109 @param monitors: L{AEMonitor}s to notify
110 @type monitors: tuple of L{AEMonitor}s
111 '''
112 self.monitors.add(pyLinAcc.Event.Event, monitors)
113
115 '''
116 @return: Collection of all loaded L{AEMonitor}s
117 @rtype: L{AEMonitor.MonitorCollection}
118 '''
119 return self.monitors
120
122 '''
123 Informs L{AEMonitor}s added via L{addMonitors} of a raw event.
124
125 @param event: Raw accessibility event
126 @type event: L{pyLinAcc.Event.Event}
127 '''
128 self.monitors.show(event=event)
129
131 '''
132 Executes the provided L{AEEvent}. Provides references to all managers as
133 named parameters to the event's execute method. Catches and logs all
134 exceptions to prevent bad events from getting re-queued for later execution.
135
136 @param event: Event to execute
137 @type event: L{AEEvent}
138 @return: Did the event execute properly or does it need to be re-queued for
139 later execution?
140 @rtype: True
141 '''
142
143 try:
144 return event.execute(view_manager=self.view_manager,
145 tier_manager=self.tier_manager,
146 event_manager=self)
147 except LookupError:
148
149 return True
150 except Exception, e:
151
152 log.exception(str(e))
153 return True
154
156 '''
157 Flushes the event queue by destroying it and recreating it.
158 '''
159 self.ae_queue = Queue.Queue()
160 self.raw_queue = Queue.Queue()
161
162 - def postEvents(self, *events):
163 '''
164 Add L{AEEvent}s to the queue. Events can be added by any part of the system
165 Events marked with immediate priority are executed now instead of being
166 added to the queue. Immediate execution is necessary for some kinds of
167 events.
168
169 @param events: Events to queue for dispatch
170 @type events: tuple of L{AEEvent}s
171 '''
172 for e in events:
173 if e is not None:
174 if e.priority == AEConstants.EXEC_IMMEDIATE:
175
176 if self._executeEvent(e) == False:
177
178 log.debug('re-queuing immediate AEEvent')
179 self.ae_queue.put_no_wait(e)
180 else:
181 self.ae_queue.put_nowait(e)
182
184 '''
185 Overrides the base implementation of L{handleEvent} so that all
186 L{pyLinAcc.Event.Event}s of interest are queued rather than immediately
187 dispatched. This breaks the synchronous connection between LSR and the rest
188 of the desktop. See L{pyLinAcc.Event.Manager.handleEvent} for more details.
189
190 @param event: Wrapped AT-SPI event
191 @type event: L{pyLinAcc.Event.Event}
192 '''
193 self.raw_queue.put_nowait(event)
194
196 '''
197 Pumps all L{pyLinAcc.Event.Event}s in the L{raw_queue}. Calls the inherited
198 L{pyLinAcc.Event.Manager._dispatchEvent} method to forward to the event to
199 all registered clients. Catches and logs all exceptions to prevent them
200 from propogating to the main loop that called this method.
201
202 This method is called on a set interval by the main event loop in
203 L{AccessEngine.AccessEngine.run}. It is registered for callbacks in the
204 constructor of this class.
205
206 @return: True to continue receiving notifications
207 @rtype: boolean
208 '''
209 for i in xrange(MAX_EVENTS):
210 try:
211
212 event = self.raw_queue.get_nowait()
213 except Queue.Empty:
214 break
215
216 self.showEvent(event)
217 try:
218 self._dispatchEvent(event)
219 except LookupError:
220 break
221 except Exception:
222
223 log.exception('Raw event exception')
224 return True
225
227 '''
228 Pumps all L{AEEvent}s in the L{ae_queue}. Executes each event pumped.
229 Re-queues events for later execution that return False from their execute
230 methods.
231
232 This method is called on a set interval by the main event loop in
233 L{AccessEngine.AccessEngine.run}. It is registered for callbacks in the
234 constructor of this class.
235
236 @return: True to continue receiving notifications
237 @rtype: boolean
238 '''
239 later = []
240 for i in xrange(MAX_EVENTS):
241 try:
242 event = self.ae_queue.get_nowait()
243 except Queue.Empty:
244 break
245 rv = self._executeEvent(event)
246 if rv == False:
247
248 later.append(event)
249 log.debug('re-queuing AEEvent')
250 self.last_event = event
251
252 map(self.postEvents, later)
253 return True
254