Nano-X API

The Nano-X API was originally designed by David Bell, with his mini-x package for the MINIX operating system. Nano-X is now running on top of the core graphics engine routines discussed in the section called Device-Independent Engine Features. Nano-X was designed for a client/server environment, as no pointers to structures are passed to the API routines, instead a call is made to the server to get an ID, which is passed to the API functions and is used to reference the data on the server. In addition, Nano-X is not message-oriented, instead modeled after the X protocol which was designed for speed on systems where the client and server machines were different.

Client/Server model

In Nano-X, there are two linking mechanisms that can be used for applications programs. In the client/server model, the application program is linked with a client library that forms a UNIX socket connection with the Nano-X server, a separate process. Each application then communicates all parameters over the UNIX socket. For speed and debugging, it is sometimes desirable to link the application directly with the server. In this case, a stub library is provided that just passes the client routines parameters to the server function.

The Nano-X naming convention uses GrXXX to designate client side callable routines, with a marshalling layer implemented in the files nanox/client.c , nanox/nxproto.c , and nanox/srvnet.c . The client/server network layer currently uses a fast approach to marshalling the data from the Gr routine into a buffer, and sent all at once to the receiving stubs in nanox/srvnet.c, before calling the server drawing routines in nanox/srvfunc.c. In the linked application scenario, the Nano-X client links directly with the functions in nanox/srvfunc.c , and the nanox/client.c and nanox/srvnet.c files are not required.

A Nano-X application must call GrOpen before calling any other Nano-X function, and call GrClose before exiting. These functions establish a connection with the server when running the client/server model, and return an error status if the server can't be found or isn't currently running.

The main loop in a Nano-X application is to create some windows, define the events you want with GrSelectEvents, and then wait for an event with GrGetNextEvent. If it is desired to merely check for an event, but not wait if there isn't one, GrCheckNextEvent can be used. GrPeekEvent can be used to examine the next event without removing it from the queue.

When running Nano-X programs in the client/server model, it's currently necessary to run the server first in a shell script, then wait a second, then run the application. Some rewriting is needed to fire up the server when an application requires it, I believe.

Events

Nano-X applications specify which events they would like to see on a per-window basis using GrSelectEvents. Then, in the main loop, the application calls GrGetNextEvent and waits for one of the event types selected for in any of the windows. Typically, a switch statement is used to determine what to do after receiving the event. This is similar to the Nano-X's API GetMessage/DispatchMessage loop, except that in Nano-X API, DispatchMessage is used to send the event to the window's handling procedure, typically located with the window object. In Nano-X, all the event handling code for each of the windows must be placed together in the main event loop, there is no automatic dispatching. Of course, widget sets serve to provide object-orientation, but this is in addition to the Nano-X API.

Following are the event types that Nano-X programs can recieve:

GR_EVENT_TYPE_NONE, ERROR, EXPOSURE, BUTTON_DOWN, BUTTON_UP, MOUSE_ENTER, MOUSE_EXIT, MOUSE_MOTION, MOUSE_POSITION, KEY_UP, KEY_DOWN, FOCUS_IN, FOCUS_OUT, FDINPUT, UPDATE, CHLD_UPDATE

Note that Nano-X API provides mouse enter and exit events whereas Nano-X API does not. Also, the exposure events are calculated and sent immediately by the server, and not combined and possibly delayed for better paint throughput as in the Nano-X API.

Window creation and destruction

Windows are created in Nano-X with the GrNewWindow function. Windows can be specified to be input-only, in which case the GrNewInputWindow function is used. The window border and color is specified in these calls, but will have to be rewritten when fancier window dressings are required. The return value from these functions is an ID that can be used in later calls to get a graphics context or perform window manipulation.

Pixmaps, which are offscreen windows, are created with GrNewPixmap. The ID returned can be used with any drawing function. Pixmaps are copied to windows using the GrCopyArea function, and destroyed like windows with GrDestroyWindow.

Window showing, hiding and moving

Windows are shown by calling the GrMapWindow function, and hidden using GrUnmapWindow. Mapping a window is required for all ancestors of a window in order for it to be visible. The GrRaiseWindow call is used to raise the Z order of a window, while GrLowerWindow is used to lower the Z order. GrMoveWindow is used to change the position of a window, and GrResizeWindow is used to resize a window. A window can be reparented with GrReparentWindow.

