[input] handle mouse release, implement stdineof, w00t!

pull/2197/head
nick black 3 years ago committed by nick black
parent 60ee94b4ca
commit d36591b01b

@ -165,6 +165,7 @@ typedef struct inputctx {
unsigned midescape; // we're in the middle of a potential escape. we need unsigned midescape; // we're in the middle of a potential escape. we need
// to do a nonblocking read and try to complete it. // to do a nonblocking read and try to complete it.
unsigned stdineof; // have we seen an EOF on stdin?
unsigned linesigs; // are line discipline signals active? unsigned linesigs; // are line discipline signals active?
unsigned drain; // drain away bulk input? unsigned drain; // drain away bulk input?
@ -446,6 +447,7 @@ create_inputctx(tinfo* ti, FILE* infp, int lmargin, int tmargin,
i->initdata_complete = NULL; i->initdata_complete = NULL;
i->stats = stats; i->stats = stats;
i->ti = ti; i->ti = ti;
i->stdineof = 0;
i->ibufvalid = 0; i->ibufvalid = 0;
// FIXME need to get this out of the initial termios // FIXME need to get this out of the initial termios
// (as stored in tpreserved) // (as stored in tpreserved)
@ -600,7 +602,8 @@ prep_all_keys(inputctx* ictx){
// populate |buf| with any new data from the specified file descriptor |fd|. // populate |buf| with any new data from the specified file descriptor |fd|.
static void static void
read_input_nblock(int fd, unsigned char* buf, size_t buflen, int *bufused){ read_input_nblock(int fd, unsigned char* buf, size_t buflen, int *bufused,
unsigned* goteof){
if(fd < 0){ if(fd < 0){
return; return;
} }
@ -612,6 +615,11 @@ read_input_nblock(int fd, unsigned char* buf, size_t buflen, int *bufused){
if(r <= 0){ if(r <= 0){
if(r < 0){ if(r < 0){
logwarn("couldn't read from %d (%s)\n", fd, strerror(errno)); logwarn("couldn't read from %d (%s)\n", fd, strerror(errno));
}else{
logwarn("got EOF on %d\n", fd);
if(goteof){
*goteof = 1;
}
} }
return; return;
} }
@ -807,9 +815,11 @@ set_sda_version(inputctx* ictx){
return buf; return buf;
} }
// ictx->numeric, ictx->p3, and ictx->p2 have the two parameters // ictx->numeric, ictx->p3, and ictx->p2 have the two parameters. we're using
// SGR (1006) mouse encoding, so use the final character to determine release
// ('M' for click, 'm' for release).
static void static void
mouse_click(inputctx* ictx){ mouse_click(inputctx* ictx, unsigned release){
// convert from 1- to 0-indexing, and account for margins // convert from 1- to 0-indexing, and account for margins
const int x = ictx->p3 - 1 - ictx->lmargin; const int x = ictx->p3 - 1 - ictx->lmargin;
const int y = ictx->numeric - 1 - ictx->tmargin; const int y = ictx->numeric - 1 - ictx->tmargin;
@ -824,12 +834,10 @@ mouse_click(inputctx* ictx){
return; return;
} }
ncinput* ni = ictx->inputs + ictx->iwrite; ncinput* ni = ictx->inputs + ictx->iwrite;
if(ictx->p2 >= 0 && ictx->p2 < 64){ if(release){
if(ictx->p2 % 4 == 3){ ni->id = NCKEY_RELEASE;
ni->id = NCKEY_RELEASE; }else if(ictx->p2 >= 0 && ictx->p2 < 64){
}else{ ni->id = NCKEY_BUTTON1 + (ictx->p2 % 4);
ni->id = NCKEY_BUTTON1 + (ictx->p2 % 4);
}
}else if(ictx->p2 >= 64 && ictx->p2 < 128){ }else if(ictx->p2 >= 64 && ictx->p2 < 128){
ni->id = NCKEY_BUTTON4 + (ictx->p2 % 4); ni->id = NCKEY_BUTTON4 + (ictx->p2 % 4);
}else if(ictx->p2 >= 128 && ictx->p2 < 192){ }else if(ictx->p2 >= 128 && ictx->p2 < 192){
@ -940,60 +948,63 @@ special_key(inputctx* ictx){
pthread_cond_broadcast(&ictx->icond); pthread_cond_broadcast(&ictx->icond);
} }
static void
send_synth_signal(int sig){
#ifndef __MINGW64__
if(sig){
raise(sig);
}
#else
(void)synth; // FIXME
#endif
}
// ictx->numeric and ictx->p2 have the two parameters, where ictx->numeric was // ictx->numeric and ictx->p2 have the two parameters, where ictx->numeric was
// optional and indicates a special key with no modifiers. // optional and indicates a special key with no modifiers.
static void static void
kitty_kbd(inputctx* ictx){ kitty_kbd(inputctx* ictx){
enum { // synthesized events derived from keypresses int synth = 0;
SYNTH_NOTHING,
SYNTH_SIGINT,
SYNTH_SIGQUIT,
} synth = SYNTH_NOTHING;
assert(ictx->numeric >= 0); assert(ictx->numeric >= 0);
assert(ictx->p2 > 0); assert(ictx->p2 > 0);
ncinput tni = {
.id = ictx->p2 == 0x7f ? NCKEY_BACKSPACE : ictx->p2,
.shift = !!((ictx->numeric - 1) & 0x1),
.alt = !!((ictx->numeric - 1) & 0x2),
.ctrl = !!((ictx->numeric - 1) & 0x4),
};
// FIXME decode remaining modifiers through 128
// standard keyboard protocol reports ctrl+ascii as the capital form,
// so (for now) conform when using kitty protocol...
if(tni.ctrl){
if(tni.id < 128 && islower(tni.id)){
tni.id = toupper(tni.id);
}
if(!tni.alt && !tni.shift){
if(tni.id == 'C'){
synth = SIGINT;
}else if(tni.id == '\\'){
synth = SIGQUIT;
}
}
}
tni.x = 0;
tni.y = 0;
pthread_mutex_lock(&ictx->ilock); pthread_mutex_lock(&ictx->ilock);
if(ictx->ivalid == ictx->isize){ if(ictx->ivalid == ictx->isize){
pthread_mutex_unlock(&ictx->ilock); pthread_mutex_unlock(&ictx->ilock);
logerror("dropping input 0x%08x 0x%02x\n", ictx->p2, ictx->numeric); logerror("dropping input 0x%08x 0x%02x\n", ictx->p2, ictx->numeric);
send_synth_signal(synth);
return; return;
} }
ncinput* ni = ictx->inputs + ictx->iwrite; ncinput* ni = ictx->inputs + ictx->iwrite;
if((ni->id = ictx->p2) == 0x7f){ memcpy(ni, &tni, sizeof(tni));
ni->id = NCKEY_BACKSPACE;
}
ni->shift = !!((ictx->numeric - 1) & 0x1);
ni->alt = !!((ictx->numeric - 1) & 0x2);
ni->ctrl = !!((ictx->numeric - 1) & 0x4);
// FIXME decode remaining modifiers through 128
// standard keyboard protocol reports ctrl+ascii as the capital form,
// so (for now) conform when using kitty protocol...
if(ni->id < 128 && islower(ni->id) && ni->ctrl){
ni->id = toupper(ni->id);
}
ni->x = 0;
ni->y = 0;
if(++ictx->iwrite == ictx->isize){ if(++ictx->iwrite == ictx->isize){
ictx->iwrite = 0; ictx->iwrite = 0;
} }
++ictx->ivalid; ++ictx->ivalid;
if(ni->ctrl && !ni->alt && !ni->shift){
if(ni->id == 'C'){
synth = SYNTH_SIGINT;
}else if(ni->id == '\\'){
synth = SYNTH_SIGQUIT;
}
}
pthread_mutex_unlock(&ictx->ilock); pthread_mutex_unlock(&ictx->ilock);
pthread_cond_broadcast(&ictx->icond); pthread_cond_broadcast(&ictx->icond);
#ifndef __MINGW64__ send_synth_signal(synth);
if(synth == SYNTH_SIGINT){
raise(SIGINT);
}else if(synth == SYNTH_SIGQUIT){
raise(SIGQUIT);
}
#else
(void)synth; // FIXME
#endif
} }
// FIXME ought implement the full Williams automaton // FIXME ought implement the full Williams automaton
@ -1147,7 +1158,11 @@ pump_control_read(inputctx* ictx, unsigned char c){
return -1; return -1;
} }
}else if(c == 'M'){ }else if(c == 'M'){
mouse_click(ictx); mouse_click(ictx, 0);
ictx->state = STATE_NULL;
return 2;
}else if(c == 'm'){
mouse_click(ictx, 1);
ictx->state = STATE_NULL; ictx->state = STATE_NULL;
return 2; return 2;
}else{ }else{
@ -1630,6 +1645,7 @@ process_escapes(inputctx* ictx, unsigned char* buf, int* bufused){
} }
logwarn("replaying %dB of %dB to ibuf\n", available, consumed); logwarn("replaying %dB of %dB to ibuf\n", available, consumed);
memcpy(ictx->ibuf + ictx->ibufvalid, buf + offset, available); memcpy(ictx->ibuf + ictx->ibufvalid, buf + offset, available);
ictx->ibufvalid += available;
} }
*bufused -= consumed; *bufused -= consumed;
offset += consumed; offset += consumed;
@ -1693,6 +1709,7 @@ process_input(const unsigned char* buf, int buflen, ncinput* ni){
// sticks that into the bulk queue. // sticks that into the bulk queue.
static int static int
process_ncinput(inputctx* ictx, const unsigned char* buf, int buflen){ process_ncinput(inputctx* ictx, const unsigned char* buf, int buflen){
fprintf(stderr, "PROCESSING UP TO %d BUF!\n", buflen);
pthread_mutex_lock(&ictx->ilock); pthread_mutex_lock(&ictx->ilock);
if(ictx->ivalid == ictx->isize){ if(ictx->ivalid == ictx->isize){
pthread_mutex_unlock(&ictx->ilock); pthread_mutex_unlock(&ictx->ilock);
@ -1837,29 +1854,37 @@ block_on_input(inputctx* ictx, unsigned* rtfd, unsigned* rifd){
#ifdef POLLRDHUP #ifdef POLLRDHUP
inevents |= POLLRDHUP; inevents |= POLLRDHUP;
#endif #endif
struct pollfd pfds[2] = { struct pollfd pfds[2];
{ int pfdcount = 0;
.fd = ictx->stdinfd, if(!ictx->stdineof){
.events = inevents, if(ictx->ibufvalid != sizeof(ictx->ibuf)){
.revents = 0, pfds[pfdcount].fd = ictx->stdinfd;
pfds[pfdcount].events = inevents;
pfds[pfdcount].revents = 0;
++pfdcount;
} }
}; }
int pfdcount = 1;
if(ictx->termfd >= 0){ if(ictx->termfd >= 0){
pfds[pfdcount].fd = ictx->termfd; pfds[pfdcount].fd = ictx->termfd;
pfds[pfdcount].events = inevents; pfds[pfdcount].events = inevents;
pfds[pfdcount].revents = 0; pfds[pfdcount].revents = 0;
++pfdcount; ++pfdcount;
} }
sigset_t smask;
sigfillset(&smask);
sigdelset(&smask, SIGCONT);
sigdelset(&smask, SIGWINCH);
if(pfdcount == 0){
loginfo("output queues full; blocking on signals\n");
int signum;
sigwait(&smask, &signum);
return 0;
}
int events; int events;
#if defined(__APPLE__) || defined(__MINGW64__) #if defined(__APPLE__) || defined(__MINGW64__)
int timeoutms = nonblock ? 0 : -1; int timeoutms = nonblock ? 0 : -1;
while((events = poll(pfds, pfdcount, timeoutms)) < 0){ // FIXME smask? while((events = poll(pfds, pfdcount, timeoutms)) < 0){ // FIXME smask?
#else #else
sigset_t smask;
sigfillset(&smask);
sigdelset(&smask, SIGCONT);
sigdelset(&smask, SIGWINCH);
struct timespec ts = { .tv_sec = 0, .tv_nsec = 0, }; struct timespec ts = { .tv_sec = 0, .tv_nsec = 0, };
struct timespec* pts = nonblock ? &ts : NULL; struct timespec* pts = nonblock ? &ts : NULL;
while((events = ppoll(pfds, pfdcount, pts, &smask)) < 0){ while((events = ppoll(pfds, pfdcount, pts, &smask)) < 0){
@ -1870,15 +1895,18 @@ block_on_input(inputctx* ictx, unsigned* rtfd, unsigned* rifd){
return resize_seen; return resize_seen;
} }
} }
loginfo("got events: %d\n", events); pfdcount = 0;
if(pfds[0].revents){ while(events){
*rifd = 1; if(pfds[pfdcount].revents){
if(events == 2){ if(pfds[pfdcount].fd == ictx->stdinfd){
*rtfd = 1; *rifd = 1;
}else if(pfds[pfdcount].fd == ictx->termfd){
*rtfd = 1;
}
--events;
} }
}else{
*rtfd = 1;
} }
loginfo("got events: %c%c %d\n", *rtfd ? 'T' : 't', *rifd ? 'I' : 'i', pfds[0].revents);
return events; return events;
#endif #endif
} }
@ -1894,13 +1922,13 @@ read_inputs_nblock(inputctx* ictx){
// first we read from the terminal, if that's a distinct source. // first we read from the terminal, if that's a distinct source.
if(rtfd){ if(rtfd){
read_input_nblock(ictx->termfd, ictx->tbuf, sizeof(ictx->tbuf), read_input_nblock(ictx->termfd, ictx->tbuf, sizeof(ictx->tbuf),
&ictx->tbufvalid); &ictx->tbufvalid, NULL);
} }
// now read bulk, possibly with term escapes intermingled within (if there // now read bulk, possibly with term escapes intermingled within (if there
// was not a distinct terminal source). // was not a distinct terminal source).
if(rifd){ if(rifd){
read_input_nblock(ictx->stdinfd, ictx->ibuf, sizeof(ictx->ibuf), read_input_nblock(ictx->stdinfd, ictx->ibuf, sizeof(ictx->ibuf),
&ictx->ibufvalid); &ictx->ibufvalid, &ictx->stdineof);
} }
} }

Loading…
Cancel
Save