devdraw: multiclient mode

This commit is contained in:
Russ Cox 2020-01-11 06:10:14 -05:00
parent 2cb85891ba
commit 892b3c4687
3 changed files with 115 additions and 42 deletions

View file

@ -54,6 +54,8 @@ struct Client
uchar* mbuf; uchar* mbuf;
int nmbuf; int nmbuf;
char* wsysid;
// drawlk protects the draw data structures. // drawlk protects the draw data structures.
// It can be acquired by an RPC thread or a graphics thread // 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. // 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 mouseswap(int);
int parsewinsize(char*, Rectangle*, int*); int parsewinsize(char*, Rectangle*, int*);
extern Client *client0; // set in single-client mode

View file

@ -30,6 +30,8 @@ AUTOFRAMEWORK(QuartzCore)
#define LOG if(0)NSLog #define LOG if(0)NSLog
// TODO: Maintain list of views for dock menu.
static void setprocname(const char*); static void setprocname(const char*);
static uint keycvt(uint); static uint keycvt(uint);
static uint msec(void); static uint msec(void);
@ -45,6 +47,7 @@ static AppDelegate *myApp = NULL;
void void
gfx_main(void) gfx_main(void)
{ {
if(client0)
setprocname(argv0); setprocname(argv0);
@autoreleasepool{ @autoreleasepool{
@ -99,7 +102,7 @@ rpc_shutdown(void)
} }
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication { - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication {
return YES; return client0 != nil;
} }
@end @end
@ -232,10 +235,7 @@ rpc_attach(Client *c, char *label, char *winsize)
r = [[NSScreen mainScreen] visibleFrame]; r = [[NSScreen mainScreen] visibleFrame];
LOG(@"makewin(%s)", s); LOG(@"makewin(%s)", s);
if(s && *s){ if(s == nil || *s == '\0' || parsewinsize(s, &wr, &set) < 0) {
if(parsewinsize(s, &wr, &set) < 0)
sysfatal("%r");
}else{
wr = Rect(0, 0, sr.size.width*2/3, sr.size.height*2/3); wr = Rect(0, 0, sr.size.width*2/3, sr.size.height*2/3);
set = 0; set = 0;
} }
@ -344,7 +344,8 @@ rpc_setlabel(Client *client, char *label)
@autoreleasepool{ @autoreleasepool{
NSString *s = [[NSString alloc] initWithUTF8String:label]; NSString *s = [[NSString alloc] initWithUTF8String:label];
[self.win setTitle:s]; [self.win setTitle:s];
[[NSApp dockTile] setBadgeLabel:s]; // TODO: Not with multiple windows if(client0)
[[NSApp dockTile] setBadgeLabel:s];
} }
} }

View file

@ -18,10 +18,14 @@ static void runmsg(Client*, Wsysmsg*);
static void replymsg(Client*, Wsysmsg*); static void replymsg(Client*, Wsysmsg*);
static void matchkbd(Client*); static void matchkbd(Client*);
static void matchmouse(Client*); static void matchmouse(Client*);
static void serve(void*); static void serveproc(void*);
static Client *client0; static void listenproc(void*);
Client *client0;
int trace = 0; int trace = 0;
static char *srvname;
static int afd;
static char adir[40];
static void static void
usage(void) usage(void)
@ -33,6 +37,31 @@ usage(void)
void void
threadmain(int argc, char **argv) threadmain(int argc, char **argv)
{ {
ARGBEGIN{
case 'D': /* for good ps -a listings */
break;
case 'f': /* fall through for backward compatibility */
case 'g':
case 'b':
break;
case 's':
// TODO: Update usage, man page.
srvname = EARGF(usage());
break;
default:
usage();
}ARGEND
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;
/* /*
* Move the protocol off stdin/stdout so that * Move the protocol off stdin/stdout so that
* any inadvertent prints don't screw things up. * any inadvertent prints don't screw things up.
@ -43,40 +72,61 @@ threadmain(int argc, char **argv)
close(1); close(1);
open("/dev/null", OREAD); open("/dev/null", OREAD);
open("/dev/null", OWRITE); open("/dev/null", OWRITE);
}
ARGBEGIN{
case 'D': /* for good ps -a listings */
break;
case 'f': /* fall through for backward compatibility */
case 'g':
case 'b':
break;
default:
usage();
}ARGEND
fmtinstall('W', drawfcallfmt); fmtinstall('W', drawfcallfmt);
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;
gfx_main(); gfx_main();
} }
void void
gfx_started(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 static void
serve(void *v) 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
serveproc(void *v)
{ {
Client *c; Client *c;
uchar buf[4], *mbuf; uchar buf[4], *mbuf;
@ -92,24 +142,30 @@ serve(void *v)
free(mbuf); free(mbuf);
mbuf = malloc(4+n); mbuf = malloc(4+n);
if(mbuf == nil) if(mbuf == nil)
sysfatal("malloc: %r"); sysfatal("out of memory");
nmbuf = n; nmbuf = n;
} }
memmove(mbuf, buf, 4); memmove(mbuf, buf, 4);
nn = readn(c->rfd, mbuf+4, n-4); nn = readn(c->rfd, mbuf+4, n-4);
if(nn != n-4) if(nn != n-4) {
sysfatal("eof during message"); fprint(2, "serveproc: eof during message\n");
break;
}
/* pick off messages one by one */ /* pick off messages one by one */
if(convM2W(mbuf, nn+4, &m) <= 0) if(convM2W(mbuf, nn+4, &m) <= 0) {
sysfatal("cannot convert message"); fprint(2, "serveproc: cannot convert message\n");
break;
}
if(trace) fprint(2, "%ud [%d] <- %W\n", nsec()/1000000, threadid(), &m); if(trace) fprint(2, "%ud [%d] <- %W\n", nsec()/1000000, threadid(), &m);
runmsg(c, &m); runmsg(c, &m);
} }
if(c == client0) {
rpc_shutdown(); rpc_shutdown();
threadexitsall(nil); threadexitsall(nil);
} }
}
static void static void
replyerror(Client *c, Wsysmsg *m) replyerror(Client *c, Wsysmsg *m)
@ -134,6 +190,11 @@ runmsg(Client *c, Wsysmsg *m)
Memimage *i; Memimage *i;
switch(m->type){ switch(m->type){
case Tctxt:
c->wsysid = strdup(m->id);
replymsg(c, m);
break;
case Tinit: case Tinit:
memimageinit(); memimageinit();
i = rpc_attach(c, m->label, m->winsize); i = rpc_attach(c, m->label, m->winsize);
@ -143,11 +204,15 @@ runmsg(Client *c, Wsysmsg *m)
case Trdmouse: case Trdmouse:
qlock(&c->eventlk); 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; c->mousetags.t[c->mousetags.wi++] = m->tag;
if(c->mousetags.wi == nelem(c->mousetags.t)) if(c->mousetags.wi == nelem(c->mousetags.t))
c->mousetags.wi = 0; c->mousetags.wi = 0;
if(c->mousetags.wi == c->mousetags.ri)
sysfatal("too many queued mouse reads");
c->mouse.stall = 0; c->mouse.stall = 0;
matchmouse(c); matchmouse(c);
qunlock(&c->eventlk); qunlock(&c->eventlk);
@ -155,11 +220,15 @@ runmsg(Client *c, Wsysmsg *m)
case Trdkbd: case Trdkbd:
qlock(&c->eventlk); 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; c->kbdtags.t[c->kbdtags.wi++] = m->tag;
if(c->kbdtags.wi == nelem(c->kbdtags.t)) if(c->kbdtags.wi == nelem(c->kbdtags.t))
c->kbdtags.wi = 0; c->kbdtags.wi = 0;
if(c->kbdtags.wi == c->kbdtags.ri)
sysfatal("too many queued keyboard reads");
c->kbd.stall = 0; c->kbd.stall = 0;
matchkbd(c); matchkbd(c);
qunlock(&c->eventlk); qunlock(&c->eventlk);
@ -268,7 +337,7 @@ replymsg(Client *c, Wsysmsg *m)
} }
convW2M(m, c->mbuf, n); convW2M(m, c->mbuf, n);
if(write(c->wfd, c->mbuf, n) != n) if(write(c->wfd, c->mbuf, n) != n)
sysfatal("write: %r"); fprint(2, "client write: %r\n");
qunlock(&c->wfdlk); qunlock(&c->wfdlk);
} }