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.ROPENIL,
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: BOOLFALSE;
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[invertedDesktop�sktop];
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: BOOLEANFALSE;
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: PROCESSNIL;
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.