1implement DMView; 2 3include "sys.m"; 4include "draw.m"; 5include "tk.m"; 6include "tkclient.m"; 7 8DMView : module { 9 init : fn (ctxt : ref Draw->Context, args : list of string); 10}; 11 12DMPORT : con 9998; 13 14sys : Sys; 15draw : Draw; 16tk : Tk; 17tkclient : Tkclient; 18 19Display, Image, Screen, Point, Rect, Chans : import draw; 20 21display : ref Display; 22screen : ref Screen; 23 24 25init(ctxt : ref Draw->Context, args : list of string) 26{ 27 sys = load Sys Sys->PATH; 28 draw = load Draw Draw->PATH; 29 tk = load Tk Tk->PATH; 30 if (tk == nil) 31 fail(sys->sprint("cannot load %s: %r", Tk->PATH), "init"); 32 33 tkclient = load Tkclient Tkclient->PATH; 34 if (tkclient == nil) 35 fail(sys->sprint("cannot load %s: %r", Tkclient->PATH), "init"); 36 37 args = tl args; 38 if (args == nil) 39 fail("usage: dmview netaddr", "usage"); 40 addr := hd args; 41 args = tl args; 42 43 display = ctxt.display; 44 screen = ctxt.screen; 45 46 tkclient ->init(); 47 48 (ok, nc) := sys->dial("tcp!"+addr+"!" + string DMPORT, nil); 49 if (ok < 0) 50 fail(sys->sprint("could not connect: %r"), "init"); 51 52 info := array [2 * 12] of byte; 53 if (sys->read(nc.dfd, info, len info) != len info) { 54 sys->print("protocol error\n"); 55 return; 56 } 57 dispw := int string info[0:12]; 58 disph := int string info[12:24]; 59 info = nil; 60 61 (tktop, wmctl) := tkclient->toplevel(ctxt, "", "dmview: "+addr, Tkclient->Hide); 62 if (tktop == nil) 63 fail("cannot create window", "init"); 64 65 cpos := mkframe(tktop, dispw, disph); 66 winr := Rect((0, 0), (dispw, disph)); 67 newwin := display.newimage(winr, display.image.chans, 0, Draw->White); 68 # newwin := screen.newwindow(winr, Draw->Refbackup, Draw->White); 69 if (newwin == nil) { 70 sys->print("failed to create window: %r\n"); 71 return; 72 } 73 tk->putimage(tktop, ".c", newwin, nil); 74 tk->cmd(tktop, ".c dirty"); 75 tk->cmd(tktop, "update"); 76 winr = winr.addpt(cpos); 77 newwin.origin(Point(0,0), winr.min); 78 79 pubscr := Screen.allocate(newwin, ctxt.display.black, 1); 80 if (pubscr == nil) { 81 sys->print("failed to create public screen: %r\n"); 82 return; 83 } 84 85 msg := array of byte sys->sprint("%11d %11s ", pubscr.id, newwin.chans.text()); 86 sys->write(nc.dfd, msg, len msg); 87 msg = nil; 88 89 pidc := chan of int; 90 spawn srv(nc.dfd, wmctl, pidc); 91 srvpid := <- pidc; 92 93 tkclient->onscreen(tktop, nil); 94 tkclient->startinput(tktop, nil); 95 96 for (;;) { 97 cmd := <- wmctl; 98 case cmd { 99 "srvexit" => 100sys->print("srv exit: %r\n"); 101 srvpid = -1; 102 "exit" => 103 if (srvpid != -1) 104 kill(srvpid); 105 return; 106 "move" => 107 newwin.origin(Point(0,0), display.image.r.max); 108 tkclient->wmctl(tktop, cmd); 109 x := int tk->cmd(tktop, ".c cget -actx"); 110 y := int tk->cmd(tktop, ".c cget -acty"); 111 newwin.origin(Point(0,0), Point(x, y)); 112 "task" => 113 newwin.origin(Point(0,0), display.image.r.max); 114 tkclient->wmctl(tktop, cmd); 115 x := int tk->cmd(tktop, ".c cget -actx"); 116 y := int tk->cmd(tktop, ".c cget -acty"); 117 newwin.origin(Point(0,0), Point(x, y)); 118 * => 119 tkclient->wmctl(tktop, cmd); 120 } 121 } 122} 123 124srv(fd : ref Sys->FD, done : chan of string, pidc : chan of int) 125{ 126 pidc <-= sys->pctl(Sys->FORKNS, nil); 127 sys->bind("/dev/draw", "/", Sys->MREPL); 128 sys->export(fd, "/", Sys->EXPWAIT); 129 done <-= "srvexit"; 130} 131 132fail(msg, exc : string) 133{ 134 sys->print("%s\n", msg); 135 raise "fail:"+exc; 136} 137 138mkframe(t : ref Tk->Toplevel, w, h : int) : Point 139{ 140 tk->cmd(t, "panel .c -width " + string w + " -height " + string h); 141 tk->cmd(t, "frame .f -borderwidth 3 -relief groove"); 142 tk->cmd(t, "pack .c -in .f"); 143 tk->cmd(t, "pack .f"); 144 tk->cmd(t, "update"); 145 146 x := int tk->cmd(t, ".c cget -actx"); 147 y := int tk->cmd(t, ".c cget -acty"); 148 149 return Point(x, y); 150} 151 152kill(pid: int) 153{ 154 if ((pctl := sys->open("/prog/" + string pid + "/ctl", Sys->OWRITE)) != nil) 155 sys->fprint(pctl, "kill"); 156} 157 158tkcmd(t : ref Tk->Toplevel, c : string) 159{ 160 s := tk->cmd(t, c); 161 if (s != nil) 162 sys->print("%s ERROR: %s\n", c, s); 163} 164