DIRECTORY Rope, Xl, XlDispatch, XlEndianPrivate, XlExtensions, XlInputExtension, XlInputExtensionPrivate, XlKeyButPrivate, XlPrivate; XlInputExtensionImpl: CEDAR MONITOR LOCKS c USING c: Xl.Connection IMPORTS Rope, Xl, XlDispatch, XlEndianPrivate, XlExtensions, XlKeyButPrivate, XlPrivate EXPORTS XlInputExtension, XlInputExtensionPrivate SHARES Xl ~ BEGIN OPEN XlInputExtension, XlInputExtensionPrivate; extensionKey: ATOM ~ $XInputExtension; deviceKeyPressKey: PUBLIC REF ¬ $deviceKeyPress; deviceKeyReleaseKey: PUBLIC REF ¬ $deviceKeyRelease; deviceButtonPressKey: PUBLIC REF ¬ $deviceButtonPress; deviceButtonReleaseKey: PUBLIC REF ¬ $deviceButtonRelease; deviceMotionNotifyKey: PUBLIC REF ¬ $deviceMotionNotify; deviceFocusInKey: PUBLIC REF ¬ $deviceFocusIn; deviceFocusOutKey: PUBLIC REF ¬ $deviceFocusOut; proximityInKey: PUBLIC REF ¬ $proximityIn; proximityOutKey: PUBLIC REF ¬ $proximityOut; deviceStateNotifyKey: PUBLIC REF ¬ $deviceStateNotify; deviceMappingNotifyKey: PUBLIC REF ¬ $deviceMapping; changeDeviceNotifyKey: PUBLIC REF ¬ $changeDeviceNotify; extPropKey: REF ATOM ~ NEW[ATOM ¬ extensionKey]; lastConnectionData: REF ConnectionData ¬ NEW[ConnectionData]; GetConnectionData: PUBLIC PROC [c: Xl.Connection] RETURNS [cd: REF ConnectionData] = { cd ¬ lastConnectionData; IF cd.c=c THEN RETURN[cd]; cd ¬ lastConnectionData ¬ NARROW[Xl.GetConnectionPropAndInit[c, extPropKey, InitExtension]]; }; InitExtension: Xl.InitializeProcType = {--init availability of extension for this connection cd: REF ConnectionData ~ NEW[ConnectionData]; cd.ex ¬ XlExtensions.StartExtension[c, extensionKey]; IF cd.ex#NIL THEN cd.ex.state ¬ NEW[ExtensionStateRec]; RETURN [cd] }; GetExtensionVersion: PUBLIC PROC [c: Xl.Connection, name: Rope.ROPE] RETURNS [present: BOOL ¬ FALSE, majorVersion: INT ¬ 0, minorVersion: INT ¬ 0] = { reply: XlPrivate.Reply; n: INT ~ Rope.Length[name]; cd: REF ConnectionData ~ GetConnectionData[c]; IF n>c.info.maxRequestLengthBytes THEN ERROR; IF cd.ex#NIL THEN { DoIt: PROC [c: Xl.Connection] = { XlPrivate.BInit[c, cd.ex.majorOpcode, opGetExtensionVersion, 2+(n+3)/4]; XlPrivate.BPut16[c, n]; -- length of name XlPrivate.BSkip[c, 2]; XlPrivate.BPutPaddedRope[c, name]; reply ¬ XlPrivate.FinishWithReply[c]; }; XlPrivate.DoWithLocks[c, DoIt, NIL]; XlPrivate.CheckReply[reply]; XlPrivate.Skip[reply, 7]; majorVersion ¬ XlPrivate.Read16[reply]; minorVersion ¬ XlPrivate.Read16[reply]; present ¬ XlPrivate.Read8[reply]#0; XlPrivate.DisposeReply[c, reply]; }; }; ListInputDevices: PUBLIC PROC [c: Xl.Connection] RETURNS [diList: LIST OF DeviceInfo ¬ NIL] = { diRest: LIST OF DeviceInfo ¬ NIL; infoRest: LIST OF REF InputInfo ¬ NIL; reply: XlPrivate.Reply; cd: REF ConnectionData ~ GetConnectionData[c]; IF cd.ex#NIL THEN { DoIt: PROC [c: Xl.Connection] = { XlPrivate.BInit[c, cd.ex.majorOpcode, opListInputDevices, 1]; reply ¬ XlPrivate.FinishWithReply[c]; }; replyLength: CARD32; numberOfDevices: BYTE; XlPrivate.DoWithLocks[c, DoIt, NIL]; XlPrivate.CheckReply[reply]; XlPrivate.Skip[reply, 3]; replyLength ¬ XlPrivate.Read32[reply]; numberOfDevices ¬ XlPrivate.Read8[reply]; XlPrivate.Skip[reply, 23]; infoRest ¬ NIL; FOR nd: INT IN [0..numberOfDevices) DO di: DeviceInfo; di.type ¬ [XlPrivate.ERead32[reply]]; di.id ¬ XlPrivate.ERead8[reply] MOD 128; di.numClasses ¬ XlPrivate.ERead8[reply]; SELECT XlPrivate.ERead8[reply] FROM 0 => di.use ¬ isXPointer; 1 => di.use ¬ isXKeyboard; ENDCASE => di.use ¬ isExtensionDevice; XlPrivate.Skip[reply, 1]; FOR nc: INT IN [0..di.numClasses) DO inf: REF InputInfo; infoRest: LIST OF REF InputInfo; classId: BYTE ¬ XlPrivate.ERead8[reply]; length: BYTE ¬ XlPrivate.ERead8[reply]; SELECT classId FROM 0 => { i: REF keyInfo InputInfo ¬ NEW[keyInfo InputInfo]; i.min ¬ XlPrivate.ERead8[reply]; i.max ¬ XlPrivate.ERead8[reply]; i.number ¬ XlPrivate.ERead16[reply]; XlPrivate.Skip[reply, 2]; inf ¬ i; }; 1 => { i: REF buttonInfo InputInfo ¬ NEW[buttonInfo InputInfo]; i.number ¬ XlPrivate.ERead16[reply]; inf ¬ i; }; 2 => { numAxes: BYTE ¬ XlPrivate.ERead8[reply]; mode: BYTE ¬ XlPrivate.ERead8[reply]; i: REF valuatorInfo InputInfo ¬ NEW[valuatorInfo InputInfo[numAxes]]; i.supportsRelative ¬ ((mode) MOD 2) = 1; i.supportsAbsolute ¬ ((mode / 2) MOD 2) = 1; i.motionBufferSize ¬ XlPrivate.ERead32[reply]; FOR n: INT IN [0..numAxes) DO i.axisInfo[n].resolution ¬ XlPrivate.ERead32[reply]; i.axisInfo[n].min ¬ XlPrivate.ERead32[reply]; i.axisInfo[n].max ¬ XlPrivate.ERead32[reply]; ENDLOOP; inf ¬ i; }; ENDCASE => {}; inf.class ¬ VAL[classId]; IF di.info=NIL THEN di.info ¬ infoRest ¬ LIST[inf] ELSE {infoRest.rest ¬ LIST[inf]; infoRest ¬ infoRest.rest} ENDLOOP; di.name ¬ XlPrivate.EReadRope[reply]; IF diRest=NIL THEN diList ¬ diRest ¬ LIST[di] ELSE {diRest.rest ¬ LIST[di]; diRest ¬ diRest.rest} ENDLOOP; XlPrivate.DisposeReply[c, reply]; }; }; OpenDevice: PUBLIC PROC [c: Xl.Connection, id: DeviceId] RETURNS [od: REF OpenDeviceRec] = { reply: XlPrivate.Reply; cd: REF ConnectionData ~ GetConnectionData[c]; replyLength: CARD32; numberOfClasses: BYTE; DoIt: PROC [c: Xl.Connection] = { XlPrivate.BInit[c, cd.ex.majorOpcode, opOpenDevice, 2]; XlPrivate.BPut8[c, id]; XlPrivate.BSkip[c, 3]; reply ¬ XlPrivate.FinishWithReply[c]; }; IF cd.ex=NIL THEN ERROR; XlPrivate.DoWithLocks[c, DoIt, NIL]; XlPrivate.CheckReply[reply]; XlPrivate.Skip[reply, 3]; replyLength ¬ XlPrivate.Read32[reply]; numberOfClasses ¬ XlPrivate.Read8[reply]; XlPrivate.Skip[reply, 23]; od ¬ NEW[OpenDeviceRec[numberOfClasses]]; od.id ¬ id; FOR i: INT IN [0..numberOfClasses) DO od[i].inputClass ¬ VAL[XlPrivate.ERead8[reply]]; od[i].eventTypeBase ¬ XlPrivate.ERead8[reply]; ENDLOOP; XlPrivate.DisposeReply[c, reply]; }; CloseDevice: PUBLIC PROC [c: Xl.Connection, deviceId: DeviceId, details: Xl.Details ¬ NIL] = { action: PROC [c: Xl.Connection] = { XlPrivate.BInit[c, cd.ex.majorOpcode, opCloseDevice, 2]; XlPrivate.BPut8[c, deviceId]; XlPrivate.BSkip[c, 3]; XlPrivate.FinishWithDetails[c, details]; }; cd: REF ConnectionData ~ GetConnectionData[c]; IF cd.ex#NIL THEN XlPrivate.DoWithLocks[c, action, details]; }; SetDeviceMode: PUBLIC PROC [c: Xl.Connection, deviceId: DeviceId, relativeMode: BOOL] RETURNS [status: DeviceStatus] = { reply: XlPrivate.Reply; action: PROC [c: Xl.Connection] = { XlPrivate.BInit[c, cd.ex.majorOpcode, opSetDeviceMode, 2]; XlPrivate.BPut8[c, deviceId]; XlPrivate.BPut8[c, ORD[relativeMode]]; XlPrivate.BSkip[c, 2]; reply ¬ XlPrivate.FinishWithReply[c]; }; cd: REF ConnectionData ~ GetConnectionData[c]; IF cd.ex=NIL THEN ERROR; XlPrivate.DoWithLocks[c, action, NIL]; XlPrivate.Skip[reply, 7]; SELECT XlPrivate.Read8[reply] FROM 0 => status ¬ success; 1 => status ¬ alreadyGrabbed; ENDCASE => status ¬ deviceBusy; XlPrivate.DisposeReply[c, reply]; }; EventClassesLength: PUBLIC PROC [interest: LIST OF EventClass] RETURNS [count: INT ¬ 0] = { limit: INT = 200; FOR l: LIST OF EventClass ¬ interest, l.rest WHILE l#NIL DO IF count>=limit THEN ERROR; count ¬ count+1; ENDLOOP; }; PutEventClasses: PUBLIC PROC [c: Xl.Connection, interest: LIST OF EventClass, count: INT] = { FOR i: INT IN [0..count) DO XlPrivate.BPut32[c, LOOPHOLE[interest.first, CARD32]]; IF interest.rest#NIL THEN interest ¬ interest.rest ENDLOOP; }; SelectExtensionEvents: PUBLIC PROC [c: Xl.Connection, window: Xl.Window, interest: LIST OF EventClass, details: Xl.Details ¬ NIL] = { count: INT ¬ EventClassesLength[interest]; action: PROC [c: Xl.Connection] = { XlPrivate.BInit[c, cd.ex.majorOpcode, opSelectExtensionEvent, 3+count]; XlPrivate.BPutDrawable[c, window]; XlPrivate.BPut16[c, count]; XlPrivate.BSkip[c, 2]; PutEventClasses[c, interest, count]; XlPrivate.FinishWithDetails[c, details]; }; cd: REF ConnectionData ~ GetConnectionData[c]; IF cd.ex#NIL THEN XlPrivate.DoWithLocks[c, action, details]; }; MakeEventClass: PUBLIC PROC [od: REF READONLY OpenDeviceRec, request: RequestableEvent] RETURNS [EventClass ¬ 0] = { id: CARD32 ¬ od.id; x: CARD32 ¬ (id MOD 128) * 256; IF request IN [devicePointerMotionHint..noExtensionEvent] THEN {x ¬ x + ORD[request]; RETURN [LOOPHOLE[x]]} ELSE { class: InputClass; offset: CARD32 ¬ 0; SELECT request FROM deviceKeyPress => {class ¬ keyClass; offset ¬ 0}; deviceKeyRelease => {class ¬ keyClass; offset ¬ 1}; deviceButtonPress => {class ¬ buttonClass; offset ¬ 0}; deviceButtonRelease => {class ¬ buttonClass; offset ¬ 1}; deviceMotionNotify => {class ¬ valuatorClass; offset ¬ 0}; deviceFocusIn => {class ¬ focusClass; offset ¬ 0}; deviceFocusOut => {class ¬ focusClass; offset ¬ 1}; proximityIn => {class ¬ proximityClass; offset ¬ 0}; proximityOut => {class ¬ proximityClass; offset ¬ 1}; deviceStateNotify => {class ¬ otherClass; offset ¬ 0}; deviceMappingNotify => {class ¬ otherClass; offset ¬ 1}; changeDeviceNotify => {class ¬ otherClass; offset ¬ 2}; ENDCASE => ERROR; --class is not known (by this version of the extension) FOR i: INT IN [0..od.numClasses) DO IF od.classes[i].inputClass=class THEN { x ¬ x + od.classes[i].eventTypeBase + offset; RETURN [LOOPHOLE[x]] }; ENDLOOP; }; ERROR; --class is not implemented (by this server instance) }; GetSelectedExtensionEvents: PUBLIC PROC [c: Xl.Connection, window: Xl.Window] RETURNS [thisClient: EventClasses ¬ NIL, allClients: EventClasses ¬ NIL] = { reply: XlPrivate.Reply; thisCnt, allCnt: NAT; action: PROC [c: Xl.Connection] = { XlPrivate.BInit[c, cd.ex.majorOpcode, opGetSelectedExtensionEvents, 2]; XlPrivate.BPutDrawable[c, window]; reply ¬ XlPrivate.FinishWithReply[c]; }; cd: REF ConnectionData ~ GetConnectionData[c]; IF cd.ex#NIL THEN { XlPrivate.DoWithLocks[c, action, NIL]; XlPrivate.CheckReply[reply]; XlPrivate.Skip[reply, 7]; thisCnt ¬ XlPrivate.Read16[reply]; allCnt ¬ XlPrivate.Read16[reply]; thisClient ¬ NEW[Xl.Card32Sequence[thisCnt]]; allClients ¬ NEW[Xl.Card32Sequence[allCnt]]; XlPrivate.Skip[reply, 20]; FOR i: NAT IN [0..thisCnt) DO thisClient[i] ¬ XlPrivate.ERead32[reply]; ENDLOOP; FOR i: NAT IN [0..allCnt) DO allClients[i] ¬ XlPrivate.ERead32[reply]; ENDLOOP; XlPrivate.DisposeReply[c, reply]; }; }; ChangeDeviceDontPropagateList: PUBLIC PROC [c: Xl.Connection, window: Xl.Window, eventClass: LIST OF EventClass, mode: ListModifierMode, details: Xl.Details ¬ NIL] = { count: INT ¬ EventClassesLength[eventClass]; cd: REF ConnectionData ~ GetConnectionData[c]; action: PROC [c: Xl.Connection] = { XlPrivate.BInit[c, cd.ex.majorOpcode, opChangeDeviceDontPropagateList, 3+count]; XlPrivate.BPutDrawable[c, window]; XlPrivate.BPut16[c, count]; XlPrivate.BPut8[c, ORD[mode]]; XlPrivate.BPut8[c, 0]; PutEventClasses[c, eventClass, count]; XlPrivate.FinishWithDetails[c, details]; }; IF cd.ex#NIL THEN XlPrivate.DoWithLocks[c, action, details]; }; GetDeviceDontPropagateList: PUBLIC PROC [c: Xl.Connection, window: Xl.Window] RETURNS [dontPropagateList: EventClasses ¬ NIL] = { reply: XlPrivate.Reply; cnt: NAT; action: PROC [c: Xl.Connection] = { XlPrivate.BInit[c, cd.ex.majorOpcode, opGetDeviceDontPropagateList, 2]; XlPrivate.BPutDrawable[c, window]; reply ¬ XlPrivate.FinishWithReply[c]; }; cd: REF ConnectionData ~ GetConnectionData[c]; IF cd.ex#NIL THEN { XlPrivate.DoWithLocks[c, action, NIL]; XlPrivate.CheckReply[reply]; XlPrivate.Skip[reply, 7]; cnt ¬ XlPrivate.Read16[reply]; dontPropagateList ¬ NEW[Xl.Card32Sequence[cnt]]; XlPrivate.Skip[reply, 22]; FOR i: NAT IN [0..cnt) DO dontPropagateList[i] ¬ XlPrivate.ERead32[reply]; ENDLOOP; XlPrivate.DisposeReply[c, reply]; }; }; DeviceTimeCoords: PUBLIC TYPE = XlPrivate.ReplyRec; GetDeviceMotionEvents: PUBLIC PROC [c: Xl.Connection, deviceId: DeviceId, start, stop: Xl.TimeStamp] RETURNS [REF DeviceTimeCoords ¬ NIL] = { reply: XlPrivate.Reply ¬ NIL; action: PROC [c: Xl.Connection] = { XlPrivate.BInit[c, cd.ex.majorOpcode, opGetDeviceDontPropagateList, 2]; XlPrivate.BPut32[c, start]; XlPrivate.BPut32[c, stop]; XlPrivate.BPut8[c, deviceId]; XlPrivate.BSkip[c, 3]; reply ¬ XlPrivate.FinishWithReply[c]; }; cd: REF ConnectionData ~ GetConnectionData[c]; IF cd.ex#NIL THEN { XlPrivate.DoWithLocks[c, action, NIL]; XlPrivate.CheckReply[reply]; RETURN [reply] }; }; IsAbsolute: PUBLIC PROC [dtc: REF DeviceTimeCoords] RETURNS [BOOL] = { RETURN [XlPrivate.Get8[dtc, 13]=0]; }; AxisCount: PUBLIC PROC [dtc: REF DeviceTimeCoords] RETURNS [NAT] = { IF dtc=NIL THEN RETURN [0]; RETURN [XlPrivate.Get8[dtc, 12]]; }; NumberOfEvents: PUBLIC PROC [dtc: REF DeviceTimeCoords] RETURNS [NAT] = { IF dtc=NIL THEN RETURN [0]; RETURN [XlPrivate.Get32[dtc, 8]]; }; TimeOfEvent: PUBLIC PROC [dtc: REF DeviceTimeCoords, eventNum: NAT] RETURNS [time: Xl.TimeStamp] = { vpe: BYTE ~ XlPrivate.Get8[dtc, 12]; XlPrivate.SetPos[dtc, 32+eventNum*(4*vpe+4)]; time ¬ [XlPrivate.ERead32[dtc]] }; ValuatorOfEvent: PUBLIC PROC [dtc: REF DeviceTimeCoords, eventNum: NAT, valuatorNum: NAT] RETURNS [CARD32] = { vpe: BYTE ~ XlPrivate.Get8[dtc, 12]; XlPrivate.SetPos[dtc, 36+eventNum*(4*vpe+4)+valuatorNum*4]; RETURN [ XlPrivate.ERead32[dtc] ] }; ChangePointerDevice: PUBLIC PROC [c: Xl.Connection, deviceId: DeviceId, xaxis, yaxis: BYTE] RETURNS [status: ChangeReply] = { reply: XlPrivate.Reply ¬ NIL; action: PROC [c: Xl.Connection] = { XlPrivate.BInit[c, cd.ex.majorOpcode, opChangePointerDevice, 2]; XlPrivate.BPut8[c, xaxis]; XlPrivate.BPut8[c, yaxis]; XlPrivate.BPut8[c, deviceId]; XlPrivate.BSkip[c, 1]; reply ¬ XlPrivate.FinishWithReply[c]; }; cd: REF ConnectionData ~ GetConnectionData[c]; IF cd.ex=NIL THEN ERROR; XlPrivate.DoWithLocks[c, action, NIL]; XlPrivate.Skip[reply, 7]; SELECT XlPrivate.Read8[reply] FROM 0 => status ¬ success; 1 => status ¬ alreadyGrabbed; ENDCASE => status ¬ deviceFrozen; XlPrivate.DisposeReply[c, reply]; }; GrabDevice: PUBLIC PROC [c: Xl.Connection, deviceId: DeviceId, grabWindow: Xl.Window, ownerEvents: BOOL, eventList: LIST OF EventClass, thisDeviceMode: Xl.Synchronicity, otherDeviceMode: Xl.Synchronicity, time: Xl.TimeStamp] RETURNS [Xl.GrabStatus] = { reply: XlPrivate.Reply ¬ NIL; got: BYTE; count: INT ¬ EventClassesLength[eventList]; action: PROC [c: Xl.Connection] = { XlPrivate.BInit[c, cd.ex.majorOpcode, opGrabDevice, 5+count]; XlPrivate.BPutDrawable[c, grabWindow]; XlPrivate.BPutTime[c, time]; XlPrivate.BPut16[c, count]; XlPrivate.BPut8[c, ORD[thisDeviceMode]]; XlPrivate.BPut8[c, ORD[otherDeviceMode]]; XlPrivate.BPut8[c, ORD[ownerEvents]]; XlPrivate.BPut8[c, deviceId]; XlPrivate.BSkip[c, 2]; PutEventClasses[c, eventList, count]; reply ¬ XlPrivate.FinishWithReply[c]; }; cd: REF ConnectionData ~ GetConnectionData[c]; IF cd.ex=NIL THEN ERROR; XlPrivate.DoWithLocks[c, action, NIL]; XlPrivate.CheckReply[reply]; got ¬ XlPrivate.Read8[reply]; IF got>ORD[Xl.GrabStatus.LAST] THEN ERROR; XlPrivate.DisposeReply[c, reply]; RETURN [VAL[got]] }; UngrabDevice: PUBLIC PROC [c: Xl.Connection, deviceId: DeviceId, time: Xl.TimeStamp ¬ Xl.currentTime, details: Xl.Details ¬ NIL] = { cd: REF ConnectionData ~ GetConnectionData[c]; action: PROC [c: Xl.Connection] = { XlPrivate.BInit[c, cd.ex.majorOpcode, opUngrabDevice, 3]; XlPrivate.BPutTime[c, time]; XlPrivate.BPut8[c, deviceId]; XlPrivate.BSkip[c, 3]; XlPrivate.FinishWithDetails[c, details]; }; IF cd.ex#NIL THEN XlPrivate.DoWithLocks[c, action, details]; }; GrabDeviceButton: PUBLIC PROC [c: Xl.Connection, deviceId: DeviceId, grabWindow: Xl.Window, modifiers: Xl.SetOfKeyButMask, modifierDevice: DeviceIdBase, button: BYTE ¬ 0, ownerEvents: BOOL, eventList: LIST OF EventClass, thisDeviceMode: Xl.Synchronicity, otherDeviceMode: Xl.Synchronicity, details: Xl.Details] = { count: INT ¬ EventClassesLength[eventList]; ownerEventsInternal: BYTE ¬ ORD[ownerEvents]; action: PROC [c: Xl.Connection] = { XlPrivate.BInit[c, cd.ex.majorOpcode, opGrabDeviceButton, 5+count]; XlPrivate.BPutDrawable[c, grabWindow]; XlPrivate.BPut8[c, deviceId]; XlPrivate.BPut8[c, modifierDevice]; XlPrivate.BPut16[c, count]; XlPrivate.BPut16[c, XlKeyButPrivate.SetToWire[modifiers]]; XlPrivate.BPut8[c, ORD[thisDeviceMode]]; XlPrivate.BPut8[c, ORD[otherDeviceMode]]; XlPrivate.BPut8[c, button]; XlPrivate.BPut8[c, ownerEventsInternal]; --? XlPrivate.BSkip[c, 2]; PutEventClasses[c, eventList, count]; XlPrivate.FinishWithDetails[c, details]; }; cd: REF ConnectionData ~ GetConnectionData[c]; IF cd.ex=NIL THEN ERROR; XlPrivate.DoWithLocks[c, action, details]; }; UngrabDeviceButton: PUBLIC PROC [c: Xl.Connection, deviceId: DeviceId, grabWindow: Xl.Window, modifiers: Xl.SetOfKeyButMask, modifierDevice: DeviceIdBase, button: BYTE, details: Xl.Details] = { cd: REF ConnectionData ~ GetConnectionData[c]; action: PROC [c: Xl.Connection] = { XlPrivate.BInit[c, cd.ex.majorOpcode, opUngrabDeviceButton, 4]; XlPrivate.BPutDrawable[c, grabWindow]; XlPrivate.BPut16[c, XlKeyButPrivate.SetToWire[modifiers]]; XlPrivate.BPut8[c, modifierDevice]; XlPrivate.BPut8[c, button]; XlPrivate.BPut8[c, deviceId]; XlPrivate.BSkip[c, 3]; XlPrivate.FinishWithDetails[c, details]; }; IF cd.ex#NIL THEN XlPrivate.DoWithLocks[c, action, details]; }; AllowDeviceEvents: PUBLIC PROC [c: Xl.Connection, deviceId: DeviceId, time: Xl.TimeStamp ¬ Xl.currentTime, mode: AllowDeviceEventsMode, details: Xl.Details ¬ NIL] = { cd: REF ConnectionData ~ GetConnectionData[c]; action: PROC [c: Xl.Connection] = { XlPrivate.BInit[c, cd.ex.majorOpcode, opAllowDeviceEvents, 2]; XlPrivate.BPutTime[c, time]; XlPrivate.BPut8[c, ORD[mode]]; XlPrivate.BPut8[c, deviceId]; XlPrivate.BSkip[c, 2]; XlPrivate.FinishWithDetails[c, details]; }; IF cd.ex#NIL THEN XlPrivate.DoWithLocks[c, action, details]; }; IntLength: PROC [list: LIST OF INT] RETURNS [cnt: BYTE ¬ 0] = { FOR l: LIST OF INT ¬ list, l.rest WHILE l#NIL DO IF cnt>=255 THEN ERROR; cnt ¬ cnt+1; ENDLOOP }; SetDeviceValuators: PUBLIC PROC [c: Xl.Connection, deviceId: DeviceId, first: INT, values: LIST OF INT] RETURNS [status: ValuatorStatus] = { reply: XlPrivate.Reply; cnt: BYTE ¬ IntLength[values]; cd: REF ConnectionData ~ GetConnectionData[c]; action: PROC [c: Xl.Connection] = { XlPrivate.BInit[c, cd.ex.majorOpcode, opSetDeviceValuators, 2+cnt]; XlPrivate.BPut8[c, deviceId]; XlPrivate.BPut8[c, first]; XlPrivate.BPut8[c, cnt]; XlPrivate.BSkip[c, 1]; FOR i: INT IN [0..cnt) DO XlPrivate.BPut32[c, LOOPHOLE[values.first, CARD32]]; IF values.rest#NIL THEN values ¬ values.rest; ENDLOOP; reply ¬ XlPrivate.FinishWithReply[c]; }; IF cd.ex=NIL THEN ERROR; IF first<0 OR first+cnt>255 THEN ERROR; XlPrivate.DoWithLocks[c, action, NIL]; XlPrivate.Skip[reply, 7]; SELECT XlPrivate.Read8[reply] FROM 0 => status ¬ success; 1 => status ¬ alreadyGrabbed; ENDCASE => ERROR; XlPrivate.DisposeReply[c, reply]; }; GetDeviceFocus: PUBLIC PROC [c: Xl.Connection, deviceId: DeviceId] RETURNS [dfr: DeviceFocusRec] = { reply: XlPrivate.Reply; x: BYTE; cd: REF ConnectionData ~ GetConnectionData[c]; action: PROC [c: Xl.Connection] = { XlPrivate.BInit[c, cd.ex.majorOpcode, opGetDeviceFocus, 2]; XlPrivate.BPut8[c, deviceId]; XlPrivate.BSkip[c, 3]; reply ¬ XlPrivate.FinishWithReply[c]; }; IF cd.ex=NIL THEN ERROR; XlPrivate.DoWithLocks[c, action, NIL]; XlPrivate.Skip[reply, 7]; dfr.window ¬ [[XlPrivate.ERead32[reply]]]; dfr.time ¬ [XlPrivate.ERead32[reply]]; x ¬ XlPrivate.Read8[reply]; IF x>ORD[DeviceFocusReversion.LAST] THEN ERROR; dfr.revertTo ¬ VAL[x]; XlPrivate.DisposeReply[c, reply]; }; SetDeviceFocus: PUBLIC PROC [c: Xl.Connection, deviceId: DeviceId, dfr: DeviceFocusRec ¬ [], details: Xl.Details] = { cd: REF ConnectionData ~ GetConnectionData[c]; action: PROC [c: Xl.Connection] = { XlPrivate.BInit[c, cd.ex.majorOpcode, opSetDeviceFocus, 4]; XlPrivate.BPutDrawable[c, dfr.window]; XlPrivate.BPutTime[c, dfr.time]; XlPrivate.BPut8[c, ORD[dfr.revertTo]]; XlPrivate.BPut8[c, deviceId]; XlPrivate.BSkip[c, 2]; XlPrivate.FinishWithDetails[c, details]; }; IF cd.ex=NIL THEN ERROR; XlPrivate.DoWithLocks[c, action, details]; }; QueryDeviceState: PUBLIC PROC [c: Xl.Connection, deviceId: DeviceId] RETURNS [s: InputStates] = { cd: REF ConnectionData ~ GetConnectionData[c]; reply: XlPrivate.Reply; action: PROC [c: Xl.Connection] ~ { XlPrivate.BInit[c, cd.ex.majorOpcode, opQueryDeviceState, 2]; XlPrivate.BPut8[c, deviceId]; XlPrivate.BSkip[c, 3]; reply ¬ XlPrivate.FinishWithReply[c]; }; lastClass: LIST OF REF InputState ¬ NIL; IF cd.ex=NIL THEN ERROR; XlPrivate.DoWithLocks[c, action, NIL]; XlPrivate.CheckReply[reply]; XlPrivate.Skip[reply, 7]; s.numberOfClasses ¬ XlPrivate.Read8[reply]; XlPrivate.Skip[reply, 23]; FOR i: BYTE IN [0..s.numberOfClasses) DO this: REF InputState ¬ NIL; x: BYTE ¬ XlPrivate.ERead8[reply]; length: BYTE ¬ XlPrivate.ERead8[reply]; number: BYTE ¬ XlPrivate.ERead8[reply]; mode: BYTE ¬ XlPrivate.ERead8[reply]; SELECT x FROM ORD[InputClass[keyClass]] => { keyThis: REF keyClass InputState ¬ NEW[keyClass InputState]; FOR i: INT IN [0..32) DO keyThis.keys[i] ¬ XlPrivate.ERead8[reply]; ENDLOOP; this ¬ keyThis; }; ORD[InputClass[buttonClass]] => { butThis: REF buttonClass InputState ¬ NEW[buttonClass InputState]; FOR i: INT IN [0..32) DO butThis.buttons[i] ¬ XlPrivate.ERead8[reply]; ENDLOOP; this ¬ butThis; }; ORD[InputClass[valuatorClass]] => { valThis: REF valuatorClass InputState ¬ NEW[valuatorClass InputState]; valThis.relativeMode ¬ ((mode) MOD 2)=0; valThis.inProximity ¬ ((mode / 2) MOD 2)=0; valThis.valuators ¬ NEW[Int32Sequence[number]]; FOR i: BYTE IN [0..number) DO valThis.valuators[i] ¬ XlPrivate.ERead32[reply]; ENDLOOP; this ¬ valThis; }; ENDCASE => ERROR; this.number ¬ number; IF lastClass=NIL THEN {lastClass ¬ s.states ¬ LIST[this]} ELSE {lastClass.rest ¬ LIST[this]; lastClass ¬ lastClass.rest} ENDLOOP; XlPrivate.DisposeReply[c, reply]; }; GetDeviceButtonMapping: PUBLIC PROC [c: Xl.Connection, deviceId: DeviceId] RETURNS [Xl.PointerMapping] = { reply: XlPrivate.Reply; action: PROC [c: Xl.Connection] ~ { XlPrivate.BInit[c, cd.ex.majorOpcode, opGetDeviceButtonMapping, 2]; XlPrivate.BPut8[c, deviceId]; XlPrivate.BSkip[c, 3]; reply ¬ XlPrivate.FinishWithReply[c]; }; n: BYTE; cd: REF ConnectionData ~ GetConnectionData[c]; pm: REF Xl.PointerMappingSequence; IF cd.ex=NIL THEN ERROR; XlPrivate.DoWithLocks[c, action, NIL]; XlPrivate.CheckReply[reply]; XlPrivate.Skip[reply, 7]; n ¬ XlPrivate.Read8[reply]; XlPrivate.Skip[reply, 23]; pm ¬ NEW[Xl.PointerMappingSequence[n+1]]; pm[0] ¬ 0; FOR i: BYTE IN [1..pm.leng) DO pm[i] ¬ XlPrivate.ERead8[reply]; ENDLOOP; XlPrivate.DisposeReply[c, reply]; RETURN [pm]; }; ExtensionStateRec: TYPE = RECORD [ lastMultiEvent: REF Xl.EventRep.extension ¬ NIL, --assigned if it could have a continuation lastMultiExt: REF ExtEventRep ¬ NIL, valuators: REF Int32Sequence ¬ NIL, keys: REF PACKED ARRAY [0..31] OF BYTE ¬ NIL, buttons: REF PACKED ARRAY [0..31] OF BYTE ¬ NIL, lastSequenceNo: Xl.SequenceNo ]; FinishMulti: PROC [state: REF ExtensionStateRec] = { XlDispatch.FindAndDispatch[state.lastMultiEvent]; state.lastMultiEvent ¬ NIL; state.lastMultiExt ¬ NIL; state.buttons ¬ NIL; state.keys ¬ NIL; state.valuators ¬ NIL; }; ProcessEvents: XlExtensions.ProcessExtensionEventProc = {--decodes arriving event eventOffset: EventOffset ~ VAL[xEvent.originalCodeByte MOD 128 - self.firstEvent]; state: REF ExtensionStateRec ~ NARROW[self.state]; DeviceBaseEvent: PROC [xEvent: REF Xl.EventRep.extension, state: REF ExtensionStateRec] RETURNS [e: REF deviceBase ExtEventRep ¬ NEW[deviceBase ExtEventRep]] = { state.lastMultiEvent ¬ xEvent; state.lastMultiExt ¬ e; e.seq ¬ state.lastSequenceNo ¬ XlEndianPrivate.InlineExtensionGet16[xEvent, 2]; e.time ¬ [XlEndianPrivate.InlineExtensionGet32[xEvent, 4]]; e.rootWindow ¬ DecodeWindow[xEvent, 8]; xEvent.dispatchDrawable ¬ e.eventWindow ¬ DecodeWindow[xEvent, 12]; e.childWindow ¬ DecodeWindow[xEvent, 16]; e.rootPos.x ¬ DecodeIntFrom16[xEvent, 20]; e.rootPos.y ¬ DecodeIntFrom16[xEvent, 22]; e.eventPos.x ¬ DecodeIntFrom16[xEvent, 24]; e.eventPos.y ¬ DecodeIntFrom16[xEvent, 26]; e.state ¬ XlKeyButPrivate.SetFromWire[XlEndianPrivate.InlineExtensionGet16[xEvent, 28]]; e.sameScreen ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 30]#0; e.deviceId ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 31] MOD 128; xEvent.decoded ¬ e; }; DeviceFocusEvent: PROC [xEvent: REF Xl.EventRep.extension, state: REF ExtensionStateRec, in: BOOL] = { e: REF deviceFocus ExtEventRep ~ NEW[deviceFocus ExtEventRep]; detail: BYTE ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 1]; mode: BYTE ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 12]; state.lastMultiEvent ¬ NIL; state.lastMultiExt ¬ NIL; IF detail>ORD[Xl.FocusDetail.LAST] OR mode>ORD[Xl.GrabMode.LAST] THEN RETURN; e.detail ¬ VAL[detail]; e.mode ¬ VAL[mode]; e.seq ¬ XlEndianPrivate.InlineExtensionGet16[xEvent, 2]; e.time ¬ [XlEndianPrivate.InlineExtensionGet32[xEvent, 4]]; e.eventWindow ¬ DecodeWindow[xEvent, 8]; e.deviceId ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 13] MOD 128; IF in THEN {e.eventOffset ¬ deviceFocusIn; xEvent.match ¬ deviceFocusInKey} ELSE {e.eventOffset ¬ deviceFocusOut; xEvent.match ¬ deviceFocusOutKey}; xEvent.decoded ¬ e; XlDispatch.FindAndDispatch[xEvent]; }; xEvent.extension ¬ extensionKey; SELECT eventOffset FROM deviceValuator => { DeviceValuator: PROC [xEvent: REF Xl.EventRep.extension, state: REF ExtensionStateRec] = { seq: Xl.SequenceNo ¬ XlEndianPrivate.InlineExtensionGet16[xEvent, 2]; valuators: REF Int32Sequence ¬ state.valuators; cnt: NAT ¬ MIN[XlEndianPrivate.InlineExtensionGet8[xEvent, 6], 6]; first: NAT ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 7]; Scan: PROC [] = { IF valuators.leng>; FOR i: NAT IN [0..cnt) DO valuators[first+i] ¬ LOOPHOLE[XlEndianPrivate.InlineExtensionGet32[xEvent, i*4 + 8]] ENDLOOP; IF first+6>=cnt THEN { FinishMulti[state]; } }; WITH state.lastMultiExt SELECT FROM b: REF deviceBase ExtEventRep => { IF valuators=NIL THEN b.valuators ¬ state.valuators ¬ valuators ¬ NEW[Int32Sequence[cnt+first]]; b.deviceState ¬ XlKeyButPrivate.SetFromWire[XlEndianPrivate.InlineExtensionGet16[xEvent, 4]]; Scan[]; }; s: REF deviceState ExtEventRep => { IF valuators=NIL THEN RETURN; Scan[]; }; ENDCASE => {} }; DeviceValuator[xEvent, state]; }; deviceFocusIn => { DeviceFocusEvent[xEvent, state, TRUE]; }; deviceFocusOut => { DeviceFocusEvent[xEvent, state, FALSE]; }; deviceStateNotify => { DeviceStateNotify: PROC [xEvent: REF Xl.EventRep.extension, state: REF ExtensionStateRec] = { x: BYTE ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 11]; e: REF deviceState ExtEventRep ~ NEW[deviceState ExtEventRep]; state.lastMultiEvent ¬ xEvent; state.lastMultiExt ¬ e; state.valuators ¬ NIL; state.keys ¬ NIL; state.buttons ¬ NIL; e.deviceId ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 1] MOD 128; e.seq ¬ state.lastSequenceNo ¬ XlEndianPrivate.InlineExtensionGet16[xEvent, 2]; e.time ¬ [XlEndianPrivate.InlineExtensionGet32[xEvent, 4]]; e.numKeys ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 8]; e.numButtons ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 9]; e.numValuators ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 10]; IF (x) MOD 2 # 0 THEN { e.keys ¬ state.keys ¬ NEW[PACKED ARRAY [0..31] OF BYTE]; state.keys[0] ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 12]; state.keys[1] ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 13]; state.keys[2] ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 14]; state.keys[3] ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 15]; }; IF (x/2) MOD 2 # 0 THEN { e.buttons ¬ state.buttons ¬ NEW[PACKED ARRAY [0..31] OF BYTE]; state.buttons[0] ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 16]; state.buttons[1] ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 17]; state.buttons[2] ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 18]; state.buttons[3] ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 19]; }; IF (x/4) MOD 2 # 0 THEN { e.valuators ¬ state.valuators ¬ NEW[Int32Sequence[e.numValuators]]; state.valuators[0] ¬ DecodeInt32[xEvent, 20]; state.valuators[1] ¬ DecodeInt32[xEvent, 24]; state.valuators[2] ¬ DecodeInt32[xEvent, 28]; }; e.relativeMode ¬ (x MOD 040H) MOD 2 # 0; e.inProximity ¬ (x MOD 080H) MOD 2 # 0; e.eventOffset ¬ deviceStateNotify; xEvent.match ¬ deviceStateNotifyKey; xEvent.decoded ¬ e; IF (state.keys=NIL OR e.numKeys<32) AND (state.buttons=NIL OR e.numButtons<32) AND (state.valuators=NIL OR e.numValuators<3) THEN FinishMulti[state]; }; DeviceStateNotify[xEvent, state]; }; deviceKeyStateNotify => { DeviceKeyStateNotify: PROC [xEvent: REF Xl.EventRep.extension, state: REF ExtensionStateRec] = { WITH state.lastMultiExt SELECT FROM s: REF deviceState ExtEventRep => { IF state.keys=NIL THEN RETURN; FOR i: INT IN [4..32) DO state.keys[i] ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, i]; ENDLOOP; IF (XlEndianPrivate.InlineExtensionGet8[xEvent, 1] / 080H) MOD 2 = 0 THEN FinishMulti[state]; }; ENDCASE => {} }; DeviceKeyStateNotify[xEvent, state]; }; deviceButtonStateNotify => { DeviceButtonStateNotify: PROC [xEvent: REF Xl.EventRep.extension, state: REF ExtensionStateRec] = { WITH state.lastMultiExt SELECT FROM s: REF deviceState ExtEventRep => { IF state.buttons=NIL THEN RETURN; FOR i: INT IN [4..32) DO state.buttons[i] ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, i]; ENDLOOP; IF (XlEndianPrivate.InlineExtensionGet8[xEvent, 1] / 080H) MOD 2 = 0 THEN FinishMulti[state]; }; ENDCASE => {} }; DeviceButtonStateNotify[xEvent, state]; }; deviceMappingNotify => { DeviceMappingNotify: PROC [xEvent: REF Xl.EventRep.extension] = { e: REF deviceMapping ExtEventRep ~ NEW[deviceMapping ExtEventRep]; request: BYTE ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 4]; IF request>2 THEN RETURN <>; e.deviceId ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 1] MOD 128; e.seq ¬ XlEndianPrivate.InlineExtensionGet16[xEvent, 2]; e.time ¬ [XlEndianPrivate.InlineExtensionGet32[xEvent, 8]]; e.firstKeycode ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 5]; e.count ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 6]; e.request ¬ VAL[request]; e.eventOffset ¬ deviceMappingNotify; xEvent.match ¬ deviceMappingNotifyKey; xEvent.decoded ¬ e; XlDispatch.FindAndDispatch[xEvent]; }; DeviceMappingNotify[xEvent] }; changeDeviceNotify => { ChangeDeviceNotify: PROC [xEvent: REF Xl.EventRep.extension] = { e: REF deviceChange ExtEventRep ~ NEW[deviceChange ExtEventRep]; what: BYTE ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 8]; IF what>1 THEN RETURN <>; e.newWhat ¬ VAL[what]; e.deviceId ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 1] MOD 128; e.seq ¬ XlEndianPrivate.InlineExtensionGet16[xEvent, 2]; e.time ¬ [XlEndianPrivate.InlineExtensionGet32[xEvent, 4]]; e.eventOffset ¬ changeDeviceNotify; xEvent.match ¬ changeDeviceNotifyKey; xEvent.decoded ¬ e; XlDispatch.FindAndDispatch[xEvent]; }; ChangeDeviceNotify[xEvent] }; deviceKeyPress => { moreEvents: BOOL; e: REF deviceBase ExtEventRep ~ DeviceBaseEvent[xEvent, state]; e.keyCode ¬ VAL[XlEndianPrivate.InlineExtensionGet8[xEvent, 1]]; e.eventOffset ¬ deviceKeyPress; xEvent.match ¬ deviceKeyPressKey; moreEvents ¬ (XlEndianPrivate.InlineExtensionGet8[xEvent, 31] / 128) # 0; IF ~moreEvents THEN XlDispatch.FindAndDispatch[xEvent]; }; deviceKeyRelease => { moreEvents: BOOL; e: REF deviceBase ExtEventRep ~ DeviceBaseEvent[xEvent, state]; e.keyCode ¬ VAL[XlEndianPrivate.InlineExtensionGet8[xEvent, 1]]; e.eventOffset ¬ deviceKeyRelease; xEvent.match ¬ deviceKeyReleaseKey; moreEvents ¬ (XlEndianPrivate.InlineExtensionGet8[xEvent, 31] / 128) # 0; IF ~moreEvents THEN XlDispatch.FindAndDispatch[xEvent]; }; deviceButtonPress => { moreEvents: BOOL; e: REF deviceBase ExtEventRep ~ DeviceBaseEvent[xEvent, state]; e.button ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 1]; e.eventOffset ¬ deviceButtonPress; xEvent.match ¬ deviceButtonPressKey; moreEvents ¬ (XlEndianPrivate.InlineExtensionGet8[xEvent, 31] / 128) # 0; IF ~moreEvents THEN XlDispatch.FindAndDispatch[xEvent]; }; deviceButtonRelease => { moreEvents: BOOL; e: REF deviceBase ExtEventRep ~ DeviceBaseEvent[xEvent, state]; e.button ¬ XlEndianPrivate.InlineExtensionGet8[xEvent, 1]; e.eventOffset ¬ deviceButtonRelease; xEvent.match ¬ deviceButtonReleaseKey; moreEvents ¬ (XlEndianPrivate.InlineExtensionGet8[xEvent, 31] / 128) # 0; IF ~moreEvents THEN XlDispatch.FindAndDispatch[xEvent]; }; deviceMotionNotify => { moreEvents: BOOL; e: REF deviceBase ExtEventRep ~ DeviceBaseEvent[xEvent, state]; e.normalHint ¬ VAL[XlEndianPrivate.InlineExtensionGet8[xEvent, 1] MOD 2]; e.eventOffset ¬ deviceMotionNotify; xEvent.match ¬ deviceMotionNotifyKey; moreEvents ¬ (XlEndianPrivate.InlineExtensionGet8[xEvent, 31] / 128) # 0; IF ~moreEvents THEN XlDispatch.FindAndDispatch[xEvent]; }; proximityIn => { moreEvents: BOOL; e: REF deviceBase ExtEventRep ~ DeviceBaseEvent[xEvent, state]; e.eventOffset ¬ proximityIn; xEvent.match ¬ proximityInKey; moreEvents ¬ (XlEndianPrivate.InlineExtensionGet8[xEvent, 31] / 128) # 0; IF ~moreEvents THEN XlDispatch.FindAndDispatch[xEvent]; }; proximityOut => { moreEvents: BOOL; e: REF deviceBase ExtEventRep ~ DeviceBaseEvent[xEvent, state]; e.eventOffset ¬ proximityOut; xEvent.match ¬ proximityOutKey; moreEvents ¬ (XlEndianPrivate.InlineExtensionGet8[xEvent, 31] / 128) # 0; IF ~moreEvents THEN XlDispatch.FindAndDispatch[xEvent]; }; ENDCASE => ERROR; }; DecodeIntFrom16: PROC [xEvent: REF Xl.EventRep.extension, pos: INT] RETURNS [i: INT] = { i ¬ LOOPHOLE[XlEndianPrivate.InlineExtensionGet16[xEvent, pos], INT16]; }; DecodeInt32: PROC [xEvent: REF Xl.EventRep.extension, pos: INT] RETURNS [i: INT] = { i ¬ LOOPHOLE[XlEndianPrivate.InlineExtensionGet32[xEvent, pos], INT32]; }; DecodeWindow: PROC [xEvent: REF Xl.EventRep.extension, pos: INT] RETURNS [w: Xl.Window] = { w ¬ LOOPHOLE[XlEndianPrivate.InlineExtensionGet32[xEvent, pos], Xl.Window]; }; XlExtensions.DefineExtensionClass[extensionKey, ProcessEvents, ORD[EventOffset.LAST]+1]; END. , XlInputExtensionImpl.mesa Copyright Ó 1991, 1992, 1993 by Xerox Corporation. All rights reserved. Created by Christian Jacobi, December 30, 1991 1:59 pm PST Christian Jacobi, February 2, 1993 4:07 pm PST --append this class (info) --append this device Data structure is not monitored and should be queried by a single process --Should we do some caching ? Events Accumulated state while accepting multi packet events This extension supports chunks of multiple events following immediately... We wait until all connected events are collected and the report the event to our client; if the events do not appear in the right order we will not crash (it could be client generated), but we won't report exactly what has been seen either. Don't test sequence numbers for the benefit of client generated event sequences. IF seq#state.lastSequenceNo THEN <> RETURN; --wrong formed events could have been sent by an other client. --don't test keys and buttons; the valuators are reported last --after deviceStateNotify --immediately after deviceStateNotify Ê"¤–(cedarcode) style•NewlineDelimiter ™codešœ™Kšœ Ïeœ=™HKšœ:™:K™.K™—šÏk œ|˜…K˜—šÏnœžœžœ˜$Kšžœžœ˜KšžœP˜WKšžœ*˜1Kšžœ˜ —Kšžœžœ,˜6K˜Kšœžœ˜&K˜Kšœžœžœ˜2Kšœžœžœ˜6Kšœžœžœ˜8Kšœžœžœ˜žœ˜^šœžœ˜#Kšœ8˜8Kšœ˜Kšœ˜Kšœ(˜(K˜—Kšœžœ'˜.Kšžœžœžœ+˜˜>Kšœ˜Kšœžœ˜Kšœ˜Kšœ˜Kšœ(˜(K˜—Kšžœžœžœ+˜—Kšžœ˜—Kšœ!˜!K˜K˜—šŸœžœžœ(žœ˜jKšœ™Kšœ˜šœžœ˜#KšœC˜CKšœ˜Kšœ˜K˜%K˜—Kšœžœ˜Kšœžœ'˜.Kšœžœ˜"Kšžœžœžœžœ˜Kšœ!žœ˜&Kšœ˜Kšœ˜K˜Kšœ˜Kšœžœ!˜)K˜ šžœžœžœž˜K˜ Kšžœ˜—Kšœ!˜!Kšžœ˜ K˜—Ihead™K˜šœžœžœ˜"Kšœ5™5Kšœžœžœ +˜\Kšœžœžœ˜$Kšœ žœžœ˜#Kš œžœžœžœ žœžœžœ˜-Kš œ žœžœžœ žœžœžœ˜0Kšœ˜Kšœ˜K˜—šŸ œžœ žœ˜4Kšœ1˜1Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœ žœ˜Kšœžœ˜Kšœ˜—K˜šŸ œ, ˜Q™JK™ð—Kšœžœžœ˜RKšœžœžœ ˜2šŸœžœ žœžœžœžœžœ˜¡K˜K˜K˜OK˜;K˜'K˜CK˜)K˜*K˜*K˜+K˜+K˜YK˜BKšœ>žœ˜FK˜Kšœ˜—š Ÿœžœ žœžœžœ˜fKšœžœžœ˜>Kšœžœ2˜>Kšœžœ3˜=Kšœžœ˜Kšœžœ˜Kšžœžœžœžœžœ žœžœžœ˜MKšœ žœ ˜Kšœ žœ˜K˜8K˜;K˜(Kšœ=žœ˜Ešžœ˜KšžœB˜FKšžœD˜H—K˜Kšœ#˜#Kšœ˜—K˜ šžœ ž˜šœ˜šŸœžœ žœžœ˜ZK˜EKšœP™PKšžœžœ žœ >™pKšœ žœ!˜/Kšœžœžœ5˜CKšœžœ3˜=šŸœžœ˜Kšžœžœžœ ˜1šžœžœžœ ž˜Kšœžœ7˜TKšžœ˜—šžœžœ˜Kšœ>™>Kšœ˜Kšœ˜—Kšœ˜—šžœžœž˜#šœžœ˜"šžœ žœžœ˜Kšœ,žœ˜J—K˜^Kšœ˜K˜—šœžœ˜#Kšžœ žœžœžœ˜Kšœ˜K˜—Kšžœ˜ —K˜—Kšœ˜Kšœ˜—šœ˜Kšœ žœ˜&Kšœ˜—šœ˜Kšœ žœ˜'Kšœ˜—šœ˜šŸœžœ žœžœ˜]Kšœžœ3˜:Kšœžœžœ˜>K˜K˜Kšœžœ˜Kšœ žœ˜Kšœžœ˜Kšœ=žœ˜EK˜OK˜;K˜;K˜>K˜Ašžœžœžœ˜Kš œžœžœžœ žœžœ˜8K˜@K˜@K˜@K˜@Kšœ˜—šžœžœžœ˜Kš œžœžœžœ žœžœ˜>K˜CK˜CK˜CK˜CKšœ˜—šžœžœžœ˜Kšœ žœ ˜CK˜-K˜-K˜-Kšœ˜—Kšœžœžœ˜(Kšœžœžœ˜'K˜#K˜$K˜Kšžœ žœžœžœžœžœžœžœžœžœ˜•Kšœ˜—Kšœ!˜!Kšœ˜—šœ˜Jšœ™šŸœžœ žœžœ˜`šžœžœž˜#šœžœ˜#Kšžœ žœžœžœ˜šžœžœžœ ž˜K˜?Kšžœ˜—Kšžœ9žœžœ˜]K˜—Kšžœ˜ —Kšœ˜—Kšœ$˜$Kšœ˜—šœ˜Jšœ%™%šŸœžœ žœžœ˜cšžœžœž˜#šœžœ˜#Kšžœžœžœžœ˜!šžœžœžœ ž˜K˜BKšžœ˜—Kšžœ9žœžœ˜]K˜—Kšžœ˜ —Kšœ˜—Kšœ'˜'Kšœ˜—šœ˜šŸœžœ žœ˜AKšœžœžœ˜BKšœ žœ2˜?Kšžœ žœžœ ˜"Kšœ<žœ˜DK˜8K˜;K˜@K˜9Kšœ žœ ˜K˜%K˜&K˜Kšœ#˜#K˜—Kšœ˜Kšœ˜—šœ˜šŸœžœ žœ˜@Kšœžœžœ˜@Kšœžœ2˜