1 '''
2 Defines a class responsible for managing all L{AETier}s.
3
4 @author: Peter Parente
5 @author: Pete Brunet
6 @organization: IBM Corporation
7 @copyright: Copyright (c) 2005, 2007 IBM Corporation
8
9 @author: Frank Zenker
10 @author: Ramona Bunk
11 @organization: IT Science Center Ruegen gGmbH, Germany
12 @copyright: Copyright (c) 2007, 2008 ITSC Ruegen
13
14 @license: I{The BSD License}
15 All rights reserved. This program and the accompanying materials are made
16 available under the terms of the BSD license which accompanies
17 this distribution, and is available at
18 U{http://www.opensource.org/licenses/bsd-license.php}
19 '''
20 import logging
21 import AccessEngine
22 from AccessEngine import AERegistrar, AEEvent, AEMonitor
23 import AEState, AEConstants
24 from AETier import AETier
25 from AERegistrar import MONITOR, SCRIPT
26 from AccessEngine.AEAccInterfaces import implements
27 from Tools.i18n import _
28
29 log = logging.getLogger('AETier')
30
31
33 '''
34 Creates L{AETier}s for all processes detectable by C{pyatspi}.
35
36 Routes L{AEEvent <AEEvent.AEEvent>}s to the active AETier for handling by
37 task functions registered by L{AEScript <AEScript.AEScript>}s.
38 Changes the active AETier as the active top-level application changes.
39
40 @ivar tiers: All L{AETier}s created for running applications::
41 Dictionary: {
42 key: unique application ID,
43 value: AETier
44 }
45 @type tiers: dictionary
46 @ivar active_tier: AETier for the application currently in focus
47 @type active_tier: L{AETier}
48 @ivar state: Global state informaion.
49
50 Has properties representing system-wide settings.
51 @type state: L{AEState <AEState.AEState>}
52 @ivar monitors: Collection of all loaded L{AEMonitor <AEMonitor.AEMonitor>}s
53 @type monitors: L{AEMonitor.MonitorCollection}
54 @ivar gesture: counts how often in a row the last key combination was pressed::
55 gesture[0]: pressed key,
56 gesture[1]: counts how often in a row the key was pressed
57 @type gesture: list with two entrys
58 '''
60 '''
61 Creates the empty dictionary for storing L{AETier}s and initializes the
62 active tier to None.
63 '''
64 self.state = None
65 self.tiers = {}
66 self.active_tier = None
67 self.monitors = AEMonitor.MonitorCollection()
68 self.gesture = [None, 0]
69
70 - def init(self, application_state):
91
104
106 '''
107 Gets the shared state for all L{AETier}s
108
109 @return: State shared across all AETiers
110 @rtype: L{AEState <AEState.AEState>}
111 '''
112 return self.state
113
115 '''
116 Gets all loaded L{AEMonitor <AEMonitor.AEMonitor>}s
117
118 @return: Collection of all loaded AEMonitors
119 @rtype: L{AEMonitor.MonitorCollection}
120 '''
121 return self.monitors
122
124 '''
125 Adds one or more L{AEMonitor <AEMonitor.AEMonitor>}s to the list of monitors
126 to be notified about events.
127
128 @param monitors: Monitors to notify
129 @type monitors: tuple of L{AEMonitor <AEMonitor.AEMonitor>}s
130 '''
131 self.monitors.add(AEEvent.Base.AEEvent, monitors)
132
134 '''
135 Informs L{AEMonitor <AEMonitor.AEMonitor>}s added via L{addMonitors} of a
136 script task executing or updating.
137
138 @param task_name: registered name of the task handling the event
139 @type task_name: string
140 @param script: Script in which the task function is implemented
141 @type script: L{AEScript <AEScript.AEScript>}
142 '''
143 self.monitors.show(task_name=task_name, script=script)
144
146 '''
147 Informs L{AEMonitor <AEMonitor.AEMonitor>}s added via L{addMonitors} of an
148 event.
149
150 @param event: An event object
151 @type event: L{AEEvent <AEEvent.AEEvent>}
152 @param tier_name: Name of the L{AETier} executing the event
153 @type tier_name: string
154 '''
155 self.monitors.show(event=event, tier_name=tier_name)
156
157 - def showChain(self, chain_type, anchor_ident):
158 '''
159 Informs L{AEMonitor <AEMonitor.AEMonitor>}s added via L{addMonitors} of a
160 chained script task executing.
161
162 @param chain_type: One of the L{AEConstants} CHAIN_* constants
163 @type chain_type: integer
164 @param anchor_ident: Identifier of the anchor task
165 @type anchor_ident: string
166 '''
167 self.monitors.show(chain_type=chain_type, anchor_ident=anchor_ident)
168
170 '''
171 Informs L{AEMonitor <AEMonitor.AEMonitor>}s added via L{addMonitors} of the
172 propagation return value from a script task.
173
174 @param propagate: Was the event consumed (C{False}) or allowed to propagate
175 (C{True})?
176 @type propagate: boolean
177 '''
178 self.monitors.show(propagate=propagate)
179
181 '''
182 Compares the list of given application names and IDs with those currently
183 associated with L{AETier}s.
184
185 Frees tiers in the L{tiers} dictionary that no longer have associated
186 applications.
187
188 @param aids: List of identifiers for applications currently in existence
189 @type aids: list
190 '''
191 map(self.removeAETier, set(self.tiers) - set(aids))
192
194 '''
195 Creates a new L{AETier} using the application name and ID as a hash code.
196
197 If C{init} is C{True}, only creates the L{AETier} if a specific
198 L{AEScript <AEScript.AEScript>} is associated with this profile for the
199 named application.
200
201 @param name: Name of the now active application
202 @type name: string
203 @param aid: Unique ID for the application associated with the L{AETier}
204 @type aid: hashable
205 @param por: Point of regard to the top object represented by the L{AETier}
206 @type por: L{AEPor <AEPor.AEPor>}
207 @param init: Initialize the L{AETier} only if a
208 L{AEScript <AEScript.AEScript>} is associated for this particular
209 application?
210 @type init: boolean
211 @return: The new L{AETier} that was created
212 @rtype: L{AETier}
213 '''
214
215 reg = AERegistrar
216 prof = AccessEngine.AESettingsManager.getProfileName()
217
218
219 if init and not reg.hasAETierAssociated(SCRIPT, prof, name):
220 return None
221
222 tier = AETier(name, aid, por)
223 self.tiers[aid] = tier
224
225 scripts = reg.loadAssociated(SCRIPT, prof, name)
226 tier.pushScript(*scripts)
227 log.debug('created AETier %s', name)
228 return tier
229
231 '''
232 Removes an existing L{AETier}.
233
234 @param aid: Unique ID for the application associated with the L{AETier}
235 @type aid: hashable
236 '''
237 self.tiers[aid].clearScripts()
238 del self.tiers[aid]
239 log.debug('removed AETier %s', aid)
240
242 '''
243 Switches the active L{AETier} based on the current view's root accessible.
244
245 The view's root accessible is queried for information that can uniquely
246 identify the AETier to use.
247
248 If an AETier already exists for the given view, it is activated. If one
249 does not exist, an AETier is created using L{createAETier} and made active.
250
251 @param name: Name of the now active application
252 @type name: string
253 @param aid: Unique ID for the application associated with the L{AETier}
254 @type aid: hashable
255 @param por: Point of regard to the top object represented by the L{AETier}
256 @type por: L{AEPor <AEPor.AEPor>}
257 '''
258 try:
259 tier = self.tiers[aid]
260 except KeyError:
261
262 tier = self.createAETier(name, aid, por, False)
263
264 self.active_tier = tier
265
267 '''
268 Informs the L{AEViewManager} of a change in interest in
269 L{AEEvent <AEEvent.AEEvent>}s by some L{AETier}.
270
271 Used to optimize which system events are monitored in order to improve
272 performance. Just acts as a proxy.
273
274 @param kind: Kind of AEEvent of interest to a script task
275 @type kind: L{AEEvent <AEEvent.AEEvent>}
276 @param wants: Does a L{AEScript <AEScript.AEScript>} wants an event
277 (i.e. a task is registering for it) or no longer wants an event
278 (i.e. a task is unregistering for it)?
279 @type wants: boolean
280 '''
281 AccessEngine.AEViewManager.setEventInterest(kind, wants)
282
284 '''
285 Resets the gesture sequence counter.
286 '''
287 self.gesture = [None, 0]
288
290 '''
291 Dispatches an L{AEEvent <AEEvent.AEEvent>} to the L{AETier} to be handled by
292 its L{AEScript <AEScript.AEScript>}s.
293
294 Makes the final determination of on what layer the event occurred. Events
295 from a focused source are already marked as
296 L{AEConstants.Event.LAYER_FOCUS}. Events from an unfocused source in the
297 active AETier are marked as L{AEConstants.Event.LAYER_TIER}. All other
298 events for which a AETier exists to handle them are marked as
299 L{AEConstants.Event.LAYER_BACKGROUND}.
300
301 @param event: Event to dispatch to the L{AETier}
302 @type event: L{AEEvent <AEEvent.AEEvent>}
303 '''
304
305
306 if self.active_tier and self.active_tier.wantsEvent(event):
307
308 task_layer = event.getLayer()
309 else:
310
311 task_layer = AEConstants.LAYER_BACKGROUND
312
313 aid = event.getAppID()
314 if aid is None:
315
316 tier = self.active_tier
317
318 else:
319 try:
320
321 tier = self.tiers[aid]
322
323 except KeyError:
324
325 return
326
327 if tier is not self.active_tier:
328
329
330 event.setLayer(AEConstants.LAYER_BACKGROUND)
331 elif task_layer != AEConstants.LAYER_FOCUS:
332
333
334 event.setLayer(AEConstants.LAYER_TIER)
335
336 tier.setShow(len(self.monitors))
337 tier.manageEvent(event)
338 tier.clearState()
339
341 '''
342 Dispatches an L{AEEvent <AEEvent.AEEvent>} to the active L{AETier} so that
343 it can determine which registered script task, if any, should be executed in
344 response to some L{AEInput.Gesture}.
345
346 @param event: Event to dispatch to the L{AETier}
347 @type event: L{AEEvent <AEEvent.AEEvent>}
348 '''
349 tier = self.active_tier
350 if tier is not None:
351
352 g = event.getTaskKey()
353 if g == self.gesture[0]:
354 self.gesture[1] += 1
355 else:
356 self.gesture[0] = g
357 self.gesture[1] = 0
358
359 tier.setShow(len(self.monitors))
360 tier.manageGesture(event, self.gesture[1])
361 tier.clearState()
362
364 '''
365 Dispatches an L{AEEvent.ChooserChange} to the L{AETier} associated with the
366 event so that it can determine which registered script task, if any, should
367 be executed in response to a change in the chooser such as its completion or
368 its cancellation.
369
370 @param event: Event to dispatch to the L{AETier}
371 @type event: L{AEEvent.ChooserChange}
372 '''
373 aid = event.getAppID()
374 try:
375
376 tier = self.tiers[aid]
377 except KeyError:
378 return
379
380 tier.setShow(len(self.monitors))
381 tier.manageChooserTask(event)
382 tier.clearState()
383
385 '''
386 Dispatches an L{AEEvent.TimerAlert} to the L{AETier} associated with the
387 event so that it can determine which registered task, if any, should be
388 executed in response to the timer firing.
389
390 @param event: Event to dispatch to the L{AETier}
391 @type event: L{AEEvent.TimerAlert}
392 '''
393 aid = event.getAppID()
394 try:
395
396 tier = self.tiers[aid]
397 except KeyError:
398 return
399 if tier is self.active_tier:
400
401 event.setLayer(AEConstants.LAYER_TIER)
402
403 tier.setShow(len(self.monitors))
404 tier.manageTimerTask(event)
405 tier.clearState()
406
408 '''
409 Dispatches an L{AEEvent.PrivateChange} to the active L{AETier} so it can
410 store important information without passing it along to
411 L{AEScript <AEScript.AEScript>}s and tasks.
412
413 @param event: Event to dispatch to the L{AETier}
414 @type event: L{AEEvent.PrivateChange}
415 '''
416 if self.active_tier is not None:
417 self.active_tier.managePrivate(event)
418 self.active_tier.clearState()
419
421 '''
422 Gets all L{AETier}s created for running applications.
423
424 @return: dictionary L{tiers} with all created L{AETier}s
425 @rtype: dictionary
426 '''
427 return self.tiers
428