DIRECTORY Convert, Rope, Xl, XlDB, XlPerDepth, XTk, XTkOps, XTkGestureInput; XTkGestureInputImpl: CEDAR MONITOR IMPORTS Convert, Xl, XlDB, XlPerDepth, XTk, XTkOps EXPORTS XTkGestureInput ~ BEGIN OPEN XTkGestureInput; GestureData: TYPE = REF GestureRec; GestureRec: TYPE = RECORD [ --hangs on widget self: XTk.Widget ¬ NIL, stroke: LIST OF Xl.Point ¬ NIL, gc: Xl.GContext ¬ NIL, delayFlush: BOOL ¬ TRUE, paint: BOOL ¬ FALSE, registrations: LIST OF RegistrationRec ¬ NIL ]; ReportData: TYPE = RECORD [ --to transmit report data to tq gd: GestureData, stroke: LIST OF Xl.Point, rrl: LIST OF RegistrationRec ]; RegistrationRec: TYPE = RECORD [ --list registrations proc: GestureReportProc, d1, d2: REF ¬ NIL, tq: Xl.TQ ¬ NIL ]; GestureReportProc: PUBLIC TYPE = PROC [w: XTk.Widget, stroke: LIST OF Xl.Point, e: Xl.Event, d1, d2: REF]; filter: Xl.EventFilter ~ Xl.CreateEventFilter[motionNotify, buttonPress, buttonRelease]; Append: PROC [gd: GestureData, e: Xl.Event, pos: Xl.Point] = { IF gd.stroke=NIL THEN gd.stroke ¬ LIST[pos] ELSE IF gd.stroke.first#pos THEN { IF gd.gc#NIL AND gd.paint THEN { Xl.DrawLine[e.connection, gd.self.window, pos, gd.stroke.first, gd.gc]; Xl.Flush[e.connection, gd.delayFlush]; }; gd.stroke ¬ CONS[pos, gd.stroke]; }; }; EventProc: Xl.EventProcType = { ENABLE { Xl.XError => GOTO oops; }; gd: GestureData ~ NARROW[clientData]; SELECT event.type FROM Xl.EventCode.motionNotify => { e: Xl.MotionNotifyEvent ~ NARROW[event]; Append[gd, e, e.pos]; }; Xl.EventCode.buttonPress => { e: Xl.ButtonPressEvent ~ NARROW[event]; gd.stroke ¬ NIL; Append[gd, e, e.pos]; }; Xl.EventCode.buttonRelease => { e: Xl.ButtonReleaseEvent ~ NARROW[event]; stroke: LIST OF Xl.Point; Append[gd, e, e.pos]; stroke ¬ gd.stroke; gd.stroke ¬ NIL; Report[gd, stroke, e]; }; ENDCASE => {}; EXITS oops => {}; }; Report: PROC [gd: GestureData, stroke: LIST OF Xl.Point, event: Xl.Event] = { FOR rrl: LIST OF RegistrationRec ¬ gd.registrations, rrl.rest WHILE rrl#NIL DO rd: REF ReportData ¬ NEW[ReportData ¬ [gd: gd, stroke: stroke, rrl: rrl]]; tq: Xl.TQ ¬ rrl.first.tq; IF tq=NIL THEN tq ¬ gd.self.rootTQ; Xl.Enqueue[tq: tq, proc: QueuedReport, data: rd, event: event] ENDLOOP }; QueuedReport: Xl.EventProcType = { rd: REF ReportData ~ NARROW[clientData]; rd.rrl.first.proc[w: rd.gd.self, stroke: rd.stroke, e: event, d1: rd.rrl.first.d1, d2: rd.rrl.first.d2]; }; propertyKey: REF INT ~ NEW[INT]; GetGestureTrait: ENTRY PROC [w: XTk.Widget] RETURNS [GestureData] = { IF w=NIL THEN RETURN [NIL]; WITH XTk.GetWidgetProp[w, propertyKey] SELECT FROM gd: GestureData => RETURN [gd]; ENDCASE => { gd: GestureData ¬ NEW[GestureRec ¬ [self: w]]; XTk.PutWidgetProp[w, propertyKey, gd]; XTkOps.CallAndRegisterOnPostRealize[w, PostRealize, gd]; XTk.RegisterNotifier[w, XTk.preStopFastAccessKey, StopAccess, gd]; RETURN [gd]; }; }; StopAccess: XTk.WidgetNotifyProc = { gd: GestureData ~ NARROW[registerData]; gd.gc ¬ NIL }; PostRealize: XTk.WidgetNotifyProc = { gd: GestureData ~ NARROW[registerData]; gestureMatch: Xl.Match ¬ NEW[Xl.MatchRep ¬ [ proc: EventProc, handles: filter, tq: TrustedSharedTQ[widget.screenDepth], data: gd ]]; IF gd.gc=NIL THEN gd.gc ¬ TrustedSharedGC[widget.screenDepth]; Xl.AddDispatch[widget.connection, widget.window, gestureMatch, [buttonMotion: TRUE, buttonRelease: TRUE, buttonPress: TRUE]]; }; SetReport: PUBLIC PROC [w: XTk.Widget, report: GestureReportProc, d1, d2: REF ¬ NIL, tq: Xl.TQ ¬ NIL] = { gd: GestureData ¬ GetGestureTrait[w]; EntryAddReport: ENTRY PROC [gd: GestureData, rr: RegistrationRec] = { gd.registrations ¬ CONS[rr, gd.registrations]; }; EntryAddReport[gd, [report, d1, d2, tq]]; }; SetPainting: PUBLIC PROC [w: XTk.Widget, addFlush: BOOL, gc: Xl.GContext ¬ NIL] = { gd: GestureData ¬ GetGestureTrait[w]; gd.paint ¬ TRUE; IF addFlush THEN gd.delayFlush ¬ FALSE; IF gc#NIL THEN gd.gc ¬ gc; }; TrustedSharedTQ: PROC [screenDepth: Xl.ScreenDepth] RETURNS [Xl.TQ] = { pdd: REF PerDepthRec ~ GetDepthData[screenDepth]; RETURN [pdd.sharedTQ] }; TrustedSharedGC: PUBLIC PROC [screenDepth: Xl.ScreenDepth] RETURNS [Xl.GContext] = { pdd: REF PerDepthRec ~ GetDepthData[screenDepth]; RETURN [pdd.gc] }; GetDepthData: PROC [screenDepth: Xl.ScreenDepth] RETURNS [REF PerDepthRec] = INLINE { RETURN [NARROW[XlPerDepth.InlineGetData[perDKey, screenDepth]]] }; PerDepthRec: TYPE = RECORD [ sharedTQ: Xl.TQ ¬ NIL, gc: Xl.GContext ]; perDKey: XlPerDepth.Handle ¬ XlPerDepth.InstallHandle[InstallDepth]; InstallDepth: XlPerDepth.InitProc = { dd: REF PerDepthRec ¬ NEW[PerDepthRec]; IF sd#NIL AND Xl.Alive[sd.screen.connection] THEN { width: INT ¬ 0; screen: Xl.Screen ¬ sd.screen; c: Xl.Connection ¬ screen.connection; gc: Xl.GContext ¬ dd.gc ¬ Xl.MakeGContext[c, screen.root.drawable]; Xl.SetGCFunction[gc: gc, function: copy]; Xl.SetGCForeground[gc: gc, foreground: screen.blackPixel]; Xl.SetGCBackground[gc: gc, background: screen.whitePixel]; BEGIN widthRope: Rope.ROPE; w: INT; widthRope ¬ XlDB.QueryStandardDB[c, "(XTkGestureInput)(StrokeWidth)"]; w ¬ Convert.IntFromRope[widthRope ! Convert.Error => {w ¬ 0; CONTINUE}]; IF w>0 AND w<20 THEN width ¬ w; END; Xl.SetGCLineWidth[gc: gc, width: width]; }; dd.sharedTQ ¬ Xl.CreateTQ[$XTkGesturesImpl]; RETURN [dd] }; END. Μ XTkGestureInputImpl.mesa Copyright Σ 1992 by Xerox Corporation. All rights reserved. Created by Christian Jacobi, October 28, 1992 2:43:24 pm PST Christian Jacobi, October 28, 1992 2:52 pm PST Κc•NewlineDelimiter ™J˜code™Kšœ Οeœ1™šžœ žœ˜Kšžœ žœ˜šžœžœžœ˜"šžœžœžœ žœ˜ K˜HK˜&K˜—Kšœ žœ˜!K˜——K˜—K˜šŸ œ˜šžœ˜Kšœ žœ˜K˜—Kšœžœ ˜%šžœ ž˜˜Kšœžœ˜(K˜K˜—˜Kšœžœ˜'Kšœ žœ˜K˜K˜—˜Kšœžœ˜)Kšœžœžœ ˜K˜Kšœ žœ˜$K˜K˜—Kšžœ˜—Kšžœ ˜K˜—K˜šŸœžœžœžœ˜Mš žœžœžœ.žœžœž˜NKšœžœžœ2˜JKšœžœ˜Kšžœžœžœ˜#K˜>Kšž˜—K˜—K˜šŸ œ˜"Kšœžœžœ ˜(K˜hK˜K˜—Kš œ žœžœžœžœ˜ K˜šŸœžœžœžœ˜EJš žœžœžœžœžœ˜šžœ#žœž˜2Kšœžœ˜šžœ˜ Kšœžœ˜.K˜&K˜8K˜BKšžœ˜ K˜——K˜—K˜šŸ œ˜$Kšœžœ˜'Jšœž˜ K˜K˜—šŸ œ˜%Kšœžœ˜'šœžœ˜,K˜SK˜—Kšžœžœžœ-˜>KšœNžœžœžœ˜K˜—K˜š Ÿ œž œ4žœžœ žœžœ˜iK˜%šŸœžœžœ+˜EKšœžœ˜.K˜—K˜)K˜—K˜š Ÿ œžœžœžœžœ˜SK˜%Kšœ žœ˜Kšžœ žœžœ˜'Kšžœžœžœ ˜˜K˜——šŸœžœžœžœ˜GKšœžœ)˜1Kšžœ˜K˜K˜—šŸœžœžœžœ˜TKšœžœ)˜1Kšžœ ˜K˜K˜—š Ÿ œžœžœžœžœ˜UJšžœžœ1˜?K˜K˜—šœ žœžœ˜Kšœ žœžœ˜K˜K˜K˜—K˜DšŸ œ˜%Kšœžœžœ˜'šžœžœžœ žœ˜3Kšœžœ˜K˜K˜%K˜CK˜)K˜:K˜:šž˜Kšœžœžœ˜K˜FKšœ=žœ˜HKšžœžœžœ ˜Kšžœ˜—K˜(K˜—K˜,Kšžœ˜ Kšœ˜—K˜Kšžœ˜—…—h—