Fix Screen Curtain (#19305)
Fixes #19263
Closes #10545
Possible fix for #18693 and #18743
### Summary of the issue:
Since #19177, if Screen Curtain fails to initialise because
`isScreenFullyBlack` returns `False`, NVDA crashes (#19263).
It would appear that from time to time, bitblitting from the desktop
context to the capture context in `nvdaHelper/local/screenCurtain.cpp`
failes due to one or both of the context handles being invalid.
I have no idea why this happens, but can only surmise that it's a timing
issue, as we check the validity of the contexts upon creation, so
something must be invalidating them in the meantime.
I strongly suspect that this is the underlying cause of Screen Curtain
failing to be activated on the Windows login screen (#18743) and after
login (#18693).
### Description of user facing changes:
NVDA no longer crashes if Screen Curtain fails to be enabled when
initializing NVDA.
Screen curtain may be enabled more reliably at the login screen and
immediately after login.
I have not included a change log entry, because #19263 was introduced as
part of 2026.1 alphas, and I don't know if this PR fixes #18693 or
#18743.
### Description of developer facing changes:
None
### Description of development approach:
* In `screenCurtain._screenCurtain.ScreenCurtain.enable`, add logic to
automatically retry enabling the Screen Curtain a fixed number of times
before admitting defeat.
If the issue really is a race condition or other timing issue, future
retries should theoretically be uneffected by the issue, so it will
succeed.
Currently the maximum number of attempts is hardcoded at 3.
* In `screenCurtain._screenCurtain.ScreenCurtain.__init__`, wrap
`self.enable` in a try/except block.
* In
`gui.settingsDialogs.PrivacyAndSecurityDialog._ensureScreenCurtainEnableState`,
wrap `screenCurtain.screenCurtain.enable` in a try/except block, and
notify the user when enabling the screen curtain has failed.
### Testing strategy:
Intentionally introduced errors into
`screenCurtain._screenCurtain.ScreenCurtain.enable`, and ensure that the
error handling works correctly.
Intentionally introduced errors that only happen a fixed number of times
into `screenCurtain._screenCurtain.ScreenCurtain.enable`, and ensure
that the retry logic works correctly.
### Known issues with pull request:
None