Repository: nvaccess/nvda

Issue:
Re-add Screen Curtain Enabled Beep at NVDA StartUp
<!--
Please thoroughly read NVDA's wiki article on how to fill in this template, including how to provide the required files.
Issues may be closed if the required information is not present.
https://github.com/nvaccess/nvda/wiki/Github-issue-template-explanation-and-examples
-->

### Is your feature request related to a problem? Please describe.
If a user is is expecting the enabled beep that was available in the Screen Curtain add-on when NVDA was started and Screen Curtain was enabled by default, they may incorrectly assume that Screen Curtain is not enabled in NVDA 2019.3beta1 after a restart.

### Describe the solution you'd like
If it is possible, it would be great to have the beep that played when NVDA started and Screen Curtain was enabled by default implemented in NVDA 2019.3. This beep provides piece of mind that Screen Curtain is in deed enabled and saves the user from having to check, especially  if they frequently have to toggle Screen Curtain on or off.

### Describe alternatives you've considered
N/A

### Additional context
N/A
Screen curtain should not automatically toggle off when switching configuration profiles
### Steps to reproduce:

1. Assign the screen curtain command to a gesture.
2. Turn on screen curtain while in the default profile. It doesn't matter if its only temporarily or permanently on while NVDA is active.
3. Switch to an app which would cause a different profile to load, e.g one for programming.

### Actual behavior:

The screen curtain is automatically disabled when switching to an application which uses a profile where screen curtain has not yet been enabled. Users also receive no alerts about this surprising and potentially dangerous behaviour. The only way to know is to visually see the screen.

### Expected behavior:

The screen curtain should not automatically disable itself when switching profiles. I think this is a setting which makes much more sense to be global to avoid unwanted surprises. I'm also not sure what the use case is for having it automatically turn on only in certain applications, which the current implementation enables.

### System configuration
#### NVDA installed/portable/running from source:

Installed

#### NVDA version:

alpha-19136,0124e647

#### Windows version:

1905

#### Name and version of other software in use when reproducing the issue:

N/a

#### Other information about your system:

N/a

### Other questions
#### Does the issue still occur after restarting your PC?

Yes

#### Have you tried any other versions of NVDA? If so, please report their behaviors.

N/a
Screen curtain should not automatically toggle off when switching configuration profiles
### Steps to reproduce:

1. Assign the screen curtain command to a gesture.
2. Turn on screen curtain while in the default profile. It doesn't matter if its only temporarily or permanently on while NVDA is active.
3. Switch to an app which would cause a different profile to load, e.g one for programming.

### Actual behavior:

The screen curtain is automatically disabled when switching to an application which uses a profile where screen curtain has not yet been enabled. Users also receive no alerts about this surprising and potentially dangerous behaviour. The only way to know is to visually see the screen.

### Expected behavior:

The screen curtain should not automatically disable itself when switching profiles. I think this is a setting which makes much more sense to be global to avoid unwanted surprises. I'm also not sure what the use case is for having it automatically turn on only in certain applications, which the current implementation enables.

### System configuration
#### NVDA installed/portable/running from source:

Installed

#### NVDA version:

alpha-19136,0124e647

#### Windows version:

1905

#### Name and version of other software in use when reproducing the issue:

N/a

#### Other information about your system:

N/a

### Other questions
#### Does the issue still occur after restarting your PC?

Yes

#### Have you tried any other versions of NVDA? If so, please report their behaviors.

N/a


Discussion:
I agree with this. In fact, a command to ask the status of this feature should be provided.
Even with the add-on, I usually have to change the screen curtain status to check if the feature is enabled or disabled.
Also a tone can be played when the screen curtain is enabled, even if the feature was enabled with a gesture.
Interesting suggestion. This might also cover the case mentioned in #10476 where someone misses the switch of the curtain.
This is an interesting point. Cc @feerrenrut 

While I think there might be potential for having screen curtain enabled only in certain profiles/applications, I think what you're raising here is actually broader than just screen curtain. The active providers are saved in a list. This means that, if you have screen curtain enabled in one profile and then disable it in another, then enabling the nvda highlighter in the default profile, the highlighter will also be off in that other profile.

I see several solutions:

1. Making the vision section a global config parameter. I think this is problematic though. While valid for the screen curtain may be, I can think of reasons why one wants the highlighter on in certain situations or hide the highlight in some other situations. Also if a magnifier would be integrated into the vision system, we have to deal with different color schemes / magnification levels
2. Giving every provider an enabled boolean in its own config section. This ensures that changes for a provider's activity in a certain profile won't touch other providers.

Additionally, we might want to make the provider announce its enabled/disabled state when the state is toggled by a config profile switch.
@leonardder I think that having the disabled state announced would mostly address the privacy concerns here, and I agree that per-profile settings are appropriate for most vision providers. Not sure if there are any other cases like this where being global is more desirable.
Wondering if an intermediate solution could be implemented in time for the release of 2019.3 to address the potential privacy concerns? E.g, an announcement when the screen curtain gets automatically toggled off.
After thinking about this a little more, I really want to keep the possibility to switch on the Screen Curtain on for some profiles and of for others.
It sounds like there is a lot of design work that will take time.

