FastMouse.mesa
Copyright © 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, May 24, 1986 6:37:12 pm 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
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];
FastMouse: CEDAR MONITOR
IMPORTS Commander, Terminal, Interminal, InterminalBackdoor, IO, Process, PrincOpsUtils, UserProfile, Rope
~ 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;
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
Process.SetPriority[Process.priorityClient3]; -- this priority is one below 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 ← position;
ENDLOOP;
};
NoteNotRunning[];
}; -- DoradoMouseProcess
DandelionMouseProcess:
PROC = {
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
xDist, yDist, xDelta, yDelta: INTEGER;
Terminal.WaitForBWVerticalRetrace[vt];
position ← Terminal.GetMousePosition[vt];
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;
ENDLOOP;
};
NoteNotRunning[];
}; -- MouseProcess
FastMouseCmd: Commander.CommandProc = {
PROC [cmd: Commander.Handle] RETURNS [result: REF ANY ← NIL, msg: ROPE ← NIL]
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;
};
Init:
PROC = {
UserProfile.CallWhenProfileChanges[ProcessProfile];
Commander.Register[key: "FastMouse", proc: FastMouseCmd,
doc: "Turn mouse speedup on or off"];
};
Init[];
END.