VirtualDesktopsImpl.mesa;
Edited by McGregor on October 26, 1982 1:12 pm
Last Edited by: Maxwell, January 21, 1983 8:56 am
DIRECTORY
Buttons USING [ButtonProc, Create],
CedarInitOps USING [Sleep],
CedarSnapshot USING [CheckpointProc, Register, RollbackProc],
ClassIncreek USING [ActionBody, GetAction, Increek, IncreekError, NewStdIncreek, SetAtLatest],
Graphics,
InputFocus USING [CaptureButtons, ReleaseButtons, SetInputFocus],
MessageWindow USING [Append],
Process USING [Abort, Pause, Seconds, SecondsToTicks],
Rope USING [Equal, ROPE],
TIPUser USING [TIPScreenCoords],
UserProfile USING [Number],
VFonts USING [defaultGFont],
ViewerClasses USING [Column, NotifyProc, Viewer],
ViewerOps,
ViewerSpecs,
VirtualDesktops,
WindowManager USING [RestoreCursor],
WindowManagerPrivate USING [rootViewerTree];
VirtualDesktopsImpl: CEDAR MONITOR
IMPORTS Buttons, CedarSnapshot, CedarInitOps, ClassIncreek,
Graphics, InputFocus, MessageWindow, Process,
Rope, UserProfile, VFonts, ViewerOps, ViewerSpecs, WindowManager, WindowManagerPrivate
EXPORTS VirtualDesktops
SHARES ViewerClasses, ViewerOps =
BEGIN OPEN ViewerClasses, VirtualDesktops;
Desktop:
TYPE =
RECORD [
tree: ARRAY Column OF Viewer ← ALL[NIL],
name: Rope.ROPE ← NIL,
centerX: INTEGER ← ViewerSpecs.openLeftWidth,
centerY: INTEGER ← ViewerSpecs.openBottomY
];
desktops: ARRAY [0..nVDesktops) OF Desktop ;
ViewerColumn:
PROC [viewer: Viewer]
RETURNS [column: Column] =
INLINE
{RETURN[IF viewer.iconic THEN static ELSE viewer.column]};
TransferViewer:
PUBLIC
PROC [viewer: Viewer, from: VirtualDesktop ← currentVDesktop, to: VirtualDesktop] =
BEGIN
v: Viewer;
column: Column ~ ViewerColumn[viewer];
current: BOOL = (desktops[from].tree=WindowManagerPrivate.rootViewerTree);
IF desktops[from].tree[column]=viewer
THEN
BEGIN
desktops[from].tree[column] ← viewer.sibling;
IF current THEN WindowManagerPrivate.rootViewerTree[column] ← viewer.sibling;
END
ELSE
FOR v ← desktops[from].tree[column], v.sibling
UNTIL v.sibling=viewer
DO
REPEAT FINISHED => v.sibling ← v.sibling.sibling;
ENDLOOP;
viewer.sibling ← NIL;
IF desktops[to].tree[column] = NIL THEN desktops[to].tree[column] ← viewer
ELSE
FOR v ← desktops[to].tree[column], v.sibling
UNTIL v.sibling=
NIL
DO
REPEAT FINISHED => v.sibling ← viewer;
ENDLOOP;
viewer.visible ← (to=currentVDesktop);
END;
FlyTo: PUBLIC ENTRY PROC [to: VirtualDesktop] = BEGIN OPEN ViewerOps;
SafeStaticXfer:
PROC =
BEGIN
s: Viewer;
v: Viewer ← WindowManagerPrivate.rootViewerTree[static];
UNTIL v=
NIL
DO
s ← v.sibling;
TransferViewer[v, currentVDesktop, to];
v ← s;
ENDLOOP;
END;
MakeVis:
PROC [v: Viewer] = {
IF v.parent = NIL OR (v.parent.visible AND ~v.parent.iconic) THEN v.visible ←
TRUE};
MakeNotVis:
PROC [v: Viewer] = {v.visible ←
FALSE};
InputFocus.SetInputFocus[];
DisablePainting;
IF to#currentVDesktop
THEN
BEGIN
desktops[currentVDesktop].tree ← WindowManagerPrivate.rootViewerTree;
desktops[currentVDesktop].centerX ← ViewerSpecs.openLeftWidth;
desktops[currentVDesktop].centerY ← ViewerSpecs.openBottomY;
SafeStaticXfer[];
WindowManagerPrivate.rootViewerTree ← desktops[to].tree;
RecursivelyEnumerate[desktops[currentVDesktop].tree[left], MakeNotVis];
RecursivelyEnumerate[desktops[currentVDesktop].tree[right], MakeNotVis];
SetCenter[desktops[to].centerX, desktops[to].centerY];
currentVDesktop ← to;
END;
RecursivelyEnumerate[desktops[to].tree[left], MakeVis];
RecursivelyEnumerate[desktops[to].tree[right], MakeVis];
RecursivelyEnumerate[desktops[to].tree[static], MakeVis];
ResetPaintCache;
EnablePainting;
PaintEverything;
MessageWindow.Append["Desktop: ", TRUE];
MessageWindow.Append[desktops[currentVDesktop].name];
WindowManager.RestoreCursor;
END;
SetCenter:
PROC [x, y:
INTEGER] =
BEGIN
OPEN ViewerSpecs;
openLeftWidth ← x;
openRightLeftX ← openLeftLeftX+openLeftWidth;
openRightWidth ← screenW-openLeftWidth;
openBottomY ← y;
END;
RecursivelyEnumerate:
PROC [top: Viewer, p:
PROC [Viewer]] =
BEGIN
FOR v: Viewer ← top, v.sibling
UNTIL v=
NIL
DO
p[v];
IF v.child#NIL THEN RecursivelyEnumerate[v.child, p];
ENDLOOP;
END;
currentVDesktop: PUBLIC VirtualDesktop ← 4; -- middle start
FlyButtonProc: Buttons.ButtonProc =
BEGIN
paintLock ← TRUE;
InputFocus.SetInputFocus[];
InputFocus.CaptureButtons[VirtualNotify, ViewerOps.FetchViewerClass[$Button].tipTable];
ViewerOps.DisablePainting;
desktops[currentVDesktop].tree ← WindowManagerPrivate.rootViewerTree; -- update since changes
VirtualDesktopDisplay;
paintLock ← FALSE;
END;
lineWidth: CARDINAL = 4;
VirtualDesktopDisplay:
PROC =
BEGIN
OPEN Graphics;
DrawViewer:
PROC [x1, y1, x2, y2:
INTEGER] =
BEGIN
myGrey: CARDINAL = 122645B;
DrawBox[context, [x1, y1, x2, y2]];
IF x1+1<x2
AND y1+1<y2
THEN
BEGIN
SetStipple[context, myGrey];
DrawBox[context, [x1+1, y1+1, x2-1, y2-1]];
SetColor[context, black];
END;
END;
x, y: INTEGER;
scale: CARDINAL = 4;
xOffset: CARDINAL = 20;
yOffset: CARDINAL = 8;
context ← NewContext[];
SetColor[context, white];
DrawBox[context, [0, 0, ViewerSpecs.screenW, ViewerSpecs.screenH]];
SetColor[context, black];
DrawBox[context, [ViewerSpecs.screenW/3, 0, ViewerSpecs.screenW/3+lineWidth,
ViewerSpecs.screenH]];
DrawBox[context, [2*ViewerSpecs.screenW/3, 0, 2*ViewerSpecs.screenW/3+lineWidth,
ViewerSpecs.screenH]];
DrawBox[context, [0, ViewerSpecs.screenH/3, ViewerSpecs.screenW,
ViewerSpecs.screenH/3+lineWidth]];
DrawBox[context, [0, 2*ViewerSpecs.screenH/3, ViewerSpecs.screenW,
2*ViewerSpecs.screenH/3+lineWidth]];
FOR d:
CARDINAL
IN [0..nVDesktops)
DO
[x, y] ← VDXY[d];
SetCP[context, x+xOffset, y+ViewerSpecs.screenH/scale+yOffset+yOffset];
DrawRope[self: context, rope: desktops[d].name, font: VFonts.defaultGFont];
FOR c: Column
IN [static..color)
DO
-- no color viewers
FOR v: Viewer ← desktops[d].tree[c], v.sibling
UNTIL v=
NIL
DO
DrawViewer[x+(v.wx/scale)+xOffset,
y+(v.wy/scale)+yOffset,
x+(v.wx/scale)+(v.ww/scale)+xOffset,
y+(v.wy/scale)+(v.wh/scale)+yOffset];
ENDLOOP;
ENDLOOP;
ENDLOOP;
END;
context: Graphics.Context;
inverted, paintLock: BOOL ← FALSE;
invertedDesktop: VirtualDesktop;
VirtualNotify: NotifyProc =
BEGIN
ENABLE UNWIND => InputFocus.ReleaseButtons[];
mouse: TIPUser.TIPScreenCoords;
IF paintLock THEN RETURN;
FOR list:
LIST
OF
REF
ANY ← input, list.rest
UNTIL list =
NIL
DO
WITH list.first
SELECT
FROM
x:
ATOM =>
SELECT x
FROM
$Hit =>
IF inverted
THEN
BEGIN
InputFocus.ReleaseButtons[];
inverted ← FALSE;
context ← NIL;
ViewerOps.EnablePainting;
FlyTo[invertedDesktop];
END;
$Mark =>
BEGIN
desktop: VirtualDesktop ← WhichDesktop[mouse];
IF inverted
THEN
BEGIN
IF invertedDesktop=desktop THEN RETURN;
InvertDesktop[invertedDesktop];
END;
InvertDesktop[invertedDesktopsktop];
inverted ← TRUE;
END;
ENDCASE => NULL; -- button junk
x: TIPUser.TIPScreenCoords => mouse ← x;
ENDCASE => NULL; -- button junk
ENDLOOP;
END;
VDXY:
PROC [desktop: VirtualDesktop]
RETURNS [x, y:
INTEGER] =
BEGIN
x ←
SELECT desktop
MOD 3
FROM
0 => 0,
1 => ViewerSpecs.screenW/3+lineWidth,
ENDCASE => ViewerSpecs.screenW/3+ViewerSpecs.screenW/3+lineWidth;
y ←
SELECT desktop/3
FROM
0 => 0,
1 => ViewerSpecs.screenH/3+lineWidth,
ENDCASE => ViewerSpecs.screenH/3+ViewerSpecs.screenH/3+lineWidth;
END;
InvertDesktop:
PROC [desktop: VirtualDesktop] =
BEGIN
OPEN Graphics;
xc, yc: INTEGER;
[xc, yc] ← VDXY[desktop];
SetColor[context, black];
[] ← SetPaintMode[context, invert];
DrawBox[context, [xc, yc,
xc+ViewerSpecs.screenW/3-(IF xc=0 THEN 0 ELSE lineWidth),
yc+ViewerSpecs.screenH/3-(IF yc=0 THEN 0 ELSE lineWidth)]];
END;
WhichDesktop:
PROC [mouse: TIPUser.TIPScreenCoords]
RETURNS [desktop: VirtualDesktop] =
BEGIN
RETURN[mouse.mouseX/(ViewerSpecs.screenW/3) + 3*(mouse.mouseY/(ViewerSpecs.screenH/3))]
END;
GetName:
PUBLIC
PROC [vd: VirtualDesktop ← currentVDesktop]
RETURNS [name: Rope.
ROPE] =
{RETURN[desktops[vd].name]};
SetName:
PUBLIC
PROC [name: Rope.
ROPE, vd: VirtualDesktop ← currentVDesktop] =
{desktops[vd].name ← name};
GetRoot:
PUBLIC
PROC [vd: VirtualDesktop ← currentVDesktop]
RETURNS [viewers: ARRAY ViewerClasses.Column OF ViewerClasses.Viewer] = BEGIN
desktops[currentVDesktop].tree ← WindowManagerPrivate.rootViewerTree;
RETURN[desktops[vd].tree];
END;
EnumerateViewers:
PUBLIC
PROC [enum: ViewerOps.EnumProc] =
BEGIN
quit: BOOLEAN ← FALSE;
desktops[currentVDesktop].tree ← WindowManagerPrivate.rootViewerTree;
FOR d:
CARDINAL
IN VirtualDesktop
UNTIL quit
DO
FOR c: Column
DECREASING
IN Column
UNTIL quit
DO
v, next: Viewer;
v ← desktops[d].tree[c];
UNTIL v=
NIL
DO
next ← v.sibling;
IF ~enum[v] THEN {quit ← TRUE; EXIT};
v ← next;
ENDLOOP;
ENDLOOP;
ENDLOOP;
END;
FindViewer:
PUBLIC
PROC [name: Rope.
ROPE]
RETURNS [viewer: Viewer, desktop: VirtualDesktop] = BEGIN
MatchName:
PROC [top: Viewer]
RETURNS [Viewer] = {
FOR v: Viewer ← top, v.sibling
UNTIL v=
NIL
DO
IF Rope.Equal[name, v.name, FALSE] THEN RETURN[v];
ENDLOOP;
RETURN[NIL];
};
desktops[currentVDesktop].tree ← WindowManagerPrivate.rootViewerTree;
FOR d:
CARDINAL
IN VirtualDesktop
DO
FOR c: Column
DECREASING
IN Column
DO
IF (viewer←MatchName[desktops[d].tree[c]])#NIL THEN RETURN [viewer, d];
ENDLOOP;
ENDLOOP;
RETURN [NIL, currentVDesktop];
END;
idleProcess: PROCESS ← NIL;
AutoIdle:
PROC =
TRUSTED BEGIN
ENABLE ANY => GOTO Punt; -- punt if bad number or ABORTED
increek: ClassIncreek.Increek;
action: ClassIncreek.ActionBody;
idleTime: Process.Seconds;
idleTime ← 60 * UserProfile.Number["AutoIdleTimeout", 20];
IF idleTime<=0 THEN RETURN;
increek ← ClassIncreek.NewStdIncreek[];
DO
-- forever
ClassIncreek.SetAtLatest[increek];
Process.Pause[Process.SecondsToTicks[idleTime]];
action ← ClassIncreek.GetAction[increek, dontWait,
----, clicksAndMotion
! ClassIncreek.IncreekError => LOOP];
WITH a: action
SELECT
FROM
timedOut => CedarInitOps.Sleep[]; -- idle
ENDCASE;
ENDLOOP;
EXITS Punt => NULL;
END;
IdleOn: CedarSnapshot.RollbackProc =
BEGIN
idleProcess ← FORK AutoIdle[];
END;
IdleOff: CedarSnapshot.CheckpointProc =
TRUSTED BEGIN
Process.Abort[idleProcess];
JOIN idleProcess;
idleProcess ← NIL;
END;
IdleProc: Buttons.ButtonProc = TRUSTED {CedarInitOps.Sleep[]};
[] ← Buttons.Create[info: [name: "Idle"], proc: IdleProc, fork:
TRUE,
documentation: "Hide desktop pending user login"];
-- [] ← Buttons.Create[info: [name: "Fly"], proc: FlyButtonProc, fork:
TRUE,
-- documentation: "Display virtual desktops"];
desktops[0].name ← "Zero";
desktops[1].name ← "One";
desktops[2].name ← "Two";
desktops[3].name ← "Three";
desktops[4].name ← "Four";
desktops[5].name ← "Five";
desktops[6].name ← "Six";
desktops[7].name ← "Seven";
desktops[8].name ← "Eight";
TRUSTED {CedarSnapshot.Register[IdleOff, IdleOn]; IdleOn[rollback]};
END.