[Nvda-dev] commit r1883 - in trunk/source: . virtualBuffers

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[Nvda-dev] commit r1883 - in trunk/source: . virtualBuffers

NVDA Subversion
Author: mdcurran
Date: Fri Apr  4 01:54:32 2008
New Revision: 1883

Log:
Again restructured the way virtualBuffers are loaded and unloaded.
*Unmerged the changes in r1872 -- that was a mistake to try using NVDA virtualBuffer objects more like managers.
*The Gecko IA2 virtualBuffer  is a lot more picky when asked if its alive, or whether in fact it should be loaded. It now *must* have readOnly and not busy.
*Greatly simplified event_gainFocus and event_stateChange in the gecko ia2 virtualBuffer as it dos not have to deal with readOnly or busy states.
*Added support for IAccessible2's documentLoadComplete event. If the object the event is for does not have a virtualBuffer, or the virtualBuffer reports as not being alive, virtualBufferHandler.update is called for this object.
*To reflect changes in the virtualBuffer library, the base virtualBuffer's loadBuffer method now passes both a windowHandle and ID to VBufClient_createBuffer. Previously the virtualBuffer library only rendered from the root IAccessible in the given window. Now it will render from the exact object its told to (using both the window and ID). The base virtualBuffer object expects that it has two properties for this use: rootWindowHandle and rootID.
*The gecko ia2 virtualBuffer sets rootWindowhandle to rootNVDAObject's event_windowhandle if it exists and its not 0, or it just uses windowHandle. This fixes a few problems where completely the wrong window was being rendered (which may have looked like the old document was rendered rather than the new one when moving from page to page).
*virtualBufferHandler.update is much more picky when it sees if this object is possibly a gecko ia2 object. It must be ia2, it must be a document, it must have readOnly, it must not have busy, and it must have a windowClass of MozillaContentWindowClass. This hopefully stops the occasional rendering of toolbars and other junk with in documents.

!!!!!Please Note!!!!
New virtualBuffers for Firefox3 / Thunderbird 3 in this revision of trunk need Misc Bindary Dependencies with a date of April 4 2008 or later, as there has been a large change  as buffers are now created with IDs, not just a windowHandle.
http://trac.nvda-project.org/wiki/MiscellaneousDependencies



Modified:
   trunk/source/IAccessibleHandler.py
   trunk/source/virtualBufferHandler.py
   trunk/source/virtualBuffer_lib.py
   trunk/source/virtualBuffers/__init__.py
   trunk/source/virtualBuffers/gecko_ia2.py

Modified: trunk/source/IAccessibleHandler.py
==============================================================================
--- trunk/source/IAccessibleHandler.py (original)
+++ trunk/source/IAccessibleHandler.py Fri Apr  4 01:54:32 2008
@@ -602,7 +602,7 @@
 winUser.EVENT_OBJECT_STATECHANGE:"stateChange",
 winUser.EVENT_OBJECT_VALUECHANGE:"valueChange",
 IA2_EVENT_TEXT_CARET_MOVED:"caret",
-IA2_EVENT_DOCUMENT_CONTENT_CHANGED:"reorder",
+IA2_EVENT_DOCUMENT_LOAD_COMPLETE:"documentLoadComplete",
 }
 
 def manageEvent(name,window,objectID,childID):
@@ -624,6 +624,11 @@
  if obj==focusObject:
  obj=focusObject
  if obj:
+ if name=="documentLoadComplete" and (not obj.virtualBuffer or not obj.virtualBuffer.isAlive()):
+ import virtualBufferHandler
+ v=virtualBufferHandler.update(obj)
+ if v:
+ obj.virtualBuffer=v
  eventHandler.manageEvent(name,obj)
 
 def winEventCallback(handle,eventID,window,objectID,childID,threadID,timestamp):

Modified: trunk/source/virtualBufferHandler.py
==============================================================================
--- trunk/source/virtualBufferHandler.py (original)
+++ trunk/source/virtualBufferHandler.py Fri Apr  4 01:54:32 2008
@@ -32,7 +32,10 @@
  states=obj.states
  #Gecko with IAccessible2 support
  if isinstance(obj,NVDAObjects.IAccessible.IA2.IA2) and windowClassName.startswith('Mozilla') and role==controlTypes.ROLE_DOCUMENT:
- classString="virtualBuffers.gecko_ia2.Gecko_ia2"
+ if controlTypes.STATE_READONLY in states and controlTypes.STATE_BUSY not in states and windowClassName=="MozillaContentWindowClass":
+ classString="virtualBuffers.gecko_ia2.Gecko_ia2"
+ else:
+ return
  #Gecko only with IAccessible support
  elif isinstance(obj,NVDAObjects.IAccessible.IAccessible) and windowClassName.startswith('Mozilla') and role==controlTypes.ROLE_DOCUMENT and controlTypes.STATE_READONLY in states:
  classString="virtualBuffers_old.gecko.Gecko"
@@ -56,10 +59,11 @@
  newClass=getattr(mod,classString)
  globalVars.log.debug("virtualBuffers.IAccessible.update: adding %s at %s (%s)"%(newClass,obj.windowHandle,obj.windowClassName))
  virtualBufferObject=newClass(obj)
