diff options
Diffstat (limited to 'appl/wm/drawmux/dmview.b')
| -rw-r--r-- | appl/wm/drawmux/dmview.b | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/appl/wm/drawmux/dmview.b b/appl/wm/drawmux/dmview.b new file mode 100644 index 00000000..92fdaa2d --- /dev/null +++ b/appl/wm/drawmux/dmview.b @@ -0,0 +1,163 @@ +implement DMView; + +include "sys.m"; +include "draw.m"; +include "tk.m"; +include "tkclient.m"; + +DMView : module { + init : fn (ctxt : ref Draw->Context, args : list of string); +}; + +DMPORT : con 9998; + +sys : Sys; +draw : Draw; +tk : Tk; +tkclient : Tkclient; + +Display, Image, Screen, Point, Rect, Chans : import draw; + +display : ref Display; +screen : ref Screen; + + +init(ctxt : ref Draw->Context, args : list of string) +{ + sys = load Sys Sys->PATH; + draw = load Draw Draw->PATH; + tk = load Tk Tk->PATH; + if (tk == nil) + fail(sys->sprint("cannot load %s: %r", Tk->PATH), "init"); + + tkclient = load Tkclient Tkclient->PATH; + if (tkclient == nil) + fail(sys->sprint("cannot load %s: %r", Tkclient->PATH), "init"); + + args = tl args; + if (args == nil) + fail("usage: dmview netaddr", "usage"); + addr := hd args; + args = tl args; + + display = ctxt.display; + screen = ctxt.screen; + + tkclient ->init(); + + (ok, nc) := sys->dial("tcp!"+addr+"!" + string DMPORT, nil); + if (ok < 0) + fail(sys->sprint("could not connect: %r"), "init"); + + info := array [2 * 12] of byte; + if (sys->read(nc.dfd, info, len info) != len info) { + sys->print("protocol error\n"); + return; + } + dispw := int string info[0:12]; + disph := int string info[12:24]; + info = nil; + + (tktop, wmctl) := tkclient->toplevel(ctxt, "", "dmview: "+addr, Tkclient->Hide); + if (tktop == nil) + fail("cannot create window", "init"); + + cpos := mkframe(tktop, dispw, disph); + winr := Rect((0, 0), (dispw, disph)); + newwin := display.newimage(winr, display.image.chans, 0, Draw->White); + # newwin := screen.newwindow(winr, Draw->Refbackup, Draw->White); + if (newwin == nil) { + sys->print("failed to create window: %r\n"); + return; + } + tk->putimage(tktop, ".c", newwin, nil); + tk->cmd(tktop, ".c dirty"); + tk->cmd(tktop, "update"); + winr = winr.addpt(cpos); + newwin.origin(Point(0,0), winr.min); + + pubscr := Screen.allocate(newwin, ctxt.display.black, 1); + if (pubscr == nil) { + sys->print("failed to create public screen: %r\n"); + return; + } + + msg := array of byte sys->sprint("%11d %11s ", pubscr.id, newwin.chans.text()); + sys->write(nc.dfd, msg, len msg); + msg = nil; + + pidc := chan of int; + spawn srv(nc.dfd, wmctl, pidc); + srvpid := <- pidc; + + tkclient->onscreen(tktop, nil); + tkclient->startinput(tktop, nil); + + for (;;) { + cmd := <- wmctl; + case cmd { + "srvexit" => +sys->print("srv exit: %r\n"); + srvpid = -1; + "exit" => + if (srvpid != -1) + kill(srvpid); + return; + "move" => + newwin.origin(Point(0,0), display.image.r.max); + tkclient->wmctl(tktop, cmd); + x := int tk->cmd(tktop, ".c cget -actx"); + y := int tk->cmd(tktop, ".c cget -acty"); + newwin.origin(Point(0,0), Point(x, y)); + "task" => + newwin.origin(Point(0,0), display.image.r.max); + tkclient->wmctl(tktop, cmd); + x := int tk->cmd(tktop, ".c cget -actx"); + y := int tk->cmd(tktop, ".c cget -acty"); + newwin.origin(Point(0,0), Point(x, y)); + * => + tkclient->wmctl(tktop, cmd); + } + } +} + +srv(fd : ref Sys->FD, done : chan of string, pidc : chan of int) +{ + pidc <-= sys->pctl(Sys->FORKNS, nil); + sys->bind("/dev/draw", "/", Sys->MREPL); + sys->export(fd, "/", Sys->EXPWAIT); + done <-= "srvexit"; +} + +fail(msg, exc : string) +{ + sys->print("%s\n", msg); + raise "fail:"+exc; +} + +mkframe(t : ref Tk->Toplevel, w, h : int) : Point +{ + tk->cmd(t, "panel .c -width " + string w + " -height " + string h); + tk->cmd(t, "frame .f -borderwidth 3 -relief groove"); + tk->cmd(t, "pack .c -in .f"); + tk->cmd(t, "pack .f"); + tk->cmd(t, "update"); + + x := int tk->cmd(t, ".c cget -actx"); + y := int tk->cmd(t, ".c cget -acty"); + + return Point(x, y); +} + +kill(pid: int) +{ + if ((pctl := sys->open("/prog/" + string pid + "/ctl", Sys->OWRITE)) != nil) + sys->fprint(pctl, "kill"); +} + +tkcmd(t : ref Tk->Toplevel, c : string) +{ + s := tk->cmd(t, c); + if (s != nil) + sys->print("%s ERROR: %s\n", c, s); +} |