I suggest as an intermediate solution just announcing when the curtain gets automatically switched off? This addresses the immediate privacy concerns, without committing to a design for how vision providers interact with profiles.
This is an interesting point. Cc @feerrenrut 

While I think there might be potential for having screen curtain enabled only in certain profiles/applications, I think what you're raising here is actually broader than just screen curtain. The active providers are saved in a list. This means that, if you have screen curtain enabled in one profile and then disable it in another, then enabling the nvda highlighter in the default profile, the highlighter will also be off in that other profile.

I see several solutions:

1. Making the vision section a global config parameter. I think this is problematic though. While valid for the screen curtain may be, I can think of reasons why one wants the highlighter on in certain situations or hide the highlight in some other situations. Also if a magnifier would be integrated into the vision system, we have to deal with different color schemes / magnification levels
2. Giving every provider an enabled boolean in its own config section. This ensures that changes for a provider's activity in a certain profile won't touch other providers.

Additionally, we might want to make the provider announce its enabled/disabled state when the state is toggled by a config profile switch.
@leonardder I think that having the disabled state announced would mostly address the privacy concerns here, and I agree that per-profile settings are appropriate for most vision providers. Not sure if there are any other cases like this where being global is more desirable.
Wondering if an intermediate solution could be implemented in time for the release of 2019.3 to address the potential privacy concerns? E.g, an announcement when the screen curtain gets automatically toggled off.
After thinking about this a little more, I really want to keep the possibility to switch on the Screen Curtain on for some profiles and of for others.
It sounds like there is a lot of design work that will take time.

I suggest as an intermediate solution just announcing when the curtain gets automatically switched off? This addresses the immediate privacy concerns, without committing to a design for how vision providers interact with profiles.

Resolving patch:
diff --git a/source/globalCommands.py b/source/globalCommands.py
--- a/source/globalCommands.py
+++ b/source/globalCommands.py
@@ -2459,10 +2459,11 @@ def _enableScreenCurtain(doEnable: bool = True):
 					enableMessage = _("Temporary Screen curtain, enabled until next restart")
 
 				try:
-					vision.handler.initializeProvider(
-						screenCurtainProviderInfo,
-						temporary=tempEnable,
-					)
+					if not alreadyRunning:
+						vision.handler.initializeProvider(
+							screenCurtainProviderInfo,
+							temporary=tempEnable,
+						)
 				except Exception:
 					log.error("Screen curtain initialization error", exc_info=True)
 					# Translators: Reported when the screen curtain could not be enabled.
diff --git a/source/visionEnhancementProviders/screenCurtain.py b/source/visionEnhancementProviders/screenCurtain.py
--- a/source/visionEnhancementProviders/screenCurtain.py
+++ b/source/visionEnhancementProviders/screenCurtain.py
@@ -18,6 +18,7 @@
 import gui
 from logHandler import log
 from typing import Optional, Type
+import nvwave
 
 
 class MAGCOLOREFFECT(Structure):
@@ -100,9 +101,16 @@ class Magnification:
 )
 
 
+# Translators: Description for a screen curtain setting to play sounds when enabling/disabling the curtain
+playToggleSoundsCheckBoxText = _("&Play sound when toggling {screenCurtainTranslatedName}").format(
+	screenCurtainTranslatedName=screenCurtainTranslatedName
+)
+
+
 class ScreenCurtainSettings(providerBase.VisionEnhancementProviderSettings):
 
 	warnOnLoad: bool
+	playToggleSounds: bool
 
 	@classmethod
 	def getId(cls) -> str:
@@ -119,9 +127,13 @@ def _get_supportedSettings(self) -> SupportedSettingType:
 				warnOnLoadCheckBoxText,
 				defaultVal=True
 			),
+			BooleanDriverSetting(
+				"playToggleSounds",
+				playToggleSoundsCheckBoxText,
+				defaultVal=True
+			),
 		]
 
-
 warnOnLoadText = _(
 	# Translators: A warning shown when activating the screen curtain.
 	# the translation of "Screen Curtain" should match the "translated name"
@@ -314,6 +326,11 @@ def __init__(self):
 		Magnification.MagInitialize()
 		Magnification.MagSetFullscreenColorEffect(TRANSFORM_BLACK)
 		Magnification.MagShowSystemCursor(False)
+		if self.getSettings().playToggleSounds:
+			try:
+				nvwave.playWaveFile(r"waves\screenCurtainOn.wav")
+			except Exception:
+				log.exception()
 
 	def terminate(self):
 		log.debug(f"Terminating ScreenCurtain")
@@ -322,6 +339,11 @@ def terminate(self):
 		finally:
 			Magnification.MagShowSystemCursor(True)
 			Magnification.MagUninitialize()
+			if self.getSettings().playToggleSounds:
+				try:
+					nvwave.playWaveFile(r"waves\screenCurtainOff.wav")
+				except Exception:
+					log.exception()
 
 	def registerEventExtensionPoints(self, extensionPoints):
 		# The screen curtain isn't interested in any events


Test patch: