EndOpsImpl.mesa
Copyright © 1985, 1986 by Xerox Corporation. All rights reserved.
Doug Wyatt, April 21, 1985 4:03:53 pm PST
Russ Atkinson (RRA) April 18, 1986 3:52:53 pm PST
DIRECTORY
Buttons USING [ButtonProc, Create],
ClassIncreek USING [ActionBody, GetAction, Increek, IncreekError, NewStdIncreek, SetAtLatest],
EndOps USING [],
Idle USING [IsIdle, Sleep],
Process USING [Detach, DisableTimeout, GetCurrent, SecondsToTicks, SetTimeout],
RuntimeError USING [UNCAUGHT],
SystemVersion USING [machineType],
UserProfile USING [CallWhenProfileChanges, Number, ProfileChangedProc],
ViewerClasses USING [Viewer],
ViewerOps USING [PaintEverything],
ViewerPrivate USING [];
EndOpsImpl: CEDAR MONITOR
IMPORTS Buttons, ClassIncreek, Process, Idle, RuntimeError, SystemVersion, UserProfile, ViewerOps
EXPORTS EndOps, ViewerPrivate
= BEGIN
EndOps related stuff
ProcList: TYPE ~ LIST OF PROC;
registerHead: ProcList ← NIL;
registerTail: ProcList ← NIL;
Register: PUBLIC ENTRY PROC [proc: PROC] = {
prev: ProcList ~ registerTail;
registerTail ← LIST[proc];
IF prev=NIL THEN registerHead ← registerTail ELSE prev.rest ← registerTail;
};
ProcessEndOpsRegistry: PUBLIC PROC = {
FOR list: ProcList ← registerHead, list.rest UNTIL list = NIL DO
list.first[ ! RuntimeError.UNCAUGHT => CONTINUE];
ENDLOOP;
};
Auto-Idle stuff (formerly in ViewerProcessesImpl)
idleProcess: PROCESSNIL;
AutoIdle terminates when not running in this process.
neverEnableAutoIdle: BOOLFALSE;
To make AutoIdle ignore the profile, set this to TRUE
autoIdleCond: CONDITION;
We wait on this condition, which will either time out or cause AutoIdle to finish
NoteAutoIdleChange: ENTRY UserProfile.ProfileChangedProc = TRUSTED {
[reason: UserProfile.ProfileChangeReason]
ENABLE UNWIND => NULL;
minutes: INT ← UserProfile.Number["Viewers.AutoIdleTimeout", 20];
IF neverEnableAutoIdle THEN minutes ← 0;
SELECT minutes FROM
<= 0, >= 40 => {
Process.DisableTimeout[@autoIdleCond];
idleProcess ← NIL;
BROADCAST autoIdleCond;
};
ENDCASE => {
Process.SetTimeout[@autoIdleCond, Process.SecondsToTicks[minutes*60]];
idleProcess ← FORK AutoIdle[];
BROADCAST autoIdleCond;
};
};
AutoIdle: ENTRY PROC = TRUSTED {
ENABLE UNWIND => NULL;
increek: ClassIncreek.Increek ← ClassIncreek.NewStdIncreek[];
DO
ClassIncreek.SetAtLatest[increek];
WAIT autoIdleCond;
IF neverEnableAutoIdle THEN EXIT;
IF Process.GetCurrent[] # idleProcess THEN EXIT ELSE {
action: ClassIncreek.ActionBody ← ClassIncreek.GetAction[self: increek, waitMode: dontWait, acceptance: clicksAndMotion
! ClassIncreek.IncreekError => LOOP];
IF neverEnableAutoIdle THEN EXIT;
IF Process.GetCurrent[] = idleProcess THEN
WITH a: action SELECT FROM
timedOut => IF IdleProc # NIL THEN {
idleProcess ← NIL;
Process.Detach[FORK IdleProc[NIL]];
This will cause us to idle, and the profile changed proc will start up a new process for AutoIdle. If we called this directly, then we could lock up since NoteAutoIdleChange is an ENTRY proc. (Thanks, Doug)
RETURN;
};
ENDCASE;
};
ENDLOOP;
};
useIdleCrock: BOOLTRUE; -- can be set to FALSE to provoke the bug
IdleProcInit: Buttons.ButtonProc = {
IF NOT Idle.IsIdle[] THEN {
Idle.Sleep[];
IF useIdleCrock AND SystemVersion.machineType = dandelion THEN
RRA: February 24, 1984 12:44:23 pm PST
This crock is here to get around a bug that is probably in VM. If we do not repaint everything, trash gets left on the screen after Idle comes back. This is tied up with the special memory used for the terminal on DLions, and nowhere else. Luckily, the bug appears benign except for the screen trash.
ViewerOps.PaintEverything[];
};
};
IdleProc: Buttons.ButtonProc ← IdleProcInit;
[] ← Buttons.Create[
info: [name: "Idle"], proc: IdleProc, fork: TRUE,
documentation: "Hide desktop pending user login"];
UserProfile.CallWhenProfileChanges[NoteAutoIdleChange];
END.