6.2. Handling Keyboard Events

This program creates a window and captures keystrokes, printing useful information to the console. Run it with the -v option to print a large amount of information. In QNX 4, run with:

[sh]$ phgamma kbd.g -v

or in QNX 6, with:

[sh]$ gamma kbd.g -v

To poll the keyboard in Photon, you actually set up an event handler as in this example, simply store all down keystrokes in a list, and remove them from the list when you receive the up keystroke. Create a timer (using the Gamma every function), and look at your list of currently pressed-down keys.

#!/usr/cogent/bin/phgamma

/* Bring in some general geometry methods for widgets */

require_lisp ("PhotonWidgets");

/* The mainline creates a blank window and attaches a raw callback to
   it.  This is how a window captures key events.  If you are looking
   for a particular key, the Pt_CB_HOTKEY callback is also useful. */

Verbose = nil;

function main ()
{
    PtInit (nil);
    w = new (PtWindow);
    w.SetDim (200,100);
    PtAttachCallback (w, Pt_CB_RAW, #cbHandleKeystroke(), Ph_EV_KEY);
    PtRealizeWidget (w);
    
    if (cadr(argv) == "-v")
    	Verbose = t;
    PtMainLoop();
}

/* The event data is available as implicit local variables in the
   callback function:
   widget	- the widget invoking this callback
   event_data   - the event data structure.
                Only one of the *_event unioned members of this
		structure is valid at any time.  Accessing the others
		may cause a crash.  The valid union member is
		determined by the type of callback being handled.  The
		member: rect is always valid.
   cbinfo        - the callback info structure.
                This is a union like event_data, where only one of
		the unioned members is valid at any one time.
		The members: event, reason, reason_subtype are always
		valid.
*/

/* The key symbols and flags are not built into the Gamma executable,
   but are readily available from /usr/include/photon/PkKeyDef.h. */

Pk_KF_Key_Down ::= 0x00000001;
Pk_KM_Shift ::= 0x00000001;
Pk_KM_Ctrl ::= 0x00000002;
Pk_KM_Alt ::= 0x00000004;

function cbHandleKeystroke ()
{
    if (Verbose)
    {
        princ ("Widget: ", class_name(widget), "\n");
        pretty_princ ("Evdata: ", event_data.key_event, "\n");
        princ ("CB Reason: ", cbinfo.reason, "\n");
        princ ("CB Subtype: ", cbinfo.reason_subtype, "\n");
        pretty_princ ("CB Event: ", cbinfo.event, "\n");
    }
    
    if ((event_data.key_event.key_flags & Pk_KF_Key_Down) != 0)
    {
        /* This is a down keystroke.  If the key_cap is above 256,
           then it is a key modifier, backspace, keypad, or other
           key that is not part of the standard ASCII key set. */
        if (Verbose || event_data.key_event.key_cap < 256)
        {
            princ ("\n");
            princ ("You pressed key cap ", event_data.key_event.key_cap,
                       " --> '");
            if (event_data.key_event.key_mods != 0)
            {
                if ((event_data.key_event.key_mods & Pk_KM_Ctrl) != 0)
                        princ ("ctrl-");
                if ((event_data.key_event.key_mods & Pk_KM_Alt) != 0)
                        princ ("alt-");
                if ((event_data.key_event.key_mods & Pk_KM_Shift) != 0)
                        princ ("shift-");
            }
            princ (char(event_data.key_event.key_cap), "'\n");
        }
    }
    
    if (Verbose)
            princ ("\n");
}