- runningTable.add(virtualBufferObject)
- if hasattr(virtualBufferObject,'unloadBuffer'):
- virtualBufferObject.loadBuffer()
- return virtualBufferObject
+ if virtualBufferObject.isAlive():
+ runningTable.add(virtualBufferObject)
+ if hasattr(virtualBufferObject,'unloadBuffer'):
+ virtualBufferObject.loadBuffer()
+ return virtualBufferObject
 
 def killVirtualBuffer(virtualBufferObject):
  try:

Modified: trunk/source/virtualBuffer_lib.py
==============================================================================
--- trunk/source/virtualBuffer_lib.py (original)
+++ trunk/source/virtualBuffer_lib.py Fri Apr  4 01:54:32 2008
@@ -14,13 +14,15 @@
 dll=cdll.virtualBuffer
 
 def dllErrorCheck(res,func,args):
- if res<0:
+ if res<0 or (func==VBufClient_createBuffer and res==0):
  raise RuntimeError("error in %s with args of %s, code %s"%(func.__name__,args,res))
+
  return res
 
 VBufClient_createBuffer=dll.VBufClient_createBuffer
 VBufClient_createBuffer.errcheck=dllErrorCheck
 
+
 VBufClient_destroyBuffer=dll.VBufClient_destroyBuffer
 VBufClient_destroyBuffer.errcheck=dllErrorCheck
 

Modified: trunk/source/virtualBuffers/__init__.py
==============================================================================
--- trunk/source/virtualBuffers/__init__.py (original)
+++ trunk/source/virtualBuffers/__init__.py Fri Apr  4 01:54:32 2008
@@ -116,25 +116,26 @@
  self.rootNVDAObject=rootNVDAObject
  super(VirtualBuffer,self).__init__()
  self.VBufHandle=None
- self.passThrough=True
+ self.passThrough=False
+ self.rootWindowHandle=self.rootNVDAObject.windowHandle
+ self.rootID=0
 
  def loadBuffer(self):
- self.VBufHandle=VBufClient_createBuffer(self.rootNVDAObject.windowHandle,self.backendLibPath)
- self.passThrough=False
+ try:
+ self.VBufHandle=VBufClient_createBuffer(self.rootWindowHandle,self.rootID,self.backendLibPath)
+ except:
+ return virtualBufferHandler.killVirtualBuffer(self)
  focusObject=api.getFocusObject()
- if focusObject==self.rootNVDAObject:
+ if self.isNVDAObjectInVirtualBuffer(focusObject):
+ speech.cancelSpeech()
  if self.passThrough:
+ self.passThrough=False
  virtualBufferHandler.reportPassThrough(self)
- speech.cancelSpeech()
- if controlTypes.STATE_BUSY in self.rootNVDAObject.states:
- speech.speakMessage(controlTypes.speechStateLabels[controlTypes.STATE_BUSY])
- return
  info=self.makeTextInfo(textHandler.POSITION_FIRST)
  sayAllHandler.readText(info,sayAllHandler.CURSOR_CARET)
 
  def unloadBuffer(self):
  if self.VBufHandle is not None:
- self.passThrough=True
  VBufClient_destroyBuffer(self.VBufHandle)
  self.VBufHandle=None
 

Modified: trunk/source/virtualBuffers/gecko_ia2.py
==============================================================================
--- trunk/source/virtualBuffers/gecko_ia2.py (original)
+++ trunk/source/virtualBuffers/gecko_ia2.py Fri Apr  4 01:54:32 2008
@@ -1,4 +1,3 @@
-import time
 import ctypes
 from . import VirtualBuffer, VirtualBufferTextInfo
 from virtualBuffer_lib import *
@@ -49,19 +48,14 @@
 
  def __init__(self,rootNVDAObject):
  super(Gecko_ia2,self).__init__(rootNVDAObject,backendLibPath=u"VBufBackend_gecko_ia2.dll",TextInfo=Gecko_ia2_TextInfo)
-
- def _set_rootNVDAObject(self,obj):
- self._rootWindowHandle=obj.windowHandle
- self._rootUniqueID=obj.IAccessibleObject.uniqueID
- self._rootNVDAObject=obj
- self._rootTime=time.time()
-
- def _get_rootNVDAObject(self):
- curTime=time.time()
- if curTime-self._rootTime<0.25:
- self._rootNVDAObject=NVDAObjects.IAccessible.getNVDAObjectFromEvent(self._rootWindowHandle,IAccessibleHandler.OBJID_CLIENT,self._rootUniqueID)
- self._rootTime=curTime
- return self._rootNVDAObject
+ rootWindowHandle=getattr(self.rootNVDAObject,'event_windowHandle',0)
+ if not rootWindowHandle:
+ rootWindowHandle=self.rootNVDAObject.windowHandle
+ self.rootWindowHandle=rootWindowHandle
+ try:
+ self.rootID=self.rootNVDAObject.IAccessibleObject.uniqueID
+ except:
+ self.rootID=0
 
  def isNVDAObjectInVirtualBuffer(self,obj):
  #Special code to handle Mozilla combobox lists
