<> <> <> <> DIRECTORY Basics, BasicTime, Process, Rope, Xl, XlDispatch, XlPrivate, XlPrivateResources, XlPrivateTypes, XlKeyButPrivate, XlPrivateErrorHandling, XlService; XlImplRequests: CEDAR MONITOR LOCKS c USING c: Connection IMPORTS Basics, BasicTime, Process, Rope, Xl, XlDispatch, XlPrivate, XlPrivateErrorHandling, XlPrivateResources, XlKeyButPrivate, XlService EXPORTS Xl, XlPrivate, XlPrivateTypes SHARES XlDispatch, XlPrivate, XlPrivateResources ~ BEGIN OPEN Xl, XlPrivate; ROPE: TYPE ~ Rope.ROPE; ConnectionPrivateImplRec: TYPE ~ XlPrivateTypes.ConnectionPrivateImplRec; <> ConnectionPrivate: PUBLIC TYPE ~ XlPrivateTypes.ConnectionPrivateImplRec; GetWindowAttributes: PUBLIC PROC [c: Connection, window: Window] RETURNS [at: RepliedAttributes] = { reply: Reply; action: PROC [c: Connection] = { BInit[c, 3, 0, 2]; BPutDrawable[c, window]; reply ¬ FinishWithReply[c]; }; DoWithLocks[c, action, NIL]; CheckReply[reply]; <> at.backingStore ¬ VAL[ERead8[reply]]; Skip[reply, 6]; at.visual.visualID ¬ ERead32[reply]; at.class ¬ VAL[ERead16[reply]]; at.bitGravity ¬ VAL[ERead8[reply]]; at.winGravity ¬ VAL[ERead8[reply]]; at.backingPlanes ¬ ERead32[reply]; at.backingPixel ¬ ERead32[reply]; at.saveUnder ¬ ERead8[reply]#0; at.isInstalled ¬ ERead8[reply]#0; at.mapState ¬ VAL[ERead8[reply]]; at.overrideRedirect ¬ ERead8[reply]#0; at.colorMap.colorMapID ¬ ERead32[reply]; at.allEventMask ¬ LOOPHOLE[ERead32[reply]]; at.yourEventMask ¬ LOOPHOLE[ERead32[reply]]; at.doNotPropagateMask ¬ LOOPHOLE[ERead32[reply]]; DisposeReply[c, reply]; }; ChangeWindowAttributes: PUBLIC PROC [c: Connection, window: Window, attributes: Attributes, details: Details] ~ { action: PROC [c: Connection] = { mask, n: CARD32; IF ~UnspecifiedEvents[attributes.eventMask] THEN { eventMask: SetOfEvent ¬ XlDispatch.EnforcedSetOfEvent[c, window, attributes.eventMask]; attributes.eventMask ¬ eventMask; }; TRUSTED {[mask, n] ¬ MakeMask[@attributes]}; IF n>0 THEN { BInit[c, 2, 0, 3+n]; BPutDrawable[c, window]; BPut32[c, mask]; TRUSTED {BPutAttributes[c, @attributes]}; FinishWithDetails[c, details]; }; }; DoWithLocks[c, action, details]; }; ConfigureWindow: PUBLIC PROC [c: Connection, window: Window, geometry: Geometry, sibling: Window ¬ nullWindow, stackMode: StackModeExtra ¬ dontChange, details: Details] = { action: PROC [c: Connection] ~ { BInit[c, 12, 0, 3+filled]; BPutDrawable[c, window]; BPut16[c, bitmask]; BSkip[c, 2]; FOR i: INT IN [0..filled) DO IBPut32[c, vals[i]]; ENDLOOP; FinishWithDetails[c, details]; }; Low: PROC [i: INT32] RETURNS [c: CARD32] = INLINE { c ¬ Basics.LowHalf[LOOPHOLE[i]]; }; CheckI16: PROC [i: INT32] = INLINE { <<--explicit check to stays if subrange checks are ommitted >> IF i>LAST[INT16] OR i> IF LOOPHOLE[i, CARD32]>LAST[CARD16] THEN ERROR }; bitmask: CARD16 ¬ 0; vals: ARRAY [0..8) OF CARD32; filled: INT ¬ 0; IF window=nullWindow THEN ERROR; IF geometry.pos.x#dontUse THEN { CheckI16[geometry.pos.x]; vals[filled] ¬ Low[geometry.pos.x]; filled ¬ filled + 1; bitmask ¬ bitmask+1; }; IF geometry.pos.y#dontUse THEN { CheckI16[geometry.pos.y]; vals[filled] ¬ Low[geometry.pos.y]; filled ¬ filled + 1; bitmask ¬ bitmask+2; }; IF geometry.size.width>0 THEN { CheckC16[geometry.size.width]; vals[filled] ¬ geometry.size.width; filled ¬ filled + 1; bitmask ¬ bitmask+4; }; IF geometry.size.height>0 THEN { CheckC16[geometry.size.height]; vals[filled] ¬ geometry.size.height; filled ¬ filled + 1; bitmask ¬ bitmask+8; }; IF geometry.borderWidth>=0 THEN { CheckC16[geometry.borderWidth]; vals[filled] ¬ geometry.borderWidth; filled ¬ filled + 1; bitmask ¬ bitmask+010H; }; IF sibling#nullWindow THEN { vals[filled] ¬ WindowId[sibling]; filled ¬ filled + 1; bitmask ¬ bitmask+020H; }; IF stackMode#dontChange THEN { vals[filled] ¬ ORD[stackMode]; filled ¬ filled + 1; bitmask ¬ bitmask+040H; }; IF filled#0 THEN DoWithLocks[c, action, details]; }; NewWindow: PROC [c: Connection] RETURNS [w: Window] = { id: CARD32 ¬ XlPrivateResources.NewResourceID[c]; w ¬ ToWindow[c, id]; XlDispatch.InitWindow[c, w]; }; CreateWindow: PUBLIC PROC [c: Connection, matchList: MatchList, parent: Window ¬ nullWindow, geometry: Geometry, class: WindowClass ¬ copyFromParent, visual: Visual ¬ nullVisual, depth: INTEGER ¬ -1, attributes: Attributes, details: Details] RETURNS [w: Window ¬ nullWindow] ~ { action: PROC [c: Connection] ~ { mask, cnt: CARD32; w ¬ NewWindow[c]; IF matchList#NIL THEN attributes.eventMask.structureNotify ¬ TRUE; TRUSTED { [mask, cnt] ¬ MakeMask[@attributes] }; FOR l: MatchList ¬ matchList, l.rest WHILE l#NIL DO XlDispatch.InternalAddMatch[c, w, l.first, attributes.eventMask]; ENDLOOP; IF depth<0 OR depth>255 THEN depth ¬ 0; BInit[c, 1, depth, cnt+8]; BPutDrawable[c, w]; -- id for the new window BPutDrawable[c, parent]; -- parent window BPutPoint[c, geometry.pos]; BPutSize[c, geometry.size]; BPutINT32as16[c, geometry.borderWidth]; BPut16[c, ORD[class]]; BPutVisual[c, visual]; BPut32[c, mask]; TRUSTED {BPutAttributes[c, @attributes]}; FinishWithDetails[c, details]; }; IF geometry.borderWidth<0 OR geometry.borderWidth>1000 THEN geometry.borderWidth ¬ 0; IF parent=nullWindow THEN parent ¬ DefaultRoot[c]; --first screen IF geometry.size.width<=0 THEN geometry.size.width ¬ 200; IF geometry.size.height<=0 THEN geometry.size.height ¬ 50; DoWithLocks[c, action, details]; }; BPutSetOfEvent: PUBLIC <> PROC [c: Connection, s: SetOfEvent] = { s.reservedforDisableEvents ¬ FALSE; XlPrivate.IBPut32[c, LOOPHOLE[s]]; }; BPutAttributes: PROC [c: Connection, p: LONG POINTER TO Attributes] = TRUSTED { IF ~IllegalPixmap[p.backgroundPixmap] THEN BPutPixmap[c, p.backgroundPixmap]; IF p.backgroundPixel#illegalPixel THEN BPut32[c, p.backgroundPixel]; IF ~IllegalPixmap[p.borderPixmap] THEN BPutPixmap[c, p.borderPixmap]; IF p.borderPixel#illegalPixel THEN BPut32[c, p.borderPixel]; IF p.bitGravity#illegal THEN BPut32[c, ORD[p.bitGravity]]; IF p.winGravity#illegal THEN BPut32[c, ORD[p.winGravity]]; IF p.backingStore#illegal THEN BPut32[c, ORD[p.backingStore]]; IF p.backingPlanes#undefinedBackingPlanes THEN BPut32[c, ORD[p.backingPlanes]]; IF p.backingPixel#illegalPixel THEN BPut32[c, p.backingPixel]; IF p.overrideRedirect#illegal THEN BPut32[c, ORD[p.overrideRedirect]]; IF p.saveUnder#illegal THEN BPut32[c, ORD[p.saveUnder]]; IF ~UnspecifiedEvents[p.eventMask] THEN BPutSetOfEvent[c, p.eventMask]; IF ~UnspecifiedEvents[p.doNotPropagateMask] THEN BPutSetOfEvent[c, p.doNotPropagateMask]; IF ~IllegalColorMap[p.colorMap] THEN BPutColorMap[c, p.colorMap]; IF ~IllegalCursor[p.cursor] THEN BPutCursor[c, p.cursor]; }; MakeMask: PROC [p: LONG POINTER TO Attributes] RETURNS [m, c: CARD32¬0] = TRUSTED { IF ~IllegalPixmap[p.backgroundPixmap] THEN {m ¬ m + 01H; c ¬ c + 1}; IF p.backgroundPixel#illegalPixel THEN {m ¬ m + 02H; c ¬ c + 1}; IF ~IllegalPixmap[p.borderPixmap] THEN {m ¬ m + 04H; c ¬ c + 1}; IF p.borderPixel#illegalPixel THEN {m ¬ m + 08H; c ¬ c + 1}; IF p.bitGravity#illegal THEN {m ¬ m + 010H; c ¬ c + 1}; IF p.winGravity#illegal THEN {m ¬ m + 020H; c ¬ c + 1}; IF p.backingStore#illegal THEN {m ¬ m + 040H; c ¬ c + 1}; IF p.backingPlanes#undefinedBackingPlanes THEN {m ¬ m + 080H; c ¬ c + 1}; IF p.backingPixel#illegalPixel THEN {m ¬ m + 0100H; c ¬ c + 1}; IF p.overrideRedirect#illegal THEN {m ¬ m + 0200H; c ¬ c + 1}; IF p.saveUnder#illegal THEN {m ¬ m + 0400H; c ¬ c + 1}; IF ~UnspecifiedEvents[p.eventMask] THEN {m ¬ m + 0800H; c ¬ c + 1}; IF ~UnspecifiedEvents[p.doNotPropagateMask] THEN {m ¬ m + 01000H; c ¬ c + 1}; IF ~IllegalColorMap[p.colorMap] THEN {m ¬ m + 02000H; c ¬ c + 1}; IF ~IllegalCursor[p.cursor] THEN {m ¬ m + 04000H; c ¬ c + 1}; }; CreatePixmap: PUBLIC PROC [c: Connection, drawable: Drawable ¬ nullDrawable, size: Size, depth: BYTE, details: Details] RETURNS [p: Pixmap ¬ nullPixmap] ~ { NewPixmap: PROC [c: Connection, id: CARD32] RETURNS [p: Pixmap] = { p ¬ ToPixmap[c, id] }; action: PROC [c: Connection] = { id: ID ¬ XlPrivateResources.NewResourceID[c]; p ¬ NewPixmap[c, id]; BInit[c, 53, depth, 4]; BPutPixmap[c, p]; -- id for the new pixmap BPutDrawable[c, drawable]; BPutSize[c, size]; FinishWithDetails[c, details] }; DoWithLocks[c, action, details]; }; FreePixmap: PUBLIC ENTRY PROC [c: Connection, pixmap: Pixmap, details: Details] = { err: ErrorNotifyEvent; BInit[c, 54, 0, 2]; BPutPixmap[c, pixmap]; err ¬ XlPrivate.FinishWithDetailsNoErrors[c, details]; IF err#NIL THEN RETURN WITH ERROR XError[err]; }; white: PUBLIC REF READONLY RGBRec ¬ NEW[RGBRec ¬ [65535, 65535, 65535]]; black: PUBLIC REF READONLY RGBRec ¬ NEW[RGBRec ¬ [0, 0, 0]]; CreateColorMap: PUBLIC PROC [c: Connection, visual: Visual, window: Window, allocAll: BOOL ¬ FALSE, details: Details] RETURNS [colorMap: ColorMap ¬ nullColorMap] = { action: PROC [c: Connection] = { colorMap ¬ [XlPrivateResources.NewResourceID[c]]; BInit[c, 78, IF allocAll THEN 1 ELSE 0, 4]; BPutColorMap[c, colorMap]; BPutDrawable[c, window]; BPutVisual[c, visual]; FinishWithDetails[c, details]; }; DoWithLocks[c, action, details]; }; FreeColorMap: PUBLIC PROC [c: Connection, colorMap: ColorMap, details: Details] = { action: PROC [c: Connection] = { BInit[c, 79, 0, 2]; BPutColorMap[c, colorMap]; FinishWithDetails[c, details]; }; DoWithLocks[c, action, details]; }; CopyColorMapAndFree: PUBLIC PROC [c: Connection, free: ColorMap, details: Details] RETURNS [colorMap: ColorMap ¬ nullColorMap] = { action: PROC [c: Connection] = { colorMap ¬ [XlPrivateResources.NewResourceID[c]]; BInit[c, 80, 0, 3]; BPutColorMap[c, colorMap]; BPutColorMap[c, free]; FinishWithDetails[c, details]; }; DoWithLocks[c, action, details]; }; InstallColorMap: PUBLIC PROC [c: Connection, colorMap: ColorMap, details: Details] = { action: PROC [c: Connection] = { BInit[c, 81, 0, 2]; BPutColorMap[c, colorMap]; FinishWithDetails[c, details]; }; DoWithLocks[c, action, details]; }; UnInstallColorMap: PUBLIC PROC [c: Connection, colorMap: ColorMap, details: Details] = { action: PROC [c: Connection] = { BInit[c, 82, 0, 2]; BPutColorMap[c, colorMap]; FinishWithDetails[c, details]; }; DoWithLocks[c, action, details]; }; ListInstalledColorMaps: PUBLIC PROC [c: Connection, window: Window] RETURNS [REF READONLY ColorMaps] = { reply: Reply; leng: CARD; maps: REF ColorMaps; action: PROC [c: Connection] = { BInit[c, 83, 0, 2]; BPutDrawable[c, window]; reply ¬ FinishWithReply[c]; }; DoWithLocks[c, action, NIL]; CheckReply[reply]; Skip[reply, 7]; leng ¬ ERead16[reply]; maps ¬ NEW[ColorMaps[leng]]; Skip[reply, 22]; FOR i: CARD IN [0..leng) DO maps[i] ¬ [ERead32[reply]]; ENDLOOP; DisposeReply[c, reply]; RETURN [maps]; }; AllocColor: PUBLIC PROC [c: Connection, colorMap: ColorMap, color: RGBRec] RETURNS [pixel: Pixel, usedColor: RGBRec] = { action: PROC [c: Connection] = { BInit[c, 84, 0, 4]; BPutColorMap[c, colorMap]; BPutRGBRec[c, color]; BPut16[c, 0]; reply ¬ FinishWithReply[c]; }; reply: Reply; DoWithLocks[c, action, NIL]; CheckReply[reply]; Skip[reply, 7]; usedColor.red ¬ ERead16[reply]; usedColor.green ¬ ERead16[reply]; usedColor.blue ¬ ERead16[reply]; Skip[reply, 2]; pixel ¬ ERead32[reply]; DisposeReply[c, reply]; }; AllocNamedColor: PUBLIC PROC [c: Connection, colorMap: ColorMap, name: ROPE] RETURNS [pixel: Pixel, exactColor, usedColor: RGBRec] = { action: PROC [c: Connection] = { BInit[c, 85, 0, 3+(leng+3)/4]; BPutColorMap[c, colorMap]; BPut16[c, leng]; BPut16[c, 0]; BPutPaddedRope[c, name]; reply ¬ FinishWithReply[c]; }; reply: Reply; leng: INT ¬ Rope.Length[name]; IF leng>c.info.maxRequestLengthBytes THEN ERROR; DoWithLocks[c, action, NIL]; CheckReply[reply]; Skip[reply, 7]; pixel ¬ ERead32[reply]; exactColor.red ¬ ERead16[reply]; exactColor.green ¬ ERead16[reply]; exactColor.blue ¬ ERead16[reply]; usedColor.red ¬ ERead16[reply]; usedColor.green ¬ ERead16[reply]; usedColor.blue ¬ ERead16[reply]; DisposeReply[c, reply]; }; AllocColorCells: PUBLIC PROC [c: Connection, colorMap: ColorMap, colors, planes: CARD16, contiguos: BOOL¬FALSE] RETURNS [pixels: REF Card32Sequence, masks: REF Card32Sequence] = { action: PROC [c: Connection] = { BInit[c, 86, ToCBool[contiguos], 3]; BPutColorMap[c, colorMap]; BPut16[c, colors]; BPut16[c, planes]; reply ¬ FinishWithReply[c]; }; reply: Reply; n, m: CARD16; DoWithLocks[c, action, NIL]; CheckReply[reply]; Skip[reply, 7]; n ¬ ERead16[reply]; m ¬ ERead16[reply]; Skip[reply, 20]; pixels ¬ NEW[Card32Sequence[n]]; FOR i: INT IN [0..n) DO pixels[i] ¬ ERead32[reply]; ENDLOOP; masks ¬ NEW[Card32Sequence[m]]; FOR i: INT IN [0..m) DO masks[i] ¬ ERead32[reply]; ENDLOOP; DisposeReply[c, reply]; }; AllocColorPlanes: PUBLIC PROC [c: Connection, colorMap: ColorMap, colors, reds, greens, blues: CARD16, contiguos: BOOL¬FALSE] RETURNS [pixels: REF Card32Sequence, redMask, greenMask, blueMask: CARD32] = { action: PROC [c: Connection] = { BInit[c, 87, ToCBool[contiguos], 4]; BPutColorMap[c, colorMap]; BPut16[c, colors]; BPut16[c, reds]; BPut16[c, greens]; BPut16[c, blues]; reply ¬ FinishWithReply[c]; }; reply: Reply; n: CARD16; DoWithLocks[c, action, NIL]; CheckReply[reply]; Skip[reply, 7]; n ¬ ERead16[reply]; Skip[reply, 2]; redMask ¬ ERead32[reply]; greenMask ¬ ERead32[reply]; blueMask ¬ ERead32[reply]; Skip[reply, 8]; pixels ¬ NEW[Card32Sequence[n]]; FOR i: INT IN [0..n) DO pixels[i] ¬ ERead32[reply]; ENDLOOP; DisposeReply[c, reply]; }; FreeColors: PUBLIC PROC [c: Connection, colorMap: ColorMap, pixels: LIST OF CARD32, planeMask: CARD32, details: Details] ~ { action: PROC [c: Connection] ~ { BInit[c, 88, 0, 3+cnt]; BPutColorMap[c, colorMap]; BPut32[c, planeMask]; FOR i: INT IN [0..cnt) DO BPut32[c, pl.first]; IF pl#NIL THEN pl ¬ pl.rest ENDLOOP; FinishWithDetails[c, details]; }; cnt: INT ¬ 0; pl: LIST OF CARD32 ¬ NIL; --no infinite loops... FOR l: LIST OF CARD32 ¬ pixels, l.rest WHILE l#NIL DO pl ¬ CONS[l.first, pl]; cnt ¬ cnt+1; IF cnt>c.info.maxRequestLength THEN ERROR; ENDLOOP; DoWithLocks[c, action, details]; }; StoreColors: PUBLIC PROC [c: Connection, colorMap: ColorMap, items: LIST OF ColorItem, details: Details] ~ { action: PROC [c: Connection] ~ { BInit[c, 89, 0, 2+3*cnt]; BPutColorMap[c, colorMap]; FOR i: INT IN [0..cnt) DO used: BYTE ¬ 0; IF pl.first.doRed THEN used ¬ used+1; IF pl.first.doGreen THEN used ¬ used+2; IF pl.first.doBlue THEN used ¬ used+4; BPut32[c, pl.first.pixel]; BPutRGBRec[c, pl.first.rgb]; BPut8[c, used]; BPut8[c, 0]; pl ¬ pl.rest ENDLOOP; FinishWithDetails[c, details]; }; cnt: INT ¬ 0; pl: LIST OF ColorItem ¬ NIL; --no infinite loops... FOR l: LIST OF ColorItem ¬ items, l.rest WHILE l#NIL DO pl ¬ CONS[l.first, pl]; cnt ¬ cnt+1; IF cnt>c.info.maxRequestLength THEN ERROR; ENDLOOP; DoWithLocks[c, action, details]; }; StoreNamedColor: PUBLIC PROC [c: Connection, colorMap: ColorMap, pixel: Pixel, name: ROPE, doRed, doGreen, doBlue: BOOL, details: Details] ~ { len: INT ¬ Rope.Length[name]; used: BYTE ¬ 0; action: PROC [c: Connection] = { BInit[c, 90, used, 4+(len+3)/4]; BPutColorMap[c, colorMap]; BPut32[c, pixel]; BPut16[c, len]; BPut16[c, 0]; BPutPaddedRope[c, name]; FinishWithDetails[c, details]; }; IF len>=c.info.maxRequestLengthBytes THEN XlPrivateErrorHandling.RaiseClientError[c, $toolong]; IF doRed THEN used ¬ used+1; IF doGreen THEN used ¬ used+2; IF doBlue THEN used ¬ used+4; DoWithLocks[c, action, details]; }; QueryColors: PUBLIC PROC [c: Connection, colorMap: ColorMap, pixels: LIST OF CARD32] RETURNS [rgbl: LIST OF RGBRec ¬ NIL] = { action: PROC [c: Connection] = { BInit[c, 91, 0, 2+cnt]; BPutColorMap[c, colorMap]; FOR i: INT IN [0..cnt) DO IBPut32[c, pl.first]; IF pl#NIL THEN pl ¬ pl.rest; ENDLOOP; reply ¬ FinishWithReply[c]; }; n: CARD16; reply: Reply; cnt: INT ¬ 0; pl: LIST OF Pixel ¬ NIL; FOR l: LIST OF Pixel ¬ pixels, l.rest WHILE l#NIL DO pl ¬ CONS[l.first, pl]; cnt ¬ cnt+1; IF cnt>c.info.maxRequestLength THEN ERROR; ENDLOOP; DoWithLocks[c, action, NIL]; CheckReply[reply]; Skip[reply, 7]; n ¬ ERead16[reply]; Skip[reply, 22]; FOR i: INT IN [0..n) DO rgb: RGBRec; rgb.red ¬ ERead16[reply]; rgb.green ¬ ERead16[reply]; rgb.blue ¬ ERead16[reply]; [] ¬ ERead16[reply]; rgbl ¬ CONS[rgb, rgbl]; ENDLOOP; DisposeReply[c, reply]; }; LookupColor: PUBLIC PROC [c: Connection, colorMap: ColorMap, name: ROPE] RETURNS [exact, used: RGBRec] = { reply: Reply; action: PROC [c: Connection] = { BInit[c, 92, 0, 3+(leng+3)/4]; BPutColorMap[c, colorMap]; BPut16[c, leng]; BPut16[c, 0]; BPutPaddedRope[c, name]; reply ¬ FinishWithReply[c]; }; leng: INT ¬ Rope.Length[name]; IF leng >= c.info.maxRequestLengthBytes THEN ERROR; DoWithLocks[c, action, NIL]; CheckReply[reply]; Skip[reply, 7]; exact.red ¬ ERead16[reply]; exact.green ¬ ERead16[reply]; exact.blue ¬ ERead16[reply]; used.red ¬ ERead16[reply]; used.green ¬ ERead16[reply]; used.blue ¬ ERead16[reply]; DisposeReply[c, reply]; }; BPutRGB: --INTERNAL-- PROC [c: Connection, rgb: REF READONLY RGBRec] = { IF rgb=NIL THEN rgb ¬ black; BPutRGBRec[c, rgb­]; }; BPutRGBRec: --INTERNAL-- PROC [c: Connection, rgb: RGBRec] = { IBPut16[c, rgb.red]; IBPut16[c, rgb.green]; IBPut16[c, rgb.blue]; }; NewCursor: PROC [c: Connection, id: CARD32] RETURNS [Cursor] = { XlPrivateResources.Attach[c, id, $mutableCursor]; RETURN [ [id] ]; }; CreateCursor: PUBLIC PROC [c: Connection, source: Pixmap, mask: Pixmap ¬ nullPixmap, hotP: Point, foreground: REF READONLY RGBRec ¬ black, background: REF READONLY RGBRec ¬ white, details: Details] RETURNS [cursor: Cursor ¬ nullCursor] = { action: PROC [c: Connection] = { cursor ¬ NewCursor[c, XlPrivateResources.NewResourceID[c]]; BInit[c, 93, 0, 8]; BPutCursor[c, cursor]; BPutPixmap[c, source]; BPutPixmap[c, mask]; BPutRGB[c, IF foreground=NIL THEN black ELSE foreground]; BPutRGB[c, IF background=NIL THEN white ELSE background]; BPutPoint[c, hotP]; FinishWithDetails[c, details]; }; DoWithLocks[c, action, details]; }; CreateGlyphCursor: PUBLIC PROC [c: Connection, sourceFont: Font, maskFont: Font ¬ nullFont, sourceChar: CARD16, maskChar: CARD16, foreground: REF READONLY RGBRec ¬ black, background: REF READONLY RGBRec ¬ white, details: Details] RETURNS [cursor: Cursor ¬ nullCursor] = { sourceFontId, maskFontId: ID; action: PROC [c: Connection] = { cursor ¬ NewCursor[c, XlPrivateResources.NewResourceID[c]]; BInit[c, 94, 0, 8]; BPutCursor[c, cursor]; BPut32[c, sourceFontId]; BPut32[c, maskFontId]; BPut16[c, sourceChar]; BPut16[c, maskChar]; BPutRGB[c, IF foreground=NIL THEN black ELSE foreground]; BPutRGB[c, IF background=NIL THEN white ELSE background]; FinishWithDetails[c, details]; }; IF sourceFont=NIL THEN XlPrivateErrorHandling.RaiseClientError[c, $font]; sourceFontId ¬ Xl.FontId[sourceFont]; maskFontId ¬ IF maskFont=NIL THEN nullID ELSE Xl.FontId[maskFont]; DoWithLocks[c, action, details]; }; ReColorCursor: PUBLIC PROC [c: Connection, cursor: Cursor, foreground: REF READONLY RGBRec ¬ black, background: REF READONLY RGBRec ¬ white, details: Details] = { action: PROC [c: Connection] = { BInit[c, 96, 0, 5]; BPutCursor[c, cursor]; BPutRGB[c, IF foreground=NIL THEN black ELSE foreground]; BPutRGB[c, IF background=NIL THEN white ELSE background]; FinishWithDetails[c, details]; }; IF XlPrivateResources.Fetch[c, cursor]#$mutableCursor THEN ERROR; --I do not believe in recoloring cursors owned by different applications is worthwhile... However, if somebody needs that operation I will remove the test as the possible dammage is really quite limited. DoWithLocks[c, action, details]; }; FreeCursor: PUBLIC PROC [c: Connection, cursor: Cursor, details: Details] = { action: PROC [c: Connection] = { BInit[c, 95, 0, 2]; BPutCursor[c, cursor]; FinishWithDetails[c, details]; XlPrivateResources.InternalFreeResourceID[c, cursor]; }; IF XlPrivateResources.Fetch[c, cursor]#$mutableCursor THEN ERROR; --I do not believe freeing cursors owned by different applications is worthwhile allowing... XlPrivateResources.Detach[c, cursor]; DoWithLocks[c, action, details]; }; BPutPointerEvents: PROC [c: Connection, ev: SetOfPointerEvent] = { events: CARD32 ~ LOOPHOLE[PointerEvents[ev]]; BPutINT32as16[c, LOOPHOLE[events]]; }; Grabber: TYPE = REF GrabberRec; <>GrabberRec: PUBLIC TYPE = RECORD [ identity: REF BasicTime.GMT, waiters: CONDITION ¬ [], isGrabbed: BOOL ¬ FALSE, didTimeOut: BOOL ¬ FALSE, timeout: INT ¬ 6, timeStamp: TimeStamp ¬ currentTime, unGrabber: InternalUngrabProcType ]; flushNowDetails: Details ¬ NEW[DetailsRec ¬ [flush: now]]; InternalUngrabProcType: TYPE = --INTERNAL-- PROC [c: Connection, timeStamp: TimeStamp, details: Details <>]; StartTimer: INTERNAL PROC [c: Connection, grabber: Grabber] = { IF grabber#NIL THEN { grabber.identity ¬ NEW[BasicTime.GMT ¬ BasicTime.Now[]]; grabber.isGrabbed ¬ TRUE; grabber.didTimeOut ¬ FALSE; NOTIFY grabber.waiters; --get rid of old processes [performance hack] TRUSTED {Process.Detach[FORK TimerProcess[c, grabber, grabber.identity]]}; }; }; TimerProcess: ENTRY PROC [c: Connection, grabber: Grabber, grabIdentity: REF BasicTime.GMT] = { <<--process to enable timeout mechanisms>> ENABLE UNWIND => NULL; DO WAIT grabber.waiters; IF ~c.alive THEN RETURN; --connection is no more alive IF ~grabber.isGrabbed THEN RETURN; --server is no more grabbed IF grabber.identity#grabIdentity THEN RETURN; --server is grabbed by different client IF BasicTime.Period[from: grabIdentity­, to: BasicTime.Now[]]>1 THEN { <<--don't bother X server too to often>> IF InternalSomeImportantDown[c] THEN grabIdentity­ ¬ BasicTime.Now[] --key down; restart timer ELSE { IF BasicTime.Period[from: grabIdentity­, to: BasicTime.Now[]]>grabber.timeout THEN { grabber.unGrabber[c, grabber.timeStamp, flushNowDetails]; grabber.didTimeOut ¬ TRUE; BROADCAST grabber.waiters; RETURN; } } }; ENDLOOP; }; GrabPointer: PUBLIC PROC [c: Connection, window: Window, ownerEvents: BOOL, eventMask: SetOfPointerEvent, pointerMode: Synchronicity, keyboardMode: Synchronicity, confine: Window, cursor: Cursor, timeStamp: TimeStamp ¬ currentTime] RETURNS [status: GrabStatus ¬ success] = { action: INTERNAL PROC [c: Connection] = { reply: Reply; BInit[c, 26, ToCBool[ownerEvents], 6]; BPutDrawable[c, window]; BPutPointerEvents[c, eventMask]; BPut8[c, ORD[pointerMode]]; BPut8[c, ORD[keyboardMode]]; BPutDrawable[c, confine]; BPutCursor[c, cursor]; BPutTime[c, timeStamp]; reply ¬ FinishWithReply[c]; status ¬ VAL[Get8[reply, 1]]; IF status=success THEN { cPriv: REF ConnectionPrivateImplRec ~ c.cPriv; IF cPriv.pointerGrabber=NIL THEN { cPriv.pointerGrabber ¬ NEW[GrabberRec]; cPriv.pointerGrabber.unGrabber ¬ InternalUngrabPointer; TRUSTED {Process.InitializeCondition[@cPriv.pointerGrabber.waiters, 1]}; }; StartTimer[c, cPriv.pointerGrabber]; }; }; DoWithLocks[c, action, NIL]; }; InternalUngrabPointer: --INTERNAL-- PROC [c: Connection, timeStamp: TimeStamp, details: Details] = { BInit[c, 27, 0, 2]; BPutTime[c, timeStamp]; FinishWithDetails[c, details]; IF details=NIL THEN [] ¬ XlPrivate.HardFlushBuffer[c]; }; UngrabPointer: PUBLIC PROC [c: Connection, timeStamp: TimeStamp, details: Details] = { action: PROC [c: Connection] = {InternalUngrabPointer[c, timeStamp, details]}; DoWithLocks[c, action, details]; }; ChangeActivePointerGrab: PUBLIC PROC [c: Connection, eventMask: SetOfPointerEvent, cursor: Cursor ¬ [0], timeStamp: TimeStamp ¬ currentTime, details: Details ¬ NIL] = { action: PROC [c: Connection] = { BInit[c, 30, 0, 4]; BPutCursor[c, cursor]; BPutTime[c, timeStamp]; BPutPointerEvents[c, eventMask]; BSkip[c, 2]; FinishWithDetails[c, details]; IF details=NIL THEN XlPrivate.HardFlushBuffer[c]; }; DoWithLocks[c, action, details]; }; GrabButton: PUBLIC PROC [c: Connection, grabWindow: Window, confineWindow: Window ¬ nullWindow, modifiers: SetOfKeyButMask, button: BYTE ¬ 0, ownerEvents: BOOL, eventMask: SetOfPointerEvent, pointerMode: Synchronicity, keyboardMode: Synchronicity, cursor: Cursor ¬ [0], details: Details] = { action: PROC [c: Connection] = { BInit[c, 28, ToCBool[ownerEvents], 6]; BPutDrawable[c, grabWindow]; BPutPointerEvents[c, eventMask]; BPut8[c, ORD[pointerMode]]; BPut8[c, ORD[keyboardMode]]; BPutDrawable[c, confineWindow]; BPutCursor[c, cursor]; BPut8[c, button]; BPut8[c, 0]; BPut16[c, XlKeyButPrivate.SetToWire[modifiers]]; FinishWithDetails[c, details]; }; DoWithLocks[c, action, details]; }; UngrabButton: PUBLIC PROC [c: Connection, window: Window, modifiers: SetOfKeyButMask, button: BYTE ¬ 0, details: Details] = { action: PROC [c: Connection] = { BInit[c, 29, button, 3]; BPutDrawable[c, window]; BPut16[c, XlKeyButPrivate.SetToWire[modifiers]]; BSkip[c, 0]; FinishWithDetails[c, details]; IF details=NIL THEN XlPrivate.HardFlushBuffer[c, TRUE]; }; DoWithLocks[c, action, details]; }; keyboardGrabCheck: ROPE = "_Cedar_KeyboardGrabCheck"; keyboardGrab: REF ¬ NEW[INT]; propertyEvents: EventFilter = CreateEventFilter[propertyNotify]; KeyboardUnWedgeProc: EventProcType = { <> WITH event SELECT FROM pne: PropertyNotifyEvent => { cPriv: REF ConnectionPrivateImplRec ~ event.connection.cPriv; IF pne.atom#cPriv.keyboardGrabAtom THEN RETURN; --safety IF pne.atom.a=0 THEN RETURN; --safety IF FirstRoot[event.connection]#pne.window THEN RETURN; --safety IF pne.state=deleted THEN { PutConnectionProp[event.connection, keyboardGrab, NIL]; --propagate notify waiting guy RETURN; --essential }; IF cPriv.keyboardGrabbed THEN { UngrabKeyboard[event.connection, currentTime]; DeleteProperty[event.connection, pne.window, pne.atom]; --notify waiting guy Flush[event.connection]; }; }; ENDCASE => {}; }; InstallKeyboardUnWedger: PROC [c: Connection] = { cPriv: REF ConnectionPrivateImplRec ~ c.cPriv; IF cPriv.keyboardGrabAtom.a=0 THEN { a: XAtom ¬ MakeAtom[c, keyboardGrabCheck]; cPriv.keyboardGrabAtom ¬ a; AddDispatch[c, FirstRoot[c], NEW[MatchRep ¬ [proc: KeyboardUnWedgeProc, handles: propertyEvents, tq: CreateTQ[$keyboardUnWedger]]]]; }; }; GrabKeyboard: PUBLIC PROC [c: Connection, grabWindow: Window, ownerEvents: BOOL, pointerMode: Synchronicity, keyboardMode: Synchronicity, time: TimeStamp] RETURNS [status: GrabStatus ¬ success] = { action: PROC [c: Connection] = { cPriv: REF ConnectionPrivateImplRec ~ c.cPriv; reply: Reply; BInit[c, 31, ToCBool[ownerEvents], 4]; BPutDrawable[c, grabWindow]; BPutTime[c, time]; BPut8[c, ORD[pointerMode]]; BPut8[c, ORD[keyboardMode]]; BPut16[c, 0]; reply ¬ FinishWithReply[c]; status ¬ VAL[Get8[reply, 1]]; IF status=success THEN { cPriv.keyboardGrabbed ¬ TRUE; XlService.PutServiceProp[c, keyboardGrab, c] }; }; InstallKeyboardUnWedger[c]; DoWithLocks[c, action, NIL]; }; UngrabKeyboard: PUBLIC PROC [c: Connection, time: TimeStamp, details: Details ¬ NIL] = { <<--the vanilla X UngrabKeyboard request>> action: PROC [c: Connection] = { cPriv: REF ConnectionPrivateImplRec ~ c.cPriv; BInit[c, 32, 0, 2]; BPutTime[c, time]; FinishWithDetails[c, details]; IF time=currentTime THEN { cPriv.keyboardGrabbed ¬ FALSE; XlService.PutServiceProp[c, keyboardGrab, NIL]; }; }; DoWithLocks[c, action, details]; }; ForcedUngrabKeyboard: PUBLIC PROC [c: Connection] = { time: BasicTime.GMT ¬ BasicTime.Now[]; cPriv: REF ConnectionPrivateImplRec ~ c.cPriv; InstallKeyboardUnWedger[c]; ChangeProperty[c: c, w: FirstRoot[c], property: cPriv.keyboardGrabAtom, type: cPriv.keyboardGrabAtom, mode: replace, data: keyboardGrabCheck]; Flush[c]; WHILE GetConnectionProp[c, keyboardGrab]#NIL DO IF BasicTime.Period[from: time, to: BasicTime.Now[]]>5 THEN RETURN; Process.PauseMsec[100]; ENDLOOP; }; GrabKey: PUBLIC PROC [c: Connection, grabWindow: Window, modifiers: SetOfKeyButMask, key: KeyCode, ownerEvents: BOOL, pointerMode: Synchronicity, keyboardMode: Synchronicity, details: Details] = { action: PROC [c: Connection] = { BInit[c, 33, ToCBool[ownerEvents], 4]; BPutDrawable[c, grabWindow]; BPut16[c, XlKeyButPrivate.SetToWire[modifiers]]; BPut8[c, ORD[key]]; BPut8[c, ORD[pointerMode]]; BPut8[c, ORD[keyboardMode]]; BSkip[c, 3]; FinishWithDetails[c, details]; }; DoWithLocks[c, action, details]; }; UngrabKey: PUBLIC PROC [c: Connection, window: Window, modifiers: SetOfKeyButMask, key: KeyCode, details: Details] = { action: PROC [c: Connection] = { BInit[c, 34, ORD[key], 3]; BPutDrawable[c, window]; BPut16[c, XlKeyButPrivate.SetToWire[modifiers]]; BSkip[c, 2]; FinishWithDetails[c, details]; }; DoWithLocks[c, action, details]; }; AllowEvents: PUBLIC PROC [c: Connection, mode: AllowEventsMode, time: TimeStamp, details: Details] = { action: PROC [c: Connection] = { BInit[c, 35, ORD[mode], 2]; BPutTime[c, time]; FinishWithDetails[c, details]; IF details=NIL THEN [] ¬ XlPrivate.HardFlushBuffer[c]; }; DoWithLocks[c, action, details]; }; AddDispatch: PUBLIC PROC [c: Connection, window: Window, match: Match, generate: SetOfEvent ¬ unspecifiedEvents, details: Details ¬ NIL] = { XlDispatch.AddMatch[c, window, match, generate, details]; }; <<>> AddDispatchJunk: PUBLIC PROC [c: Connection, match: Match] = { XlDispatch.AddMatchForUnregistered[c, match] }; <<>> ClearArea: PUBLIC PROC [c: Connection, window: Window, pos: Point, size: Size, exposures: BOOL, details: Details] ~ { action: PROC [c: Connection] = { BInit[c, 61, ToCBool[exposures], 4]; BPutDrawable[c, window]; BPutRect[c, pos, size]; FinishWithDetails[c, details]; }; DoWithLocks[c, action, details]; }; InternalSomeImportantDown: INTERNAL PROC [c: Connection] RETURNS [down: BOOL] = { reply: Reply ¬ InternalQueryPointer[c, nullWindow]; down ¬ Get8[reply, 24]#0 OR Get8[reply, 25]#0; DisposeReply[c, reply]; }; InternalQueryPointer: --INTERNAL-- PROC [c: Connection, window: Window] RETURNS [reply: Reply] = { BInit[c, 38, 0, 2]; IF window=nullWindow THEN window ¬ DefaultRoot[c]; BPutDrawable[c, window]; reply ¬ FinishWithReply[c]; }; QueryPointer: PUBLIC PROC [c: Connection, window: Window ¬ nullWindow] RETURNS [qr: PointerReply] = { reply: Reply; action: PROC [c: Connection] = {reply ¬ InternalQueryPointer[c, window]}; DoWithLocks[c, action, NIL]; CheckReply[reply]; qr.sameScreen ¬ ERead8[reply]#0; Skip[reply, 6]; qr.root ¬ ToWindow[c, ERead32[reply]]; qr.child ¬ ToWindow[c, ERead32[reply]]; qr.rootP.x ¬ ERead16[reply]; qr.rootP.y ¬ ERead16[reply]; qr.pos.x ¬ ERead16[reply]; qr.pos.y ¬ ERead16[reply]; qr.mask ¬ [ERead16[reply]]; DisposeReply[c, reply]; }; WarpPointer: PUBLIC PROC [c: Connection, dstWindow: Window, dstPos: Point, srcWindow: Window, srcPos: Point, srcSize: Size, details: Details] = { action: PROC [c: Connection] = { BInit[c, 41, 0, 6]; BPutDrawable[c, srcWindow]; BPutDrawable[c, dstWindow]; BPutPoint[c, srcPos]; BPutSize[c, srcSize]; BPutPoint[c, dstPos]; FinishWithDetails[c, details]; }; DoWithLocks[c, action, details]; }; GetMotionEvents: PUBLIC PROC [c: Connection, window: Window, start, stop: TimeStamp] RETURNS [tc: REF TimeCoords ¬ NIL] = { action: PROC [c: Connection] = { BInit[c, 39, 0, 4]; BPutDrawable[c, window]; BPutTime[c, start]; BPutTime[c, stop]; reply ¬ FinishWithReply[c]; }; reply: Reply; tcLeng: CARD; replyExtLeng: CARD; DoWithLocks[c, action, NIL]; CheckReply[reply]; Skip[reply, 3]; replyExtLeng ¬ ERead32[reply]; tcLeng ¬ ERead32[reply]; Skip[reply, 20]; IF (tcLeng > c.info.motionBufferSize) OR (tcLeng*2 > replyExtLeng) THEN { XlPrivateErrorHandling.RaiseServerError[c, $GetMotionEvents, reply]; tcLeng ¬ 0; }; tc ¬ NEW[TimeCoords[tcLeng]]; FOR i: CARD IN [0..tcLeng) DO tc[i].time ¬ [ERead32[reply]]; tc[i].p.x ¬ INT32[LOOPHOLE[ERead16[reply], INT16]]; tc[i].p.y ¬ INT32[LOOPHOLE[ERead16[reply], INT16]]; ENDLOOP; DisposeReply[c, reply]; }; QueryBestSize: PUBLIC PROC [c: Connection, class: BestSizeClass, drawable: Drawable, size: Size] RETURNS [best: Size] = { reply: Reply; action: PROC [c: Connection] = { BInit[c, 97, ORD[class], 3]; BPutDrawable[c, drawable]; BPutSize[c, size]; reply ¬ FinishWithReply[c]; }; DoWithLocks[c, action, NIL]; CheckReply[reply]; Skip[reply, 7]; best.width ¬ ERead16[reply]; best.height ¬ ERead16[reply]; DisposeReply[c, reply]; }; TranslateCoordinates: PUBLIC PROC [c: Connection, srcWindow, dstWindow: Window, srcPos: Point] RETURNS [trans: TranslateRec] = { reply: Reply; action: PROC [c: Connection] = { BInit[c, 40, 0, 4]; BPutDrawable[c, srcWindow]; BPutDrawable[c, dstWindow]; BPutPoint[c, srcPos]; reply ¬ FinishWithReply[c]; }; DoWithLocks[c, action, NIL]; CheckReply[reply]; trans.sameScreen ¬ ERead8[reply]#0; Skip[reply, 6]; trans.child ¬ ToWindow[c, ERead32[reply]]; trans.pos.x ¬ LONG[LOOPHOLE[ERead16[reply], INT16]]; trans.pos.y ¬ LONG[LOOPHOLE[ERead16[reply], INT16]]; DisposeReply[c, reply]; }; InternalUngrabServer: --INTERNAL-- PROC [c: Connection, timeStamp: TimeStamp, details: Details] = { BInit[c, 37, 0, 1]; FinishWithDetails[c, details]; IF details=NIL THEN [] ¬ XlPrivate.HardFlushBuffer[c]; }; UngrabServer: PUBLIC PROC [c: Connection, details: Details] = { action: PROC [c: Connection] ~ { cPriv: REF ConnectionPrivateImplRec ~ c.cPriv; InternalUngrabServer[c, currentTime, details]; cPriv.serverGrabber.isGrabbed ¬ FALSE; }; DoWithLocks[c, action, details]; }; GrabServer: PUBLIC PROC [c: Connection, details: Details] = { cPriv: REF ConnectionPrivateImplRec ~ c.cPriv; gr: REF GrabberRec ¬ cPriv.serverGrabber; action: INTERNAL PROC [c: Connection] ~ { cPriv: REF ConnectionPrivateImplRec ~ c.cPriv; IF cPriv.serverGrabber=NIL THEN TRUSTED { cPriv.serverGrabber ¬ NEW[GrabberRec]; cPriv.serverGrabber.unGrabber ¬ InternalUngrabServer; TRUSTED {Process.InitializeCondition[@cPriv.serverGrabber.waiters, 2]}; }; BInit[c, 36, 0, 1]; FinishWithDetails[c, details]; StartTimer[c, cPriv.serverGrabber]; }; IF gr#NIL AND gr.isGrabbed THEN XlPrivateErrorHandling.RaiseClientError[c, $GrabWhileGrabbed]; DoWithLocks[c, action, details]; }; GetGeometry: PUBLIC PROC [c: Connection, drawable: Drawable] RETURNS [g: GeometryRec] = { action: PROC [c: Connection] ~ { BInit[c, 14, 0, 2]; BPutDrawable[c, drawable]; reply ¬ FinishWithReply[c]; }; reply: Reply; DoWithLocks[c, action, NIL]; CheckReply[reply]; g.depth ¬ Read8[reply]; Skip[reply, 6]; g.root ¬ ToWindow[c, ERead32[reply]]; g.geometry.pos.x ¬ ERead16[reply]; g.geometry.pos.y ¬ ERead16[reply]; g.geometry.size.width ¬ ERead16[reply]; g.geometry.size.height ¬ ERead16[reply]; g.geometry.borderWidth ¬ ERead16[reply]; DisposeReply[c, reply]; }; QueryTree: PUBLIC PROC [c: Connection, window: Window] RETURNS [treeInfo: REF TreeInfoRec] = { action: PROC [c: Connection] ~ { BInit[c, 15, 0, 2]; BPutDrawable[c, window]; reply ¬ FinishWithReply[c]; }; reply: Reply; n: CARD16; root, parent: Window; DoWithLocks[c, action, NIL]; CheckReply[reply]; Skip[reply, 7]; root ¬ ToWindow[c, ERead32[reply]]; parent ¬ ToWindow[c, ERead32[reply]]; n ¬ ERead16[reply]; Skip[reply, 14]; treeInfo ¬ NEW[TreeInfoRec[n]]; treeInfo.root ¬ root; treeInfo.parent ¬ parent; FOR i: NAT IN [0..n) DO treeInfo.children[i] ¬ ToWindow[c, ERead32[reply]]; ENDLOOP; DisposeReply[c, reply]; }; CirculateWindow: PUBLIC PROC [c: Connection, window: Window, direction: CirculateDirection, details: Details] = { action: PROC [c: Connection] = { BInit[c, 13, ORD[direction], 2]; BPutDrawable[c, window]; FinishWithDetails[c, details]; }; DoWithLocks[c, action, details]; }; ReparentWindow: PUBLIC PROC [c: Connection, window: Window, newParent: Window, pos: Point, details: Details] = { action: PROC [c: Connection] = { BInit[c, 7, 0, 4]; BPutDrawable[c, window]; BPutDrawable[c, newParent]; BPutPoint[c, pos]; FinishWithDetails[c, details]; }; DoWithLocks[c, action, details]; }; SendClientMessage32: PUBLIC PROC [c: Connection, destination: Window, propagate: BOOL, eventMask: SetOfEvent, window: Window, type: XAtom, data: ARRAY [0..5) OF CARD32, details: Details] = { action: PROC [c: Connection] = { BInit[c, 25, ToCBool[propagate], 11]; BPutDrawable[c, destination]; BPut32[c, LOOPHOLE[eventMask]]; BPut8[c, ORD[EventCode[clientMessage]]]; BPut8[c, 32]; BPut16[c, 0]; --sequence number BPutDrawable[c, window]; BPut32[c, type.a]; FOR i: [0..5) IN [0..5) DO BPut32[c, data[i]] ENDLOOP; FinishWithDetails[c, details]; }; DoWithLocks[c, action, details]; }; SendEvent: PUBLIC PROC [c: Connection, destination: Window, propagate: BOOL, eventMask: SetOfEvent, eventBody: EventRep, details: Details] = { <<--Ignores originalCodeByte, dispatchDrawable, connection, and, sequence number in eventBody>> <<--WARNING: Some of the event types have not yet been tested>> action: PROC [c: Connection] = { BInit[c, 25, ToCBool[propagate], 11]; BPutDrawable[c, destination]; BPutSetOfEvent[c, eventMask]; BPut8[c, ORD[EventCode[eventBody.type]]]; TRUSTED { WITH ev: eventBody SELECT FROM keyPress, keyRelease => { BPut8[c, ORD[ev.keyCode]]; BSkip[c, 2]; --sequence number BPutTime[c, ev.timeStamp]; BPutDrawable[c, ev.root]; BPutDrawable[c, ev.eventWindow]; BPutDrawable[c, ev.child]; BPutPoint[c, ev.rootP]; BPutPoint[c, ev.pos]; BPut16[c, XlKeyButPrivate.SetToWire[ev.state]]; BPutBool[c, ev.sameScreen]; BPut8[c, 0]; --unused }; buttonPress, buttonRelease => { BPut8[c, ORD[ev.button]]; BSkip[c, 2]; --sequence number BPutTime[c, ev.timeStamp]; BPutDrawable[c, ev.root]; BPutDrawable[c, ev.eventWindow]; BPutDrawable[c, ev.child]; BPutPoint[c, ev.rootP]; BPutPoint[c, ev.pos]; BPut16[c, XlKeyButPrivate.SetToWire[ev.state]]; BPutBool[c, ev.sameScreen]; BPut8[c, 0]; --unused }; unmapNotify => { BSkip[c, 3]; --unused and sequence number BPutDrawable[c, ev.eventWindow]; BPutDrawable[c, ev.window]; BPutBool[c, ev.fromConfigure]; BSkip[c, 19]; }; motionNotify => { BPut8[c, ORD[ev.detail]]; BSkip[c, 2]; --sequence number BPutTime[c, ev.timeStamp]; BPutDrawable[c, ev.root]; BPutDrawable[c, ev.eventWindow]; BPutDrawable[c, ev.child]; BPutPoint[c, ev.rootP]; BPutPoint[c, ev.pos]; BPut16[c, XlKeyButPrivate.SetToWire[ev.state]]; BPutBool[c, ev.sameScreen]; BSkip[c, 1]; }; enterNotify, leaveNotify => { BPut8[c, ORD[ev.detail]]; BSkip[c, 2]; --sequence number BPutTime[c, ev.timeStamp]; BPutDrawable[c, ev.root]; BPutDrawable[c, ev.eventWindow]; BPutDrawable[c, ev.child]; BPutPoint[c, ev.rootP]; BPutPoint[c, ev.eventP]; BPut16[c, XlKeyButPrivate.SetToWire[ev.state]]; BPut8[c, ORD[ev.mode]]; BPut8[c, ORD[ev.sameScreen]*2+ORD[ev.focus]]; }; focusIn, focusOut => { BPut8[c, ORD[ev.detail]]; BSkip[c, 2]; --sequence number BPutDrawable[c, ev.eventWindow]; BPut8[c, ORD[ev.mode]]; BSkip[c, 23]; }; keymapNotify => { FOR i: [1..31] IN [1..31] DO BPut8[c, ev.keys[i]] ENDLOOP; }; expose => { BSkip[c, 3]; --unused and sequence number BPutDrawable[c, ev.window]; BPutRect[c, ev.pos, ev.size]; --pos is INT16 instead of CARD16, happens to run fine BPut16[c, ev.count]; BSkip[c, 14]; }; graphicsExposure => { BSkip[c, 3]; --unused and sequence number BPutDrawable[c, ev.drawable]; BPutRect[c, ev.pos, ev.size]; --pos is INT16 instead of CARD16, happens to run fine BPut16[c, ev.minorOpcode]; BPut16[c, ev.count]; BPut8[c, ev.majorOpcode]; BSkip[c, 11]; }; noExposure => { BSkip[c, 3]; --unused and sequence number BPutDrawable[c, ev.drawable]; BPut16[c, ev.minorOpcode]; BPut8[c, ev.majorOpcode]; BSkip[c, 21]; }; visibilityNotify => { BSkip[c, 3]; --unused and sequence number BPutDrawable[c, ev.window]; BPut8[c, ORD[ev.state]]; BSkip[c, 23]; }; createNotify => { BSkip[c, 3]; --unused and sequence number BPutDrawable[c, ev.parent]; BPutDrawable[c, ev.window]; BPutRect[c, ev.geometry.pos, ev.geometry.size]; BPutINT32as16[c, ev.geometry.borderWidth]; BPutBool[c, ev.overrideRedirect]; BSkip[c, 9]; }; destroyNotify => { BSkip[c, 3]; --unused and sequence number BPutDrawable[c, ev.eventWindow]; BPutDrawable[c, ev.window]; BSkip[c, 20]; }; mapNotify => { BSkip[c, 3]; --unused and sequence number BPutDrawable[c, ev.eventWindow]; BPutDrawable[c, ev.window]; BPutBool[c, ev.overrideRedirect]; BSkip[c, 19]; }; mapRequest => { BSkip[c, 3]; --unused and sequence number BPutDrawable[c, ev.parent]; BPutDrawable[c, ev.window]; BSkip[c, 20]; }; reparentNotify => { BSkip[c, 3]; --unused and sequence number BPutDrawable[c, ev.eventWindow]; BPutDrawable[c, ev.window]; BPutDrawable[c, ev.parent]; BPutPoint[c, ev.pos]; BPutBool[c, ev.overrideRedirect]; BSkip[c, 11]; }; configureNotify => { BSkip[c, 3]; --unused and sequence number BPutDrawable[c, ev.eventWindow]; BPutDrawable[c, ev.window]; BPutDrawable[c, ev.aboveSibling]; BPutRect[c, ev.geometry.pos, ev.geometry.size]; BPutINT32as16[c, ev.geometry.borderWidth]; BPut8[c, ev.overrideRedirect]; BSkip[c, 5]; }; configureRequest => { BPut8[c, ORD[ev.stackMode]]; BSkip[c, 2]; --sequence number BPutDrawable[c, ev.parent]; BPutDrawable[c, ev.window]; BPutDrawable[c, ev.sibling]; BPutRect[c, ev.geometry.pos, ev.geometry.size]; BPutINT32as16[c, ev.geometry.borderWidth]; BPut16[c, ev.valueMask]; BSkip[c, 4]; }; gravityNotify => { BSkip[c, 3]; --unused and sequence number BPutDrawable[c, ev.eventWindow]; BPutDrawable[c, ev.window]; BPutPoint[c, ev.pos]; BSkip[c, 16]; }; resizeRequest => { BSkip[c, 3]; --unused and sequence number BPutDrawable[c, ev.window]; BPutSize[c, ev.size]; BSkip[c, 20]; }; circulateNotify => { BSkip[c, 3]; --unused and sequence number BPutDrawable[c, ev.eventWindow]; BPutDrawable[c, ev.window]; BSkip[c, 4]; --unused window BPut8[c, ORD[ev.place]]; BSkip[c, 15]; }; circulateRequest => { BSkip[c, 3]; --unused and sequence number BPutDrawable[c, ev.parent]; BPutDrawable[c, ev.window]; BSkip[c, 4]; --unused BPut8[c, ORD[ev.place]]; BSkip[c, 15]; }; propertyNotify => { BSkip[c, 3]; --unused and sequence number BPutDrawable[c, ev.window]; BPut32[c, Xl.AtomId[ev.atom]]; BPutTime[c, ev.timeStamp]; BPut8[c, ORD[ev.state]]; BSkip[c, 15]; }; selectionClear => { BSkip[c, 3]; --unused and sequence number BPutTime[c, ev.timeStamp]; BPutDrawable[c, ev.owner]; BPut32[c, Xl.AtomId[ev.selection]]; BSkip[c, 16]; }; selectionRequest => { BSkip[c, 3]; --unused and sequence number BPutTime[c, ev.timeStamp]; BPutDrawable[c, ev.owner]; BPutDrawable[c, ev.requestor]; BPut32[c, Xl.AtomId[ev.selection]]; BPut32[c, Xl.AtomId[ev.target]]; BPut32[c, Xl.AtomId[ev.property]]; BSkip[c, 4]; }; selectionNotify => { BSkip[c, 3]; --unused and sequence number BPutTime[c, ev.timeStamp]; BPutDrawable[c, ev.requestor]; BPut32[c, Xl.AtomId[ev.selection]]; BPut32[c, Xl.AtomId[ev.target]]; BPut32[c, Xl.AtomId[ev.property]]; BSkip[c, 8]; }; colorMapNotify => { BSkip[c, 3]; --unused and sequence number BPutDrawable[c, ev.window]; BPutColorMap[c, ev.colorMap]; BPutBool[c, ev.new]; BPutBool[c, ev.installed]; BSkip[c, 18]; }; clientMessage => { BPut8[c, ev.format]; BPut16[c, 0]; --sequence number BPutDrawable[c, ev.window]; BPut32[c, ev.typeAtom.a]; SELECT ev.format FROM 32 => FOR i: [0..5) IN [0..5) DO BPut32[c, ev.w[i]] ENDLOOP; 8 => FOR i: [0..20) IN [0..20) DO BPut8[c, ev.b[i]] ENDLOOP; 16 => FOR i: [0..10) IN [0..10) DO BPut16[c, ev.h[i]] ENDLOOP; ENDCASE => ERROR; }; mappingNotify => { BSkip[c, 3]; --unused and sequence number BPut8[c, ORD[ev.request]]; BPut8[c, ev.firstKeycode]; BPut8[c, ev.count]; BSkip[c, 25]; }; ENDCASE => ERROR; }; FinishWithDetails[c, details]; }; TRUSTED { <<--check validity outside of connections monitor>> WITH ev: eventBody SELECT FROM local, errorNotify => ERROR; clientMessage => { SELECT ev.format FROM 8, 16, 32 => {}; ENDCASE => ERROR }; extension, tipEvent => ERROR; keyPress, keyRelease, buttonPress, buttonRelease, motionNotify, enterNotify, leaveNotify, focusIn, focusOut, keymapNotify, expose, graphicsExposure, noExposure, visibilityNotify, createNotify, destroyNotify, unmapNotify, mapNotify, mapRequest, reparentNotify, configureNotify, configureRequest, gravityNotify, resizeRequest, circulateNotify, circulateRequest, propertyNotify, selectionClear, selectionRequest, selectionNotify, colorMapNotify, mappingNotify => {}; ENDCASE => ERROR; }; DoWithLocks[c, action, details]; }; END.