xref: /inferno-os/appl/wm/drawmux/dmview.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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