XlInputExtension.mesa
Copyright Ó 1991, 1992 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, December 30, 1991 1:59 pm PST
Christian Jacobi, March 27, 1992 10:27 am PST
Supports the input extension for the X Window system (X11).
DIRECTORY Rope, Xl;
XlInputExtension: CEDAR DEFINITIONS ~ BEGIN
All requests and types are set up to exactly match the features of the protocol, unless specified differently. All differences in semantics or naming to the protocol are commented. Names are chosen like in the protocol, even when the protocol appears to be inconsistent.
A difference to the protocol specification is the way events are received. Events which are generated in groups by the server (because the data wouldn't fit in 32 bytes) are combined by XlInputExtension. In such cases a single event with all the data is handed to the Cedar client.
SendEvent, keyboard, and, most window manager functions are to be looked for in "extras" packages. This base package is not support the complete extension, but complete enough so that no recompilation is needed to add the missing requests in extra modules.
General Types
Atom or name for this extension is $XInputExtension
Int32Sequence: TYPE ~ RECORD[SEQUENCE leng: NAT OF INT32];
InputClass: TYPE ~ MACHINE DEPENDENT {keyClass(0), buttonClass(1), valuatorClass(2), feedbackClass(3), proximityClass(4), focusClass(5), otherClass(6), (255)};
May be extended by future versions of the input extension protocol
DeviceId: TYPE ~ DeviceIdBase[0..128);
Representation of used input extension device.
DeviceIdBase: TYPE = [0..256); --Used to be able to hold special input values, and, sometimes to allocate the right number of bits.
General Requests
GetExtensionVersion: PROC [c: Xl.Connection, name: Rope.ROPE] RETURNS [present: BOOL, majorVersion, minorVersion: INT];
Difference to protocol: available: is true when the extension is available and the version number allows usage of the reminder of this interface. This procedure may be used independently whether the connection supports the input extension or not.
ListInputDevices: PROC [c: Xl.Connection] RETURNS [LIST OF DeviceInfo];
Lists available devices. This procedure may be used independently whether the connection supports the input extension or not.
DeviceInfo: TYPE ~ RECORD [
type: Xl.XAtom, --nature of device; defined types listed below
id: DeviceId, --uniquely identifies device
numClasses: BYTE,
use: CurrentUse, --describes current use
info: LIST OF REF InputInfo,
name: Rope.ROPE--one of the defined types
];
CurrentUse: TYPE = {isXPointer, isXKeyboard, isExtensionDevice};
InputInfo: TYPE ~ RECORD [
class: InputClass,
info: SELECT type: InfoSelector FROM
keyInfo => [
min: BYTE,
max: BYTE,
number: CARD16],
buttonInfo => [
number: CARD16],
valuatorInfo => [
supportsRelative: BOOL,
supportsAbsolute: BOOL,
motionBufferSize: CARD32,
axisInfo: SEQUENCE numberOfAxis: BYTE OF AxisInfo],
ENDCASE
];
InfoSelector: TYPE ~ {keyInfo, buttonInfo, valuatorInfo};
AxisInfo: TYPE ~ RECORD [
resolution: CARD32,
min: CARD32,
max: CARD32
];
Typical extension types: MOUSE, TABLET, KEYBOARD, TOUCHSCREEN, TOUCHPAD, BUTTONBOX, BARCODE, KNOB𡤋OX, TRACKBALL, QUADRATURE, SPACEBALL, DATAGLOVE, EYETRACKER, CURSORKEYS, FOOTMOUSE, ID←MODULE, ONE←KNOB, NINE←KNOB
OpenDevice: PROC [c: Xl.Connection, id: DeviceId] RETURNS [REF OpenDeviceRec];
Opens a device; use id from ListInputDevices.
OpenDeviceRec: TYPE ~ RECORD [
id: DeviceId, --same id
classes: SEQUENCE numClasses: INT OF InputClassInfo
];
InputClassInfo: TYPE ~ PACKED RECORD [
inputClass: InputClass,
eventTypeBase: BYTE --this is used to compose values for EventClass
];
A client may open a device multiple times. However, a single CloseDevice closes all open instances of that device.
CloseDevice: PROC [c: Xl.Connection, deviceId: DeviceId, details: Xl.Details ¬ NIL];
Closes all open instances of that device for this connection.
SetDeviceMode: PROC [c: Xl.Connection, deviceId: DeviceId, relativeMode: BOOL] RETURNS [status: DeviceStatus];
Choose between absolute and relative mode.
DeviceStatus: TYPE ~ MACHINE DEPENDENT {success, alreadyGrabbed, deviceBusy};
SetDeviceValuators: PROC [c: Xl.Connection, deviceId: DeviceId, first: INT, values: LIST OF INT] RETURNS [status: ValuatorStatus];
Initialize valuators. Necessary e.g. when device is switched to absolute mode.
ValuatorStatus: TYPE ~ MACHINE DEPENDENT {success, alreadyGrabbed};
GetDeviceMotionEvents: PROC [c: Xl.Connection, deviceId: DeviceId, start, stop: Xl.TimeStamp ¬ Xl.currentTime] RETURNS [REF DeviceTimeCoords];
Returns positions in devices motion history buffer. The actual content is received through access functions to reduce the number of necessary allocations.
DeviceTimeCoords: TYPE;
IsAbsolute: PROC [dtc: REF DeviceTimeCoords] RETURNS [BOOL];
AxisCount: PROC [dtc: REF DeviceTimeCoords] RETURNS [NAT];
NumberOfEvents: PROC [dtc: REF DeviceTimeCoords] RETURNS [NAT];
TimeOfEvent: PROC [dtc: REF DeviceTimeCoords, eventNum: NAT] RETURNS [Xl.TimeStamp];
ValuatorOfEvent: PROC [dtc: REF DeviceTimeCoords, eventNum: NAT, valuatorNum: NAT] RETURNS [CARD32];
QueryDeviceState: PROC [c: Xl.Connection, deviceId: DeviceId] RETURNS [InputStates];
Returns current logical state of device.
InputStates: TYPE ~ RECORD [
numberOfClasses: BYTE,
states: LIST OF REF InputState
];
InputState: TYPE ~ RECORD [
number: BYTE,
s: SELECT class: InputClass FROM
keyClass => [
keys: PACKED ARRAY [0..31] OF BYTE
],
buttonClass => [
buttons: PACKED ARRAY [0..31] OF BYTE
],
valuatorClass => [
relativeMode: BOOL,
inProximity: BOOL,
valuators: REF Int32Sequence ¬ NIL
],
ENDCASE
];
Requesting Events
EventClass: TYPE ~ CARD32;
A wierd encoding on what kind of events should be generated. XlInputExtension uses the identical representation which is used by the protocol.
EventClasses: TYPE ~ REF Xl.Card32Sequence;
Type used for returned EventClass'es.
MakeEventClass: PROC [od: REF READONLY OpenDeviceRec, request: RequestableEvent] RETURNS [EventClass];
This is used to be able to specify what kind of events are desired.
It implements the "MACRO" as advertized in the protocol and found in the C library, just using a simpler input specification.
RequestableEvent: TYPE = MACHINE DEPENDENT {
devicePointerMotionHint, deviceButton1Motion, deviceButton2Motion, deviceButton3Motion, deviceButton4Motion, deviceButton5Motion, deviceButtonMotion, deviceButtonGrab, deviceOwnerGrabButton, noExtensionEvent,
deviceKeyPress, deviceKeyRelease, deviceButtonPress, deviceButtonRelease, deviceMotionNotify, deviceFocusIn, deviceFocusOut, proximityIn, proximityOut, deviceStateNotify, deviceMappingNotify, changeDeviceNotify,
(255)};
This RequestableEvent type is conveniantly made up to denote input for MakeEventClass; it has no direct aequivalent in the protocol. (Implementor warning: the values have well defined order useful for some arithmetic operations.)
For deviceButtonPress use also deviceButtonGrab to imply grabs. Usage then is exclusive. Otherwise no implicite grab is hold. Similar, add deviceOwnerGrabButton, deviceButtonMotion to modify other specification.
SelectExtensionEvents: PROC [c: Xl.Connection, window: Xl.Window, interest: LIST OF EventClass, details: Xl.Details ¬ NIL];
Requests server to send events
GetSelectedExtensionEvents: PROC [c: Xl.Connection, window: Xl.Window] RETURNS [thisClient: EventClasses, allClients: EventClasses];
Query which events currently are selected.
ChangeDeviceDontPropagateList: PROC [c: Xl.Connection, window: Xl.Window, eventClass: LIST OF EventClass, mode: ListModifierMode, details: Xl.Details ¬ NIL];
Specify whether events shall be propagated up the window hierarchy until an ancestor is found that is interested.
ListModifierMode: TYPE = MACHINE DEPENDENT {addToList, deleteFromList};
GetDeviceDontPropagateList: PROC [c: Xl.Connection, window: Xl.Window] RETURNS [dontPropagateList: EventClasses];
Returns which events are not propagated up the window hierarchy.
Changing Core devices
ChangeReply: TYPE ~ MACHINE DEPENDENT {success, alreadyGrabbed, deviceFrozen};
ChangePointerDevice: PROC [c: Xl.Connection, deviceId: DeviceId, xaxis, yaxis: BYTE] RETURNS [ChangeReply];
Changes which physical device is used as the X pointer.
Grab stuff
Active Grabs
GrabDevice: PROC [c: Xl.Connection, deviceId: DeviceId, grabWindow: Xl.Window, ownerEvents: BOOL, eventList: LIST OF EventClass, thisDeviceMode: Xl.Synchronicity, otherDeviceMode: Xl.Synchronicity, time: Xl.TimeStamp ¬ Xl.currentTime] RETURNS [Xl.GrabStatus];
Active grab. Like GrabKeyboard.
UngrabDevice: PROC [c: Xl.Connection, deviceId: DeviceId, time: Xl.TimeStamp ¬ Xl.currentTime, details: Xl.Details ¬ NIL];
Releases grab.
Passive Grabs
useXKeyboard: DeviceIdBase ~ 0FFH; --for GrabDeviceButton, UngrabDeviceButton
anyButton: BYTE ~ 0; --for GrabDeviceButton, UngrabDeviceButton
GrabDeviceButton: PROC [c: Xl.Connection, deviceId: DeviceId, grabWindow: Xl.Window, modifiers: Xl.SetOfKeyButMask ¬ [anyModfier: TRUE], modifierDevice: DeviceIdBase ¬ useXKeyboard, button: BYTE ¬ anyButton, ownerEvents: BOOL, eventList: LIST OF EventClass, thisDeviceMode: Xl.Synchronicity, otherDeviceMode: Xl.Synchronicity, details: Xl.Details ¬ NIL];
Passive grab for a single button Like GrabButton, but no cursor or confineTo parameter.
UngrabDeviceButton: PROC [c: Xl.Connection, deviceId: DeviceId, grabWindow: Xl.Window, modifiers: Xl.SetOfKeyButMask ¬ [anyModfier: TRUE], modifierDevice: DeviceIdBase ¬ useXKeyboard, button: BYTE ¬ anyButton, details: Xl.Details ¬ NIL];
Releases passive grab.
Thawing
AllowDeviceEventsMode: TYPE ~ MACHINE DEPENDENT {asyncThisDevice, syncThisDevice, replayThisDevice, asyncOtherDevices, asyncAll, syncAll};
AllowDeviceEvents: PROC [c: Xl.Connection, deviceId: DeviceId, time: Xl.TimeStamp ¬ Xl.currentTime, mode: AllowDeviceEventsMode, details: Xl.Details ¬ NIL];
Allow further events to be processed when device has been frozen.
Focus
DeviceFocusReversion: TYPE ~ MACHINE DEPENDENT {none, pointerRoot, parent, followKeyboard}; --like FocusReversion but additional value followKeyboard
focusNone: Xl.Window ~ [[0]];
focusPointerRoot: Xl.Window ~ [[1]];
focusFollowKeyboard: Xl.Window ~ [[3]];
DeviceFocusRec: TYPE ~ RECORD [
window: Xl.Window ¬ Xl.nullWindow,
revertTo: DeviceFocusReversion ¬ none,
time: Xl.TimeStamp ¬ Xl.currentTime
];
GetDeviceFocus: PROC [c: Xl.Connection, deviceId: DeviceId] RETURNS [DeviceFocusRec];
SetDeviceFocus: PROC [c: Xl.Connection, deviceId: DeviceId, dfr: DeviceFocusRec ¬ [], details: Xl.Details ¬ NIL];
Control destination window of events from this device.
Device Encoding
GetDeviceButtonMapping: PROC [c: Xl.Connection, deviceId: DeviceId] RETURNS [Xl.PointerMapping];
Analogous to Xl.GetPointerMapping
Events
deviceKeyPressKey, deviceKeyReleaseKey, deviceButtonPressKey, deviceButtonReleaseKey, deviceMotionNotifyKey, deviceFocusInKey, deviceFocusOutKey, proximityInKey, proximityOutKey, deviceStateNotifyKey, deviceMappingNotifyKey, changeDeviceNotifyKey: READONLY REF ANY;
Keys to enable matching of events.
Example usage: Xl.FullCreateEventFilter[extensions: LIST[XlInputExtension.deviceKeyPressKey]]
Some events, (deviceValuator, deviceKeyStateNotify, deviceButtonStateNotify) are generated only when the original event does not carry enough bits for the information; these events are collected by XlInputExtensionImpl and returned together with the original even. They can not be matched explicitely by clients.
EventOffset: TYPE ~ MACHINE DEPENDENT {deviceValuator(0), deviceKeyPress(1), deviceKeyRelease(2), deviceButtonPress(3), deviceButtonRelease(4), deviceMotionNotify(5), deviceFocusIn(6), deviceFocusOut(7), proximityIn(8), proximityOut(9), deviceStateNotify(10), deviceMappingNotify(11), changeDeviceNotify(12), deviceKeyStateNotify(13), deviceButtonStateNotify(14)};
Offsets for distingushing different event types as defined by the protocol.
EventDataType: TYPE ~ {deviceBase, deviceFocus, deviceState, deviceMapping, deviceChange};
Tags for different types in event data-structure.
ExtEvent: TYPE ~ REF READONLY ExtEventRep;
ExtEventRep: TYPE ~ RECORD [
--This is the thing where the "decoded" field of an Xl.EventRep.extension points to.
eventOffset: EventOffset,
seq: Xl.SequenceNo ¬ 0,
time: Xl.TimeStamp,
deviceId: DeviceId,
details: SELECT type: EventDataType FROM
deviceBase => [
--deviceKeyPress, deviceKeyRelease, deviceButtonPress, deviceButtonRelease, deviceMotionNotify, proximityIn, proximityOut
--(hidden deviceValuator)
rootWindow: Xl.Window,
eventWindow: Xl.Window,
childWindow: Xl.Window, -- ¬ nullWindow,
sameScreen: BOOL,
rootPos: Xl.Point,
eventPos: Xl.Point, --of core pointer (even if device itself points somewhere else)
state: Xl.SetOfKeyButMask, --of core buttons and modifiers (just before event)
detail:
--For deviceKeyPress, deviceKeyRelease
keyCode: Xl.KeyCode ¬ VAL[0],
--For deviceButtonPress, deviceButtonRelease
button: BYTE ¬ 0,
--For deviceMotionNotify
-- BTW: granularity of motion not defined
normalHint: Xl.NormalHint ¬ normal,
--For proximityIn, proximityOut
--
deviceState: Xl.SetOfKeyButMask, --set only if valuators are reported
valuators: REF READONLY Int32Sequence ¬ NIL
],
deviceFocus => [
--deviceFocusIn, deviceFocusOut
detail: Xl.FocusDetail,
eventWindow: Xl.Window,
mode: Xl.GrabMode
],
deviceState => [
--DeviceStateNotify
--(hidden deviceKeyStateNotify, deviceButtonStateNotify)
numKeys: BYTE,
numButtons: BYTE,
numValuators: BYTE,
relativeMode: BOOL,
inProximity: BOOL,
keys: REF READONLY PACKED ARRAY [0..31] OF BYTE ¬ NIL,
buttons: REF READONLY PACKED ARRAY [0..31] OF BYTE ¬ NIL,
valuators: REF READONLY Int32Sequence ¬ NIL
],
deviceMapping => [
--deviceMapping
request: Xl.MappingNotifyKind,
firstKeycode: BYTE,
count: BYTE
],
deviceChange => [
--changeDeviceNotify
newWhat: {newPointer, newKeyboard}
],
ENDCASE
];
Warning about events sent from other clients using SendExtensionEvent:
The fields are carefully read from the connection; bad data will not cause a crash of XlInputExtensionImpl. However, in such a case some data could be truncated, or, events could be discarded.
DeviceBaseEvent: TYPE ~ REF READONLY deviceBase ExtEventRep;
DeviceFocusEvent: TYPE ~ REF READONLY deviceFocus ExtEventRep;
DeviceStateEvent: TYPE ~ REF READONLY deviceState ExtEventRep;
DeviceMappingEvent: TYPE ~ REF READONLY deviceMapping ExtEventRep;
DeviceChangeEvent: TYPE ~ REF READONLY deviceChange ExtEventRep;
END.