XEMUL(4) —
NAME
xemul − X input emulator for queuing keyboard and mouse events
SYNOPSIS
pseudo-device xemul
DESCRIPTION
Xemul is used for queuing input events from the keyboard and mouse into a queue area shared between the kernel and a user-level window manager (such as X).
Starting the X Emulator
Since xemul is a non-standard input emulator, the user should open the non-standard console device associated with the display being used, e.g. /dev/aed, /dev/apa8. After the open, the user should perform the EISETD ioctl command to set the E_XINPUT emulator. The following piece of code does this initialization:
#include <machinecons/screen_conf.h>
#include <machinecons/xio.h>
main()
{
int fd, input_emul;
fd = open ("/dev/apa16", O_RDWR);
input_emul = E_XINPUT;
ioctl (fd, EISETD, &input_emul);
}
Once you have set the input emulator to E_XINPUT, all input from the keyboard is queued in shared memory. The normal read system call returns an error. As described in the emulator document, when you open the non-standard device, the output emulator defaults to the buffer emulator. This assumes the user process takes over the display and any write system calls are buffered until the user process gives up the display; see bufemul(4). Also see stdemul(4) or ibmemul(4) if you wish to change the output emulator back to the standard emulator.
To forward mouse events to xemul, set the mouse device associated with the display to a line discipline which forwards to an input emulator. See tb(4) for more information. Because xemul is a non-standard emulator, the default emulators are restored automatically when the last process holding the display open dies or closes the device.
Data Structures
The following data structures are defined in <machinecons/xio.h> and in <machinecons/qevent.h> and describe the data shared between the kernel and the user-level process. (Since xio.h includes qevent.h, user programs need only include xio.h.)
typedef struct _XIoAddr {
short status;/∗ Status of emulator (not used) ∗/
XEvent ∗ibuff;/∗ Pointer to event queue ∗/
int iqsize;/∗ Circular queue size (power of 2) ∗/
int ihead;/∗ Queue head ∗/
int itail;/∗ Queue tail ∗/
XCursor mouse;/∗ Current Mouse position ∗/
XCursor hotspot;/∗ Current Mouse hot spot ∗/
XBox mbox;/∗ Current Mouse movement box ∗/
int make_break;/∗ =0 then make =1 then break ∗/
short mthreshold;/∗ Mouse motion parameter ∗/
short mscale;/∗ Mouse scale factor (if negative
then do square). ∗/
MSBox hmbox;/∗ Hide mouse box ∗/
} XIoAddr;
typedef XIoAddr ∗XIoAddrAddr;
struct XBuffArea {
XIoAddr xioa;/∗ Queue and control information ∗/
XEvent ibuff[XMAXEVQ];/∗ Circular event queue ∗/
};
/∗ The event queue ∗/
typedef struct _X_eventqueue {
XEvent ∗events;/∗ input event buffer ∗/
int size;/∗ size of event buffer ∗/
int head;/∗ index into events ∗/
int tail;/∗ index into events ∗/
} XEventQueue;
typedef struct _X_event {
u_short xe_x;/∗ x position ∗/
u_short xe_y;/∗ y position ∗/
u_short xe_time;/∗ 10 millisecond units (button only) ∗/
u_char xe_type;/∗ button or motion? ∗/
u_char xe_key;/∗ the key (button only) ∗/
u_char xe_direction;/∗ which direction (button only) ∗/
u_char xe_device;/∗ which device (button only) ∗/
} XEvent;
/∗ xe_type field ∗/
#define XE_BUTTON0/∗ button moved ∗/
#define XE_MMOTION1/∗ mouse moved ∗/
#define XE_TMOTION2/∗ tablet moved ∗/
/∗ xe_direction field ∗/
#define XE_KBTUP0/∗ up ∗/
#define XE_KBTDOWN1/∗ down ∗/
#define XE_KBTRAW2/∗ undetermined ∗/
/∗ xe_device field ∗/
#define XE_MOUSE1/∗ mouse ∗/
#define XE_DKB2/∗ main keyboard ∗/
#define XE_TABLET3/∗ graphics tablet ∗/
#define XE_AUX4/∗ auxiliary ∗/
#define XE_CONSOLE5/∗ console ∗/
/∗ mouse motion rectangle ∗/
typedef struct _X_box {
short bottom;
short right;
short left;
short top;
} XBox;
/∗ mouse cursor position ∗/
typedef struct _X_cursor {
short x;
short y;
} XCursor;
/∗ Mouse locator bitmap ∗/
typedef struct
{
short data[16];
short mask[16];
struct {
short v, h;
} hotSpot;
} QIOLocator;
typedef struct {
short bottom;
short top;
short left;
short right;
int flags;/∗ 0 - not active, 1 - active ∗/
} MSBox;
Shared Memory
Once the user process sets xemul, the following code should be performed to get the address of the shared memory:
#include<machinecons/xio.h>
XIoAddrAddr XAddr;
XEventQueue ∗queue;
ioctl (fd, QIOCADDR, &XAddr);
queue = (XEventQueue ∗) (&XAddr->ibuff);
The last assignment above creates a pointer to the section of the shared memory where the queue pointers and information are kept.
Event Queue
At the start, the head and tail indices in the XEventQueue are both zero. When an event occurs, the information is stored at the tail, and the index is bumped up by one. If the tail index has reached the end of the queue, it wraps around to zero (circular queue). All input events are ignored if the tail index catches up to the head index.
The user should poll or issue a select to find out when one event occurs (head != tail). The user should then process the information from the event pointed to by the head index and then adjust the head index in the same manner as that described for the tail. The following code is an example of this process:
XEvent ∗ev;
while (queue->head != queue->tail) {
ev = &queue->events[queue->head];
switch (ev->xe_type) {
case XE_BUTTON: /∗ A key/button moved ∗/
key_button_motion (ev);
break;
case XE_MMOTION: /∗ The mouse moved ∗/
mouse_motion (ev);
break;
}
if ((nexthead = queue->head+1) >= queue_size)
nexthead = 0;
queue->head = nexthead;
}
Event Data
The user need only to analyze the data in the event passed to determine what has occurred. The xe_x and xe_y always contain the current mouse (x, y) position for any event. This same information is also always available in the mouse entry in the XIoAddr structure. The xe_time entry is a timestamp (in 10 millisecond units) marking that event. The xe_type entry describes what type of event occurred, XE_BUTTON meaning a keyboard key or mouse button event, XE_MMOTION meaning a mouse motion event, and XE_TMOTION meaning a tablet motion event. Only if the event was an XE_BUTTON will the xe_key, xe_direction, and xe_device fields be filled in accordingly. The xe_device tells you whether the event was from the keyboard, mouse, tablet, etc. The xe_key contains the keyboard key code or describes the mouse button. The xe_direction tells you whether the key/button was depressed or released (DOWN or UP). Button events are always presented as new events. See hardware documentation for the keyboard codes and tb(4) for the mouse-button report.
Motion Events
Motion events are joined if the previous event was a motion and the user had not yet read it. As stated before, the current mouse position is always kept in the shared memory structure XIoAddr.mouse. Motion events are not always reported as events to the user. The user may set the mouse motion box, XIoAddr.mbox, to a rectangle in which motion events should not be reported. This is a key feature of xemul, which optimizes events to those about which the user cares. This is possible because xemul tracks the mouse with the cursor/locator on the screen being used. Not being responsible for tracking the mouse on the screen, the user doesn’t need to know every motion event.
Cursor/Locator Control
The user can perform the following ioctls for controlling the mouse cursor tracking.
QIOCADDR The user passes the address of an XIoAddrAddr which is filled with the address in shared memory where the structure is found.
QIOCADDEVENT The user passes an XEvent structure to be added to the event queue. If the event queue is full, ENOBUFS is returned.
QIOCMUSTADD The user passes an XEvent structure to be added to the event queue. If the queue is full, the last event is dropped.
QIOCSMSTATE Set the mouse state. The user passes the XCursor structure to specify the new mouse position.
QIOCLDCUR The user passes a QIOLocator structure indicating what the cursor/locator bitmap should be on the display.
QIOCHIDECUR This ioctl inhibits the cursor/locator from being displayed on the screen. The cursor is still tracked and reported to the user.
QIOCSHOWCUR The user issues this ioctl to show the cursor/locator after it was hidden. The locator appears at its current location (not where it was hidden). The locator defaults to show.
QIOCSETSIZE Change the limits of the box in which the mouse tracks. Issuing this ioctl turns off kernel mouse tracking and disables QIOCSHOWCUR.
QIOCGETSIZE Return the current limits of the mouse box.
The user can also control the mouse cursor/locator by writing into the XIoAddr shared memory structure. The following is a synopsis of each remaining part of this structure:
mouse The current mouse position. XCursor structure.
hotspot Current Mouse hot spot offset from the mouse position. XCursor structure.
mbox Current Mouse movement box. XBox structure.
mthreshold Mouse motion parameter (not used currently).
mscale Mouse scale factor, if negative then do square (not used currently).
hmbox Hide mouse box, which the user specifies to give xemul a rectangle in which it should hide the mouse. The emulator passes this box to the hardware locator routines mainly so software driven cursors do not display within this box. This is only used by displays with no hardware cursor support which need to know when to get the software cursor out of the way.
Keyboard Ioctl Control
QIOCBELL Ring keyboard bell with integer volume passed from 0 (off) to 7 (loud).
QIOCCLICK Set autokeyclick to integer volume passed between -1 (default), 0 (off) and 8 (loud).
QIOCAUTOREP Turn keyboard keys autorepeat (1) on or (0) off, integer argument.
QIOCSETCAPSL Turn on Caps Lock light on keyboard.
QIOCCLRCAPSL Turn off Caps Lock light on keyboard.
QIOCSETNUML Turn on Num Lock light on keyboard.
QIOCCLRNUML Turn off Num Lock light on keyboard.
QIOCSETSCROLLL Turn on Scroll Lock light on keyboard.
QIOCCLRSCROLLL Turn off Scroll Lock light on keyboard.
FILES
/dev/aedIBM Academic Information Systems experimental display
/dev/apa8IBM 6153 Monochrome Display
/dev/apa8cIBM 6154 Advanced Color Graphics Display
/dev/apa16IBM 6155 Extended Monochrome Graphics Display
/dev/egaIBM 5154 Enhanced Color Display (no kernel cursor tracking)
/dev/mpelIBM 5081 MegaPel Display (no kernel cursor tracking)
/dev/vgaIBM PS/2’s planar display port (no kernel cursor tracking)
/dev/ibm8514IBM 8514/A display interface (no kernel cursor tracking)
SEE ALSO
bufemul(4), ibmemul(4), kbdemul(4), mouse(4), stdemul(4), tb(4)
“IBM/4.3 Console Emulators” in Volume II, Supplementary Documents
BUGS
Xemul does not implement threshold and scale features for the mouse.
PRPQs 5799-WZQ/5799-PFF: IBM/4.3 — Sept 1988