@@ -85,10 +79,17 @@
 
  def isAlive(self):
  root=self.rootNVDAObject
- if root and winUser.isWindow(root.windowHandle) and controlTypes.STATE_DEFUNCT not in root.states and root.role!=controlTypes.ROLE_UNKNOWN:
- return True
- else:
+ if not root:
+ return False
+ states=root.states
+ if not winUser.isWindow(root.windowHandle) or controlTypes.STATE_DEFUNCT in states or controlTypes.STATE_READONLY not in states or controlTypes.STATE_BUSY in states:
  return False
+ try:
+ if not NVDAObjects.IAccessible.getNVDAObjectFromEvent(root.windowHandle,IAccessibleHandler.OBJID_CLIENT,root.IAccessibleObject.uniqueID):
+ return False
+ except:
+ return False
+ return True
 
  def event_focusEntered(self,obj,nextHandler):
  pass
@@ -96,33 +97,33 @@
  def event_gainFocus(self,obj,nextHandler):
  if self._inFind:
  return
- if not self.isAlive():
- return virtualBufferHandler.killVirtualBuffer(self)
  api.setNavigatorObject(obj)
- states=self.rootNVDAObject.states
- if controlTypes.STATE_BUSY in states:
- speech.speakMessage(controlTypes.speechStateLabels[controlTypes.STATE_BUSY])
- if self.VBufHandle is not None and controlTypes.STATE_READONLY not in states:
- self.unloadBuffer()
+ if self.VBufHandle is None:
  return nextHandler()
- elif self.VBufHandle is not None and controlTypes.STATE_READONLY not in states:
- return self.unloadBuffer()
- elif self.VBufHandle is None:
- self.loadBuffer()
+ if sayAllHandler.isRunning():
+ sayAllHandler.stop()
+ wasSayAll=True
+ else:
+ wasSayAll=False
  if obj==self.rootNVDAObject:
- return speech.speakObjectProperties(obj,name=True)
+ speech.cancelSpeech()
+ speech.speakObjectProperties(obj,name=True,role=True)
+ info=self.makeTextInfo(textHandler.POSITION_FIRST)
+ sayAllHandler.readText(info,sayAllHandler.CURSOR_CARET)
+ return
  if obj.role==controlTypes.ROLE_DOCUMENT:
  return
- if self.VBufHandle is None:
- return nextHandler()
  #We only want to update the caret and speak the field if we're not in the same one as before
  oldInfo=self.makeTextInfo(textHandler.POSITION_CARET)
  try:
  oldDocHandle,oldID=VBufClient_getFieldIdentifierFromBufferOffset(self.VBufHandle,oldInfo._startOffset)
  except:
  oldDocHandle=oldID=0
- docHandle=obj.IAccessibleObject.windowHandle
- ID=obj.IAccessibleObject.uniqueID
+ try:
+ docHandle=obj.IAccessibleObject.windowHandle
+ ID=obj.IAccessibleObject.uniqueID
+ except:
+ return nextHandler()
  if (docHandle!=oldDocHandle or ID!=oldID) and ID!=0:
  try:
  start,end=VBufClient_getBufferOffsetsFromFieldIdentifier(self.VBufHandle,docHandle,ID)
@@ -135,8 +136,7 @@
  endToStart=newInfo.compareEndPoints(oldInfo,"endToStart")
  endToEnd=newInfo.compareEndPoints(oldInfo,"endToEnd")
  if (startToStart<0 and endToEnd>0) or (startToStart>0 and endToEnd<0) or endToStart<0 or startToEnd>0:  
- if sayAllHandler.isRunning():
- speech.cancelSpeech()
+ speech.cancelSpeech()
  speech.speakFormattedTextWithXML(newInfo.XMLContext,newInfo.XMLText,self,newInfo.getXMLFieldSpeech,reason=speech.REASON_FOCUS)
  newInfo.collapse()
  newInfo.updateCaret()
@@ -188,25 +188,9 @@
 
  def event_stateChange(self,obj,nextHandler):
  if not self.isAlive():
- return virtualBufferHandler.killVirtualBuffer(self)
- states=self.rootNVDAObject.states
- if controlTypes.STATE_BUSY in states:
- speech.speakMessage(controlTypes.speechStateLabels[controlTypes.STATE_BUSY])
- if self.VBufHandle is not None and controlTypes.STATE_READONLY not in states:
- self.unloadBuffer()
- return nextHandler()
- elif self.VBufHandle is not None and controlTypes.STATE_READONLY not in states:
- return self.unloadBuffer()
- elif self.VBufHandle is None:
- self.loadBuffer()
+ return virtualBufferHandler.killVirtualBuffer()
  return nextHandler()
 
- def loadBuffer(self):
- states=self.rootNVDAObject.states
- if controlTypes.STATE_BUSY in states or controlTypes.STATE_READONLY not in states:
- return
- super(Gecko_ia2,self).loadBuffer()
-
  def event_scrollingStart(self,obj,nextHandler):
  if self.VBufHandle is None:
  return nextHandler()