Top |
event_t | |
#define | evtype_None |
#define | evtype_Timer |
#define | evtype_CharInput |
#define | evtype_LineInput |
#define | evtype_MouseInput |
#define | evtype_Arrange |
#define | evtype_Redraw |
#define | evtype_SoundNotify |
#define | evtype_Hyperlink |
#define | evtype_VolumeNotify |
As described in Your Program's Main
Function, all player input is handed to
your program by the glk_select()
call, in the form of events.
You should write at least one event loop to retrieve these events.
void
glk_select (event_t *event
);
Causes the program to wait for an event, and then store it in the structure
pointed to by event
. Unlike most Glk functions that take pointers, the
argument of glk_select()
may not be NULL
.
Most of the time, you only get the events that you request. However, there
are some events which can arrive at any time. This is why you must always
call glk_select()
in a loop, and continue the loop until you get the event
you really want.
void
glk_select_poll (event_t *event
);
You can also inquire if an event is available, without stopping to wait for one to occur.
This checks if an internally-spawned event is available. If so, it stores it
in the structure pointed to by event
. If not, it sets event->type
to
evtype_None
.
Either way, it returns almost immediately.
The first question you now ask is, what is an internally-spawned event?
glk_select_poll()
does not check for or return evtype_CharInput
,
evtype_LineInput
, evtype_MouseInput
, or evtype_Hyperlink
events. It is
intended for you to test conditions which may have occurred while you are
computing, and not interfacing with the player. For example, time may pass
during slow computations; you can use glk_select_poll()
to see if a
evtype_Timer
event has occurred.
(See Timer Events.)
At the moment, glk_select_poll()
checks for evtype_Timer
, evtype_Arrange
,
evtype_Redraw
and evtype_SoundNotify
events.
But see Other Events.
The second question is, what does it mean that glk_select_poll()
returns
“almost immediately”?
In some Glk libraries, text that you send to a window is buffered; it does
not actually appear until you request player input with glk_select()
.
glk_select_poll()
attends to this buffer-flushing task in the same way.
(Although it does not do the “Hit any key to scroll down
” waiting which may
be done in glk_select()
; that's a player-input task.)
Similarly, on multitasking platforms, glk_select()
may yield time to other
processes; and glk_select_poll()
does this as well.
The upshot of this is that you should not call glk_select_poll()
very often.
If you are not doing much work between player inputs, you should not need to
call it at all.
For example, in a virtual machine interpreter, you should not call
glk_select_poll()
after every opcode.
However, if you are doing intense computation, you may wish to call
glk_select_poll()
every so often to yield time to other processes. And if you
are printing intermediate results during this computation, you should
glk_select_poll()
every so often, so that you can be certain your output will
be displayed before the next glk_select()
.
However, you should call glk_tick()
often — once per opcode in a VM
interpreter. See The Tick
Thing.
typedef struct { glui32 type; winid_t win; glui32 val1, val2; } event_t;
The event structure is self-explanatory. type
is the event type. The window
that spawned the event, if relevant, is in win
. The remaining fields contain
more information specific to the event.
The event types are described below. Note that evtype_None
is zero, and the
other values are positive. Negative event types (0x80000000 to 0xFFFFFFFF)
are reserved for implementation-defined events.
#define evtype_None (0)
No event. This is a placeholder, and glk_select()
never returns it.
#define evtype_CharInput (2)
A keystroke event in a window. See Character Input Events.
If a window has a pending request for character input, and the player hits a
key in that window, glk_select()
will return an event whose type is
evtype_CharInput
. Once this happens, the request is complete; it is no
longer pending. You must call glk_request_char_event()
or
glk_request_char_event_uni()
if you want another character from that window.
In the event structure, win
tells what window the event came from. val1
tells what character was entered; this will be a character code, or a special
keycode.
(See Character Input.)
If you called glk_request_char_event()
, val1
will be in 0..255, or else a
special keycode.
In any case, val2
will be 0.
#define evtype_LineInput (3)
A full line of input completed in a window. See Line Input Events.
If a window has a pending request for line input, the player can generally hit the enter key (in that window) to complete line input. The details will depend on the platform's native user interface.
When line input is completed, glk_select()
will return an event whose type is
evtype_LineInput
. Once this happens, the request is complete; it is no
longer pending. You must call glk_request_line_event()
if you want another
line of text from that window.
In the event structure, win
tells what window the event came from. val1
tells how many characters were entered. val2
will be 0 unless input was
ended by a special terminator key, in which case val2
will be the keycode
(one of the values passed to glk_set_terminators_line_event()
).
The characters themselves are stored in the buffer specified in the original
glk_request_line_event()
or glk_request_line_event_uni()
call.
There is no null terminator or newline stored in the buffer.
It is illegal to print anything to a window which has line input pending.
This is because the window may be displaying and editing the player's input, and printing anything would make life unnecessarily complicated for the library.
#define evtype_Arrange (5)
An event signalling that the sizes of some windows have changed.
Some platforms allow the player to resize the Glk window during play. This
will naturally change the sizes of your windows. If this occurs, then
immediately after all the rearrangement, glk_select()
will return an event
whose type is evtype_Arrange
. You can use this notification to redisplay the
contents of a graphics or text grid window whose size has changed.
The display of a text buffer window is entirely up to the library, so you don't need to worry about those.
In the event structure, win
will be NULL
if all windows are affected. If
only some windows are affected, win
will refer to a window which contains
all the affected windows. val1
and val2
will be 0.
You can always play it safe, ignore win
, and redraw every graphics and
text grid window.
An arrangement event is guaranteed to occur whenever the player causes any window to change size, as measured by its own metric.
Size changes caused by you — for example, if you open, close, or resize a window — do not trigger arrangement events. You must be aware of the effects of your window management, and redraw the windows that you affect.
It is possible that several different player actions can cause windows to change size. For example, if the player changes the screen resolution, an arrangement event might be triggered. This might also happen if the player changes his display font to a different size; the windows would then be different “sizes” in the metric of rows and columns, which is the important metric and the only one you have access to.
Arrangement events, like timer events, can be returned by glk_select_poll()
.
But this will not occur on all platforms. You must be ready to receive an
arrangement event when you call glk_select_poll()
, but it is possible that it
will not arrive until the next time you call glk_select()
.
This is because on some platforms, window resizing is handled as part of player input; on others, it can be triggered by an external process such as a window manager.
#define evtype_Redraw (6)
An event signalling that graphics windows must be redrawn.
On platforms that support graphics, it is possible that the contents of a
graphics window will be lost, and have to be redrawn from scratch. If this
occurs, then glk_select()
will return an event whose type is evtype_Redraw
.
In the event structure, win
will be NULL
if all windows are affected. If
only some windows are affected, win
will refer to a window which contains
all the affected windows. val1
and val2
will be 0.
You can always play it safe, ignore win
, and redraw every graphics window.
Affected windows are already cleared to their background color when you receive the redraw event.
Redraw events can be returned by glk_select_poll()
. But, like arrangement
events, this is platform-dependent. See evtype_Arrange
.
For more about redraw events and how they affect graphics windows, see Graphics Windows.
#define evtype_SoundNotify (7)
The completion of a sound being played in a sound channel.
On platforms that support sound, you can request to receive an
evtype_SoundNotify
event when a sound finishes playing.
See Playing Sounds.
#define evtype_Hyperlink (8)
The selection of a hyperlink in a window.
On platforms that support hyperlinks, you can request to receive an
evtype_Hyperlink
event when the player selects a link.
See Accepting Hyperlink Events.
#define evtype_VolumeNotify (9)
The completion of a gradual volume change in a sound channel.
On platforms that support sound, you can request to receive an
evtype_VolumeNotify
event when a gradual volume change completes.
See Playing Sounds.