The Inside Story of NVDA: does NVDA sleep after pressing NVDA+Shift+S/Z? Not really #NVDA_Internals
The following Inside Story stems from the question posed in this thread: how does NVDA know to pass keyboard commands to the app while it is sleeping? The deeper question is, “is NVDA ‘sleeping’ when pressing NVDA+Shift+S/Z to toggle sleep mode?” The subject line gave the answer, and hopefully the below story should clarify as to why:
When you read the user guide, one of the commands you will come across is NVDA+Shift+S (laptop: NVDA+Shift+Z). This command toggles sleep mode where NVDA will not announce anything from the focused app, as well as passing keyboard commands to the application. But how? If you recall the Inside Story on NVDA components, NVDA consists of multiple parts, including input, output, event handling, and things in between, and parts of these components are turned off (not entered, technically) while NVDA is “sleeping” (notice the quotes, will explain shortly).
During normal business hours (when NVDA is not sleeping), NVDA will handle commands by itself or pass them to the application. First, after receiving a piece of keyboard input, NVDA converts what’s called “scan code” from the keyboard driver (as seen by Windows) to a form that NVDA can understand (typically to a string). Then, NVDA converts this into a gesture, which is then passed to input manager (inputCore.InputManager) which then runs the command associated with the gesture via “executeGesture” method (or function, if you will). The job of “execute gesture” routine is to figure out if there is a script for (bound to) the keyboard command you’ve entered, and if it does, it performs whatever you want NVDA to do; if not, it passes the keyboard input to the focused application unless NVDA is “taking a break” (or rather, you told NVDA to take a break a.k.a. sleep in the focused app).
In addition to keyboard commands, NVDA can react to events coming from the program. This is handled via “execute event” (eventHandler.executeEvent) routine where it checks various conditions to make sure it can react to whatever event it is handling at that moment. If the incoming event can be handled, NVDA then asks global plugins, app modules, tree interceptors, and NVDA objects (in that order) to handle current event in whatever shape or form, and this is where you will hear NVDA say something if any of the layers listed above tells the screen reader to do it.
But what happens when sleep mode is enabled, and if enabled, does it make NVDA “sleep”? The answer is no. Remember that whenever keyboard input is received by the screen reader, it wants to know if there is a command (script) associated with it. I did say that it will do something unless it is taking a break, and that happens to be checking a flag to see if NVDA should do nothing if the focused control and the app says, “go to sleep for now”. This attribute or a flag, called “sleepMode” (a true/false value) is defined in two places:
Ultimately, sleep mode in NVDA depends on the sleep mode flag from the app module. The sleep mode toggle command goes something like this:
What happens while NVDA is sleeping? From the input perspective:
On the event handling side (somewhat tied to output):
I won’t go into output side of things (speech and braille) as it will touch NVDA Controller client (a DLL used by third-party applications to send speech and braille text to be announced by NVDA), but suffice to say that speech and braille announcements will be vetoed by NVDA if sleep mode is on for the focused application.
You may have noticed that sleep mode flag from app modules is what really makes NVDA do things or stay silent, more so when handling events. This is evident when you hear notifications from an app that is not the focused app (say, toast notifications) while sleep mode is active. This should answer a question I might come back to later: how can NVDA say things in the background? This is tied to event processing from foreground and background controls, more so when you think about background progress bar announcements (another time). For now, the key takeaway from this Inside Story is this: NVDA stays active even when you think it is sleeping as long as you don’t quit NVDA.
Hope this clarifies many things.
P.S. The code fragment comes from latest NVDA alpha snapshot (master branch in NVDA source code).