123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- MODULE WMVNCView; (** AUTHOR "TF"; PURPOSE "VNC Viewport"; *)
- IMPORT
- Raster, Rect := WMRectangles, WMWindowManager, VNCServer, Modules, KernelLog, Commands,
- Graphics := WMGraphics, Messages := WMMessages, Strings, Texts, TextUtilities;
- TYPE
- Window = WMWindowManager.Window;
- Rectangle = Rect.Rectangle;
- String = Strings.String;
- VNCView = OBJECT (WMWindowManager.ViewPort)
- VAR
- server: VNCServer.Server;
- error:BOOLEAN;
- backbuffer* : Graphics.Image;
- c : Graphics.BufferCanvas;
- state : Graphics.CanvasState;
- navig : BOOLEAN;
- scrollLock : BOOLEAN;
- fx, fy, inffx, inffy, factor, intfactor : REAL;
- active : BOOLEAN;
- PROCEDURE &New*(manager:WMWindowManager.WindowManager; port, dx, dy, w, h:LONGINT; name, password:ARRAY OF CHAR);
- VAR str : ARRAY 16 OF CHAR;
- BEGIN
- NEW(backbuffer);
- Raster.Create(backbuffer, w, h, Raster.BGR565);
- NEW(c, backbuffer);
- c.SetFont(Graphics.GetDefaultFont());
- c.SaveState(state);
- SetExtents(w, h);
- width0 := w; height0 := h;
- range.l := dx; range.t := dy; range.r := dx + w; range.b := dy + h;
- Strings.IntToStr(port, str);
- desc := "VNC view on port "; Strings.Append(desc, str);
- factor := 1; intfactor := 1;
- fx := factor; fy := factor; inffx := 1 ; inffy := inffx;
- active := FALSE;
- server := VNCServer.OpenServer(port, backbuffer, name, password, MouseEvent, KeyEvent, ClipboardEvent, CheckActive);
- IF server # NIL THEN
- manager.AddView(SELF);
- manager.RefreshView(SELF);
- error := FALSE
- ELSE error := TRUE
- END;
- Texts.clipboard.onTextChanged.Add(ClipboardChanged)
- END New;
- PROCEDURE CheckActive(nof : LONGINT);
- BEGIN
- IF ~active & (nof > 0) THEN
- active := TRUE;
- manager.RefreshView(SELF)
- END
- END CheckActive;
- PROCEDURE Update*(r : Rectangle; top : WMWindowManager.Window);
- BEGIN
- IF ~active THEN RETURN END;
- Draw(Rect.ResizeRect(r, 1), top.prev)
- END Update;
- PROCEDURE Refresh*(top : Window);
- BEGIN
- Update(Rect.MakeRect(ENTIER(range.l)-1, ENTIER(range.t)-1, ENTIER(range.r) + 1, ENTIER(range.b) + 1), top)
- END Refresh;
- (* in wm coordinates *)
- PROCEDURE Draw(r : Rectangle; top : Window);
- VAR cur : Window;
- wr, nr : Rectangle;
- PROCEDURE InternalDraw(r : Rectangle; cur : Window);
- VAR nr, cb, tnr, dsr : Rectangle;
- BEGIN
- IF cur.useAlpha & (cur.prev # NIL) THEN Draw(r, cur.prev)
- ELSE
- WHILE cur # NIL DO (* draw r in wm coordinates in all the windows from cur to top *)
- nr := r; cb := cur.bounds; Rect.ClipRect(nr, cb);
- dsr.l := ENTIER((nr.l - range.l) * fx) ; dsr.t := ENTIER((nr.t - range.t) * fy);
- dsr.r := ENTIER((nr.r - range.l) * fx + 0.5); dsr.b := ENTIER((nr.b - range.t) * fy + 0.5);
- IF ~Rect.RectEmpty(dsr) THEN
- c.SetClipRect(dsr); (* Set clip rect to dsr, clipped at current window *)
- c.ClipRectAsNewLimits(ENTIER((cur.bounds.l - range.l) * fx), ENTIER((cur.bounds.t - range.t) * fy));
- (* range can not be factored out because of rounding *)
- IF navig THEN
- cur.Draw(c, ENTIER((cb.r - range.l)* fx) - ENTIER((cb.l - range.l) * fx),
- ENTIER((cb.b - range.t) * fy) - ENTIER((cb.t - range.t) * fy), 0);
- ELSE
- cur.Draw(c, ENTIER((cb.r - range.l)* fx) - ENTIER((cb.l - range.l) * fx),
- ENTIER((cb.b - range.t) * fy) - ENTIER((cb.t - range.t) * fy), 1);
- END;
- c.RestoreState(state);
- END;
- cur := cur.next
- END;
- tnr.l := ENTIER((r.l - range.l) * fx); tnr.t := ENTIER((r.t - range.t) * fy);
- tnr.r := ENTIER((r.r - range.l) * fx + 0.5); tnr.b := ENTIER((r.b - range.t) * fy + 0.5);
- ClipAtImage(tnr, backbuffer);
- server.AddDirty(tnr)
- END
- END InternalDraw;
- BEGIN
- cur := top;
- IF (cur # NIL) & (~Rect.RectEmpty(r)) THEN
- wr := cur.bounds;
- IF ~Rect.IsContained(wr, r) THEN
- IF Rect.Intersect(r, wr) THEN
- (* r contains wr calculate r - wr and recursively call for resulting rectangles*)
- (* calculate top rectangle *)
- IF wr.t > r.t THEN Rect.SetRect(nr, r.l, r.t, r.r, wr.t); Draw(nr, cur.prev) END;
- (* calculate bottom rectangle *)
- IF wr.b < r.b THEN Rect.SetRect(nr, r.l, wr.b, r.r, r.b); Draw(nr, cur.prev) END;
- (* calculate left rectangle *)
- IF wr.l > r.l THEN Rect.SetRect(nr, r.l, MAX(r.t, wr.t), wr.l, MIN(r.b, wr.b)); Draw(nr, cur.prev) END;
- (* calculate left rectangle *)
- IF wr.r < r.r THEN Rect.SetRect(nr, wr.r, MAX(r.t, wr.t), r.r, MIN(r.b, wr.b)); Draw(nr, cur.prev) END;
- (* calculate overlapping *)
- nr := r; Rect.ClipRect(nr, wr);
- IF ~Rect.RectEmpty(nr) THEN InternalDraw(nr, cur) END
- ELSE Draw(r, cur.prev)
- END
- ELSE InternalDraw(r, cur)
- END
- END
- END Draw;
- PROCEDURE SetExtents(w, h : LONGINT);
- BEGIN
- range.r := range.l + w; range.b := range.t + h;
- END SetExtents;
- PROCEDURE SetScaleFactor(factor : REAL);
- VAR centerX, centerY : REAL;
- BEGIN
- centerX := (range.l + range.r) / 2; centerY := (range.t + range.b) /2;
- fx := factor; fy := factor; inffx := 1 / factor; inffy := inffx;
- SELF.factor := factor;
- range.l := centerX - inffx * 0.5 * backbuffer.width;
- range.t := centerY - inffy * 0.5 * backbuffer.height;
- range.r := centerX + inffx * 0.5 * backbuffer.width;
- range.b := centerY + inffy * 0.5 * backbuffer.height
- END SetScaleFactor;
- PROCEDURE KeyEvent(ucs: LONGINT; flags : SET; keysym : LONGINT);
- VAR msg : Messages.Message;
- BEGIN
- manager.lock.AcquireWrite;
- msg.originator := SELF;
- IF keysym = 0FFC9H THEN scrollLock := ~scrollLock END;
- msg.msgType := Messages.MsgKey;
- msg.x := ucs;
- msg.y := keysym;
- msg.flags := flags;
- manager.Handle(msg);
- manager.lock.ReleaseWrite
- END KeyEvent;
- PROCEDURE MouseEvent(x, y, dz: LONGINT; keys : SET);
- VAR msg : Messages.Message;
- BEGIN
- manager.lock.AcquireWrite;
- msg.originator := SELF;
- msg.msgType := Messages.MsgPointer;
- msg.x := ENTIER(range.l + x * inffx); msg.y := ENTIER(range.t + y * inffy);
- msg.dz := dz;
- msg.flags := keys;
- IF manager # NIL THEN manager.Handle(msg) END;
- manager.lock.ReleaseWrite
- END MouseEvent;
- PROCEDURE ClipboardEvent(text : String);
- BEGIN {EXCLUSIVE}
- Texts.clipboard.onTextChanged.Remove(ClipboardChanged);
- Texts.clipboard.AcquireWrite;
- Texts.clipboard.Delete(0, Texts.clipboard.GetLength());
- TextUtilities.StrToText(Texts.clipboard, 0, text^);
- Texts.clipboard.ReleaseWrite;
- Texts.clipboard.onTextChanged.Add(ClipboardChanged)
- END ClipboardEvent;
- PROCEDURE ClipboardChanged(sender, data : ANY);
- VAR text : String;
- BEGIN {EXCLUSIVE}
- NEW(text, 16 * 1024);
- TextUtilities.TextToStr(Texts.clipboard, text^);
- IF server = NIL THEN KernelLog.String("Cann not understand how this could possibly happen :-( "); KernelLog.Ln
- ELSE
- server.SendClipboard(text)
- END
- END ClipboardChanged;
- PROCEDURE Close;
- BEGIN
- Texts.clipboard.onTextChanged.Remove(ClipboardChanged);
- manager.RemoveView(SELF); server.Close
- END Close;
- END VNCView;
- TYPE
- VVList = POINTER TO RECORD
- v:VNCView;
- next:VVList
- END;
- VAR v: VVList;
- PROCEDURE Bound(VAR x:LONGINT; min, max:LONGINT);
- BEGIN
- IF x < min THEN x := min ELSE IF x > max THEN x := max END END
- END Bound;
- PROCEDURE ClipAtImage(VAR x: Rectangle; img:Raster.Image);
- BEGIN
- Bound(x.l, 0, img.width - 1);Bound(x.r, 0, img.width - 1);
- Bound(x.t, 0, img.height - 1);Bound(x.b, 0, img.height - 1)
- END ClipAtImage;
- (** name password port x y w h
- name and password are strings optionally in " "
- use "" for no password
- *)
- PROCEDURE Install*(context : Commands.Context); (** name password [port [x [ y [ width [ height ] ] ] ] ] ~ *)
- VAR
- name:ARRAY 100 OF CHAR;
- password: ARRAY 32 OF CHAR;
- port, dx, dy, w, h:LONGINT;
- nv:VNCView;
- vl:VVList;
- BEGIN
- context.arg.SkipWhitespace;
- context.arg.String(name);
- context.arg.SkipWhitespace;
- context.arg.String(password);
- context.arg.SkipWhitespace;
- (* port *)
- port := 5901;
- IF (context.arg.Peek() >= '0') & (context.arg.Peek() <= '9') THEN context.arg.Int(port, TRUE) END;
- context.arg.SkipWhitespace;
- (* dx *)
- dx := 0;
- IF (context.arg.Peek() >= '0') & (context.arg.Peek() <= '9') OR (context.arg.Peek()='-') THEN context.arg.Int(dx, TRUE) END;
- context.arg.SkipWhitespace;
- (* dy *)
- dy := 0; IF (context.arg.Peek() >= '0') & (context.arg.Peek() <= '9') OR (context.arg.Peek()='-') THEN context.arg.Int(dy, TRUE) END;
- context.arg.SkipWhitespace;
- (* w *)
- w := 1024; IF (context.arg.Peek() >= '0') & (context.arg.Peek() <= '9') THEN context.arg.Int(w, TRUE) END;
- context.arg.SkipWhitespace;
- (* h *)
- h := 768; IF (context.arg.Peek() >= '0') & (context.arg.Peek() <= '9') THEN context.arg.Int(h, TRUE) END;
- context.arg.SkipWhitespace;
- NEW(nv, WMWindowManager.GetDefaultManager(), port, dx, dy, w, h, name, password);
- context.out.String("VNC server started. Listening on port : "); context.out.Int(port, 4);
- context.out.Ln; context.out.String("Position (x, y): "); context.out.Int(dx, 4); context.out.String(", "); context.out.Int(dy, 4);
- context.out.Ln; context.out.String("Size (w, h): "); context.out.Int(w, 4); context.out.String(", "); context.out.Int(h, 4);
- IF ~nv.error THEN
- NEW(vl); vl.v:=nv;
- vl.next:=v; v:=vl
- END;
- END Install;
- PROCEDURE Uninstall*;
- BEGIN
- WHILE v # NIL DO v.v.Close; v := v.next END;
- END Uninstall;
- PROCEDURE Cleanup;
- BEGIN
- Uninstall;
- END Cleanup;
- BEGIN
- Modules.InstallTermHandler(Cleanup)
- END WMVNCView.
- System.Free WMVNCView VNCServer~
- Aos.Call WMVNCView.Install "Bluebottle VNC View1" "" 5903 0 0 1024 768~
- Aos.Call WMVNCView.Install "Bluebottle VNC View1" "" 5902 1280 0 1280 1024~
- Aos.Call WMVNCView.Install "Bluebottle VNC View1" "" 5903 0 0 1024 768~
- Aos.Call WMVNCView.Uninstall (BYE)
|