2011-09-06 10:10:43 -04:00
|
|
|
/*
|
|
|
|
|
* Window system protocol server.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <u.h>
|
|
|
|
|
#include <libc.h>
|
2020-01-08 20:03:31 -05:00
|
|
|
#include <thread.h>
|
2011-09-06 10:10:43 -04:00
|
|
|
#include <draw.h>
|
|
|
|
|
#include <memdraw.h>
|
|
|
|
|
#include <keyboard.h>
|
|
|
|
|
#include <mouse.h>
|
|
|
|
|
#include <cursor.h>
|
|
|
|
|
#include <drawfcall.h>
|
2020-01-08 20:07:15 -05:00
|
|
|
#include "mac-screen.h"
|
2011-09-06 10:10:43 -04:00
|
|
|
#include "devdraw.h"
|
|
|
|
|
|
|
|
|
|
typedef struct Kbdbuf Kbdbuf;
|
|
|
|
|
typedef struct Mousebuf Mousebuf;
|
|
|
|
|
typedef struct Fdbuf Fdbuf;
|
|
|
|
|
typedef struct Tagbuf Tagbuf;
|
|
|
|
|
|
|
|
|
|
struct Kbdbuf
|
|
|
|
|
{
|
2018-10-21 20:59:21 -05:00
|
|
|
Rune r[256];
|
2011-09-06 10:10:43 -04:00
|
|
|
int ri;
|
|
|
|
|
int wi;
|
|
|
|
|
int stall;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct Mousebuf
|
|
|
|
|
{
|
2018-10-21 20:59:21 -05:00
|
|
|
Mouse m[256];
|
2011-09-06 10:10:43 -04:00
|
|
|
Mouse last;
|
|
|
|
|
int ri;
|
|
|
|
|
int wi;
|
|
|
|
|
int stall;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct Tagbuf
|
|
|
|
|
{
|
2018-10-21 20:59:21 -05:00
|
|
|
int t[256];
|
2011-09-06 10:10:43 -04:00
|
|
|
int ri;
|
|
|
|
|
int wi;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Kbdbuf kbd;
|
|
|
|
|
Mousebuf mouse;
|
|
|
|
|
Tagbuf kbdtags;
|
|
|
|
|
Tagbuf mousetags;
|
|
|
|
|
|
|
|
|
|
void runmsg(Wsysmsg*);
|
|
|
|
|
void replymsg(Wsysmsg*);
|
|
|
|
|
void matchkbd(void);
|
|
|
|
|
void matchmouse(void);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QLock lk;
|
|
|
|
|
void
|
|
|
|
|
zlock(void)
|
|
|
|
|
{
|
|
|
|
|
qlock(&lk);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
zunlock(void)
|
|
|
|
|
{
|
|
|
|
|
qunlock(&lk);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int trace = 0;
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
servep9p(void)
|
|
|
|
|
{
|
|
|
|
|
uchar buf[4], *mbuf;
|
|
|
|
|
int nmbuf, n, nn;
|
|
|
|
|
Wsysmsg m;
|
|
|
|
|
|
|
|
|
|
fmtinstall('W', drawfcallfmt);
|
2020-01-10 14:44:21 +00:00
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
mbuf = nil;
|
|
|
|
|
nmbuf = 0;
|
|
|
|
|
while((n = read(3, buf, 4)) == 4){
|
|
|
|
|
GET(buf, n);
|
|
|
|
|
if(n > nmbuf){
|
|
|
|
|
free(mbuf);
|
|
|
|
|
mbuf = malloc(4+n);
|
|
|
|
|
if(mbuf == nil)
|
|
|
|
|
sysfatal("malloc: %r");
|
|
|
|
|
nmbuf = n;
|
|
|
|
|
}
|
|
|
|
|
memmove(mbuf, buf, 4);
|
|
|
|
|
nn = readn(3, mbuf+4, n-4);
|
|
|
|
|
if(nn != n-4)
|
|
|
|
|
sysfatal("eof during message");
|
|
|
|
|
|
|
|
|
|
/* pick off messages one by one */
|
|
|
|
|
if(convM2W(mbuf, nn+4, &m) <= 0)
|
|
|
|
|
sysfatal("cannot convert message");
|
2018-10-21 20:59:21 -05:00
|
|
|
if(trace) fprint(2, "%ud [%d] <- %W\n", nsec()/1000000, threadid(), &m);
|
2011-09-06 10:10:43 -04:00
|
|
|
runmsg(&m);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
replyerror(Wsysmsg *m)
|
|
|
|
|
{
|
|
|
|
|
char err[256];
|
2020-01-10 14:44:21 +00:00
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
rerrstr(err, sizeof err);
|
|
|
|
|
m->type = Rerror;
|
|
|
|
|
m->error = err;
|
|
|
|
|
replymsg(m);
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-10 14:44:21 +00:00
|
|
|
/*
|
|
|
|
|
* Handle a single wsysmsg.
|
2011-09-06 10:10:43 -04:00
|
|
|
* Might queue for later (kbd, mouse read)
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
runmsg(Wsysmsg *m)
|
|
|
|
|
{
|
|
|
|
|
static uchar buf[65536];
|
|
|
|
|
int n;
|
|
|
|
|
Memimage *i;
|
2020-01-10 14:44:21 +00:00
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
switch(m->type){
|
|
|
|
|
case Tinit:
|
|
|
|
|
memimageinit();
|
|
|
|
|
i = attachscreen(m->label, m->winsize);
|
|
|
|
|
_initdisplaymemimage(i);
|
|
|
|
|
replymsg(m);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Trdmouse:
|
|
|
|
|
zlock();
|
|
|
|
|
mousetags.t[mousetags.wi++] = m->tag;
|
|
|
|
|
if(mousetags.wi == nelem(mousetags.t))
|
|
|
|
|
mousetags.wi = 0;
|
|
|
|
|
if(mousetags.wi == mousetags.ri)
|
|
|
|
|
sysfatal("too many queued mouse reads");
|
|
|
|
|
mouse.stall = 0;
|
|
|
|
|
matchmouse();
|
|
|
|
|
zunlock();
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Trdkbd:
|
|
|
|
|
zlock();
|
|
|
|
|
kbdtags.t[kbdtags.wi++] = m->tag;
|
|
|
|
|
if(kbdtags.wi == nelem(kbdtags.t))
|
|
|
|
|
kbdtags.wi = 0;
|
|
|
|
|
if(kbdtags.wi == kbdtags.ri)
|
|
|
|
|
sysfatal("too many queued keyboard reads");
|
|
|
|
|
kbd.stall = 0;
|
|
|
|
|
matchkbd();
|
|
|
|
|
zunlock();
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Tmoveto:
|
|
|
|
|
setmouse(m->mouse.xy);
|
|
|
|
|
replymsg(m);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Tcursor:
|
2019-04-05 15:09:35 -04:00
|
|
|
if(m->arrowcursor)
|
|
|
|
|
setcursor(nil, nil);
|
|
|
|
|
else
|
|
|
|
|
setcursor(&m->cursor, nil);
|
|
|
|
|
replymsg(m);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Tcursor2:
|
2011-09-06 10:10:43 -04:00
|
|
|
if(m->arrowcursor)
|
2018-11-15 20:28:56 -05:00
|
|
|
setcursor(nil, nil);
|
2011-09-06 10:10:43 -04:00
|
|
|
else
|
2018-11-15 20:28:56 -05:00
|
|
|
setcursor(&m->cursor, &m->cursor2);
|
2011-09-06 10:10:43 -04:00
|
|
|
replymsg(m);
|
|
|
|
|
break;
|
2020-01-10 14:44:21 +00:00
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
case Tbouncemouse:
|
|
|
|
|
// _xbouncemouse(&m->mouse);
|
|
|
|
|
replymsg(m);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Tlabel:
|
|
|
|
|
kicklabel(m->label);
|
|
|
|
|
replymsg(m);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Trdsnarf:
|
|
|
|
|
m->snarf = getsnarf();
|
|
|
|
|
replymsg(m);
|
|
|
|
|
free(m->snarf);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Twrsnarf:
|
|
|
|
|
putsnarf(m->snarf);
|
|
|
|
|
replymsg(m);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Trddraw:
|
2018-10-21 20:59:21 -05:00
|
|
|
zlock();
|
2011-09-06 10:10:43 -04:00
|
|
|
n = m->count;
|
|
|
|
|
if(n > sizeof buf)
|
|
|
|
|
n = sizeof buf;
|
|
|
|
|
n = _drawmsgread(buf, n);
|
|
|
|
|
if(n < 0)
|
|
|
|
|
replyerror(m);
|
|
|
|
|
else{
|
|
|
|
|
m->count = n;
|
|
|
|
|
m->data = buf;
|
|
|
|
|
replymsg(m);
|
|
|
|
|
}
|
2018-10-21 20:59:21 -05:00
|
|
|
zunlock();
|
2011-09-06 10:10:43 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Twrdraw:
|
2018-10-21 20:59:21 -05:00
|
|
|
zlock();
|
2011-09-06 10:10:43 -04:00
|
|
|
if(_drawmsgwrite(m->data, m->count) < 0)
|
|
|
|
|
replyerror(m);
|
|
|
|
|
else
|
|
|
|
|
replymsg(m);
|
2018-10-21 20:59:21 -05:00
|
|
|
zunlock();
|
2011-09-06 10:10:43 -04:00
|
|
|
break;
|
2020-01-10 14:44:21 +00:00
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
case Ttop:
|
2012-01-16 17:04:28 -05:00
|
|
|
topwin();
|
2011-09-06 10:10:43 -04:00
|
|
|
replymsg(m);
|
|
|
|
|
break;
|
2020-01-10 14:44:21 +00:00
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
case Tresize:
|
2018-10-21 20:59:21 -05:00
|
|
|
resizewindow(m->rect);
|
2011-09-06 10:10:43 -04:00
|
|
|
replymsg(m);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Reply to m.
|
|
|
|
|
*/
|
|
|
|
|
QLock replylock;
|
|
|
|
|
void
|
|
|
|
|
replymsg(Wsysmsg *m)
|
|
|
|
|
{
|
|
|
|
|
int n;
|
|
|
|
|
static uchar *mbuf;
|
|
|
|
|
static int nmbuf;
|
|
|
|
|
|
|
|
|
|
/* T -> R msg */
|
|
|
|
|
if(m->type%2 == 0)
|
|
|
|
|
m->type++;
|
2020-01-10 14:44:21 +00:00
|
|
|
|
2018-10-21 20:59:21 -05:00
|
|
|
if(trace) fprint(2, "%ud [%d] -> %W\n", nsec()/1000000, threadid(), m);
|
2011-09-06 10:10:43 -04:00
|
|
|
/* copy to output buffer */
|
|
|
|
|
n = sizeW2M(m);
|
|
|
|
|
|
|
|
|
|
qlock(&replylock);
|
|
|
|
|
if(n > nmbuf){
|
|
|
|
|
free(mbuf);
|
|
|
|
|
mbuf = malloc(n);
|
|
|
|
|
if(mbuf == nil)
|
|
|
|
|
sysfatal("out of memory");
|
|
|
|
|
nmbuf = n;
|
|
|
|
|
}
|
|
|
|
|
convW2M(m, mbuf, n);
|
|
|
|
|
if(write(4, mbuf, n) != n)
|
|
|
|
|
sysfatal("write: %r");
|
|
|
|
|
qunlock(&replylock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Match queued kbd reads with queued kbd characters.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
matchkbd(void)
|
|
|
|
|
{
|
|
|
|
|
Wsysmsg m;
|
2020-01-10 14:44:21 +00:00
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
if(kbd.stall)
|
|
|
|
|
return;
|
|
|
|
|
while(kbd.ri != kbd.wi && kbdtags.ri != kbdtags.wi){
|
|
|
|
|
m.type = Rrdkbd;
|
|
|
|
|
m.tag = kbdtags.t[kbdtags.ri++];
|
|
|
|
|
if(kbdtags.ri == nelem(kbdtags.t))
|
|
|
|
|
kbdtags.ri = 0;
|
|
|
|
|
m.rune = kbd.r[kbd.ri++];
|
|
|
|
|
if(kbd.ri == nelem(kbd.r))
|
|
|
|
|
kbd.ri = 0;
|
|
|
|
|
replymsg(&m);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Match queued mouse reads with queued mouse events.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
matchmouse(void)
|
|
|
|
|
{
|
|
|
|
|
Wsysmsg m;
|
2020-01-10 14:44:21 +00:00
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
while(mouse.ri != mouse.wi && mousetags.ri != mousetags.wi){
|
|
|
|
|
m.type = Rrdmouse;
|
|
|
|
|
m.tag = mousetags.t[mousetags.ri++];
|
|
|
|
|
if(mousetags.ri == nelem(mousetags.t))
|
|
|
|
|
mousetags.ri = 0;
|
|
|
|
|
m.mouse = mouse.m[mouse.ri];
|
|
|
|
|
m.resized = mouseresized;
|
2018-10-21 20:59:21 -05:00
|
|
|
mouseresized = 0;
|
2011-09-06 10:10:43 -04:00
|
|
|
/*
|
|
|
|
|
if(m.resized)
|
|
|
|
|
fprint(2, "sending resize\n");
|
|
|
|
|
*/
|
|
|
|
|
mouse.ri++;
|
|
|
|
|
if(mouse.ri == nelem(mouse.m))
|
|
|
|
|
mouse.ri = 0;
|
|
|
|
|
replymsg(&m);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2011-09-19 08:58:59 -04:00
|
|
|
mousetrack(int x, int y, int b, uint ms)
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
|
|
|
|
Mouse *m;
|
2020-01-10 14:44:21 +00:00
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
if(x < mouserect.min.x)
|
|
|
|
|
x = mouserect.min.x;
|
|
|
|
|
if(x > mouserect.max.x)
|
|
|
|
|
x = mouserect.max.x;
|
|
|
|
|
if(y < mouserect.min.y)
|
|
|
|
|
y = mouserect.min.y;
|
|
|
|
|
if(y > mouserect.max.y)
|
|
|
|
|
y = mouserect.max.y;
|
|
|
|
|
|
|
|
|
|
zlock();
|
|
|
|
|
// If reader has stopped reading, don't bother.
|
|
|
|
|
// If reader is completely caught up, definitely queue.
|
|
|
|
|
// Otherwise, queue only button change events.
|
|
|
|
|
if(!mouse.stall)
|
|
|
|
|
if(mouse.wi == mouse.ri || mouse.last.buttons != b){
|
|
|
|
|
m = &mouse.last;
|
|
|
|
|
m->xy.x = x;
|
|
|
|
|
m->xy.y = y;
|
|
|
|
|
m->buttons = b;
|
|
|
|
|
m->msec = ms;
|
|
|
|
|
|
|
|
|
|
mouse.m[mouse.wi] = *m;
|
|
|
|
|
if(++mouse.wi == nelem(mouse.m))
|
|
|
|
|
mouse.wi = 0;
|
|
|
|
|
if(mouse.wi == mouse.ri){
|
|
|
|
|
mouse.stall = 1;
|
|
|
|
|
mouse.ri = 0;
|
|
|
|
|
mouse.wi = 1;
|
|
|
|
|
mouse.m[0] = *m;
|
|
|
|
|
}
|
|
|
|
|
matchmouse();
|
|
|
|
|
}
|
|
|
|
|
zunlock();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
kputc(int c)
|
|
|
|
|
{
|
|
|
|
|
zlock();
|
|
|
|
|
kbd.r[kbd.wi++] = c;
|
|
|
|
|
if(kbd.wi == nelem(kbd.r))
|
|
|
|
|
kbd.wi = 0;
|
|
|
|
|
if(kbd.ri == kbd.wi)
|
|
|
|
|
kbd.stall = 1;
|
|
|
|
|
matchkbd();
|
|
|
|
|
zunlock();
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-16 17:08:31 -05:00
|
|
|
static int alting;
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
abortcompose(void)
|
|
|
|
|
{
|
|
|
|
|
if(alting)
|
|
|
|
|
keystroke(Kalt);
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
void
|
|
|
|
|
keystroke(int c)
|
|
|
|
|
{
|
|
|
|
|
static Rune k[10];
|
2012-01-16 17:08:31 -05:00
|
|
|
static int nk;
|
2011-09-06 10:10:43 -04:00
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if(c == Kalt){
|
|
|
|
|
alting = !alting;
|
2012-01-16 17:08:31 -05:00
|
|
|
nk = 0;
|
2011-09-06 10:10:43 -04:00
|
|
|
return;
|
|
|
|
|
}
|
2012-11-25 23:47:54 -05:00
|
|
|
if(c == Kcmd+'r') {
|
2012-11-25 23:38:14 -05:00
|
|
|
if(forcedpi)
|
|
|
|
|
forcedpi = 0;
|
|
|
|
|
else if(displaydpi >= 200)
|
|
|
|
|
forcedpi = 100;
|
|
|
|
|
else
|
|
|
|
|
forcedpi = 225;
|
|
|
|
|
resizeimg();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2011-09-06 10:10:43 -04:00
|
|
|
if(!alting){
|
|
|
|
|
kputc(c);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(nk >= nelem(k)) // should not happen
|
|
|
|
|
nk = 0;
|
|
|
|
|
k[nk++] = c;
|
|
|
|
|
c = _latin1(k, nk);
|
|
|
|
|
if(c > 0){
|
|
|
|
|
alting = 0;
|
|
|
|
|
kputc(c);
|
|
|
|
|
nk = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(c == -1){
|
|
|
|
|
alting = 0;
|
|
|
|
|
for(i=0; i<nk; i++)
|
|
|
|
|
kputc(k[i]);
|
|
|
|
|
nk = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// need more input
|
|
|
|
|
return;
|
|
|
|
|
}
|