1 '''
2 Defines a class responsible for handling events in the currently focused view.
3
4 @var CHECK_INTERVAL: Time in ms that the L{AEViewManager} will iterate over all
5 top level applications and provide them in a list to L{AETierManager}
6 @type CHECK_INTERVAL: integer
7 @var DEFAULT_EVENTS: Names of events that will be dispatched by the
8 L{AEViewManager} by default
9 @type DEFAULT_EVENTS: list
10
11 @author: Peter Parente
12 @author: Pete Brunet
13 @author: Brett Clippingdale
14 @organization: IBM Corporation
15 @copyright: Copyright (c) 2005, 2007 IBM Corporation
16
17 @author: Frank Zenker
18 @author: Ramona Bunk
19 @organization: IT Science Center Ruegen gGmbH, Germany
20 @copyright: Copyright (c) 2007, 2008 ITSC Ruegen
21
22 @license: I{The BSD License}
23 All rights reserved. This program and the accompanying materials are made
24 available under the terms of the BSD license which accompanies
25 this distribution, and is available at
26 U{http://www.opensource.org/licenses/bsd-license.php}
27 '''
28 import pyatspi
29 import AccessEngine
30 from AEEvent import *
31 from AEPor import AEPor
32 from AEAccInterfaces import *
33 from AEWalkers import AccessibleWalker
34
35
36
37 CHECK_INTERVAL = 60000
38
39
40 DEFAULT_EVENTS = [ViewChange, FocusChange, SelectorChange, CaretChange,
41 PropertyChange, PrivateChange]
42
44 '''
45 Stores a root accessible representing the active view when an event occurs
46 indicating that the view may have changed.
47
48 Two view roots must be tracked
49 by this object. The first, the raw view, is needed by L{AEAccAdapters} which will
50 handle raw view change events. The second, the L{AccessEngine} view, is
51 needed by the rest of the system when processing L{AEEvent <AEEvent.AEEvent>}s.
52
53 @ivar raw_view: Root accessible representing the active view according to the
54 raw event stream.
55 @type raw_view: C{pyatspi.Accessible}
56 @ivar ae_view: Root L{AEPor} representing the active view according to the
57 L{AEEvent <AEEvent.AEEvent>} stream.
58 @type ae_view: L{AEPor}
59 @ivar wanted_events: Lookup table for what L{AEEvent <AEEvent.AEEvent>}s are
60 desired by any task in any L{AEScript <AEScript.AEScript>} in all L{AETier}s.
61
62 Used to optimize event dispatch and processing. Unwanted events are ignored.
63 @type wanted_events: dictionary
64 @ivar raw_active: Is there an raw active view?
65 @type raw_active: boolean
66 '''
77
94
96 '''Does nothing and is called by L{AEMain} when quitting the main loop.'''
97 pass
98
100 '''
101 Walks through the top level applications on the first desktop.
102
103 Calls the method C{AETierManager.createAETier} for application encountered.
104 If the L{AETierManager} determines that an app has at least one
105 L{AEScript <AEScript.AEScript>} written for that application, creates an
106 L{AETier} for the application and loads all of
107 its L{AEScript <AEScript.AEScript>}s.
108
109 If the L{AETier} is created, this method sends
110 L{AEEvent.ViewChange} messages to the L{AETier} with a flag of
111 L{AEConstants.Event.EVENT_VIEW_STARTUP} such that L{AEScript <AEScript.AEScript>}s in the L{AETier}
112 may initialize themselves and begin any desired background processes.
113 '''
114 try:
115 d = pyatspi.Registry.getDesktop(0)
116 except Exception:
117
118 return
119 ai = IAccessibleInfo(AEPor(d))
120 an = IAccessibleNav(AEPor(d))
121 events = []
122
123 for i in xrange(ai.getAccChildCount()):
124 try:
125 app = an.getChildAcc(i)
126 except (LookupError, IndexError):
127 continue
128
129 aai = IAccessibleInfo(app)
130 aid = aai.getAccAppID()
131 name = aai.getAccAppName()
132
133 if AccessEngine.AETierManager.createAETier(name, aid, app, True) is not None:
134 events.append(ViewChange(app, AEConstants.EVENT_VIEW_STARTUP))
135
136 if self.raw_view is not None:
137 continue
138 aan = IAccessibleNav(app)
139
140 for x in xrange(aai.getAccChildCount()):
141 try:
142 win = aan.getChildAcc(x)
143 except (LookupError, IndexError):
144 continue
145
146 wai = IAccessibleInfo(win)
147 if wai.hasAccState('active'):
148 self.raw_view = win
149 self.raw_active = True
150 break
151
152 if self.raw_view is not None:
153 events.append(ViewChange(self.raw_view,
154 AEConstants.EVENT_VIEW_FIRST_GAINED))
155 AccessEngine.AEEventManager.postEvents(*events)
156
158 '''
159 Sets or unsets an interest in a particular kind of
160 L{AEEvent <AEEvent.AEEvent>}.
161
162 This information is used to register or unregister for raw events on-demand
163 as an optimization.
164
165 @param kind: Indicates the type of L{AEEvent <AEEvent.AEEvent>} some part of
166 the system wants to be able to process
167 @type kind: L{AEEvent <AEEvent.AEEvent>}
168 @param wants: Does the system want to process the given kind of
169 L{AEEvent <AEEvent.AEEvent>}?
170 @type wants: boolean
171 '''
172 count = self.wanted_events.setdefault(kind, 0)
173 if wants:
174 count += 1
175 else:
176 count -= 1
177 if count <= 0:
178 del self.wanted_events[kind]
179 AccessEngine.AEEventManager.acc_reg.deregisterEventListener(self.onRawEvent,
180 *IEventHandler().getRawEvents(kind))
181 return
182 elif count == 1:
183 AccessEngine.AEEventManager.acc_reg.registerEventListener(self.onRawEvent,
184 *IEventHandler().getRawEvents(kind))
185 self.wanted_events[kind] = count
186
188 '''
189 Gets whether some view is active or not.
190
191 @return: Value of L{raw_active}
192 @rtype: boolean
193 '''
194 return self.raw_active
195
197 '''
198 Sets whether some view is active or not.
199
200 @param val: Value to store in L{raw_active}
201 @type val: boolean
202 '''
203 self.raw_active = val
204
206 '''
207 Gets the root L{AEPor} of the active view according to the raw event
208 stream.
209
210 This is the view known to L{AEAccAdapters}.
211
212 @see: L{setRawView}
213 @return: Root L{AEPor} of the raw active view
214 @rtype: L{AEPor}
215 '''
216 return self.raw_view
217
219 '''
220 Stores the root L{AEPor} of the active view according to the raw event
221 stream.
222
223 This is the view known to L{AEAccAdapters}.
224
225 @see: L{getRawView}
226 @param accessible: Event source that triggered the change of view. Usually
227 a top level window or panel.
228 @type accessible: C{pyatspi.Accessible}
229 @return: Was a new view root set or not?
230 @rtype: boolean
231 '''
232 rv = False
233
234 root = AEPor(accessible)
235
236 if root != self.raw_view:
237
238 self.raw_view = root
239 rv = True
240 return rv
241
243 '''
244 Gets the root L{AEPor} of the active view according to the
245 L{AEEvent <AEEvent.AEEvent>} stream.
246
247 This is the view known to L{AEScript <AEScript.AEScript>}s.
248
249 @see: L{setAEView}
250 @return: Root L{AEPor} of the active L{AEMain} view
251 @rtype: L{AEPor}
252 '''
253 return self.ae_view
254
256 '''
257 Stores the root L{AEPor} of the active view according to the
258 L{AEEvent <AEEvent.AEEvent>} stream.
259
260 This is the view known to L{AEAccAdapters}.
261
262 @see: L{getAEView}
263 @param por: New root L{AEPor} of the active L{AEMain} view. May
264 be set to C{None} if there is no active view.
265 @type por: L{AEPor}
266 '''
267 self.ae_view = por
268
270 '''
271 Collects all application names and IDs and gives them to the L{AETierManager}
272 so it can free any L{AETier}s that are no longer associated with running
273 applications.
274
275 @return: C{True} to continue receiving notifications
276 @rtype: boolean
277 '''
278 try:
279 d = pyatspi.Registry.getDesktop(0)
280 except Exception:
281
282 return
283 ai = IAccessibleInfo(AEPor(d))
284 an = IAccessibleNav(AEPor(d))
285 aids = []
286
287 for i in xrange(ai.getAccChildCount()):
288 try:
289 app = an.getChildAcc(i)
290 except (LookupError, IndexError):
291 continue
292
293 aai = IAccessibleInfo(app)
294 aids.append(aai.getAccAppID())
295
296 AccessEngine.AETierManager.freeDeadAETiers(aids)
297 return True
298
300 '''
301 Based on a raw C{pyatspi.event.Event} posts L{AEEvent <AEEvent.AEEvent>}s
302 to the active L{AETier} through the L{AEEventManager}.
303
304 @param event: Event indicating some change
305 @type event: C{pyatspi.event.Event}
306 '''
307
308 if self.raw_view is not None:
309 try:
310 eh = IEventHandler(event.source)
311 eh.getAEEvents(event, AccessEngine.AEEventManager.postEvents)
312 except LookupError:
313
314 return
315
317 '''
318 Creates a L{AEEvent.ViewChange} event in response to a window activation or
319 deactivation.
320
321 Also responds to create or destroy events from floating
322 windows. Called in response to any of the raw events returned by
323 L{AEAccInterfaces.IEventHandler.getAEViewEvents} and registered with the
324 L{AEEventManager} in the C{AEViewManager.init} method when this object was
325 created.
326
327 @param event: Event that may indicate the view has changed
328 @type event: C{pyatspi.event.Event}
329 '''
330 try:
331 eh = IEventHandler(event.source)
332 eh.getAEViewEvents(event, AccessEngine.AEEventManager.postEvents, self)
333 except LookupError:
334
335 return
336