Repository: nvaccess/nvda

Issue:
Braille message timeout, 0 to disable
IMO the value 0 should lead to no timeout. Currently this value disables messages altogether, which isn't very useful. If it *is* needed to disable messages it should be a global toggle that also affects speech.

To make this work:
- Implement in braille.py.
- Change the setting label to "Message timeout (sec, 0 to disable)".

Related: #6470


Discussion:
This was implemented (#2482 d30a09bf) at the request of several users (and
the patch came from one of those users). I too argued it was not useful,
but apparently, several braille + speech users disagreed.

You can set a long timeout to keep the messages on the display for longer.
Do you have a desire for keeping them there forever? If so, we might need
to consider a check box plus timeout.

> Do you have a desire for keeping them there forever?

Not really, just long enough to read them if they are a bit more complex than usual text. A longer timeout is fine, though to me "0 to disable" feels more natural than "0 to completely turn off the feature". As a compromise, could we update the label to include "(0 to disable messages)"?
Random idea, but why not make the timeout increase a little if the user 
presses the right advancer button.


On 1/3/2017 9:18 AM, Davy Kager wrote:
>
>     Do you have a desire for keeping them there forever?
>     Not really, just long enough to read them if they are a bit more
>     complex than usual text. A longer timeout is fine, though to me "0
>     to disable" feels more natural than "0 to completely turn off the
>     feature". As a compromise, could we update the label to include
>     "(0 to disable messages)"?
>
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub 
> <https://github.com/nvaccess/nvda/issues/6669#issuecomment-270153042>, 
> or mute the thread 
> <https://github.com/notifications/unsubscribe-auth/AFGiveJbNQ3oqN9eLxjfyTLScEb9a4y3ks5rOnTkgaJpZM4LUzSl>.
>

-- 
------------------------------------------------------------------------


    Derek Riemer

  * Department of computer science, third year undergraduate student.
  * Proud user of the NVDA screen reader.
  * Open source enthusiast.
  * Member of Bridge Cu
  * Avid skiier.

Websites:
Honors portfolio <http://derekriemer.com>
Awesome little hand built weather app! 
<http://django.derekriemer.com/weather/>

email me at derek.riemer@colorado.edu <mailto:derek.riemer@colorado.edu>
Phone: (303) 906-2194


