summaryrefslogtreecommitdiff
path: root/appl/wm/drawmux/dmwm.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/wm/drawmux/dmwm.b')
-rw-r--r--appl/wm/drawmux/dmwm.b207
1 files changed, 207 insertions, 0 deletions
diff --git a/appl/wm/drawmux/dmwm.b b/appl/wm/drawmux/dmwm.b
new file mode 100644
index 00000000..45d80f8a
--- /dev/null
+++ b/appl/wm/drawmux/dmwm.b
@@ -0,0 +1,207 @@
+implement Dmwm;
+include "sys.m";
+ sys: Sys;
+include "draw.m";
+ draw: Draw;
+ Screen, Display, Image, Rect, Point, Wmcontext, Pointer: import draw;
+include "drawmux.m";
+ dmux : Drawmux;
+include "wmsrv.m";
+ wmsrv: Wmsrv;
+ Window, Client: import wmsrv;
+include "tk.m";
+include "wmclient.m";
+ wmclient: Wmclient;
+include "string.m";
+ str: String;
+include "dialog.m";
+ dialog: Dialog;
+include "arg.m";
+
+Wm: module {
+ init: fn(ctxt: ref Draw->Context, argv: list of string);
+};
+
+Dmwm: module {
+ init: fn(ctxt: ref Draw->Context, argv: list of string);
+};
+
+Background: con int 16r777777FF;
+
+screen: ref Screen;
+display: ref Display;
+
+badmodule(p: string)
+{
+ sys->fprint(sys->fildes(2), "wm: cannot load %s: %r\n", p);
+ raise "fail:bad module";
+}
+
+init(ctxt: ref Draw->Context, argv: list of string)
+{
+ sys = load Sys Sys->PATH;
+ draw = load Draw Draw->PATH;
+ if(draw == nil)
+ badmodule(Draw->PATH);
+
+ str = load String String->PATH;
+ if(str == nil)
+ badmodule(String->PATH);
+
+ wmsrv = load Wmsrv Wmsrv->PATH;
+ if(wmsrv == nil)
+ badmodule(Wmsrv->PATH);
+
+ wmclient = load Wmclient Wmclient->PATH;
+ if(wmclient == nil)
+ badmodule(Wmclient->PATH);
+ wmclient->init();
+
+ dialog = load Dialog Dialog->PATH;
+ if (dialog == nil) badmodule(Dialog->PATH);
+ dialog->init();
+
+ sys->pctl(Sys->NEWPGRP|Sys->FORKNS, nil);
+ if (ctxt == nil)
+ ctxt = wmclient->makedrawcontext();
+ display = ctxt.display;
+
+ dmux = load Drawmux Drawmux->PATH;
+ if (dmux != nil) {
+ (err, disp) := dmux->init();
+ if (err != nil) {
+ dmux = nil;
+ sys->fprint(stderr(), "wm: cannot start drawmux: %s\n", err);
+ }
+ else
+ display = disp;
+ }
+
+ buts := Wmclient->Appl;
+ if(ctxt.wm == nil)
+ buts = Wmclient->Plain;
+ # win := wmclient->window(ctxt, "Wm", buts);
+ # wmclient->win.onscreen("place");
+ # wmclient->win.startinput("kbd" :: "ptr" :: nil);
+
+ # screen = makescreen(win.image);
+
+ (clientwm, join, req) := wmsrv->init();
+ clientctxt := ref Draw->Context(display, nil, nil);
+
+ sync := chan of string;
+ argv = tl argv;
+ if(argv == nil)
+ argv = "wm/toolbar" :: nil;
+ argv = "wm/wm" :: argv;
+ spawn command(clientctxt, argv, sync);
+ if((e := <-sync) != nil)
+ fatal("cannot run command: " + e);
+
+ dmuxrequest := chan of (string, ref Sys->FD);
+ if (dmux != nil)
+ spawn dmuxlistener(dmuxrequest);
+
+ for(;;) alt {
+ (name, fd) := <- dmuxrequest =>
+ spawn dmuxask(ctxt, name, fd);
+ }
+}
+
+makescreen(img: ref Image): ref Screen
+{
+ screen = Screen.allocate(img, img.display.color(Background), 0);
+ img.draw(img.r, screen.fill, nil, screen.fill.r.min);
+ return screen;
+}
+
+kill(pid: int, note: string): int
+{
+ fd := sys->open("/prog/"+string pid+"/ctl", Sys->OWRITE);
+ if(fd == nil || sys->fprint(fd, "%s", note) < 0)
+ return -1;
+ return 0;
+}
+
+fatal(s: string)
+{
+ sys->fprint(sys->fildes(2), "wm: %s\n", s);
+ kill(sys->pctl(0, nil), "killgrp");
+ raise "fail:error";
+}
+
+command(ctxt: ref Draw->Context, args: list of string, sync: chan of string)
+{
+ fds := list of {0, 1, 2};
+ pid := sys->pctl(sys->NEWFD, fds);
+
+ cmd := hd args;
+ file := cmd;
+
+ if(len file<4 || file[len file-4:]!=".dis")
+ file += ".dis";
+
+ c := load Wm file;
+ if(c == nil) {
+ err := sys->sprint("%r");
+ if(err != "permission denied" && err != "access permission denied" && file[0]!='/' && file[0:2]!="./"){
+ c = load Wm "/dis/"+file;
+ if(c == nil)
+ err = sys->sprint("%r");
+ }
+ if(c == nil){
+ sync <-= sys->sprint("%s: %s\n", cmd, err);
+ exit;
+ }
+ }
+ sync <-= nil;
+ c->init(ctxt, args);
+}
+
+dmuxlistener(newclient : chan of (string, ref Sys->FD))
+{
+ (aok, c) := sys->announce("tcp!*!9998");
+ if (aok < 0) {
+ sys->print("cannot announce drawmux port: %r\n");
+ return;
+ }
+ buf := array [Sys->ATOMICIO] of byte;
+ for (;;) {
+ (ok, nc) := sys->listen(c);
+ if (ok < 0) {
+ sys->fprint(stderr(), "wm: dmux listen failed: %r\n");
+ return;
+ }
+ fd := sys->open(nc.dir+"/remote", Sys->OREAD);
+ name := "unknown";
+ if (fd == nil)
+ sys->fprint(stderr(), "wm: dmux cannot access remote address: %r\n");
+ else {
+ n := sys->read(fd, buf, len buf);
+ if (n > 0) {
+ name = string buf[0:n];
+ for (i := len name -1; i > 0; i--)
+ if (name[i] == '!')
+ break;
+ if (i != 0)
+ name = name[0:i];
+ }
+ }
+ fd = sys->open(nc.dir+"/data", Sys->ORDWR);
+ if (fd != nil)
+ newclient <-= (name, fd);
+ }
+}
+
+dmuxask(ctxt: ref Draw->Context, name : string, fd : ref Sys->FD)
+{
+ msg := sys->sprint("Screen snoop request\nAddress: %s\n\nProceed?", name);
+ labs := "Ok" :: "No way!" :: nil;
+ if (1 || dialog->prompt(ctxt, nil, nil, "Snoop!", msg, 1, labs) == 0)
+ dmux->newviewer(fd);
+}
+
+stderr(): ref Sys->FD
+{
+ return sys->fildes(2);
+}