aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/devdraw
diff options
context:
space:
mode:
authorRuss Cox <rsc@swtch.com>2020-01-11 06:10:14 -0500
committerRuss Cox <rsc@swtch.com>2020-01-13 16:46:14 -0500
commit892b3c4687eacf6b090bb9a5196ce882e113c423 (patch)
tree759c84ea734f8ffeb9e596680bd71d8a0cae1a77 /src/cmd/devdraw
parent2cb85891ba58a83263ef30dc9799d1fda9fb71af (diff)
downloadplan9port-892b3c4687eacf6b090bb9a5196ce882e113c423.tar.gz
plan9port-892b3c4687eacf6b090bb9a5196ce882e113c423.tar.bz2
plan9port-892b3c4687eacf6b090bb9a5196ce882e113c423.zip
devdraw: multiclient mode
Diffstat (limited to 'src/cmd/devdraw')
-rw-r--r--src/cmd/devdraw/devdraw.h3
-rw-r--r--src/cmd/devdraw/mac-screen.m15
-rw-r--r--src/cmd/devdraw/srv.c139
3 files changed, 115 insertions, 42 deletions
diff --git a/src/cmd/devdraw/devdraw.h b/src/cmd/devdraw/devdraw.h
index dd7fc8ba..06ce4f8a 100644
--- a/src/cmd/devdraw/devdraw.h
+++ b/src/cmd/devdraw/devdraw.h
@@ -54,6 +54,8 @@ struct Client
uchar* mbuf;
int nmbuf;
+ char* wsysid;
+
// drawlk protects the draw data structures.
// It can be acquired by an RPC thread or a graphics thread
// but must not be held on one thread while waiting for the other.
@@ -219,3 +221,4 @@ int latin1(Rune*, int);
int mouseswap(int);
int parsewinsize(char*, Rectangle*, int*);
+extern Client *client0; // set in single-client mode
diff --git a/src/cmd/devdraw/mac-screen.m b/src/cmd/devdraw/mac-screen.m
index 2ce6bb34..b3a21101 100644
--- a/src/cmd/devdraw/mac-screen.m
+++ b/src/cmd/devdraw/mac-screen.m
@@ -30,6 +30,8 @@ AUTOFRAMEWORK(QuartzCore)
#define LOG if(0)NSLog
+// TODO: Maintain list of views for dock menu.
+
static void setprocname(const char*);
static uint keycvt(uint);
static uint msec(void);
@@ -45,7 +47,8 @@ static AppDelegate *myApp = NULL;
void
gfx_main(void)
{
- setprocname(argv0);
+ if(client0)
+ setprocname(argv0);
@autoreleasepool{
[NSApplication sharedApplication];
@@ -99,7 +102,7 @@ rpc_shutdown(void)
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication {
- return YES;
+ return client0 != nil;
}
@end
@@ -232,10 +235,7 @@ rpc_attach(Client *c, char *label, char *winsize)
r = [[NSScreen mainScreen] visibleFrame];
LOG(@"makewin(%s)", s);
- if(s && *s){
- if(parsewinsize(s, &wr, &set) < 0)
- sysfatal("%r");
- }else{
+ if(s == nil || *s == '\0' || parsewinsize(s, &wr, &set) < 0) {
wr = Rect(0, 0, sr.size.width*2/3, sr.size.height*2/3);
set = 0;
}
@@ -344,7 +344,8 @@ rpc_setlabel(Client *client, char *label)
@autoreleasepool{
NSString *s = [[NSString alloc] initWithUTF8String:label];
[self.win setTitle:s];
- [[NSApp dockTile] setBadgeLabel:s]; // TODO: Not with multiple windows
+ if(client0)
+ [[NSApp dockTile] setBadgeLabel:s];
}
}
diff --git a/src/cmd/devdraw/srv.c b/src/cmd/devdraw/srv.c
index 5169c113..23422ad6 100644
--- a/src/cmd/devdraw/srv.c
+++ b/src/cmd/devdraw/srv.c
@@ -18,10 +18,14 @@ static void runmsg(Client*, Wsysmsg*);
static void replymsg(Client*, Wsysmsg*);
static void matchkbd(Client*);
static void matchmouse(Client*);
-static void serve(void*);
-static Client *client0;
+static void serveproc(void*);
+static void listenproc(void*);
+Client *client0;
int trace = 0;
+static char *srvname;
+static int afd;
+static char adir[40];
static void
usage(void)
@@ -33,17 +37,6 @@ usage(void)
void
threadmain(int argc, char **argv)
{
- /*
- * Move the protocol off stdin/stdout so that
- * any inadvertent prints don't screw things up.
- */
- dup(0,3);
- dup(1,4);
- close(0);
- close(1);
- open("/dev/null", OREAD);
- open("/dev/null", OWRITE);
-
ARGBEGIN{
case 'D': /* for good ps -a listings */
break;
@@ -51,32 +44,89 @@ threadmain(int argc, char **argv)
case 'g':
case 'b':
break;
+ case 's':
+ // TODO: Update usage, man page.
+ srvname = EARGF(usage());
+ break;
default:
usage();
}ARGEND
- fmtinstall('W', drawfcallfmt);
+ if(srvname == nil) {
+ client0 = mallocz(sizeof(Client), 1);
+ if(client0 == nil){
+ fprint(2, "initdraw: allocating client0: out of memory");
+ abort();
+ }
+ client0->displaydpi = 100;
+ client0->rfd = 3;
+ client0->wfd = 4;
- client0 = mallocz(sizeof(Client), 1);
- if(client0 == nil){
- fprint(2, "initdraw: allocating client0: out of memory");
- abort();
+ /*
+ * Move the protocol off stdin/stdout so that
+ * any inadvertent prints don't screw things up.
+ */
+ dup(0,3);
+ dup(1,4);
+ close(0);
+ close(1);
+ open("/dev/null", OREAD);
+ open("/dev/null", OWRITE);
}
- client0->displaydpi = 100;
- client0->rfd = 3;
- client0->wfd = 4;
+ fmtinstall('W', drawfcallfmt);
gfx_main();
}
void
gfx_started(void)
{
- proccreate(serve, client0, 0);
+ char *addr;
+
+ if(srvname == nil) {
+ // Legacy mode: serving single client on pipes.
+ proccreate(serveproc, client0, 0);
+ return;
+ }
+
+ // Server mode.
+ addr = smprint("unix!%s/%s", getns(), srvname);
+ if(addr == nil)
+ sysfatal("out of memory");
+
+ if((afd = announce(addr, adir)) < 0)
+ sysfatal("announce %s: %r", addr);
+
+ proccreate(listenproc, nil, 0);
+}
+
+static void
+listenproc(void *v)
+{
+ Client *c;
+ int fd;
+ char dir[40];
+
+ USED(v);
+
+ for(;;) {
+ fd = listen(adir, dir);
+ if(fd < 0)
+ sysfatal("listen: %r");
+ c = mallocz(sizeof(Client), 1);
+ if(c == nil){
+ fprint(2, "initdraw: allocating client0: out of memory");
+ abort();
+ }
+ c->displaydpi = 100;
+ c->rfd = fd;
+ c->wfd = fd;
+ proccreate(serveproc, c, 0);
+ }
}
static void
-serve(void *v)
+serveproc(void *v)
{
Client *c;
uchar buf[4], *mbuf;
@@ -92,23 +142,29 @@ serve(void *v)
free(mbuf);
mbuf = malloc(4+n);
if(mbuf == nil)
- sysfatal("malloc: %r");
+ sysfatal("out of memory");
nmbuf = n;
}
memmove(mbuf, buf, 4);
nn = readn(c->rfd, mbuf+4, n-4);
- if(nn != n-4)
- sysfatal("eof during message");
+ if(nn != n-4) {
+ fprint(2, "serveproc: eof during message\n");
+ break;
+ }
/* pick off messages one by one */
- if(convM2W(mbuf, nn+4, &m) <= 0)
- sysfatal("cannot convert message");
+ if(convM2W(mbuf, nn+4, &m) <= 0) {
+ fprint(2, "serveproc: cannot convert message\n");
+ break;
+ }
if(trace) fprint(2, "%ud [%d] <- %W\n", nsec()/1000000, threadid(), &m);
runmsg(c, &m);
}
- rpc_shutdown();
- threadexitsall(nil);
+ if(c == client0) {
+ rpc_shutdown();
+ threadexitsall(nil);
+ }
}
static void
@@ -134,6 +190,11 @@ runmsg(Client *c, Wsysmsg *m)
Memimage *i;
switch(m->type){
+ case Tctxt:
+ c->wsysid = strdup(m->id);
+ replymsg(c, m);
+ break;
+
case Tinit:
memimageinit();
i = rpc_attach(c, m->label, m->winsize);
@@ -143,11 +204,15 @@ runmsg(Client *c, Wsysmsg *m)
case Trdmouse:
qlock(&c->eventlk);
+ if((c->mousetags.wi+1)%nelem(c->mousetags.t) == c->mousetags.ri) {
+ qunlock(&c->eventlk);
+ werrstr("too many queued mouse reads");
+ replyerror(c, m);
+ break;
+ }
c->mousetags.t[c->mousetags.wi++] = m->tag;
if(c->mousetags.wi == nelem(c->mousetags.t))
c->mousetags.wi = 0;
- if(c->mousetags.wi == c->mousetags.ri)
- sysfatal("too many queued mouse reads");
c->mouse.stall = 0;
matchmouse(c);
qunlock(&c->eventlk);
@@ -155,11 +220,15 @@ runmsg(Client *c, Wsysmsg *m)
case Trdkbd:
qlock(&c->eventlk);
+ if((c->kbdtags.wi+1)%nelem(c->kbdtags.t) == c->kbdtags.ri) {
+ qunlock(&c->eventlk);
+ werrstr("too many queued keyboard reads");
+ replyerror(c, m);
+ break;
+ }
c->kbdtags.t[c->kbdtags.wi++] = m->tag;
if(c->kbdtags.wi == nelem(c->kbdtags.t))
c->kbdtags.wi = 0;
- if(c->kbdtags.wi == c->kbdtags.ri)
- sysfatal("too many queued keyboard reads");
c->kbd.stall = 0;
matchkbd(c);
qunlock(&c->eventlk);
@@ -268,7 +337,7 @@ replymsg(Client *c, Wsysmsg *m)
}
convW2M(m, c->mbuf, n);
if(write(c->wfd, c->mbuf, n) != n)
- sysfatal("write: %r");
+ fprint(2, "client write: %r\n");
qunlock(&c->wfdlk);
}