devdraw: multiclient mode
This commit is contained in:
parent
2cb85891ba
commit
892b3c4687
3 changed files with 115 additions and 42 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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,7 +47,8 @@ static AppDelegate *myApp = NULL;
|
||||||
void
|
void
|
||||||
gfx_main(void)
|
gfx_main(void)
|
||||||
{
|
{
|
||||||
setprocname(argv0);
|
if(client0)
|
||||||
|
setprocname(argv0);
|
||||||
|
|
||||||
@autoreleasepool{
|
@autoreleasepool{
|
||||||
[NSApplication sharedApplication];
|
[NSApplication sharedApplication];
|
||||||
|
|
@ -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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,17 +37,6 @@ usage(void)
|
||||||
void
|
void
|
||||||
threadmain(int argc, char **argv)
|
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{
|
ARGBEGIN{
|
||||||
case 'D': /* for good ps -a listings */
|
case 'D': /* for good ps -a listings */
|
||||||
break;
|
break;
|
||||||
|
|
@ -51,32 +44,89 @@ threadmain(int argc, char **argv)
|
||||||
case 'g':
|
case 'g':
|
||||||
case 'b':
|
case 'b':
|
||||||
break;
|
break;
|
||||||
|
case 's':
|
||||||
|
// TODO: Update usage, man page.
|
||||||
|
srvname = EARGF(usage());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
}ARGEND
|
}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){
|
* Move the protocol off stdin/stdout so that
|
||||||
fprint(2, "initdraw: allocating client0: out of memory");
|
* any inadvertent prints don't screw things up.
|
||||||
abort();
|
*/
|
||||||
|
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();
|
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,23 +142,29 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc_shutdown();
|
if(c == client0) {
|
||||||
threadexitsall(nil);
|
rpc_shutdown();
|
||||||
|
threadexitsall(nil);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue