Synopsis #
Header: fxcg/keyboard.h
Syscall index: 0x0EAB
Function signature: int GetKey(int* key)
A blocking function that waits for a key to be pressed and puts the VRAM contents to screen (as if Bdisp_PutDisp_DD had been called). This function handles the MENU key (even though this can be controlled); process switching when inside an eActivity strip; text selection, and cutting/copying of that selection, when performing text edition; powering off when Shift+AC/on is pressed; taking screenshots when Shift+7 is pressed; opening the function catalog (Shift+4, can be controlled), and much more.
Despite taking only one int* parameter and returning an int, this is a very important syscall whose function goes beyond merely reading keyboard input: it plays a central role in coordinating different aspects of the interaction between add-ins, built-in OS apps and the main OS process.
Parameters #
int* key - pointer to integer that will receive the key code once a key is pressed and the function returns. The relationship between keys and keycodes can be found here.
Returns #
- 0 if a CTRL-key is pressed;
- 1 if a CHAR-key is pressed.
Comments #
As described above, this is a very complex syscall of high importance, so complex that its full importance is yet to be understood. It does a number of useful things (“useful”, at least in the context of normal and “boring” OS apps and add-ins):
- It puts the VRAM contents to display so that Bdisp_PutDisp_DD doesn’t need to be manually called;
- It will call DisplayStatusArea if EnableDisplayHeader returns a non-zero value.
- It checks that screen backlight and power off timeouts have not passed, and when they do, it does the appropriate actions (lower brightness or power off the calculator);
- Handles special keys such as the MENU, CAPTURE (Shift+7), CATALOG
(Shift+4), CLIP (Shift+8), and Shift and Alpha itself.
When such a special key is pressed, GetKey may return immediately or not, and regardless of returning, it may call functions or set setup flags as needed to show a certain OS behavior. Examples:- Shift and Alpha: the function returns and sets key to the respective key code, but before returning it automatically sets the setup entry with ID 0x14 to the appropriate keyboard mode;
- CLIP (Shift+8) - If not doing text editing, GetKey returns immediately after setting the value of key. Otherwise, it also returns, but only after letting the user select and cut or copy the text being edited.
- CAPTURE (Shift+7) - The function returns immediately, setting key to the key code of CAPTURE; however, it opens the screenshot taking dialog on the next call to it, and if the user presses EXIT on the dialog, it will return again, setting key to the key code for the EXIT key.
- MENU - Under normal conditions, GetKey doesn’t return when this key is pressed - as far as it is concerned, the Main Menu can be opened and closed and your add-in will never know it. However, depending on system flags, the special behavior for this key can be disabled, and MENU will be treated like any other key (meaning users won’t be able to open the Main Menu).
- OFF (Shift+AC/on) - like what happens with the MENU key, GetKey doesn’t return with this key either - and similarly, as far as it is concerned, the calculator can be turned off and back on, and your add-in will never know it.
- It allows for switching between the main process (eActivity document) and the child process, when an eActivity strip is open.
GetKey as the process switcher and power manager #
As described above, GetKey not only allows for switching to the Main Menu and back, it is also the component that, on eActivity strips, allows for switching between the main eActivity process and the child process (possibly an add-in), as well as switching apps inside the strip (by opening what can be described as the child process’ equivalent of the Main Menu). Furthermore, it is also responsible for calling the power off (actually “hibernate”) routine, as well as handling the restore from the “hibernation”.
The OS idles on GetKey - even when there is a cursor flashing, GetKey is waiting for a keyboard input or a timeout - and apparently no big period of time passes without this syscall being called. Over 95% of the user interaction with the OS and its apps takes place through this syscall. Examples of human-noticeable periods when, in official add-ins or built-in apps, GetKey is not running (but other keyboard reading methods may be):
- graph drawing;
- expression computation;
- running BASIC programs;
- accessing and sorting files and folders for list display;
- storage memory optimization;
- storage memory file saving/loading…
As you can see, none of these take very long periods of time - except maybe running programs, but even there we’re not certain that GetKey is not being called, even if only for short periods of time. Which leads us to the next point…
When to call GetKey #
Basically, GetKey should be called whenever you can afford stopping execution to wait for keyboard input. This certainly includes most situations on add-ins that are not games, and even games do not always need non-blocking input.
If you use any non-blocking input method, to preserve user experience, you should at least make sure that it handles the MENU key and that its only action is opening the Main Menu - see Keyboard - usability guidelines.
If you can’t handle the MENU key, at least make sure that when users choose to exit your add-in, they are put on a loop with GetKey, so that they can press MENU to exit. Note that it is very annoying for users to have to press EXIT (or who knows what else) on multiple screens before getting to a screen where they can finally press MENU to exit. Even more annoying, is setting MENU to do something else other than opening the Main Menu, and requiring users to use EXIT to exit the add-in. This kind of broken behavior was a “tradition” present on many custom add-ins for the fx-9860G, and which some developers brought in when developing for the Prizm. Fortunately, the situation with the latter isn’t as bad, so far.
Even though the OS doesn’t visibly fail if an add-in returns to the caller, this is not the recommended way of doing things, not only because it breaks the user experience but also because it may break things under-the-hood, and may cause unexpected behavior in future OS versions or with future custom add-in launchers.
GetKey as an exit point #
GetKey can be the exit point of your add-in - in fact, it is the only “correct” exit point (that is, compatible with what the OS expects). The GetKey call will put a stop to your program execution when the user decides to launch another app from the main menu, or to safely turn off the calculator then take off the batteries (or press RESTART on the back). If the add-in is running as an eActivity strip, other options exist: the user may switch back to the main eActivity screen with Shift+(the key above AC/on) and never come back, or he could launch another app by pressing Shift+(the comma key, to the left of the last one).
Ideally, and to sum it up, when your add-in calls GetKey, it must be prepared to be exited… but of course, you can run cleanup routines (possibly not necessary
- the OS will reset stack, heap and user timers for you, but not Bfile handlers) or ask users one last question, for instance, to save file contents like eActivity does, by using SetQuitHandler.
Blocking function catalog (Shift+4) access #
Disabling access to the function catalog, which is useless in most situations where one is not inputting a math expression, is as easy as calling Bkey_SetAllFlags with 0x80 as the parameter:
Bkey_SetAllFlags(0x80);
More specifically, it’s the bit 0x0080 of the Bkey flags that is responsible for disabling catalog access. To re-enable catalog access, you can unset all flags:
Bkey_SetAllFlags(0);
Blocking Main Menu access #
Note that Main Menu access should not normally be blocked, to keep the user experience intact - see #When_to_call_GetKey. However, if such blocking is justified, it can be done. There is a flag, whose location in memory changes depending on the OS version and possibly other factors, that determines part of the behavior of the syscall when it comes to locking functionality. There is a syscall to get the flag value, GetGetkeyToMainFunctionReturnFlag, but no syscall exists for setting it. Because of this, Simon Lothar developed a custom function to do its job.
List of key codes #
A list of key codes set by this syscall in the key parameter, can be found at can be found in the keycode reference. For easier usage of the values in source code, the fxcg/keyboard.h header contains defines for the codes - the ones that apply start with KEY_CTRL_ or KEY_CHAR_.