[**@dkager**](https://github.com/dkager) commented on [4 Jan. 2017, 2:18 am AEST](https://github.com/nvaccess/nvda/issues/6669#issuecomment-270153042 "2017-01-03T16:18:43Z - Replied by Github Reply Comments"):
> A longer timeout is fine, though to me "0 to disable" feels more natural than "0 to completely turn off the feature". As a compromise, could we update the label to include "(0 to disable messages)"?

I guess that's an option. Still, perhaps this whole magic value thing is just too ugly and we should just have an explicit check box. @feerrenrut, @qchristensen, thoughts?

[**@derekriemer**](https://github.com/derekriemer) commented on [4 Jan. 2017, 3:07 am AEST](https://github.com/nvaccess/nvda/issues/6669#issuecomment-270165673 "2017-01-03T17:07:03Z - Replied by Github Reply Comments"):
> Random idea, but why not make the timeout increase a little if the user 
> presses the right advancer button.

It already does. In fact, it resets the timeout completely if the user scrolls either right or left.
I can see both arguments to what 0 should mean here.  There is a logic to 0 disabling messages, as if messages time out after 0 seconds, then you would never get a chance to read them anyway.  I think the label should specify what a value of 0 means if not that messages instantly disappear.

A checkbox to specify whether to display messages and then a value for how long to display them would be one extra control but would probably be the clearest option.
An alternative might be to change the way that the values are reported. In some applications "slider" type controls have special values at each end, the minimum value might report as "messages disabled" and the maximum value might report as "no timeout" and in between are the values 1 - X. For this to work there needs to be a label, or read only text control (or similar) that shows the current value of the slider.

However if we only need one special value a checkbox would be simpler.
I'd go checkbox, also because no other setting currently uses special sliders as far as I know.

Resolving patch:
diff --git a/source/braille.py b/source/braille.py
--- a/source/braille.py
+++ b/source/braille.py
@@ -1612,6 +1612,8 @@ def _resetMessageTimer(self):
 		"""Reset the message timeout.
 		@precondition: A message is currently being displayed.
 		"""
+		if config.conf["braille"]["noMessageTimeout"]:
+			return
 		# Configured timeout is in seconds.
 		timeout = config.conf["braille"]["messageTimeout"] * 1000
 		if self._messageCallLater:
@@ -1626,8 +1628,9 @@ def _dismissMessage(self):
 		"""
 		self.buffer.clear()
 		self.buffer = self.mainBuffer
-		self._messageCallLater.Stop()
-		self._messageCallLater = None
+		if not config.conf["braille"]["noMessageTimeout"]:
+			self._messageCallLater.Stop()
+			self._messageCallLater = None
 		self.update()
 
 	def handleGainFocus(self, obj):
diff --git a/source/config/configSpec.py b/source/config/configSpec.py
--- a/source/config/configSpec.py
+++ b/source/config/configSpec.py
@@ -57,6 +57,7 @@
 	cursorBlink = boolean(default=true)
 	cursorBlinkRate = integer(default=500,min=200,max=2000)
 	cursorShape = integer(default=192,min=1,max=255)
+	noMessageTimeout = boolean(default=false)
 	messageTimeout = integer(default=4,min=0,max=20)
 	tetherTo = string(default="focus")
 	readByParagraph = boolean(default=false)
diff --git a/source/gui/settingsDialogs.py b/source/gui/settingsDialogs.py
--- a/source/gui/settingsDialogs.py
+++ b/source/gui/settingsDialogs.py
@@ -1562,14 +1562,22 @@ def makeSettings(self, settingsSizer):
 			self.shapeList.Disable()
 
 		# Translators: The label for a setting in braille settings to change how long a message stays on the braille display (in seconds).
-		messageTimeoutText = _("Message timeout (sec)")
+		messageTimeoutText = _("Message &timeout (sec)")
 		self.messageTimeoutEdit = sHelper.addLabeledControl(messageTimeoutText, nvdaControls.SelectOnFocusSpinCtrl,
 			min=int(config.conf.getConfigValidationParameter(["braille", "messageTimeout"], "min")),
 			max=int(config.conf.getConfigValidationParameter(["braille", "messageTimeout"], "max")),
 			initial=config.conf["braille"]["messageTimeout"])
 
+		# Translators: The label for a setting in braille settings to display a message on the braille display indefinitely.
+		noMessageTimeoutLabelText = _("Show &messages indefinitely")
+		self.noMessageTimeoutCheckBox = sHelper.addItem(wx.CheckBox(self, label=noMessageTimeoutLabelText))
+		self.noMessageTimeoutCheckBox.Bind(wx.EVT_CHECKBOX, self.onNoMessageTimeoutChange)
+		self.noMessageTimeoutCheckBox.SetValue(config.conf["braille"]["noMessageTimeout"])
+		if self.noMessageTimeoutCheckBox.GetValue():
+			self.messageTimeoutEdit.Disable()
+
 		# Translators: The label for a setting in braille settings to set whether braille should be tethered to focus or review cursor.
-		tetherListText = _("Braille tethered to:")
+		tetherListText = _("B&raille tethered to:")
 		# Translators: The value for a setting in the braille settings, to set whether braille should be tethered to focus or review cursor.
 		self.tetherValues=[("focus",_("focus")),("review",_("review"))]
 		tetherChoices = [x[1] for x in self.tetherValues]
@@ -1611,6 +1619,7 @@ def onOk(self, evt):
 		config.conf["braille"]["cursorBlink"] = self.cursorBlinkCheckBox.GetValue()
 		config.conf["braille"]["cursorBlinkRate"] = self.cursorBlinkRateEdit.GetValue()
 		config.conf["braille"]["cursorShape"] = self.cursorShapes[self.shapeList.GetSelection()]
+		config.conf["braille"]["noMessageTimeout"] = self.noMessageTimeoutCheckBox.GetValue()
 		config.conf["braille"]["messageTimeout"] = self.messageTimeoutEdit.GetValue()
 		braille.handler.tether = self.tetherValues[self.tetherList.GetSelection()][0]
 		config.conf["braille"]["readByParagraph"] = self.readByParagraphCheckBox.Value
@@ -1650,6 +1659,9 @@ def onShowCursorChange(self, evt):
 	def onBlinkCursorChange(self, evt):
 		self.cursorBlinkRateEdit.Enable(evt.IsChecked())
 
+	def onNoMessageTimeoutChange(self, evt):
+		self.messageTimeoutEdit.Enable(not evt.IsChecked())
+
 class AddSymbolDialog(wx.Dialog):
 
 	def __init__(self, parent):


Test patch: