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>
|
2020-01-08 20:28:17 -05:00
|
|
|
#include <memlayer.h>
|
2011-09-06 10:10:43 -04:00
|
|
|
#include <keyboard.h>
|
|
|
|
|
#include <mouse.h>
|
|
|
|
|
#include <cursor.h>
|
|
|
|
|
#include <drawfcall.h>
|
|
|
|
|
#include "devdraw.h"
|
|
|
|
|
|
2020-01-09 21:47:14 -05:00
|
|
|
static void runmsg(Client*, Wsysmsg*);
|
|
|
|
|
static void replymsg(Client*, Wsysmsg*);
|
|
|
|
|
static void matchkbd(Client*);
|
|
|
|
|
static void matchmouse(Client*);
|
2020-01-11 06:10:14 -05:00
|
|
|
static void serveproc(void*);
|
|
|
|
|
static void listenproc(void*);
|
|
|
|
|
Client *client0;
|
2011-09-06 10:10:43 -04:00
|
|
|
|
|
|
|
|
int trace = 0;
|
2020-01-11 06:10:14 -05:00
|
|
|
static char *srvname;
|
|
|
|
|
static int afd;
|
|
|
|
|
static char adir[40];
|
2011-09-06 10:10:43 -04:00
|
|
|
|
2020-01-10 00:11:55 -05:00
|
|
|
static void
|
|
|
|
|
usage(void)
|
|
|
|
|
{
|
|
|
|
|
fprint(2, "usage: devdraw (don't run directly)\n");
|
|
|
|
|
threadexitsall("usage");
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
void
|
2020-01-10 00:11:55 -05:00
|
|
|
threadmain(int argc, char **argv)
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
2020-01-10 00:11:55 -05:00
|
|
|
ARGBEGIN{
|
|
|
|
|
case 'D': /* for good ps -a listings */
|
|
|
|
|
break;
|
|
|
|
|
case 'f': /* fall through for backward compatibility */
|
|
|
|
|
case 'g':
|
|
|
|
|
case 'b':
|
|
|
|
|
break;
|
2020-01-11 06:10:14 -05:00
|
|
|
case 's':
|
|
|
|
|
// TODO: Update usage, man page.
|
|
|
|
|
srvname = EARGF(usage());
|
|
|
|
|
break;
|
2020-01-10 00:11:55 -05:00
|
|
|
default:
|
|
|
|
|
usage();
|
|
|
|
|
}ARGEND
|
|
|
|
|
|
2020-01-11 06:10:14 -05:00
|
|
|
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
|
|
|
|
|
* 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);
|
2020-01-10 00:11:55 -05:00
|
|
|
}
|
|
|
|
|
|
2020-01-11 06:10:14 -05:00
|
|
|
fmtinstall('W', drawfcallfmt);
|
2020-01-10 00:11:55 -05:00
|
|
|
gfx_main();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
gfx_started(void)
|
|
|
|
|
{
|
2020-01-11 06:10:14 -05:00
|
|
|
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);
|
2020-01-10 00:11:55 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2020-01-11 06:10:14 -05:00
|
|
|
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)
|
2020-01-10 00:11:55 -05:00
|
|
|
{
|
|
|
|
|
Client *c;
|
2011-09-06 10:10:43 -04:00
|
|
|
uchar buf[4], *mbuf;
|
|
|
|
|
int nmbuf, n, nn;
|
|
|
|
|
Wsysmsg m;
|
|
|
|
|
|
2020-01-10 00:11:55 -05:00
|
|
|
c = v;
|
2011-09-06 10:10:43 -04:00
|
|
|
mbuf = nil;
|
|
|
|
|
nmbuf = 0;
|
2020-01-08 20:28:17 -05:00
|
|
|
while((n = read(c->rfd, buf, 4)) == 4){
|
2011-09-06 10:10:43 -04:00
|
|
|
GET(buf, n);
|
|
|
|
|
if(n > nmbuf){
|
|
|
|
|
free(mbuf);
|
|
|
|
|
mbuf = malloc(4+n);
|
|
|
|
|
if(mbuf == nil)
|
2020-01-11 06:10:14 -05:00
|
|
|
sysfatal("out of memory");
|
2011-09-06 10:10:43 -04:00
|
|
|
nmbuf = n;
|
|
|
|
|
}
|
|
|
|
|
memmove(mbuf, buf, 4);
|
2020-01-08 20:28:17 -05:00
|
|
|
nn = readn(c->rfd, mbuf+4, n-4);
|
2020-01-11 06:10:14 -05:00
|
|
|
if(nn != n-4) {
|
|
|
|
|
fprint(2, "serveproc: eof during message\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
2011-09-06 10:10:43 -04:00
|
|
|
|
|
|
|
|
/* pick off messages one by one */
|
2020-01-11 06:10:14 -05:00
|
|
|
if(convM2W(mbuf, nn+4, &m) <= 0) {
|
|
|
|
|
fprint(2, "serveproc: cannot convert message\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
2018-10-21 20:59:21 -05:00
|
|
|
if(trace) fprint(2, "%ud [%d] <- %W\n", nsec()/1000000, threadid(), &m);
|
2020-01-08 20:28:17 -05:00
|
|
|
runmsg(c, &m);
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
2020-01-10 00:11:55 -05:00
|
|
|
|
2020-01-11 06:10:14 -05:00
|
|
|
if(c == client0) {
|
|
|
|
|
rpc_shutdown();
|
|
|
|
|
threadexitsall(nil);
|
|
|
|
|
}
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
|
2020-01-09 21:47:14 -05:00
|
|
|
static void
|
2020-01-08 20:28:17 -05:00
|
|
|
replyerror(Client *c, Wsysmsg *m)
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
|
|
|
|
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;
|
2020-01-08 20:28:17 -05:00
|
|
|
replymsg(c, m);
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
|
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)
|
|
|
|
|
*/
|
2020-01-09 21:47:14 -05:00
|
|
|
static void
|
2020-01-08 20:28:17 -05:00
|
|
|
runmsg(Client *c, Wsysmsg *m)
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
|
|
|
|
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){
|
2020-01-11 06:10:14 -05:00
|
|
|
case Tctxt:
|
|
|
|
|
c->wsysid = strdup(m->id);
|
|
|
|
|
replymsg(c, m);
|
|
|
|
|
break;
|
|
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
case Tinit:
|
|
|
|
|
memimageinit();
|
2020-01-10 00:11:55 -05:00
|
|
|
i = rpc_attach(c, m->label, m->winsize);
|
|
|
|
|
draw_initdisplaymemimage(c, i);
|
2020-01-08 20:28:17 -05:00
|
|
|
replymsg(c, m);
|
2011-09-06 10:10:43 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Trdmouse:
|
2020-01-10 00:11:55 -05:00
|
|
|
qlock(&c->eventlk);
|
2020-01-11 06:10:14 -05:00
|
|
|
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;
|
|
|
|
|
}
|
2020-01-08 20:28:17 -05:00
|
|
|
c->mousetags.t[c->mousetags.wi++] = m->tag;
|
|
|
|
|
if(c->mousetags.wi == nelem(c->mousetags.t))
|
|
|
|
|
c->mousetags.wi = 0;
|
|
|
|
|
c->mouse.stall = 0;
|
|
|
|
|
matchmouse(c);
|
2020-01-10 00:11:55 -05:00
|
|
|
qunlock(&c->eventlk);
|
2011-09-06 10:10:43 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Trdkbd:
|
2020-01-10 00:11:55 -05:00
|
|
|
qlock(&c->eventlk);
|
2020-01-11 06:10:14 -05:00
|
|
|
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;
|
|
|
|
|
}
|
2020-01-08 20:28:17 -05:00
|
|
|
c->kbdtags.t[c->kbdtags.wi++] = m->tag;
|
|
|
|
|
if(c->kbdtags.wi == nelem(c->kbdtags.t))
|
|
|
|
|
c->kbdtags.wi = 0;
|
|
|
|
|
c->kbd.stall = 0;
|
|
|
|
|
matchkbd(c);
|
2020-01-10 00:11:55 -05:00
|
|
|
qunlock(&c->eventlk);
|
2011-09-06 10:10:43 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Tmoveto:
|
2020-01-09 21:47:14 -05:00
|
|
|
rpc_setmouse(c, m->mouse.xy);
|
2020-01-08 20:28:17 -05:00
|
|
|
replymsg(c, m);
|
2011-09-06 10:10:43 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Tcursor:
|
2019-04-05 15:09:35 -04:00
|
|
|
if(m->arrowcursor)
|
2020-01-09 21:47:14 -05:00
|
|
|
rpc_setcursor(c, nil, nil);
|
|
|
|
|
else {
|
|
|
|
|
scalecursor(&m->cursor2, &m->cursor);
|
|
|
|
|
rpc_setcursor(c, &m->cursor, &m->cursor2);
|
|
|
|
|
}
|
2020-01-08 20:28:17 -05:00
|
|
|
replymsg(c, m);
|
2019-04-05 15:09:35 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Tcursor2:
|
2011-09-06 10:10:43 -04:00
|
|
|
if(m->arrowcursor)
|
2020-01-09 21:47:14 -05:00
|
|
|
rpc_setcursor(c, nil, nil);
|
2011-09-06 10:10:43 -04:00
|
|
|
else
|
2020-01-09 21:47:14 -05:00
|
|
|
rpc_setcursor(c, &m->cursor, &m->cursor2);
|
2020-01-08 20:28:17 -05:00
|
|
|
replymsg(c, m);
|
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 Tbouncemouse:
|
2020-01-12 14:53:46 -05:00
|
|
|
rpc_bouncemouse(c, m->mouse);
|
2020-01-08 20:28:17 -05:00
|
|
|
replymsg(c, m);
|
2011-09-06 10:10:43 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Tlabel:
|
2020-01-09 21:47:14 -05:00
|
|
|
rpc_setlabel(c, m->label);
|
2020-01-08 20:28:17 -05:00
|
|
|
replymsg(c, m);
|
2011-09-06 10:10:43 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Trdsnarf:
|
2020-01-09 21:47:14 -05:00
|
|
|
m->snarf = rpc_getsnarf();
|
2020-01-08 20:28:17 -05:00
|
|
|
replymsg(c, m);
|
2011-09-06 10:10:43 -04:00
|
|
|
free(m->snarf);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Twrsnarf:
|
2020-01-10 00:11:55 -05:00
|
|
|
rpc_putsnarf(m->snarf);
|
2020-01-08 20:28:17 -05:00
|
|
|
replymsg(c, m);
|
2011-09-06 10:10:43 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Trddraw:
|
|
|
|
|
n = m->count;
|
|
|
|
|
if(n > sizeof buf)
|
|
|
|
|
n = sizeof buf;
|
2020-01-10 00:11:55 -05:00
|
|
|
n = draw_dataread(c, buf, n);
|
2011-09-06 10:10:43 -04:00
|
|
|
if(n < 0)
|
2020-01-08 20:28:17 -05:00
|
|
|
replyerror(c, m);
|
2011-09-06 10:10:43 -04:00
|
|
|
else{
|
|
|
|
|
m->count = n;
|
|
|
|
|
m->data = buf;
|
2020-01-08 20:28:17 -05:00
|
|
|
replymsg(c, m);
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Twrdraw:
|
2020-01-10 00:11:55 -05:00
|
|
|
if(draw_datawrite(c, m->data, m->count) < 0)
|
2020-01-08 20:28:17 -05:00
|
|
|
replyerror(c, m);
|
2011-09-06 10:10:43 -04:00
|
|
|
else
|
2020-01-08 20:28:17 -05:00
|
|
|
replymsg(c, m);
|
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:
|
2020-01-09 21:47:14 -05:00
|
|
|
rpc_topwin(c);
|
2020-01-08 20:28:17 -05:00
|
|
|
replymsg(c, m);
|
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 Tresize:
|
2020-01-09 21:47:14 -05:00
|
|
|
rpc_resizewindow(c, m->rect);
|
2020-01-08 20:28:17 -05:00
|
|
|
replymsg(c, m);
|
2011-09-06 10:10:43 -04:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Reply to m.
|
|
|
|
|
*/
|
2020-01-09 21:47:14 -05:00
|
|
|
static void
|
2020-01-08 20:28:17 -05:00
|
|
|
replymsg(Client *c, Wsysmsg *m)
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
|
|
|
|
int n;
|
|
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
|
2020-01-10 00:11:55 -05:00
|
|
|
qlock(&c->wfdlk);
|
|
|
|
|
if(n > c->nmbuf){
|
|
|
|
|
free(c->mbuf);
|
|
|
|
|
c->mbuf = malloc(n);
|
|
|
|
|
if(c->mbuf == nil)
|
2011-09-06 10:10:43 -04:00
|
|
|
sysfatal("out of memory");
|
2020-01-10 00:11:55 -05:00
|
|
|
c->nmbuf = n;
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
2020-01-10 00:11:55 -05:00
|
|
|
convW2M(m, c->mbuf, n);
|
|
|
|
|
if(write(c->wfd, c->mbuf, n) != n)
|
2020-01-11 06:10:14 -05:00
|
|
|
fprint(2, "client write: %r\n");
|
2020-01-10 00:11:55 -05:00
|
|
|
qunlock(&c->wfdlk);
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Match queued kbd reads with queued kbd characters.
|
|
|
|
|
*/
|
2020-01-09 21:47:14 -05:00
|
|
|
static void
|
2020-01-08 20:28:17 -05:00
|
|
|
matchkbd(Client *c)
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
|
|
|
|
Wsysmsg m;
|
2020-01-10 14:44:21 +00:00
|
|
|
|
2020-01-08 20:28:17 -05:00
|
|
|
if(c->kbd.stall)
|
2011-09-06 10:10:43 -04:00
|
|
|
return;
|
2020-01-08 20:28:17 -05:00
|
|
|
while(c->kbd.ri != c->kbd.wi && c->kbdtags.ri != c->kbdtags.wi){
|
2011-09-06 10:10:43 -04:00
|
|
|
m.type = Rrdkbd;
|
2020-01-08 20:28:17 -05:00
|
|
|
m.tag = c->kbdtags.t[c->kbdtags.ri++];
|
|
|
|
|
if(c->kbdtags.ri == nelem(c->kbdtags.t))
|
|
|
|
|
c->kbdtags.ri = 0;
|
|
|
|
|
m.rune = c->kbd.r[c->kbd.ri++];
|
|
|
|
|
if(c->kbd.ri == nelem(c->kbd.r))
|
|
|
|
|
c->kbd.ri = 0;
|
|
|
|
|
replymsg(c, &m);
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-09 21:47:14 -05:00
|
|
|
// matchmouse matches queued mouse reads with queued mouse events.
|
2020-01-10 00:11:55 -05:00
|
|
|
// It must be called with c->eventlk held.
|
2020-01-09 21:47:14 -05:00
|
|
|
static void
|
2020-01-08 20:28:17 -05:00
|
|
|
matchmouse(Client *c)
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
|
|
|
|
Wsysmsg m;
|
2020-01-10 14:44:21 +00:00
|
|
|
|
2020-01-10 00:11:55 -05:00
|
|
|
if(canqlock(&c->eventlk)) {
|
2020-01-09 21:47:14 -05:00
|
|
|
fprint(2, "misuse of matchmouse\n");
|
|
|
|
|
abort();
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-08 20:28:17 -05:00
|
|
|
while(c->mouse.ri != c->mouse.wi && c->mousetags.ri != c->mousetags.wi){
|
2011-09-06 10:10:43 -04:00
|
|
|
m.type = Rrdmouse;
|
2020-01-08 20:28:17 -05:00
|
|
|
m.tag = c->mousetags.t[c->mousetags.ri++];
|
|
|
|
|
if(c->mousetags.ri == nelem(c->mousetags.t))
|
|
|
|
|
c->mousetags.ri = 0;
|
|
|
|
|
m.mouse = c->mouse.m[c->mouse.ri];
|
|
|
|
|
m.resized = c->mouse.resized;
|
|
|
|
|
c->mouse.resized = 0;
|
2011-09-06 10:10:43 -04:00
|
|
|
/*
|
|
|
|
|
if(m.resized)
|
|
|
|
|
fprint(2, "sending resize\n");
|
|
|
|
|
*/
|
2020-01-08 20:28:17 -05:00
|
|
|
c->mouse.ri++;
|
|
|
|
|
if(c->mouse.ri == nelem(c->mouse.m))
|
|
|
|
|
c->mouse.ri = 0;
|
|
|
|
|
replymsg(c, &m);
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-14 19:43:32 -05:00
|
|
|
void
|
|
|
|
|
gfx_mouseresized(Client *c)
|
|
|
|
|
{
|
|
|
|
|
gfx_mousetrack(c, -1, -1, -1, -1);
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
void
|
2020-01-09 21:47:14 -05:00
|
|
|
gfx_mousetrack(Client *c, 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
|
|
|
|
2020-01-10 00:11:55 -05:00
|
|
|
qlock(&c->eventlk);
|
2020-01-14 19:43:32 -05:00
|
|
|
if(x == -1 && y == -1 && b == -1 && ms == -1) {
|
|
|
|
|
Mouse *copy;
|
|
|
|
|
// repeat last mouse event for resize
|
|
|
|
|
if(c->mouse.ri == 0)
|
|
|
|
|
copy = &c->mouse.m[nelem(c->mouse.m)-1];
|
|
|
|
|
else
|
|
|
|
|
copy = &c->mouse.m[c->mouse.ri-1];
|
|
|
|
|
x = copy->xy.x;
|
|
|
|
|
y = copy->xy.y;
|
|
|
|
|
b = copy->buttons;
|
|
|
|
|
ms = copy->msec;
|
|
|
|
|
}
|
2020-01-08 20:28:17 -05:00
|
|
|
if(x < c->mouserect.min.x)
|
|
|
|
|
x = c->mouserect.min.x;
|
|
|
|
|
if(x > c->mouserect.max.x)
|
|
|
|
|
x = c->mouserect.max.x;
|
|
|
|
|
if(y < c->mouserect.min.y)
|
|
|
|
|
y = c->mouserect.min.y;
|
|
|
|
|
if(y > c->mouserect.max.y)
|
|
|
|
|
y = c->mouserect.max.y;
|
2011-09-06 10:10:43 -04:00
|
|
|
|
|
|
|
|
// If reader has stopped reading, don't bother.
|
|
|
|
|
// If reader is completely caught up, definitely queue.
|
|
|
|
|
// Otherwise, queue only button change events.
|
2020-01-08 20:28:17 -05:00
|
|
|
if(!c->mouse.stall)
|
|
|
|
|
if(c->mouse.wi == c->mouse.ri || c->mouse.last.buttons != b){
|
|
|
|
|
m = &c->mouse.last;
|
2011-09-06 10:10:43 -04:00
|
|
|
m->xy.x = x;
|
|
|
|
|
m->xy.y = y;
|
|
|
|
|
m->buttons = b;
|
|
|
|
|
m->msec = ms;
|
|
|
|
|
|
2020-01-08 20:28:17 -05:00
|
|
|
c->mouse.m[c->mouse.wi] = *m;
|
|
|
|
|
if(++c->mouse.wi == nelem(c->mouse.m))
|
|
|
|
|
c->mouse.wi = 0;
|
|
|
|
|
if(c->mouse.wi == c->mouse.ri){
|
|
|
|
|
c->mouse.stall = 1;
|
|
|
|
|
c->mouse.ri = 0;
|
|
|
|
|
c->mouse.wi = 1;
|
|
|
|
|
c->mouse.m[0] = *m;
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
2020-01-08 20:28:17 -05:00
|
|
|
matchmouse(c);
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
2020-01-10 00:11:55 -05:00
|
|
|
qunlock(&c->eventlk);
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
|
2020-01-09 21:47:14 -05:00
|
|
|
// kputc adds ch to the keyboard buffer.
|
2020-01-10 00:11:55 -05:00
|
|
|
// It must be called with c->eventlk held.
|
2020-01-09 21:47:14 -05:00
|
|
|
static void
|
2020-01-08 20:28:17 -05:00
|
|
|
kputc(Client *c, int ch)
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
2020-01-10 00:11:55 -05:00
|
|
|
if(canqlock(&c->eventlk)) {
|
2020-01-09 21:47:14 -05:00
|
|
|
fprint(2, "misuse of kputc\n");
|
|
|
|
|
abort();
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-08 20:28:17 -05:00
|
|
|
c->kbd.r[c->kbd.wi++] = ch;
|
|
|
|
|
if(c->kbd.wi == nelem(c->kbd.r))
|
|
|
|
|
c->kbd.wi = 0;
|
|
|
|
|
if(c->kbd.ri == c->kbd.wi)
|
|
|
|
|
c->kbd.stall = 1;
|
|
|
|
|
matchkbd(c);
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
|
2020-01-09 21:47:14 -05:00
|
|
|
// gfx_abortcompose stops any pending compose sequence,
|
|
|
|
|
// because a mouse button has been clicked.
|
|
|
|
|
// It is called from the graphics thread with no locks held.
|
2012-01-16 17:08:31 -05:00
|
|
|
void
|
2020-01-09 21:47:14 -05:00
|
|
|
gfx_abortcompose(Client *c)
|
2012-01-16 17:08:31 -05:00
|
|
|
{
|
2020-01-10 00:11:55 -05:00
|
|
|
qlock(&c->eventlk);
|
2020-01-09 21:47:14 -05:00
|
|
|
if(c->kbd.alting) {
|
|
|
|
|
c->kbd.alting = 0;
|
|
|
|
|
c->kbd.nk = 0;
|
|
|
|
|
}
|
2020-01-10 00:11:55 -05:00
|
|
|
qunlock(&c->eventlk);
|
2012-01-16 17:08:31 -05:00
|
|
|
}
|
|
|
|
|
|
2020-01-09 21:47:14 -05:00
|
|
|
// gfx_keystroke records a single-rune keystroke.
|
|
|
|
|
// It is called from the graphics thread with no locks held.
|
2011-09-06 10:10:43 -04:00
|
|
|
void
|
2020-01-09 21:47:14 -05:00
|
|
|
gfx_keystroke(Client *c, int ch)
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
2020-01-10 00:11:55 -05:00
|
|
|
qlock(&c->eventlk);
|
2020-01-08 20:28:17 -05:00
|
|
|
if(ch == Kalt){
|
|
|
|
|
c->kbd.alting = !c->kbd.alting;
|
2020-01-09 21:47:14 -05:00
|
|
|
c->kbd.nk = 0;
|
2020-01-10 00:11:55 -05:00
|
|
|
qunlock(&c->eventlk);
|
2011-09-06 10:10:43 -04:00
|
|
|
return;
|
|
|
|
|
}
|
2020-01-08 20:28:17 -05:00
|
|
|
if(ch == Kcmd+'r') {
|
|
|
|
|
if(c->forcedpi)
|
|
|
|
|
c->forcedpi = 0;
|
|
|
|
|
else if(c->displaydpi >= 200)
|
|
|
|
|
c->forcedpi = 100;
|
2012-11-25 23:38:14 -05:00
|
|
|
else
|
2020-01-08 20:28:17 -05:00
|
|
|
c->forcedpi = 225;
|
2020-01-10 00:11:55 -05:00
|
|
|
qunlock(&c->eventlk);
|
2020-01-09 21:47:14 -05:00
|
|
|
rpc_resizeimg(c);
|
2012-11-25 23:38:14 -05:00
|
|
|
return;
|
|
|
|
|
}
|
2020-01-08 20:28:17 -05:00
|
|
|
if(!c->kbd.alting){
|
|
|
|
|
kputc(c, ch);
|
2020-01-10 00:11:55 -05:00
|
|
|
qunlock(&c->eventlk);
|
2011-09-06 10:10:43 -04:00
|
|
|
return;
|
|
|
|
|
}
|
2020-01-09 21:47:14 -05:00
|
|
|
if(c->kbd.nk >= nelem(c->kbd.k)) // should not happen
|
|
|
|
|
c->kbd.nk = 0;
|
|
|
|
|
c->kbd.k[c->kbd.nk++] = ch;
|
2020-01-10 00:11:55 -05:00
|
|
|
ch = latin1(c->kbd.k, c->kbd.nk);
|
2020-01-08 20:28:17 -05:00
|
|
|
if(ch > 0){
|
|
|
|
|
c->kbd.alting = 0;
|
|
|
|
|
kputc(c, ch);
|
2020-01-09 21:47:14 -05:00
|
|
|
c->kbd.nk = 0;
|
2020-01-10 00:11:55 -05:00
|
|
|
qunlock(&c->eventlk);
|
2011-09-06 10:10:43 -04:00
|
|
|
return;
|
|
|
|
|
}
|
2020-01-08 20:28:17 -05:00
|
|
|
if(ch == -1){
|
|
|
|
|
c->kbd.alting = 0;
|
2020-01-09 21:47:14 -05:00
|
|
|
for(i=0; i<c->kbd.nk; i++)
|
|
|
|
|
kputc(c, c->kbd.k[i]);
|
|
|
|
|
c->kbd.nk = 0;
|
2020-01-10 00:11:55 -05:00
|
|
|
qunlock(&c->eventlk);
|
2011-09-06 10:10:43 -04:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// need more input
|
2020-01-10 00:11:55 -05:00
|
|
|
qunlock(&c->eventlk);
|
2011-09-06 10:10:43 -04:00
|
|
|
return;
|
|
|
|
|
}
|