Drawing to a window

Nano-X requires both a window ID and a graphics context ID in order to draw to a window. Nano-X sends expose events to the application when a window needs to be redrawn. Unlike the Nano-X API, Nano-X clients are typically required to create their drawing graphics contexts early on and keep them for the duration of the application. Like Nano-X though, the graphics contexts record information like the current background and foreground colors so they don't have to be specified in every graphics API call.

Graphics contexts

To allocate a graphics context for a window, call GrNewGC. On termination, call GrDestroyGC. GrCopyGC can be used to copy on GC to another. GrGetGCInfo is used to retrieve the settings contained in a GC. After creating a graphics context, the server returns a graphics context ID. This is then used as a parameter in all the graphics drawing API functions. In Nano-X programs, the current clipping region and window coordinate system aren't stored with the GC, as they are in Nano-X' DCs. This is because, first, Nano-X doesn't support dual coordinate systems for drawing to the "window dressing" area versus the "user" area of the window (window and client coordinates in Nano-X). User programs can't draw the border area of the window, only a single color and width can be specified. Although resembling X, this will have to change, so that widget sets can specify the look and feel of all aspects of the windows they maintain. Since the clipping region isn't maintained with the graphics context, but instead with the window data structure, Nano-X applications must specify both a window ID and a graphics context ID when calling any graphics API function. Because of this, many Nano-X applications allocate all graphics contexts in the beginning of the program, and hold them throughout execution, since the graphics contexts hold only things like foreground color, etc, and no window information. This cannot be done with Nano-X API because the DC's contain window clipping information and must be released before processing the next message.

Graphics drawing API

Following are the graphics drawing functions available with Nano-X. Like Nano-X API, these all match up eventually to the graphics engine GdXXX routines.

Table 6-10. Nano-X Graphics Drawing Functions

FunctionDescription
GrGetGCTextSizeReturn text width and height information.
GrClearWindowClear a window to it's background color.
GrSetGCForegroundSet the foreground color in a graphics context.
GrSetGCBackgroundSet the background color in a graphics context.
GrSetGCUseBackgroundSet the "use background color" in a graphics context.
GrSetGCModeSet the drawing mode.
GrSetGCFontSet the font.
GrPointDraw a point in the passed gc's foreground color.
GrLineDraw a line in the passed gc's foreground color.
GrRectDraw a rectangle in passed gc's foreground color.
GrFillRectFill a rectangle with the passed gc's foreground color.
GrEllipseDraw a circle or ellipse with the passed gc's foreground color.
GrFillEllipseFill a circle or ellipse with the passed gc's foreground color.
GrPolyDraw a polygon using the passed gc's foreground color.
GrFillPolyFill a polygon using the passed gc's foreground color.
GrTextDraw a text string using the foreground and possibly background colors.
GrBitmapDraw an image using a passed monocrhome bitmap, use fb/bg colors.
GrBMPDraw an image from a .bmp file.
GrJPEGDraw an image from a .jpg file.
GrAreaDraw a rectangular area using the passed device-dependent pixels.
GrReadAreaRead the pixel values from the screen and return them.
GrGetSystemPaletteEntriesGet the currently in-use system palette entries.
GrFindColorTranslate an RGB color value to a PIXELVAL pixel value.

Utility functions

Various functions serve as utility functions to manipulate windows and provide other information. These include the following:

Table 6-11. Nano-X Utility Functions

FunctionDescription
GrSetBorderColorSet the border color of a window. Not suitable for 3d look and feel.
GrSetCursorSet the cursor bitmap for the window.
GrMoveCursorMove the cursor to absolute screen coordinates.
GrSetFocusSet the keyboard input focus window.
GrRedrawScreenRedraw the entire screen.
GrGetScreenInfoReturn information about the size of the physical display.
GrGetWindowInfoReturn information about the passed window.
GrGetGCInfoReturn information about the passed graphics context.
GrGetFontInfoReturn information about the passed font number.
GrRegisterInputRegister a file descriptor to return an event when read data available.
GrPrepareSelectPrepare the fd_set and maxfd variables for using Nano-X as a passive library.
GrServiceSelectCallback the passed GetNextEvent routine when Nano-X has events requiring processing.
GrMainLoopA convenience routine for a typical Nano-X application main loop.