This is the second time that I have forgotten how NxTerm keyboard input is handled and was inspired to write a Wiki page. The first was when I analyzed CNxConsole Keyboard Input. This time, I am focused on the NxTerm example at apps/examples/nxterm.
The NxTerm example initializes the NX Server through the following steps:
boardctl(BOARDIOC_NX_START, 0) to start the NX server, thennx_connect() to connect to the NX server. nxterm_listener() to listen for NX server events.The Nxterm Example then initializes the Windows:
nxtk_openwindow() to create a bordered window, nxtk_setposition() and nxtk_setsize() to position the window in the display,nxtk_opentoolbar() to create a toolbar sub-window on the main window (This toolbar window is not used by the example, it is just for illustration).And binds the Nxterm driver to the permit drawing in the window. This is done when it:
boardctl(BOARDIOC_NXTERM, (uintptr_t)&nxcreate)Finally, it sets up the NxTerm and starts the console task:
stdout and stderr to the NxTerm driver. This will cause all standard output to be rendered into the main windows, andKeyboard and mouse inputs are received by the application through window callbacks, just like with the Xorg X server. Some listener needs to inject the keyboard input via nx_kbdin() (libs/libnx/nx_kbdin.c) which sends a message containing the keyboard input to the NX server. The NX server will forward that keyboard input to the window that has focus.
The Window application listens for NX server events by calling nx_eventhandler() (libs/libnx/nx_eventhandler) on another listener thread. If the window has focus when the key press is entered, nx_eventhandler()will forward the key press information to the registered window event handler.
In apps/examples/nxterm, nxterm_listener.c is the thread that drives nx_eventhandler(). The window NX keyboard callback is the function nxwndo_kbdin() in nxterm_wndo.c. That callback function is just a stub that writes the keyboard data to stdout. It is a stub because keyboard input is not received from the NxTerm in this example.
apps/examples/nxterm does not do things in the normal way. NSH does not receive keyboard input from NX; it gets keyboard input directly from the default stdin which is probably not a keyboard at all but more likely the host PC serial console. This is okay because only a single window is used and that example does not need the help of NX to select the window that has focus.
stdin in and stderr are re-directed to the NxTerm character driver in nxterm_main.c just before starting the console task. That logic looks like this:
/* Now re-direct stdout and stderr so that they use the NX console driver. * Note that stdin is retained (file descriptor 0, probably the serial * console). */
printf("nxterm_main: Starting the console task\n");
fflush(stdout);fflush(stderr);
fclose(stdout);fclose(stderr);
dup2(fd, 1);dup2(fd, 2);
Note that stdin is not re-directed in this example! This means that keyboard input does not come from the NxTerm driver but, rather, from whatever input device was previously configured for stdin, often a serial console.
There is a configuration option that determines if NxTerm receives keyboard input or not: CONFIG_NXTERM_NXKBDIN, For this NxTerm example, that option can be disabled
The boardctl() command BOARDIOC_NXTERM_IOCTL allows an application to inject keyboard data into NX for forwarding to the window with focus. In apps/examples/nxterm, the BOARDIOC_NXTERM_IOCTL is only called for the case of a redraw event. A redraw event may happen when a window above the current window is moved and the text is exposed.
If you use only a single window for the NxTerm example, then that window will always have focus. It will always have focus and will never be redrawn and the BOARDIOC_NXTERM_IOCTL will never be used (Unless, perhaps, you choose to implement pop-up error messages or menus on top of the NxTerm window).
Redraw callbacks will not be received even in a multi-window configuration if you use per-window frame buffers, either. In that case, the system will automatically redraw windows as needed using the per-window frame buffer shadow memory. This is controlled by the option CONFIG_NX_RAMBACKED. This option is recommended for performance reasons if you have sufficient memory to support it.
In this simple, single-window case, BOARDIOC_NXTERM_IOCTL will never be used.
See, for an example, apps/graphics/nxwm/src/cnxterm.cxx. In this case, the behavior will change, depending on the selection of CONFIG_NXTERM_NXKBDIN: If CONFIG_NXTERM_NXKBDIN is not selected, then the behavior will be similar to apps/examples/nxterm; stdin will not be redirected an keyboard input will come directly from the the system console.
But is CONFIG_NXTERM_NXKBDIN is select, NSH's stdin will be re-redirected to the to the NxTerm character driver. Keyboard input will arrive on stdin from the NxTerm driver rather than from the system console. The following sequence describes the keyboard input in this latter case:
nx_kbdin(),kbdin() method of the window that has focus, providing the keyboard input to the window application. In this case, the window application of interest is the NxTerm character driver,stdin which was re-directed to the NxTerm character driver. NSH processes the input, andstdout which was re-directed to the NxTerm character driver.Related articles: NuttX Window Manager (NxWM), NxWM (October 2019), NxWM Threading, and NxWM Threading Model.