Module ViewManager
[hide private]
[frames] | no frames]

Source Code for Module ViewManager

  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{ViewManager} will iterate over all 
  5    top level applications and provide them in a list to L{TierManager} 
  6  @type CHECK_INTERVAL: integer 
  7  @var DEFAULT_EVENTS: Names of events that will be dispatched by the  
  8    L{ViewManager} 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  @license: The BSD License 
 17   
 18  All rights reserved. This program and the accompanying materials are made  
 19  available under the terms of the BSD license which accompanies 
 20  this distribution, and is available at 
 21  U{http://www.opensource.org/licenses/bsd-license.php} 
 22  ''' 
 23  import logging 
 24  import pyLinAcc 
 25  from AEEvent import * 
 26  from POR import POR 
 27  from AEInterfaces import * 
 28  from Walker import AccessibleWalker 
 29   
 30  log = logging.getLogger('View') 
 31   
 32  # interval on which the manager will search for dead views 
 33  CHECK_INTERVAL = 60000 
 34   
 35  # events that we should always watch, regardless of Task interests 
 36  DEFAULT_EVENTS = [ViewChange, FocusChange, SelectorChange, CaretChange,  
 37                    PropertyChange, PrivateChange] 
 38   
39 -class ViewManager(object):
40 ''' 41 Stores a root accessible representing the active view when an event occurs 42 indicating that the view may have changed. Two view roots must be tracked 43 by this object. The first, the raw view, is needed by L{Adapters} which will 44 handle raw view change events. The second, the L{AccessEngine} view, is 45 needed by the rest of the system when processing L{AEEvent}s. 46 47 @ivar event_manager: Reference to the L{EventManager} 48 @type event_manager: L{EventManager} 49 @ivar raw_view: Root accessible representing the active view according to the 50 raw event stream. 51 @type raw_view: L{pyLinAcc.Accessible} 52 @ivar ae_view: Root L{POR} represnting the active view according to the 53 L{AEEvent} stream. 54 @type ae_view: L{POR} 55 @ivar tier_manager: Reference to the L{TierManager} for clearing dead L{Tier} 56 objects on a set interval 57 @type tier_manager: L{TierManager} 58 @ivar wanted_events: Lookup table for what L{AEEvent}s are desired by any 59 L{Task} in any L{Perk} in all L{Tier}s. Used to optimize event dispatch and 60 processing. Unwanted events are ignored. 61 @type wanted_events: dictionary 62 @ivar raw_active: Is there an raw active view? 63 @type raw_active: boolean 64 '''
65 - def __init__(self, ae):
66 ''' 67 Initializes instance variables that will store a reference to the 68 L{EventManager} and active view to None. 69 70 @param ae: Reference to the L{AccessEngine}, currently unused 71 @type ae: L{AccessEngine} 72 ''' 73 self.tier_manager = None 74 self.event_manager = None 75 self.raw_view = None 76 self.wanted_events = {} 77 self.raw_active = False 78 # register for a callback to check living applications 79 ae.addTimer(self.onIterateApps, CHECK_INTERVAL)
80
81 - def init(self, event_man, tier_man, **kwargs):
82 ''' 83 Stores a reference to the L{EventManager}. Registers with the 84 L{EventManager} using the L{EventManager.EventManager.addClient} to receive 85 raw events related to the active view. Also registers 86 for raw events that may indicate that this L{ViewManager} needs to manage a 87 new view. Called by L{AccessEngine} at startup. 88 89 @param event_man: Reference to the L{EventManager} 90 @type event_man: L{EventManager} 91 ''' 92 # store the tier manager so we can note running applications at startup 93 self.tier_manager = tier_man 94 # store the event manager so we can post events later 95 self.event_manager = event_man 96 # register for events that almost certainly mean the view has changed 97 self.event_manager.addClient(self.onRawViewEvent, 98 *IEventHandler().getRawEvents(ViewChange)) 99 # track how many dependencies we have on a certain kind of event 100 for kind in DEFAULT_EVENTS: 101 self.setEventInterest(kind, True)
102
103 - def close(self):
104 '''Does nothing.''' 105 pass
106
107 - def initViews(self):
108 ''' 109 Walks through the top level applications on the first desktop. Calls 110 L{TierManager.TierManager.createTier} for application encountered. If the 111 L{TierManager} determines that an app has at least one L{Perk} written for 112 that application, creates a L{Tier} for the application and loads all of 113 its L{Perk}s. If the L{Tier} is created, this method sends 114 L{AEEvent.ViewChange} messages to the L{Tier} with a flag of 115 L{AEConstants.Event.EVENT_VIEW_STARTUP} such that L{Perk}s in the L{Tier} 116 may initialize themselves and begin any desired background processes. 117 ''' 118 try: 119 d = pyLinAcc.Registry.getDesktop(0) 120 except Exception: 121 # just stop if we get an error right away 122 return 123 ai = IAccessibleInfo(POR(d)) 124 an = IAccessibleNav(POR(d)) 125 events = [] 126 # iterate over all children of the desktop 127 for i in xrange(ai.getAccChildCount()): 128 try: 129 app = an.getChildAcc(i) 130 except (LookupError, IndexError): 131 continue 132 # get application names and IDs 133 aai = IAccessibleInfo(app) 134 aid = aai.getAccAppID() 135 name = aai.getAccAppName() 136 # inform the tier manager 137 if self.tier_manager.createTier(name, aid, app, True) is not None: 138 events.append(ViewChange(app, AEConstants.EVENT_VIEW_STARTUP)) 139 # if we've found the active app, just continue 140 if self.raw_view is not None: 141 continue 142 aan = IAccessibleNav(app) 143 # iterate over all top level windows in the app 144 for x in xrange(aai.getAccChildCount()): 145 try: 146 win = aan.getChildAcc(x) 147 except (LookupError, IndexError): 148 continue 149 # look for one that has state active 150 wai = IAccessibleInfo(win) 151 if wai.hasAccState('active'): 152 self.raw_view = win 153 self.raw_active = True 154 break 155 # send a view change gained event to the active tier 156 if self.raw_view is not None: 157 events.append(ViewChange(self.raw_view, 158 AEConstants.EVENT_VIEW_FIRST_GAINED)) 159 self.event_manager.postEvents(*events)
160
161 - def setEventInterest(self, kind, wants):
162 ''' 163 Sets or unsets an interest in a particular kind of L{AEEvent}. This 164 information is used to register or unregister for raw events on-demand as 165 an optimization. 166 167 @param kind: Indicates the type of L{AEEvent} some part of the system wants 168 to be able to process 169 @type kind: L{AEEvent} class 170 @param wants: Does the system want to process the given kind of L{AEEvent}? 171 @type wants: boolean 172 ''' 173 count = self.wanted_events.setdefault(kind, 0) 174 if wants: 175 count += 1 176 else: 177 count -= 1 178 if count <= 0: 179 del self.wanted_events[kind] 180 self.event_manager.removeClient(self.onRawEvent, 181 *IEventHandler().getRawEvents(kind)) 182 return 183 elif count == 1: 184 self.event_manager.addClient(self.onRawEvent, 185 *IEventHandler().getRawEvents(kind)) 186 self.wanted_events[kind] = count
187
188 - def getRawActive(self):
189 ''' 190 Gets the whether some view is active or not. 191 192 @return: Value of L{raw_active} 193 @rtype: boolean 194 ''' 195 return self.raw_active
196
197 - def setRawActive(self, val):
198 ''' 199 Sets the whether some view is active or not. 200 201 @param val: Value to store in L{raw_active} 202 @type val: boolean 203 ''' 204 self.raw_active = val
205
206 - def getRawView(self):
207 ''' 208 Gets the root L{POR} of the active view according to the raw event 209 stream. This is the view known to L{Adapters}. 210 211 @see: L{setRawView} 212 @return: Root L{POR} of the raw active view 213 @rtype: L{POR} 214 ''' 215 return self.raw_view
216
217 - def setRawView(self, accessible):
218 ''' 219 Stores the root L{POR} of the active view according to the raw event 220 stream. This is the view known to L{Adapters}. 221 222 @see: L{getRawView} 223 @param accessible: Event source that triggered the change of view. Usually 224 a top level window or panel. 225 @type accessible: L{pyLinAcc.Accessible} 226 @return: Was a new view root set or not? 227 @rtype: boolean 228 ''' 229 rv = False 230 # walk to the first POR 231 root = POR(accessible) 232 # see if it is different from our current root POR 233 if root != self.raw_view: 234 # store the new view 235 self.raw_view = root 236 rv = True 237 return rv
238
239 - def getAEView(self):
240 ''' 241 Gets the root L{POR} of the active view according to the L{AEEvent} stream. 242 This is the view known to L{Perk}s. 243 244 @see: L{setAEView} 245 @return: Root L{POR} of the active L{AccessEngine} view 246 @rtype: L{POR} 247 ''' 248 return self.ae_view
249
250 - def setAEView(self, por):
251 ''' 252 Stores the root L{POR} of the active view according to the L{AEEvent} 253 stream. This is the view known to L{Adapters}. 254 255 @see: L{getAEView} 256 @param por: New root L{POR} of the active L{AccessEngine} view. May be 257 set to None if there is no active view. 258 @type por: L{POR} 259 ''' 260 self.ae_view = por
261
262 - def onIterateApps(self):
263 ''' 264 Collects all application names and IDs and gives them to the L{TierManager} 265 so it can free any L{Tier}s that are no longer associated with running 266 applications. 267 268 @return: True to continue receiving notifications 269 @rtype: boolean 270 ''' 271 try: 272 d = pyLinAcc.Registry.getDesktop(0) 273 except Exception: 274 # stop if we get an error immediately 275 return 276 ai = IAccessibleInfo(POR(d)) 277 an = IAccessibleNav(POR(d)) 278 aids = [] 279 # iterate over all children of the desktop 280 for i in xrange(ai.getAccChildCount()): 281 try: 282 app = an.getChildAcc(i) 283 except (LookupError, IndexError): 284 continue 285 # get all application identifiers 286 aai = IAccessibleInfo(app) 287 aids.append(aai.getAccAppID()) 288 # inform the TierManager about the living applications 289 self.tier_manager.freeDeadTiers(aids) 290 return True
291
292 - def onRawEvent(self, event):
293 ''' 294 Based on a raw L{pyLinAcc.Event.Event} posts L{AEEvent}s to the active 295 L{Tier} through the L{EventManager}. 296 297 @param event: Event indicating some change 298 @type event: L{pyLinAcc.Event.Event} 299 ''' 300 # only forward events if there is a view 301 if self.raw_view is not None: 302 try: 303 eh = IEventHandler(event.source) 304 eh.getAEEvents(event, self.event_manager.postEvents) 305 except LookupError: 306 # ignore dead accessibles 307 return
308
309 - def onRawViewEvent(self, event):
310 ''' 311 Creates a L{AEEvent.ViewChange} event in response to a window activation or 312 deactivation. Also responds to create or destroy events from floating 313 windows. Called in response to any of the raw events returned by 314 L{AEInterfaces.IEventHandler.getAEViewEvents} and registered with the 315 L{EventManager} in the L{ViewManager.init} method when this object was 316 created. 317 318 @param event: Event that may indicate the view has changed 319 @type event: L{pyLinAcc.Event.Event} 320 ''' 321 try: 322 eh = IEventHandler(event.source) 323 eh.getAEViewEvents(event, self.event_manager.postEvents, self) 324 except LookupError: 325 # ignore dead accessibles 326 return
327