DIRECTORY Commander USING [ CommandProc, Handle, Register ], Interminal USING [ GetMousePosition ], InterminalBackdoor USING [ terminal ], IO USING [ EndOf, GetTokenRope, RIS, SkipWhitespace, STREAM ], PrincOpsUtils USING [ VERSION ], Process USING [ SetPriority, priorityClient3, priorityRealTime ], Rope USING [ Equal, ROPE ], Terminal USING [ Position, GetMousePosition, SetMousePosition, WaitForBWVerticalRetrace, Virtual ], UserProfile USING [ ProfileChangedProc, Number, Token, CallWhenProfileChanges ], Cursory USING [ SetMousePositionProc, CallWhenMousePositionChanges ]; FastMouse: CEDAR MONITOR IMPORTS Commander, Terminal, Interminal, InterminalBackdoor, IO, Process, PrincOpsUtils, UserProfile, Rope, Cursory ~ BEGIN ROPE: TYPE = Rope.ROPE; mouseProcess: PROCESS _ NIL; vt: Terminal.Virtual ~ InterminalBackdoor.terminal; position, prevPosition: Terminal.Position; width: NAT; height: NAT; cursorInColorDisplay: BOOL _ FALSE; speedUpLinear: BOOL _ TRUE; -- Acceleration law (linear or squared) threshold: INTEGER _ 2; -- Speedup control parameters thresholdxTen: INTEGER _ 20; ampxTenX: INTEGER _ 15; ampxTenY: INTEGER _ 15; ratioYtoXxTen: INTEGER _ 10; overShoot: INTEGER _ 0; -- to allow Escape velocity hack bwOverShoot: INTEGER _ 0; clrOverShoot: INTEGER _ 0; enabled: BOOL _ TRUE; shouldRun: BOOL _ TRUE; running: BOOL _ FALSE; ShouldRun: ENTRY PROC RETURNS [run: BOOL] = { IF NOT (run _ shouldRun) THEN RETURN; IF running THEN RETURN [FALSE]; running _ TRUE; }; NoteNotRunning: ENTRY PROC = {running _ FALSE}; DoradoMouseProcess: PROC = { IF NOT ShouldRun[] THEN RETURN; {ENABLE UNWIND => NoteNotRunning[]; Process.SetPriority[Process.priorityRealTime]; -- this priority is above fault handlers prevPosition _ Terminal.GetMousePosition[vt]; width _ vt.bwWidth; height _ vt.bwHeight; WHILE shouldRun DO xDist, yDist, xDelta, yDelta: INTEGER; Terminal.WaitForBWVerticalRetrace[vt]; position _ Terminal.GetMousePosition[vt]; IF prevPosition = position THEN LOOP; TRUSTED { IF cursorInColorDisplay # Interminal.GetMousePosition[].color THEN { prevPosition _ position; cursorInColorDisplay _ Interminal.GetMousePosition[].color; IF cursorInColorDisplay THEN { width _ vt.colorWidth; height _ vt.colorHeight; overShoot _ clrOverShoot; } ELSE { width _ vt.bwWidth; height _ vt.bwHeight; overShoot _ bwOverShoot; }; LOOP; }; }; xDelta _ position.x - prevPosition.x; yDelta _ position.y - prevPosition.y; xDist _ ABS[xDelta]; yDist _ ABS[yDelta]; IF xDist > threshold OR yDist > threshold THEN { IF speedUpLinear THEN position _ [ -- linear law speedup MAX[ -overShoot, MIN[ width+overShoot, position.x + (xDelta*ampxTenX / 10)] ], MAX[ 0, MIN[ height, position.y + (yDelta*ampxTenY / 10)] ] ] ELSE position _ [ -- square law speedup MAX[ -overShoot, MIN[ width+overShoot, position.x + (xDelta*xDist / threshold)] ], MAX[ 0, MIN[ height, position.y + (yDelta*yDist*ratioYtoXxTen / thresholdxTen) ] ] ]; Terminal.SetMousePosition[vt, position]; }; prevPosition _ [ MAX[ 0, MIN[ width, position.x ]], position.y ]; ENDLOOP; }; NoteNotRunning[]; }; -- DoradoMouseProcess DandelionMouseProcess: PROC = { -- note, doesn't work on Dandelions IF NOT ShouldRun[] THEN RETURN; {ENABLE UNWIND => NoteNotRunning[]; Process.SetPriority[Process.priorityClient3]; -- this priority is one below fault handlers prevPosition _ Terminal.GetMousePosition[vt]; width _ vt.bwWidth; height _ vt.bwHeight; WHILE shouldRun DO Terminal.WaitForBWVerticalRetrace[vt]; position _ Terminal.GetMousePosition[vt]; ENDLOOP; }; NoteNotRunning[]; }; -- MouseProcess FastMouseCmd: Commander.CommandProc = { in: IO.STREAM _ IO.RIS[cmd.commandLine]; ok, on: BOOL _ FALSE; [] _ in.SkipWhitespace[]; IF NOT in.EndOf[] THEN { arg: ROPE _ in.GetTokenRope[].token; [] _ in.SkipWhitespace[]; IF NOT in.EndOf[] THEN NULL ELSE IF arg.Equal["on", FALSE] THEN {ok _ TRUE; on _ TRUE} ELSE IF arg.Equal["off", FALSE] THEN {ok _ TRUE; on _ FALSE}; }; IF ok THEN {enabled _ on; HandleChange[]} ELSE {result _ $Failure; msg _ "Usage: FastMouse on|off"} }; ProcessProfile: UserProfile.ProfileChangedProc = TRUSTED { enableToken: ROPE _ UserProfile.Token["FastMouse.Enabled", "UNSPECIFIED"]; IF enableToken.Equal["TRUE"] THEN enabled _ TRUE ELSE IF enableToken.Equal["FALSE"] THEN enabled _ FALSE; threshold _ UserProfile.Number["FastMouse.Threshold", 2]; thresholdxTen _ threshold * 10; ampxTenX _ UserProfile.Number["FastMouse.AmpxTen", 15]; ratioYtoXxTen _ UserProfile.Number["FastMouse.RatioYtoXxTen", 10]; ampxTenY _ ampxTenX * ratioYtoXxTen / 10; speedUpLinear _ Rope.Equal[UserProfile.Token["FastMouse.SpeedUp", "linear"], "linear"]; bwOverShoot _ UserProfile.Number["Interminal.VBWEscape", 0] + 1; clrOverShoot _ UserProfile.Number["Interminal.VColorEscape", 0] + 1; IF cursorInColorDisplay THEN overShoot _ clrOverShoot ELSE overShoot _ bwOverShoot; HandleChange[]; }; HandleChange: ENTRY PROC = { shouldRun _ enabled; IF shouldRun AND NOT running THEN SELECT PrincOpsUtils.VERSION[].machineType FROM dorado => mouseProcess _ FORK DoradoMouseProcess[]; dandelion => mouseProcess _ FORK DandelionMouseProcess[]; dolphin => mouseProcess _ FORK DoradoMouseProcess[]; ENDCASE; }; ProcessMouseChange: Cursory.SetMousePositionProc ~ { IF NOT running THEN RETURN; Terminal.WaitForBWVerticalRetrace[vt]; prevPosition _ newPosition; Terminal.SetMousePosition[vt, position]; }; Init: PROC = { UserProfile.CallWhenProfileChanges[ProcessProfile]; Cursory.CallWhenMousePositionChanges[ProcessMouseChange]; Commander.Register[key: "FastMouse", proc: FastMouseCmd, doc: "Turn mouse speedup on or off"]; }; Init[]; END. XFastMouse.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Written by: CharlieLevy Revised by Randy Gobbel: 10-May-83 9:56:34 Revised by McGregor: June 24, 1983 4:54 pm Last Edited by: Beach, September 1, 1983 2:08 pm Revised by: Crow, July 8, 1986 11:48:21 am PDT for Cedar 6.1 Last Edited by: Spreitzer, November 18, 1984 4:13:53 pm PST Doug Wyatt, April 21, 1985 3:24:27 pm PST Cancel overshoot, preventing bounce when corrected by Interminal xDist, yDist, xDelta, yDelta: INTEGER; IF prevPosition = position THEN LOOP; xDelta _ position.x - prevPosition.x; yDelta _ position.y - prevPosition.y; xDist _ ABS[xDelta]; yDist _ ABS[yDelta]; IF xDist > thresholdX OR yDist > thresholdY THEN { IF speedUpLinear THEN position _ [ -- linear law speedup MAX[ MIN[ position.x + (xDelta * ampxTenX / 10), width], 0], MAX[ MIN[ position.y + (yDelta * ampxTenY / 10), height], 0] ] ELSE position _ [ -- square law speedup MAX[ MIN[ position.x + (xDelta * xDist / threshold), width], 0], MAX[ MIN[ position.y + (yDelta * yDist / threshold), height], 0] ]; Terminal.SetMousePosition[vt, position]; }; prevPosition _ position; PROC [cmd: Commander.Handle] RETURNS [result: REF ANY _ NIL, msg: ROPE _ NIL] This should wait until MouseProcess has just run since it runs at lower priority Make sure vt.MousePosition gets set before next retrace Κε˜codešœ™Kšœ Οmœ7™BKšœ™Kšœ+™+KšΟc*™*K™0Kšœ<™˜RKšŸœŸœP˜[Kšœ˜——Kšœ(˜(K˜—šœŸœŸœ%˜AKšœ@™@—KšŸœ˜ —K˜—K˜Kšœž˜—š‘œŸœž#˜DšŸœŸœ ŸœŸœ˜KšœŸœŸœ˜#Kšœ0ž,˜\Kšœ-˜-Kšœ˜Kšœ˜šŸœ Ÿ˜KšœŸœ™&Kšœ&˜&Kšœ)˜)Kšœ%™%Kšœ%™%Kšœ%™%KšœŸœ ™KšœŸœ ™šŸœŸœŸœ™2Kšœ™šœ'™'KšŸœŸœ6™>KšŸœŸœ6™>—šœ'™'KšŸœŸœ:™BKšŸœŸœ;™C—Kšœ(™(K™—Kšœ™KšŸœ˜—K˜—K˜Kšœž˜—K˜š‘ œ˜'KšŸœŸœ ŸœŸœŸœŸœŸœ™MKš œŸœŸœŸœŸœ˜(KšœŸœŸœ˜K˜šŸœŸœ Ÿœ˜KšœŸœ˜$K˜KšŸœŸœ ŸœŸ˜Kš ŸœŸœŸœŸœŸœŸœ˜:Kš ŸœŸœŸœŸœŸœŸœ˜=K˜—šŸœ˜KšŸœ˜#KšŸœ5˜9—Kšœ˜—K˜š‘œ#Ÿœ˜:Kšœ Ÿœ9˜JKšŸœŸœ ŸœŸ˜5KšŸœŸœ Ÿœ˜3Kšœ9˜9Kšœ˜Kšœ7˜7KšœB˜BKšœ)˜)KšœW˜WKšœ@˜@KšœD˜DKšŸœŸœŸœ˜SKšœ˜Kšœ˜—K˜š‘ œŸœŸœ˜Kšœ˜š Ÿœ ŸœŸœ ŸœŸœŸœŸ˜QKšœŸœ˜3KšœŸœ˜9KšœŸœ˜4KšŸœ˜—K˜—K˜š‘œ"˜4KšŸœŸœ ŸœŸœ˜šœ&˜&KšœP™P—Kšœ˜šœ(˜(Kšœ7™7—Kšœ˜K˜—š‘œŸœ˜Kšœ3˜3Kšœ9˜9K˜_Kšœ˜K˜—Kšœ˜K˜KšŸœ˜—…—#W