Changeset 2468

Show
Ignore:
Timestamp:
11/04/08 10:45:51 (2 months ago)
Author:
bzr
Message:

Merge vbufPassThroughImprovements branch.

  • change: Instead of virtual buffer pass through on and off, NVDA now reports focus mode (pass through on) and browse mode (pass through off).
  • new: You can now press escape when in focus mode to return to browse mode.
  • new: In virtual buffers, when the focus changes or the caret is moved, NVDA can automatically switch to focus mode or browse mode as appropriate for the control under the caret. This is configured from the Virtual Buffers dialog. (#157)
Location:
trunk
Files:
12 modified

Legend:

Unmodified
Added
Removed
  • trunk

    • Property bzr:revision-info
      •  

        old new  
        1 timestamp: 2008-11-04 13:55:06.174999952 +1000 
         1timestamp: 2008-11-04 20:40:07.644999981 +1000 
        22committer: James Teh <jamie@jantrid.net> 
        33properties:  
    • Property bzr:ancestry:v3-list-QlpoOTFBWSZTWbrL2vUAAB1VgAAQABCAQDrrnqAgAFCgaaGRkxBoTIJ6mmaNRwhndFAoNhZjh_YY4a01fOg1ulgNNC2UrzPdXXEnDpX8XckU4UJC6y9r1A..
      •  

        old new  
        1111mick@kulgan.net-20080830094018-0azn22n453on23ve 
        1212jamie@jantrid.net-20081022055144-zd6v96gjzz94ript 
         13jamie@jantrid.net-20081104100702-aqivw5dfzmygyo17 
    • Property bzr:revision-id:v3-list-QlpoOTFBWSZTWbrL2vUAAB1VgAAQABCAQDrrnqAgAFCgaaGRkxBoTIJ6mmaNRwhndFAoNhZjh_YY4a01fOg1ulgNNC2UrzPdXXEnDpX8XckU4UJC6y9r1A..
      •  

        old new  
        2372372265 jamie@jantrid.net-20081104005145-d5zkn1d8te4kvezj 
        2382382266 jamie@jantrid.net-20081104035506-jmi7y9p2500s7p0l 
         2392267 jamie@jantrid.net-20081104104007-7d800nkvlxe21gil 
    • Property bzr:file-ids
      •  

        old new  
         1source/NVDAObjects/IAccessible/__init__.py      683@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:source%2FNVDAObjects%2FIAccessible%2F__init__.py 
         2source/NVDAObjects/__init__.py  683@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:source%2FNVDAObjects%2F__init__.py 
         3source/appModules/_default.py   92@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:source%2FappModules%2F_default.py 
         4source/config/__init__.py       46@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:source%2Fconfig%2F__init__.py 
         5source/eventHandler.py  378@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:source%2FeventHandler.py 
         6source/gui/settingsDialogs.py   299@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:source%2Fgui%2FsettingsDialogs.py 
         7source/scriptHandler.py 362@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:source%2FscriptHandler.py 
         8source/virtualBufferHandler.py  1490@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:source%2FvirtualBufferHandler.py 
         9source/virtualBuffers/__init__.py       1675@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:source%2FvirtualBuffers%2F__init__.py 
         10source/virtualBuffers/gecko_ia2.py      1694@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:source%2FvirtualBuffers%2Fgecko_ia2.py 
        111user_docs/whats%20new.txt       559@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:user_docs%2Fwhats%20new.txt 
    • Property bzr:text-parents
      •  

        old new  
         1source/NVDAObjects/IAccessible/__init__.py      jamie@jantrid.net-20081104035949-menxppbx7lu6kk1l 
         2source/NVDAObjects/__init__.py  jamie@jantrid.net-20081104035949-menxppbx7lu6kk1l 
         3source/appModules/_default.py   jamie@jantrid.net-20081104040919-kdab03dj6kgjrq9w 
         4source/config/__init__.py       jamie@jantrid.net-20081104084400-w9vcwql6u6stx6d8 
         5source/eventHandler.py  jamie@jantrid.net-20081104035949-menxppbx7lu6kk1l 
         6source/gui/settingsDialogs.py   jamie@jantrid.net-20081104084716-851brawm7ev122o0 
         7source/scriptHandler.py jamie@jantrid.net-20081104035949-menxppbx7lu6kk1l 
         8source/virtualBufferHandler.py  jamie@jantrid.net-20081104040919-kdab03dj6kgjrq9w 
         9source/virtualBuffers/__init__.py       jamie@jantrid.net-20081104100702-aqivw5dfzmygyo17 
         10source/virtualBuffers/gecko_ia2.py      jamie@jantrid.net-20081104060842-57uuq0hsdhlk0x5z 
  • trunk/source/NVDAObjects/IAccessible/__init__.py

    r2436 r2468  
    371371                                        ("ExtendedUp","moveByLine"), 
    372372                                        ("ExtendedDown","moveByLine"), 
     373                                        ("control+ExtendedUp","moveByLine"), 
     374                                        ("control+ExtendedDown","moveByLine"), 
    373375                                        ("ExtendedLeft","moveByCharacter"), 
    374376                                        ("ExtendedRight","moveByCharacter"), 
  • trunk/source/NVDAObjects/__init__.py

    r2436 r2468  
    745745                bookmark=info.bookmark 
    746746                sendKey(keyPress) 
    747                 # We'll try waiting for the caret to move, but we don't care if it doesn't. 
    748                 self._hasCaretMoved(bookmark) 
     747                if not self._hasCaretMoved(bookmark): 
     748                        eventHandler.executeEvent("caretMovementFailed", self, keyPress=keyPress) 
    749749                if not isScriptWaiting(): 
    750750                        focus=api.getFocusObject() 
     
    766766                bookmark=info.bookmark 
    767767                sendKey(keyPress) 
    768                 # We'll try waiting for the caret to move, but we don't care if it doesn't. 
    769                 self._hasCaretMoved(bookmark) 
     768                if not self._hasCaretMoved(bookmark): 
     769                        eventHandler.executeEvent("caretMovementFailed", self, keyPress=keyPress) 
    770770                if not isScriptWaiting(): 
    771771                        focus=api.getFocusObject() 
     
    787787                bookmark=info.bookmark 
    788788                sendKey(keyPress) 
    789                 # We'll try waiting for the caret to move, but we don't care if it doesn't. 
    790                 self._hasCaretMoved(bookmark) 
     789                if not self._hasCaretMoved(bookmark): 
     790                        eventHandler.executeEvent("caretMovementFailed", self, keyPress=keyPress) 
    791791                if not isScriptWaiting(): 
    792792                        focus=api.getFocusObject() 
     
    808808                bookmark=info.bookmark 
    809809                sendKey(keyPress) 
    810                 # We'll try waiting for the caret to move, but we don't care if it doesn't. 
    811                 self._hasCaretMoved(bookmark) 
     810                if not self._hasCaretMoved(bookmark): 
     811                        eventHandler.executeEvent("caretMovementFailed", self, keyPress=keyPress) 
    812812                if not isScriptWaiting(): 
    813813                        focus=api.getFocusObject() 
  • trunk/source/appModules/_default.py

    r2466 r2468  
    550550                vbuf.passThrough = not vbuf.passThrough 
    551551                virtualBufferHandler.reportPassThrough(vbuf) 
    552         script_toggleVirtualBufferPassThrough.__doc__=_("Toggles virtualBuffer pass-through mode on and off. When on, keys will pass straight through the current virtualBuffer, allowing you to interact with a control without the virtualBuffer doing something else with the key.") 
     552        script_toggleVirtualBufferPassThrough.__doc__=_("Toggles between browse mode and focus mode. When in focus mode, keys will pass straight through to the application, allowing you to interact directly with a control. When in browse mode, you can navigate the document with the cursor, quick navigation keys, etc.") 
    553553 
    554554        def script_quit(self,keyPress): 
  • trunk/source/config/__init__.py

    r2436 r2468  
    108108        reportParagraphs = boolean(default=false) 
    109109        reportFrames = boolean(default=true) 
     110        autoPassThroughOnFocusChange = boolean(default=true) 
     111        autoPassThroughOnCaretMove = boolean(default=false) 
    110112 
    111113#Settings for document reading (such as MS Word and wordpad) 
  • trunk/source/eventHandler.py

    r2402 r2468  
    5959                return (eventName,obj) in _pendingEventCountsByNameAndObj 
    6060 
    61 def executeEvent(eventName,obj): 
     61def executeEvent(eventName,obj,**kwargs): 
    6262        """Executes an NVDA event. 
    6363        @param eventName: the name of the event type (e.g. 'gainFocus', 'nameChange') 
     
    6565        @param obj: the object the event is for 
    6666        @type obj: L{NVDAObjects.NVDAObject} 
     67        @param kwargs: Additional event parameters as keyword arguments. 
    6768        """ 
    6869        if eventName=="gainFocus": 
     
    7273        elif eventName=="documentLoadComplete": 
    7374                doPreDocumentLoadComplete(obj) 
    74         executeEvent_appModuleLevel(eventName,obj) 
     75        executeEvent_appModuleLevel(eventName,obj,**kwargs) 
    7576 
    7677def doPreGainFocus(obj): 
     
    118119 
    119120 
    120 def executeEvent_appModuleLevel(name,obj): 
     121def executeEvent_appModuleLevel(name,obj,**kwargs): 
    121122        appModule=obj.appModule 
    122123        if hasattr(appModule,"event_%s"%name): 
    123                 getattr(appModule,"event_%s"%name)(obj,lambda: executeEvent_defaultAppModuleLevel(name,obj))  
     124                getattr(appModule,"event_%s"%name)(obj,lambda: executeEvent_defaultAppModuleLevel(name,obj,**kwargs),**kwargs)  
    124125        else: 
    125                 executeEvent_defaultAppModuleLevel(name,obj) 
     126                executeEvent_defaultAppModuleLevel(name,obj,**kwargs) 
    126127 
    127 def executeEvent_defaultAppModuleLevel(name,obj): 
     128def executeEvent_defaultAppModuleLevel(name,obj,**kwargs): 
    128129        default=appModuleHandler.default 
    129130        if hasattr(default,"event_%s"%name): 
    130                 getattr(default,"event_%s"%name)(obj,lambda: executeEvent_virtualBufferLevel(name,obj))  
     131                getattr(default,"event_%s"%name)(obj,lambda: executeEvent_virtualBufferLevel(name,obj,**kwargs),**kwargs)  
    131132        else: 
    132                 executeEvent_virtualBufferLevel(name,obj) 
     133                executeEvent_virtualBufferLevel(name,obj,**kwargs) 
    133134 
    134 def executeEvent_virtualBufferLevel(name,obj): 
     135def executeEvent_virtualBufferLevel(name,obj,**kwargs): 
    135136        virtualBuffer=obj.virtualBuffer 
    136137        if hasattr(virtualBuffer,'event_%s'%name): 
    137                 getattr(virtualBuffer,'event_%s'%name)(obj,lambda: executeEvent_NVDAObjectLevel(name,obj)) 
     138                getattr(virtualBuffer,'event_%s'%name)(obj,lambda: executeEvent_NVDAObjectLevel(name,obj,**kwargs),**kwargs) 
    138139        else: 
    139                 executeEvent_NVDAObjectLevel(name,obj) 
     140                executeEvent_NVDAObjectLevel(name,obj,**kwargs) 
    140141 
    141 def executeEvent_NVDAObjectLevel(name,obj): 
     142def executeEvent_NVDAObjectLevel(name,obj,**kwargs): 
    142143        if hasattr(obj,'event_%s'%name): 
    143                 getattr(obj,'event_%s'%name)() 
     144                getattr(obj,'event_%s'%name)(**kwargs) 
  • trunk/source/gui/settingsDialogs.py

    r2436 r2468  
    558558                self.framesCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report f&rames")) 
    559559                self.framesCheckBox.SetValue(config.conf["virtualBuffers"]["reportFrames"]) 
     560                self.autoPassThroughOnFocusChangeCheckBox=wx.CheckBox(self,wx.ID_ANY,label=_("Automatic focus mode for focus changes")) 
     561                self.autoPassThroughOnFocusChangeCheckBox.SetValue(config.conf["virtualBuffers"]["autoPassThroughOnFocusChange"]) 
     562                self.autoPassThroughOnCaretMoveCheckBox=wx.CheckBox(self,wx.ID_ANY,label=_("Automatic focus mode for caret movement")) 
     563                self.autoPassThroughOnCaretMoveCheckBox.SetValue(config.conf["virtualBuffers"]["autoPassThroughOnCaretMove"]) 
    560564                settingsSizer.Add(self.framesCheckBox,border=10,flag=wx.BOTTOM) 
    561565 
     
    590594                config.conf["virtualBuffers"]["reportParagraphs"]=self.paragraphsCheckBox.IsChecked() 
    591595                config.conf["virtualBuffers"]["reportFrames"]=self.framesCheckBox.IsChecked() 
     596                config.conf["virtualBuffers"]["autoPassThroughOnFocusChange"]=self.autoPassThroughOnFocusChangeCheckBox.IsChecked() 
     597                config.conf["virtualBuffers"]["autoPassThroughOnCaretMove"]=self.autoPassThroughOnCaretMoveCheckBox.IsChecked() 
    592598                super(VirtualBuffersDialog, self).onOk(evt) 
    593599 
  • trunk/source/scriptHandler.py

    r2425 r2468  
    4242def findScript_virtualBufferLevel(keyPress): 
    4343        virtualBuffer=api.getFocusObject().virtualBuffer 
    44         if virtualBuffer and not virtualBuffer.passThrough: 
     44        if virtualBuffer: 
    4545                func=virtualBuffer.getScript(keyPress) 
    46                 if func: 
     46                if func and (not virtualBuffer.passThrough or getattr(func,"ignoreVirtualBufferPassThrough",False)): 
    4747                        return func 
    4848        return findScript_NVDAObjectLevel(keyPress) 
  • trunk/source/virtualBufferHandler.py

    r2177 r2468  
    9191        """ 
    9292        if virtualBuffer.passThrough != reportPassThrough.last: 
    93                 speech.speakMessage(_("virtual buffer pass through") + " " + (_("on") if virtualBuffer.passThrough else _("off"))) 
     93                speech.speakMessage(_("focus mode") if virtualBuffer.passThrough else _("browse mode")) 
    9494                reportPassThrough.last = virtualBuffer.passThrough 
    9595reportPassThrough.last = False 
  • trunk/source/virtualBuffers/__init__.py

    r2436 r2468  
    88import baseObject 
    99from keyUtils import sendKey 
     10import scriptHandler 
    1011from scriptHandler import isScriptWaiting 
    1112import speech 
     
    2728import eventHandler 
    2829import braille 
     30import queueHandler 
    2931 
    3032class VirtualBufferTextInfo(NVDAObjects.NVDAObjectTextInfo): 
     33 
     34        UNIT_CONTROLFIELD = "controlField" 
    3135 
    3236        def _getNVDAObjectFromOffset(self,offset): 
     
    5660                return self._getNVDAObjectFromOffset(self._startOffset) 
    5761 
    58         def _getLineNumFromOffset(offset): 
    59                 #virtualBuffers have no concept of line numbers 
    60                 return 0 
    61  
    6262        def _getSelectionOffsets(self): 
    6363                start,end=VBufClient_getBufferSelectionOffsets(self.obj.VBufHandle) 
     
    117117                return None 
    118118 
     119        def _get_fieldIdentifierAtStart(self): 
     120                return VBufClient_getFieldIdentifierFromBufferOffset(self.obj.VBufHandle, self._startOffset) 
     121 
     122        def _getUnitOffsets(self, unit, offset): 
     123                if unit == self.UNIT_CONTROLFIELD: 
     124                        docHandle, ID = self.fieldIdentifierAtStart 
     125                        return VBufClient_getBufferOffsetsFromFieldIdentifier(self.obj.VBufHandle, docHandle, ID) 
     126                return super(VirtualBufferTextInfo, self)._getUnitOffsets(unit, offset) 
     127 
    119128        def getXMLFieldSpeech(self,attrs,fieldType,extraDetail=False,reason=None): 
    120129                return speech.getXMLFieldSpeech(self,attrs,fieldType,extraDetail=extraDetail,reason=reason) 
    121130 
    122131class VirtualBuffer(cursorManager.CursorManager): 
     132 
     133        REASON_QUICKNAV = "quickNav" 
    123134 
    124135        def __init__(self,rootNVDAObject,backendLibPath=None,TextInfo=VirtualBufferTextInfo): 
     
    200211                pass 
    201212 
    202         def _set_selection(self, info): 
     213        def _set_selection(self, info, reason=speech.REASON_CARET): 
    203214                super(VirtualBuffer, self)._set_selection(info) 
    204215                if isScriptWaiting() or not info.isCollapsed: 
     
    211222                if not eventHandler.isPendingEvents("gainFocus") and obj != api.getFocusObject() and self._shouldSetFocusToObj(obj): 
    212223                        obj.setFocus() 
     224                self.passThrough=self.shouldPassThrough(obj,reason=reason) 
     225                # Queue the reporting of pass through mode so that it will be spoken after the actual content. 
     226                queueHandler.queueFunction(queueHandler.eventQueue, virtualBufferHandler.reportPassThrough, self) 
    213227 
    214228        def _shouldSetFocusToObj(self, obj): 
     
    283297                speech.speakTextInfo(info, reason=speech.REASON_FOCUS) 
    284298                info.collapse() 
    285                 self.selection = info 
     299                self._set_selection(info, reason=self.REASON_QUICKNAV) 
    286300 
    287301        @classmethod 
     
    338352        script_linksList.__doc__ = _("displays a list of links") 
    339353 
     354        def shouldPassThrough(self, obj, reason=None): 
     355                """Determine whether pass through mode should be enabled or disabled for a given object. 
     356                @param obj: The object in question. 
     357                @type obj: L{NVDAObjects.NVDAObject} 
     358                @param reason: The reason for this query; one of the speech reasons, L{REASON_QUICKNAV}, or C{None} for manual pass through mode activation by the user. 
     359                @return: C{True} if pass through mode should be enabled, C{False} if it should be disabled. 
     360                """ 
     361                if reason and ( 
     362                        (reason == speech.REASON_FOCUS and not config.conf["virtualBuffers"]["autoPassThroughOnFocusChange"]) 
     363                        or (reason == speech.REASON_CARET and not config.conf["virtualBuffers"]["autoPassThroughOnCaretMove"]) 
     364                ): 
     365                        # This check relates to auto pass through and auto pass through is disabled, so don't change the pass through state. 
     366                        return self.passThrough 
     367                states = obj.states 
     368                if controlTypes.STATE_FOCUSABLE not in states or controlTypes.STATE_READONLY in states: 
     369                        return False 
     370                role = obj.role 
     371                if reason == self.REASON_QUICKNAV: 
     372                        return False 
     373                if reason == speech.REASON_CARET: 
     374                        return role == controlTypes.ROLE_EDITABLETEXT 
     375                if reason == speech.REASON_FOCUS and role == controlTypes.ROLE_LISTITEM: 
     376                        return True 
     377                if role in (controlTypes.ROLE_COMBOBOX,controlTypes.ROLE_EDITABLETEXT,controlTypes.ROLE_LIST,controlTypes.ROLE_SLIDER) or controlTypes.STATE_EDITABLE in states: 
     378                        return True 
     379                return False 
     380 
     381        def event_caretMovementFailed(self, obj, nextHandler, keyPress=None): 
     382                if not self.passThrough or not keyPress or not config.conf["virtualBuffers"]["autoPassThroughOnCaretMove"]: 
     383                        return nextHandler() 
     384                if keyPress[1] in ("extendedhome", "extendedend"): 
     385                        # Home, end, control+home and control+end should not disable pass through. 
     386                        return nextHandler() 
     387                script = self.getScript(keyPress) 
     388                if not script: 
     389                        return nextHandler() 
     390 
     391                # We've hit the edge of the focused control. 
     392                # Therefore, move the virtual caret to the same edge of the field. 
     393                info = self.makeTextInfo(textHandler.POSITION_CARET) 
     394                info.expand(info.UNIT_CONTROLFIELD) 
     395                if keyPress[1] in ("extendedleft", "extendedup", "extendedprior"): 
     396                        info.collapse() 
     397                else: 
     398                        info.collapse(end=True) 
     399                        info.move(textHandler.UNIT_CHARACTER, -1) 
     400                info.updateCaret() 
     401 
     402                scriptHandler.queueScript(script, keyPress) 
     403 
     404        def script_disablePassThrough(self, keyPress): 
     405                if not self.passThrough: 
     406                        return sendKey(keyPress) 
     407                self.passThrough = False 
     408                virtualBufferHandler.reportPassThrough(self) 
     409        script_disablePassThrough.ignoreVirtualBufferPassThrough = True 
     410 
     411        def script_collapseOrExpandControl(self, keyPress): 
     412                sendKey(keyPress) 
     413                if not self.passThrough: 
     414                        return 
     415                self.passThrough = False 
     416                virtualBufferHandler.reportPassThrough(self) 
     417        script_collapseOrExpandControl.ignoreVirtualBufferPassThrough = True 
     418 
    340419[VirtualBuffer.bindKey(keyName,scriptName) for keyName,scriptName in [ 
    341420        ("Return","activatePosition"), 
     
    344423        ("NVDA+v","toggleScreenLayout"), 
    345424        ("NVDA+f7","linksList"), 
     425        ("escape","disablePassThrough"), 
     426        ("alt+extendedUp","collapseOrExpandControl"), 
     427        ("alt+extendedDown","collapseOrExpandControl"), 
    346428]] 
    347429 
  • trunk/source/virtualBuffers/gecko_ia2.py

    r2418 r2468  
    126126                                start,end=VBufClient_getBufferOffsetsFromFieldIdentifier(self.VBufHandle,docHandle,ID) 
    127127                        except: 
    128                                 #log.error("VBufClient_getBufferOffsetsFromFieldIdentifier",exc_info=True) 
     128                                # This object is not in the virtual buffer, even though it resides beneath the document. 
     129                                # Automatic pass through should be enabled in certain circumstances where this occurs. 
     130                                if not self.passThrough and self.shouldPassThrough(obj,reason=speech.REASON_FOCUS): 
     131                                        self.passThrough=True 
     132                                        virtualBufferHandler.reportPassThrough(self) 
    129133                                return nextHandler() 
    130134                        newInfo=self.makeTextInfo(textHandler.Offsets(start,end)) 
     
    134138                        endToEnd=newInfo.compareEndPoints(oldInfo,"endToEnd") 
    135139                        if (startToStart<0 and endToEnd>0) or (startToStart>0 and endToEnd<0) or endToStart<=0 or startToEnd>0: 
     140                                self.passThrough=self.shouldPassThrough(obj,reason=speech.REASON_FOCUS) 
     141                                speech.cancelSpeech() 
    136142                                if not self.passThrough: 
    137                                         speech.cancelSpeech() 
    138143                                        # We read the info from the buffer instead of the control itself. 
    139144                                        speech.speakTextInfo(newInfo,reason=speech.REASON_FOCUS) 
     
    143148                                        nextHandler() 
    144149                                newInfo.collapse() 
    145                                 self.selection=newInfo 
     150                                self._set_selection(newInfo,reason=speech.REASON_FOCUS) 
    146151                else: 
    147                         # The virtual buffer caret was already at the focused node, so we don't speak it. 
    148                         # However, we still want to update the speech property cache so that property changes will be spoken properly. 
     152                        # The virtual buffer caret was already at the focused node. 
    149153                        if not self.passThrough: 
     154                                # This focus change was caused by a virtual caret movement, so don't speak the focused node to avoid double speaking. 
     155                                # However, we still want to update the speech property cache so that property changes will be spoken properly. 
    150156                                speech.speakObject(obj,speech.REASON_ONLYCACHE) 
    151157                        else: 
     
    161167                try: 
    162168                        obj=NVDAObjects.IAccessible.getNVDAObjectFromEvent(docHandle,IAccessibleHandler.OBJID_CLIENT,ID) 
    163                         role=obj.role 
    164                         states=obj.states 
    165                         if role in (controlTypes.ROLE_COMBOBOX,controlTypes.ROLE_EDITABLETEXT,controlTypes.ROLE_LIST,controlTypes.ROLE_SLIDER) or controlTypes.STATE_EDITABLE in states: 
     169                        if self.shouldPassThrough(obj): 
    166170                                obj.setFocus() 
    167171                                self.passThrough=True 
     
    322326                speech.speakTextInfo(newInfo,reason=speech.REASON_FOCUS) 
    323327                newInfo.collapse() 
    324                 self.selection=newInfo 
     328                self._set_selection(newInfo,reason=speech.REASON_FOCUS) 
    325329                return True 
    326330 
  • trunk/user_docs/whats new.txt

    r2467 r2468  
    4242* new: Support for braille displays! 
    4343* new: Added a command (NVDA+c) to report the text on the Windows clipboard. (#193) 
     44* change: Instead of virtual buffer pass through on and off, NVDA now reports focus mode (pass through on) and browse mode (pass through off). 
     45* new: You can now press escape when in focus mode to return to browse mode. 
     46* new: In virtual buffers, when the focus changes or the caret is moved, NVDA can automatically switch to focus mode or browse mode as appropriate for the control under the caret. This is configured from the Virtual Buffers dialog. (#157) 
    4447 
    4548