diff --git a/source/NVDAObjects/IAccessible/mozilla.py b/source/NVDAObjects/IAccessible/mozilla.py index 55f899f75db..186787a61c9 100755 --- a/source/NVDAObjects/IAccessible/mozilla.py +++ b/source/NVDAObjects/IAccessible/mozilla.py @@ -17,39 +17,11 @@ import textInfos.offsets from NVDAObjects.behaviors import RowWithFakeNavigation from virtualBuffers import VirtualBuffer -import api from . import IA2TextTextInfo from . import ia2Web class Mozilla(ia2Web.Ia2Web): - def _getPhysicalFocus(self): - try: - paccParent=self.IAccessibleObject.accParent - except COMError: - paccParent=None - if not paccParent: - return - try: - paccFocus=paccParent.accFocus - except COMError: - paccFocus=None - if not paccFocus: - return - return IAccessible(IAccessibleObject=IAccessibleHandler.normalizeIAccessible(paccFocus),IAccessibleChildID=0) - - def setFocus(self): - oldFocus=self._getPhysicalFocus() - super(Mozilla,self).setFocus() - # Although all versions of Firefox block inSetFocus or in accFocus until the physical focus has moved, - # Firefox 57 and above return before they fire a focus winEvent communicating the focus change to ATs. - # Therefore, If the call to setFocus did change the physical focus, - # Wait for a focus event to be queued to NVDA before returning. - newFocus=self._getPhysicalFocus() - if newFocus and newFocus!=oldFocus: - while not eventHandler.isPendingEvents("gainFocus"): - api.processPendingEvents(processEventQueue=False) - def _get_parent(self): #Special code to support Mozilla node_child_of relation (for comboboxes) res=IAccessibleHandler.accNavigate(self.IAccessibleObject,self.IAccessibleChildID,IAccessibleHandler.NAVRELATION_NODE_CHILD_OF) diff --git a/source/brailleViewer/brailleViewerGui.py b/source/brailleViewer/brailleViewerGui.py index 9866fd42fb3..8b8f2e4ad75 100644 --- a/source/brailleViewer/brailleViewerGui.py +++ b/source/brailleViewer/brailleViewerGui.py @@ -53,38 +53,45 @@ def __init__(self, numCells, onDestroyed): self._brailleOutputLastSet = BRAILLE_INIT_CHARACTER * numCells self._rawTextOutputLastSet = SPACE_CHARACTER - mainSizer = wx.BoxSizer(wx.VERTICAL) + self.frameContentsSizer = wx.BoxSizer(wx.HORIZONTAL) + self.SetSizer(self.frameContentsSizer) + self.panel = wx.Panel(self) + self.frameContentsSizer.Add(self.panel, proportion=1, flag=wx.EXPAND) + + self.panelContentsSizer = wx.BoxSizer(wx.VERTICAL) + self.panel.SetSizer(self.panelContentsSizer) + borderSizer = wx.BoxSizer(wx.VERTICAL) - mainSizer.Add( + self.panelContentsSizer .Add( borderSizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=5, ) - self._brailleOutput = wx.StaticText(self, label=self._brailleOutputLastSet) + self._createControls(borderSizer, self.panel) + self.ShowWithoutActivating() + + def _createControls(self, sizer, parent): + self._brailleOutput = wx.StaticText(parent, label=self._brailleOutputLastSet) self._brailleOutput.Font = self._setBrailleFont(self._brailleOutput.GetFont()) log.debug(f"Font for braille: {self._brailleOutput.Font.GetNativeFontInfoUserDesc()}") - borderSizer.Add(self._brailleOutput, flag=wx.EXPAND, proportion=1) + sizer.Add(self._brailleOutput, flag=wx.EXPAND, proportion=1) - self._rawTextOutput = wx.StaticText(self, label=self._rawTextOutputLastSet) + self._rawTextOutput = wx.StaticText(parent, label=self._rawTextOutputLastSet) self._rawTextOutput.Font = self._setRawTextFont(self._rawTextOutput.Font) log.debug(f"Font for raw text: {self._rawTextOutput.Font.GetNativeFontInfoUserDesc()}") - borderSizer.Add(self._rawTextOutput, flag=wx.EXPAND, proportion=1) + sizer.Add(self._rawTextOutput, flag=wx.EXPAND, proportion=1) # Translators: The label for a setting in the braille viewer that controls # whether the braille viewer is shown at startup or not. showOnStartupCheckboxLabel = _("&Show Braille Viewer on Startup") self._shouldShowOnStartupCheckBox = wx.CheckBox( - parent=self, + parent=parent, label=showOnStartupCheckboxLabel) self._shouldShowOnStartupCheckBox.SetValue(config.conf["brailleViewer"]["showBrailleViewerAtStartup"]) self._shouldShowOnStartupCheckBox.Bind(wx.EVT_CHECKBOX, self._onShouldShowOnStartupChanged) - borderSizer.AddSpacer(5) - borderSizer.Add(self._shouldShowOnStartupCheckBox) - - mainSizer.Fit(self) - self.Sizer = mainSizer - self.ShowWithoutActivating() + sizer.AddSpacer(5) + sizer.Add(self._shouldShowOnStartupCheckBox) def _onShouldShowOnStartupChanged(self, evt): config.conf["brailleViewer"]["showBrailleViewerAtStartup"] = self._shouldShowOnStartupCheckBox.IsChecked() diff --git a/source/speechViewer.py b/source/speechViewer.py index bfe96dfabf9..323433e89ca 100644 --- a/source/speechViewer.py +++ b/source/speechViewer.py @@ -12,35 +12,86 @@ # Inherit from wx.Frame because these windows show in the alt+tab menu (where miniFrame does not) +# We have to manually add a wx.Panel to get correct tab ordering behaviour. # wx.Dialog causes a crash on destruction when multiple were created at the same time (brailleViewer # may start at the same time) class SpeechViewerFrame(wx.Frame): - def __init__(self, onDestroyCallBack): - dialogSize=wx.Size(500, 500) - dialogPos=wx.DefaultPosition + def _getDialogSizeAndPosition(self): + dialogSize = wx.Size(500, 500) + dialogPos = wx.DefaultPosition if not config.conf["speechViewer"]["autoPositionWindow"] and self.doDisplaysMatchConfig(): log.debug("Setting speechViewer window position") speechViewSection = config.conf["speechViewer"] dialogSize = wx.Size(speechViewSection["width"], speechViewSection["height"]) dialogPos = wx.Point(x=speechViewSection["x"], y=speechViewSection["y"]) - super(SpeechViewerFrame, self).__init__(gui.mainFrame, wx.ID_ANY, _("NVDA Speech Viewer"), size=dialogSize, pos=dialogPos, style=wx.CAPTION | wx.RESIZE_BORDER | wx.STAY_ON_TOP) + return dialogSize, dialogPos + + def __init__(self, onDestroyCallBack): + dialogSize, dialogPos = self._getDialogSizeAndPosition() + super().__init__( + gui.mainFrame, + title=_("NVDA Speech Viewer"), + size=dialogSize, + pos=dialogPos, + style=wx.CAPTION | wx.RESIZE_BORDER | wx.STAY_ON_TOP + ) + self._isDestroyed = False self.onDestroyCallBack = onDestroyCallBack self.Bind(wx.EVT_CLOSE, self.onClose) self.Bind(wx.EVT_WINDOW_DESTROY, self.onDestroy) - sizer = wx.BoxSizer(wx.VERTICAL) - self.textCtrl = wx.TextCtrl(self, -1,style=wx.TE_RICH2|wx.TE_READONLY|wx.TE_MULTILINE) - sizer.Add(self.textCtrl, proportion=1, flag=wx.EXPAND) - # Translators: The label for a setting in the speech viewer that controls whether the speech viewer is shown at startup or not. - self.shouldShowOnStartupCheckBox = wx.CheckBox(self,wx.ID_ANY,label=_("&Show Speech Viewer on Startup")) - self.shouldShowOnStartupCheckBox.SetValue(config.conf["speechViewer"]["showSpeechViewerAtStartup"]) - self.shouldShowOnStartupCheckBox.Bind(wx.EVT_CHECKBOX, self.onShouldShowOnStartupChanged) - sizer.Add(self.shouldShowOnStartupCheckBox, border=5, flag=wx.ALL) - # set the check box as having focus, by default the textCtrl has focus which stops the speechviewer output (even if another window is in focus) - self.shouldShowOnStartupCheckBox.SetFocus() - self.SetSizer(sizer) + self.Bind(wx.EVT_ACTIVATE, self._onDialogActivated, source=self) + + self.frameContentsSizer = wx.BoxSizer(wx.HORIZONTAL) + self.SetSizer(self.frameContentsSizer) + self.panel = wx.Panel(self) + self.frameContentsSizer.Add(self.panel, proportion=1, flag=wx.EXPAND) + + self.panelContentsSizer = wx.BoxSizer(wx.VERTICAL) + self.panel.SetSizer(self.panelContentsSizer) + + self._createControls(sizer=self.panelContentsSizer, parent=self.panel) + + # Don't let speech viewer to steal keyboard focus when opened self.ShowWithoutActivating() + def _createControls(self, sizer, parent): + self.textCtrl = wx.TextCtrl( + parent, + style=wx.TE_RICH2 | wx.TE_READONLY | wx.TE_MULTILINE + ) + sizer.Add( + self.textCtrl, + proportion=1, + flag=wx.EXPAND + ) + + self.shouldShowOnStartupCheckBox = wx.CheckBox( + parent, + # Translators: The label for a setting in the speech viewer that controls + # whether the speech viewer is shown at startup or not. + label=_("&Show Speech Viewer on Startup") + ) + sizer.Add( + self.shouldShowOnStartupCheckBox, + border=5, + flag=wx.EXPAND | wx.ALL + ) + self.shouldShowOnStartupCheckBox.SetValue(config.conf["speechViewer"]["showSpeechViewerAtStartup"]) + self.shouldShowOnStartupCheckBox.Bind( + wx.EVT_CHECKBOX, + self.onShouldShowOnStartupChanged + ) + + def _onDialogActivated(self, evt): + # Check for destruction, if the speechviewer window has focus when we exit NVDA it regains focus briefly + # when the quit NVDA dialog disappears. Then shouldShowOnStartupCheckBox is a deleted window when we + # try to setFocus + if not self._isDestroyed: + # focus is normally set to the first child, however, + # the checkbox gives more context, and makes it obvious how to stop showing the dialog. + self.shouldShowOnStartupCheckBox.SetFocus() + def onClose(self, evt): if not evt.CanVeto(): deactivate() @@ -50,7 +101,10 @@ def onClose(self, evt): def onShouldShowOnStartupChanged(self, evt): config.conf["speechViewer"]["showSpeechViewerAtStartup"] = self.shouldShowOnStartupCheckBox.IsChecked() + _isDestroyed: bool + def onDestroy(self, evt): + self._isDestroyed = True log.debug("SpeechViewer destroyed") self.onDestroyCallBack() evt.Skip() diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t index 706576f5ad6..90876580adb 100644 --- a/user_docs/en/changes.t2t +++ b/user_docs/en/changes.t2t @@ -79,6 +79,7 @@ What's New in NVDA - Don't double speak name when aria-labelledby relation target is an inner element. (#10552) - On Windows 10 version 1607 and later, typed characters from Braille keyboards are spoken in more situations. (#10569) - When changing the audio output device, tones played by NVDA will now play through the newly selected device. (#2167) +- In Mozilla Firefox, moving focus in browse mode is faster. This makes moving the cursor in browse mode more responsive in many cases. (#10584) == Changes for Developers == diff --git a/user_docs/en/userGuide.t2t b/user_docs/en/userGuide.t2t index e839f90d6ce..668be8f0173 100644 --- a/user_docs/en/userGuide.t2t +++ b/user_docs/en/userGuide.t2t @@ -761,7 +761,7 @@ Pressing dot 7 + dot 8 translates any braille input, but without adding a space %kc:endInclude + Vision +[Vision] -While NVDA is primairly aimed at blind or vision impaired people how primarily use speech and/or braille to operate a computer, it also provides built-in facilities to change the contents of the screen. +While NVDA is primarily aimed at blind or vision impaired people who primarily use speech and/or braille to operate a computer, it also provides built-in facilities to change the contents of the screen. Within NVDA, such a visual aid is called a vision enhancement provider. NVDA offers several built-in vision enhancement providers which are described below. @@ -1061,7 +1061,7 @@ The available logging levels are: - If you are concerned about privacy, do not set the logging level to this option. - Debug: In addition to info, warning, and input/output messages, additional debug messages will be logged. - Just like input/output, if you are concerned about privacy, you should not set the logging level to this option. -- + ==== Automatically start NVDA after I log on to Windows ====[GeneralSettingsStartAfterLogOn] If this option is enabled, NVDA will start automatically as soon as you log on to Windows. @@ -1544,6 +1544,7 @@ This checkbox, when checked, tells NVDA to report help balloons and toast notifi - Help Balloons are like tooltips, but are usually larger in size, and are associated with system events such as a network cable being unplugged, or perhaps to alert you about Windows security issues. - Toast notifications have been introduced in Windows 10 and appear in the notification center in the system tray, informing about several events (i.e. if an update has been downloaded, a new e-mail arived in your inbox, etc.). + ==== Report Object Shortcut Keys ====[ObjectPresentationShortcutKeys] When this checkbox is checked, NVDA will include the shortcut key that is associated with a certain object or control when it is reported. For example the File menu on a menu bar may have a shortcut key of alt+f.