61
61
NVDAHelper.localLib.VBuf_locateControlFieldNodeAtOffset(self.obj.VBufHandle, offset, ctypes.byref(startOffset), ctypes.byref(endOffset), ctypes.byref(docHandle), ctypes.byref(ID))
62
62
return docHandle.value, ID.value
64
def _getNVDAObjectFromOffset(self,offset):
65
docHandle,ID=self._getFieldIdentifierFromOffset(offset)
66
return self.obj.getNVDAObjectFromIdentifier(docHandle,ID)
68
def _getOffsetsFromNVDAObject(self,obj):
69
docHandle,ID=self.obj.getIdentifierFromNVDAObject(obj)
64
def _getOffsetsFromFieldIdentifier(self, docHandle, ID):
70
65
node = NVDAHelper.localLib.VBuf_getControlFieldNodeWithIdentifier(self.obj.VBufHandle, docHandle, ID)
75
70
NVDAHelper.localLib.VBuf_getFieldNodeOffsets(self.obj.VBufHandle, node, ctypes.byref(start), ctypes.byref(end))
76
71
return start.value, end.value
73
def _getPointFromOffset(self,offset):
74
o=self._getNVDAObjectFromOffset(offset)
75
return textInfos.Point(o.location[0],o.location[1])
77
def _getNVDAObjectFromOffset(self,offset):
78
docHandle,ID=self._getFieldIdentifierFromOffset(offset)
79
return self.obj.getNVDAObjectFromIdentifier(docHandle,ID)
81
def _getOffsetsFromNVDAObjectInBuffer(self,obj):
82
docHandle,ID=self.obj.getIdentifierFromNVDAObject(obj)
83
return self._getOffsetsFromFieldIdentifier(docHandle,ID)
85
def _getOffsetsFromNVDAObject(self, obj):
89
return self._getOffsetsFromNVDAObjectInBuffer(obj)
92
# Interactive list/combo box descendants aren't rendered into the buffer, even though they are still considered part of it.
93
# Use the list/combo box in this case.
94
if ancestorCount == 2:
95
# This is not a list/combo box descendant.
99
if not obj or obj.role not in (controlTypes.ROLE_LIST, controlTypes.ROLE_COMBOBOX):
78
102
def __init__(self,obj,position):
80
if isinstance(position,NVDAObjects.NVDAObject):
81
start,end=self._getOffsetsFromNVDAObject(position)
82
position=textInfos.offsets.Offsets(start,end)
83
104
super(VirtualBufferTextInfo,self).__init__(obj,position)
85
def _get_NVDAObjectAtStart(self):
86
return self._getNVDAObjectFromOffset(self._startOffset)
88
106
def _getSelectionOffsets(self):
89
107
start=ctypes.c_int()
90
108
end=ctypes.c_int()
150
168
tableLayout=attrs.get('table-layout')
152
170
attrs['table-layout']=tableLayout=="1"
172
# Handle table row and column headers.
173
for axis in "row", "column":
174
attr = attrs.pop("table-%sheadercells" % axis, None)
177
cellIdentifiers = [identifier.split(",") for identifier in attr.split(";") if identifier]
178
# Get the text for the header cells.
180
for docHandle, ID in cellIdentifiers:
182
start, end = self._getOffsetsFromFieldIdentifier(int(docHandle), int(ID))
183
except (LookupError, ValueError):
185
textList.append(self.obj.makeTextInfo(textInfos.offsets.Offsets(start, end)).text)
186
attrs["table-%sheadertext" % axis] = "\n".join(textList)
155
190
def _normalizeFormatField(self, attrs):
171
206
return startOffset.value,endOffset.value
172
207
return super(VirtualBufferTextInfo, self)._getUnitOffsets(unit, offset)
174
def getXMLFieldSpeech(self,attrs,fieldType,extraDetail=False,reason=None):
175
return speech.getXMLFieldSpeech(self,attrs,fieldType,extraDetail=extraDetail,reason=reason)
177
def copyToClipboard(self):
209
def _get_clipboardText(self):
178
210
# Blocks should start on a new line, but they don't necessarily have an end of line indicator.
179
211
# Therefore, get the text in block (paragraph) chunks and join the chunks with \r\n.
180
212
blocks = (block.strip("\r\n") for block in self.getTextInChunks(textInfos.UNIT_PARAGRAPH))
181
return api.copyToClip("\r\n".join(blocks))
213
return "\r\n".join(blocks)
183
215
def getControlFieldSpeech(self, attrs, ancestorAttrs, fieldType, formatConfig=None, extraDetail=False, reason=None):
216
248
child = wx.RadioBox(self, wx.ID_ANY, label=_("Type:"), choices=tuple(et[1] for et in self.ELEMENT_TYPES))
217
249
child.Bind(wx.EVT_RADIOBOX, self.onElementTypeChange)
250
mainSizer.Add(child,proportion=1)
220
252
self.tree = wx.TreeCtrl(self, wx.ID_ANY, style=wx.TR_HAS_BUTTONS | wx.TR_HIDE_ROOT | wx.TR_SINGLE)
221
253
self.tree.Bind(wx.EVT_SET_FOCUS, self.onTreeSetFocus)
222
254
self.tree.Bind(wx.EVT_CHAR, self.onTreeChar)
223
255
self.treeRoot = self.tree.AddRoot("root")
224
mainSizer.Add(self.tree)
256
mainSizer.Add(self.tree,proportion=7)
226
258
sizer = wx.BoxSizer(wx.HORIZONTAL)
227
259
label = wx.StaticText(self, wx.ID_ANY, _("&Filter by:"))
484
516
programmaticScrollMayFireEvent = False
486
518
def __init__(self,rootNVDAObject,backendName=None):
519
super(VirtualBuffer,self).__init__(rootNVDAObject)
487
520
self.backendName=backendName
488
self.rootNVDAObject=rootNVDAObject
489
super(VirtualBuffer,self).__init__()
490
521
self.VBufHandle=None
491
self._passThrough=False
492
523
self.disableAutoPassThrough = False
493
524
self.rootDocHandle,self.rootID=self.getIdentifierFromNVDAObject(self.rootNVDAObject)
494
525
self._lastFocusObj = None
495
526
self._hadFirstGainFocus = False
496
527
self._lastProgrammaticScrollTime = None
498
def _get_passThrough(self):
499
return self._passThrough
501
def _set_passThrough(self, state):
502
if self._passThrough == state:
528
# We need to cache this because it will be unavailable once the document dies.
529
self.documentConstantIdentifier = self.documentConstantIdentifier
530
if not hasattr(self.rootNVDAObject.appModule, "_vbufRememberedCaretPositions"):
531
self.rootNVDAObject.appModule._vbufRememberedCaretPositions = {}
532
self._lastCaretPosition = None
535
self.shouldPrepare=False
538
def _get_shouldPrepare(self):
539
return not self.isLoading and not self.VBufHandle
542
if not self.VBufHandle:
504
self._passThrough = state
506
braille.handler.handleGainFocus(api.getFocusObject())
508
braille.handler.handleGainFocus(self)
545
if self.shouldRememberCaretPositionAcrossLoads and self._lastCaretPosition:
547
self.rootNVDAObject.appModule._vbufRememberedCaretPositions[self.documentConstantIdentifier] = self._lastCaretPosition
548
except AttributeError:
549
# The app module died.
554
def _get_isReady(self):
555
return bool(self.VBufHandle and not self.isLoading)
510
557
def loadBuffer(self):
511
558
self.isLoading = True
549
597
def makeTextInfo(self,position):
550
598
return self.TextInfo(self,position)
552
def isNVDAObjectInVirtualBuffer(self,obj):
600
def isNVDAObjectPartOfLayoutTable(self,obj):
601
docHandle,ID=self.getIdentifierFromNVDAObject(obj)
603
info=self.makeTextInfo(obj)
605
info.expand(textInfos.UNIT_CHARACTER)
606
fieldCommands=[x for x in info.getTextWithFields() if isinstance(x,textInfos.FieldCommand)]
609
for fieldCommand in fieldCommands:
610
fieldID=fieldCommand.field.get("controlIdentifier_ID") if fieldCommand.field else None
612
tableLayout=fieldCommand.field.get('table-layout')
613
if tableLayout is not None:
615
tableID=fieldCommand.field.get('table-id')
619
for fieldCommand in fieldCommands:
620
fieldID=fieldCommand.field.get("controlIdentifier_ID") if fieldCommand.field else None
622
tableLayout=fieldCommand.field.get('table-layout',False)
558
629
def getNVDAObjectFromIdentifier(self, docHandle, ID):
559
630
"""Retrieve an NVDAObject for a given node identifier.
577
648
raise NotImplementedError
579
def event_virtualBuffer_gainFocus(self):
650
def event_treeInterceptor_gainFocus(self):
580
651
"""Triggered when this virtual buffer gains focus.
581
652
This event is only fired upon entering this buffer when it was not the current buffer before.
582
653
This is different to L{event_gainFocus}, which is fired when an object inside this buffer gains focus, even if that object is in the same buffer.
584
656
if not self._hadFirstGainFocus:
585
657
# This buffer is gaining focus for the first time.
586
self._setInitialCaretPos()
587
658
# Fake a focus event on the focus object, as the buffer may have missed the actual focus event.
588
659
focus = api.getFocusObject()
589
660
self.event_gainFocus(focus, lambda: focus.event_gainFocus())
590
661
if not self.passThrough:
591
speech.cancelSpeech()
592
virtualBufferHandler.reportPassThrough(self)
593
speech.speakObjectProperties(self.rootNVDAObject,name=True)
662
# We only set the caret position if in browse mode.
663
# If in focus mode, the document must have forced the focus somewhere,
664
# so we don't want to override it.
665
initialPos = self._getInitialCaretPos()
667
self.selection = self.makeTextInfo(initialPos)
668
reportPassThrough(self)
669
doSayAll=config.conf['virtualBuffers']['autoSayAllOnPageLoad']
670
self._hadFirstGainFocus = True
672
if not self.passThrough:
674
speech.speakObjectProperties(self.rootNVDAObject,name=True,states=True,reason=speech.REASON_FOCUS)
594
675
info=self.makeTextInfo(textInfos.POSITION_CARET)
595
676
sayAllHandler.readText(info,sayAllHandler.CURSOR_CARET)
596
self._hadFirstGainFocus = True
599
# This buffer has had focus before.
600
if not self.passThrough:
601
678
# Speak it like we would speak focus on any other document object.
602
679
speech.speakObject(self.rootNVDAObject, reason=speech.REASON_FOCUS)
603
680
info = self.selection
647
720
super(VirtualBuffer, self)._set_selection(info)
648
721
if isScriptWaiting() or not info.isCollapsed:
650
api.setReviewPosition(info)
651
obj=info.NVDAObjectAtStart
653
log.debugWarning("Invalid NVDAObjectAtStart")
655
if obj==self.rootNVDAObject:
723
# Save the last caret position for use in terminate().
724
# This must be done here because the buffer might be cleared just before terminate() is called,
725
# causing the last caret position to be lost.
728
self._lastCaretPosition = caret.bookmark
729
if config.conf['reviewCursor']['followCaret'] and api.getNavigatorObject() is self.rootNVDAObject:
730
api.setReviewPosition(info)
657
731
if reason == speech.REASON_FOCUS:
658
732
focusObj = api.getFocusObject()
733
if focusObj==self.rootNVDAObject:
660
736
focusObj=info.focusableNVDAObjectAtStart
661
if reason != speech.REASON_FOCUS:
737
obj=info.NVDAObjectAtStart
739
log.debugWarning("Invalid NVDAObjectAtStart")
741
if obj==self.rootNVDAObject:
662
743
if focusObj and not eventHandler.isPendingEvents("gainFocus") and focusObj!=self.rootNVDAObject and focusObj != api.getFocusObject() and self._shouldSetFocusToObj(focusObj):
663
744
focusObj.setFocus()
664
745
obj.scrollIntoView()
677
758
return controlTypes.STATE_FOCUSABLE in obj.states
679
def script_activatePosition(self,keyPress):
680
if self.VBufHandle is None:
681
return sendKey(keyPress)
760
def script_activatePosition(self,gesture):
682
761
info=self.makeTextInfo(textInfos.POSITION_CARET)
683
762
self._activatePosition(info)
684
script_activatePosition.__doc__ = _("activates the current object in the virtual buffer")
686
def _caretMovementScriptHelper(self, *args, **kwargs):
687
if self.VBufHandle is None:
689
super(VirtualBuffer, self)._caretMovementScriptHelper(*args, **kwargs)
691
def script_refreshBuffer(self,keyPress):
692
if self.VBufHandle is None:
763
script_activatePosition.__doc__ = _("activates the current object in the document")
765
def script_refreshBuffer(self,gesture):
766
if scriptHandler.isScriptWaiting():
767
# This script may cause subsequently queued scripts to fail, so don't execute.
694
769
self.unloadBuffer()
695
770
self.loadBuffer()
696
script_refreshBuffer.__doc__ = _("Refreshes the virtual buffer content")
771
script_refreshBuffer.__doc__ = _("Refreshes the document content")
698
def script_toggleScreenLayout(self,keyPress):
773
def script_toggleScreenLayout(self,gesture):
699
774
config.conf["virtualBuffers"]["useScreenLayout"]=not config.conf["virtualBuffers"]["useScreenLayout"]
700
775
onOff=_("on") if config.conf["virtualBuffers"]["useScreenLayout"] else _("off")
701
776
speech.speakMessage(_("use screen layout %s")%onOff)
702
script_toggleScreenLayout.__doc__ = _("Toggles on and off if the screen layout is preserved while rendering the virtual buffer content")
777
script_toggleScreenLayout.__doc__ = _("Toggles on and off if the screen layout is preserved while rendering the document content")
704
779
def _searchableAttributesForNodeType(self,nodeType):
762
835
scriptSuffix = nodeType[0].upper() + nodeType[1:]
763
836
scriptName = "next%s" % scriptSuffix
764
837
funcName = "script_%s" % scriptName
765
script = lambda self,keyPress: self._quickNavScript(keyPress, nodeType, "next", nextError, readUnit)
838
script = lambda self,gesture: self._quickNavScript(gesture, nodeType, "next", nextError, readUnit)
766
839
script.__doc__ = nextDoc
767
840
script.__name__ = funcName
768
841
setattr(cls, funcName, script)
769
cls.bindKey(key, scriptName)
842
cls.__gestures["kb:%s" % key] = scriptName
770
843
scriptName = "previous%s" % scriptSuffix
771
844
funcName = "script_%s" % scriptName
772
script = lambda self,keyPress: self._quickNavScript(keyPress, nodeType, "previous", prevError, readUnit)
845
script = lambda self,gesture: self._quickNavScript(gesture, nodeType, "previous", prevError, readUnit)
773
846
script.__doc__ = prevDoc
774
847
script.__name__ = funcName
775
848
setattr(cls, funcName, script)
776
cls.bindKey("shift+%s" % key, scriptName)
849
cls.__gestures["kb:shift+%s" % key] = scriptName
778
def script_elementsList(self,keyPress):
779
if self.VBufHandle is None:
851
def script_elementsList(self,gesture):
781
852
# We need this to be a modal dialog, but it mustn't block this script.
783
854
gui.mainFrame.prePopup()
805
876
if reason == self.REASON_QUICKNAV:
807
878
states = obj.states
808
if controlTypes.STATE_FOCUSABLE not in states or controlTypes.STATE_READONLY in states:
879
if controlTypes.STATE_FOCUSABLE not in states and controlTypes.STATE_FOCUSED not in states:
882
if controlTypes.STATE_READONLY in states and role != controlTypes.ROLE_EDITABLETEXT:
811
884
if reason == speech.REASON_CARET:
812
885
return role == controlTypes.ROLE_EDITABLETEXT or (role == controlTypes.ROLE_DOCUMENT and controlTypes.STATE_EDITABLE in states)
813
if reason == speech.REASON_FOCUS and role in (controlTypes.ROLE_LISTITEM, controlTypes.ROLE_RADIOBUTTON):
886
if reason == speech.REASON_FOCUS and role in (controlTypes.ROLE_LISTITEM, controlTypes.ROLE_RADIOBUTTON, controlTypes.ROLE_TAB):
815
if role in (controlTypes.ROLE_COMBOBOX, controlTypes.ROLE_EDITABLETEXT, controlTypes.ROLE_LIST, controlTypes.ROLE_SLIDER, controlTypes.ROLE_TABCONTROL, controlTypes.ROLE_TAB, controlTypes.ROLE_MENUBAR, controlTypes.ROLE_POPUPMENU, controlTypes.ROLE_MENUITEM, controlTypes.ROLE_TREEVIEW, controlTypes.ROLE_TREEVIEWITEM, controlTypes.ROLE_SPINBUTTON) or controlTypes.STATE_EDITABLE in states:
888
if role in (controlTypes.ROLE_COMBOBOX, controlTypes.ROLE_EDITABLETEXT, controlTypes.ROLE_LIST, controlTypes.ROLE_SLIDER, controlTypes.ROLE_TABCONTROL, controlTypes.ROLE_MENUBAR, controlTypes.ROLE_POPUPMENU, controlTypes.ROLE_MENUITEM, controlTypes.ROLE_TREEVIEW, controlTypes.ROLE_TREEVIEWITEM, controlTypes.ROLE_SPINBUTTON) or controlTypes.STATE_EDITABLE in states:
819
def event_caretMovementFailed(self, obj, nextHandler, keyPress=None):
820
if not self.passThrough or not keyPress or not config.conf["virtualBuffers"]["autoPassThroughOnCaretMove"]:
892
def event_caretMovementFailed(self, obj, nextHandler, gesture=None):
893
if not self.passThrough or not gesture or not config.conf["virtualBuffers"]["autoPassThroughOnCaretMove"]:
821
894
return nextHandler()
822
if keyPress[1] in ("extendedhome", "extendedend"):
895
if gesture.mainKeyName in ("home", "end"):
823
896
# Home, end, control+home and control+end should not disable pass through.
824
897
return nextHandler()
825
script = self.getScript(keyPress)
898
script = self.getScript(gesture)
827
900
return nextHandler()
830
903
# Therefore, move the virtual caret to the same edge of the field.
831
904
info = self.makeTextInfo(textInfos.POSITION_CARET)
832
905
info.expand(info.UNIT_CONTROLFIELD)
833
if keyPress[1] in ("extendedleft", "extendedup", "extendedprior"):
906
if gesture.mainKeyName in ("extendedleft", "extendedup", "extendedprior"):
836
909
info.collapse(end=True)
837
910
info.move(textInfos.UNIT_CHARACTER, -1)
838
911
info.updateCaret()
840
scriptHandler.queueScript(script, keyPress)
913
scriptHandler.queueScript(script, gesture)
842
def script_disablePassThrough(self, keyPress):
915
def script_disablePassThrough(self, gesture):
843
916
if not self.passThrough or self.disableAutoPassThrough:
844
return sendKey(keyPress)
917
return gesture.send()
845
918
self.passThrough = False
846
919
self.disableAutoPassThrough = False
847
virtualBufferHandler.reportPassThrough(self)
848
script_disablePassThrough.ignoreVirtualBufferPassThrough = True
920
reportPassThrough(self)
921
script_disablePassThrough.ignoreTreeInterceptorPassThrough = True
850
def script_collapseOrExpandControl(self, keyPress):
852
if not self.passThrough:
854
self.passThrough = False
855
virtualBufferHandler.reportPassThrough(self)
856
script_collapseOrExpandControl.ignoreVirtualBufferPassThrough = True
923
def script_collapseOrExpandControl(self, gesture):
926
if not self.disableAutoPassThrough:
927
self.passThrough = False
928
reportPassThrough(self)
930
oldFocus = api.getFocusObject()
931
oldFocusStates = oldFocus.states
933
if oldFocus.role == controlTypes.ROLE_COMBOBOX and controlTypes.STATE_COLLAPSED in oldFocusStates:
934
self.passThrough = True
935
reportPassThrough(self)
936
script_collapseOrExpandControl.ignoreTreeInterceptorPassThrough = True
858
938
def _tabOverride(self, direction):
859
939
"""Override the tab order if the virtual buffer caret is not within the currently focused node.
877
954
# We only want to override the tab order if the caret is not within the focused node.
878
955
caretInfo=self.makeTextInfo(textInfos.POSITION_CARET)
879
# Expand to one character, as isOverlapping() doesn't yield the desired results with collapsed ranges.
880
caretInfo.expand(textInfos.UNIT_CHARACTER)
881
if focusInfo.isOverlapping(caretInfo):
956
#Only check that the caret is within the focus for things that ar not documents
957
#As for documents we should always override
958
if focus.role!=controlTypes.ROLE_DOCUMENT or controlTypes.STATE_EDITABLE in focus.states:
959
# Expand to one character, as isOverlapping() doesn't yield the desired results with collapsed ranges.
960
caretInfo.expand(textInfos.UNIT_CHARACTER)
961
if focusInfo.isOverlapping(caretInfo):
883
963
# If we reach here, we do want to override tab/shift+tab if possible.
884
964
# Find the next/previous focusable node.
933
1013
@type obj: L{NVDAObjects.NVDAObject}
1016
def _replayFocusEnteredEvents(self):
1017
# We blocked the focusEntered events because we were in browse mode,
1018
# but now that we've switched to focus mode, we need to fire them.
1019
for parent in api.getFocusAncestors()[api.getFocusDifferenceLevel():]:
1021
parent.event_focusEntered()
1023
log.exception("Error executing focusEntered event: %s" % parent)
936
1025
def event_gainFocus(self, obj, nextHandler):
1026
if not self.isReady:
1027
if self.passThrough:
937
1030
if not self.passThrough and self._lastFocusObj==obj:
938
1031
# This was the last non-document node with focus, so don't handle this focus event.
939
1032
# Otherwise, if the user switches away and back to this document, the cursor will jump to this node.
940
1033
# This is not ideal if the user was positioned over a node which cannot receive focus.
942
if self.VBufHandle is None:
944
1035
if obj==self.rootNVDAObject:
945
1036
if self.passThrough:
946
1037
return nextHandler()
1141
1235
info.collapse()
1142
1236
self.selection = info
1144
def script_nextRow(self, keyPress):
1238
def script_nextRow(self, gesture):
1145
1239
self._tableMovementScriptHelper(axis="row", movement="next")
1146
1240
script_nextRow.__doc__ = _("moves to the next table row")
1148
def script_previousRow(self, keyPress):
1242
def script_previousRow(self, gesture):
1149
1243
self._tableMovementScriptHelper(axis="row", movement="previous")
1150
1244
script_previousRow.__doc__ = _("moves to the previous table row")
1152
def script_nextColumn(self, keyPress):
1246
def script_nextColumn(self, gesture):
1153
1247
self._tableMovementScriptHelper(axis="column", movement="next")
1154
1248
script_nextColumn.__doc__ = _("moves to the next table column")
1156
def script_previousColumn(self, keyPress):
1250
def script_previousColumn(self, gesture):
1157
1251
self._tableMovementScriptHelper(axis="column", movement="previous")
1158
1252
script_previousColumn.__doc__ = _("moves to the previous table column")
1188
1282
yield 0, link2end, link1start
1189
1283
link1node, link1start, link1end = link2node, link2start, link2end
1191
def _setInitialCaretPos(self):
1192
"""Set the initial position of the caret after the buffer has been loaded.
1193
The return value is primarily used so that overriding methods can determine whether they need to set an initial position.
1194
@return: C{True} if an initial position was set.
1285
def _getInitialCaretPos(self):
1286
"""Retrieve the initial position of the caret after the buffer has been loaded.
1287
This position, if any, will be passed to L{makeTextInfo}.
1288
Subclasses should extend this method.
1289
@return: The initial position of the caret, C{None} if there isn't one.
1290
@rtype: TextInfo position
1292
if self.shouldRememberCaretPositionAcrossLoads:
1294
return self.rootNVDAObject.appModule._vbufRememberedCaretPositions[self.documentConstantIdentifier]
1299
def _get_documentConstantIdentifier(self):
1300
"""Get the constant identifier for this document.
1301
This identifier should uniquely identify all instances (not just one instance) of a document for at least the current session of the hosting application.
1302
Generally, the document URL should be used.
1303
@return: The constant identifier for this document, C{None} if there is none.
1307
def _get_shouldRememberCaretPositionAcrossLoads(self):
1308
"""Specifies whether the position of the caret should be remembered when this document is loaded again.
1309
This is useful when the browser remembers the scroll position for the document,
1310
but does not communicate this information via APIs.
1311
The remembered caret position is associated with this document using L{documentConstantIdentifier}.
1312
@return: C{True} if the caret position should be remembered, C{False} if not.
1315
docConstId = self.documentConstantIdentifier
1316
# Return True if the URL indicates that this is probably a web browser document.
1317
# We do this check because we don't want to remember caret positions for email messages, etc.
1318
return isinstance(docConstId, basestring) and docConstId.split("://", 1)[0] in ("http", "https", "ftp", "ftps", "file")
1199
[VirtualBuffer.bindKey(keyName,scriptName) for keyName,scriptName in (
1200
("Return","activatePosition"),
1201
("Space","activatePosition"),
1202
("NVDA+f5","refreshBuffer"),
1203
("NVDA+v","toggleScreenLayout"),
1204
("NVDA+f7","elementsList"),
1205
("escape","disablePassThrough"),
1206
("alt+extendedUp","collapseOrExpandControl"),
1207
("alt+extendedDown","collapseOrExpandControl"),
1209
("shift+tab", "shiftTab"),
1210
("control+alt+extendedDown", "nextRow"),
1211
("control+alt+extendedUp", "previousRow"),
1212
("control+alt+extendedRight", "nextColumn"),
1213
("control+alt+extendedLeft", "previousColumn"),
1321
"kb:enter": "activatePosition",
1322
"kb:space": "activatePosition",
1323
"kb:NVDA+f5": "refreshBuffer",
1324
"kb:NVDA+v": "toggleScreenLayout",
1325
"kb:NVDA+f7": "elementsList",
1326
"kb:escape": "disablePassThrough",
1327
"kb:alt+upArrow": "collapseOrExpandControl",
1328
"kb:alt+downArrow": "collapseOrExpandControl",
1330
"kb:shift+tab": "shiftTab",
1331
"kb:control+alt+downArrow": "nextRow",
1332
"kb:control+alt+upArrow": "previousRow",
1333
"kb:control+alt+rightArrow": "nextColumn",
1334
"kb:control+alt+leftArrow": "previousColumn",
1216
1337
# Add quick navigation scripts.
1217
1338
qn = VirtualBuffer.addQuickNav
1268
1389
qn("embeddedObject", key="o", nextDoc=_("moves to the next embedded object"), nextError=_("no next embedded object"),
1269
1390
prevDoc=_("moves to the previous embedded object"), prevError=_("no previous embedded object"))
1393
def reportPassThrough(virtualBuffer):
1394
"""Reports the virtual buffer pass through mode if it has changed.
1395
@param virtualBuffer: The current virtual buffer.
1396
@type virtualBuffer: L{virtualBuffers.VirtualBuffer}
1398
if virtualBuffer.passThrough != reportPassThrough.last:
1399
if config.conf["virtualBuffers"]["passThroughAudioIndication"]:
1400
sound = r"waves\focusMode.wav" if virtualBuffer.passThrough else r"waves\browseMode.wav"
1401
nvwave.playWaveFile(sound)
1403
speech.speakMessage(_("focus mode") if virtualBuffer.passThrough else _("browse mode"))
1404
reportPassThrough.last = virtualBuffer.passThrough
1405
reportPassThrough.last = False