[input] break up events #2174

pull/2197/head
nick black 3 years ago committed by nick black
parent 24eac43f4f
commit e12aceccce

@ -198,7 +198,7 @@ void Tick(ncpp::NotCurses* nc, uint64_t sec) {
void Ticker(ncpp::NotCurses* nc) { void Ticker(ncpp::NotCurses* nc) {
do{ do{
std::this_thread::sleep_for(std::chrono::milliseconds{100}); std::this_thread::sleep_for(std::chrono::milliseconds{1000});
const uint64_t sec = (timenow_to_ns() - start) / NANOSECS_IN_SEC; const uint64_t sec = (timenow_to_ns() - start) / NANOSECS_IN_SEC;
Tick(nc, sec); Tick(nc, sec);
}while(!done); }while(!done);
@ -309,6 +309,11 @@ int input_demo(ncpp::NotCurses* nc) {
n->printf("Unicode: [0x%08x] '%lc'", r, (wchar_t)r); n->printf("Unicode: [0x%08x] '%lc'", r, (wchar_t)r);
} }
} }
int x;
n->get_cursor_yx(nullptr, &x);
for(int i = x ; i < n->get_dim_x() ; ++i){
n->putc(' ');
}
if(!dim_rows(n)){ if(!dim_rows(n)){
break; break;
} }

@ -1000,6 +1000,7 @@ kitty_kbd(inputctx* ictx){
// FIXME sloppy af in general // FIXME sloppy af in general
// returns 1 after handling the Device Attributes response, 0 if more input // returns 1 after handling the Device Attributes response, 0 if more input
// ought be fed to the machine, and -1 on an invalid state transition. // ought be fed to the machine, and -1 on an invalid state transition.
// returns 2 on a valid accept state that is not the final state.
static int static int
pump_control_read(inputctx* ictx, unsigned char c){ pump_control_read(inputctx* ictx, unsigned char c){
logdebug("state: %2d char: %1c %3d %02x\n", ictx->state, isprint(c) ? c : ' ', c, c); logdebug("state: %2d char: %1c %3d %02x\n", ictx->state, isprint(c) ? c : ' ', c, c);
@ -1044,6 +1045,7 @@ pump_control_read(inputctx* ictx, unsigned char c){
case STATE_APC_ST: case STATE_APC_ST:
if(c == '\\'){ if(c == '\\'){
ictx->state = STATE_NULL; ictx->state = STATE_NULL;
return 2;
}else{ }else{
ictx->state = STATE_APC_DRAIN; ictx->state = STATE_APC_DRAIN;
} }
@ -1070,7 +1072,7 @@ pump_control_read(inputctx* ictx, unsigned char c){
return -1; return -1;
} }
ictx->state = STATE_NULL; ictx->state = STATE_NULL;
break; return 2;
} }
ictx->numeric = c; ictx->numeric = c;
if(ruts_string(ictx, STATE_BG1)){ if(ruts_string(ictx, STATE_BG1)){
@ -1181,6 +1183,7 @@ pump_control_read(inputctx* ictx, unsigned char c){
} }
} }
ictx->state = STATE_NULL; ictx->state = STATE_NULL;
return 2;
}else if(c == 't'){ }else if(c == 't'){
//fprintf(stderr, "CELLS X: %d\n", ictx->numeric); //fprintf(stderr, "CELLS X: %d\n", ictx->numeric);
if(ictx->initdata){ if(ictx->initdata){
@ -1188,6 +1191,7 @@ pump_control_read(inputctx* ictx, unsigned char c){
ictx->initdata->dimy = ictx->p2; ictx->initdata->dimy = ictx->p2;
} }
ictx->state = STATE_NULL; ictx->state = STATE_NULL;
return 2;
}else if(c == 'u'){ }else if(c == 'u'){
// kitty keyboard protocol // kitty keyboard protocol
kitty_kbd(ictx); kitty_kbd(ictx);
@ -1225,6 +1229,7 @@ pump_control_read(inputctx* ictx, unsigned char c){
loginfo("got pixel geometry: %d/%d\n", ictx->initdata->pixy, ictx->initdata->pixx); loginfo("got pixel geometry: %d/%d\n", ictx->initdata->pixy, ictx->initdata->pixx);
} }
ictx->state = STATE_NULL; ictx->state = STATE_NULL;
return 2;
}else{ }else{
ictx->state = STATE_NULL; ictx->state = STATE_NULL;
} }
@ -1240,6 +1245,7 @@ pump_control_read(inputctx* ictx, unsigned char c){
loginfo("got cell geometry: %d/%d\n", ictx->initdata->dimy, ictx->initdata->dimx); loginfo("got cell geometry: %d/%d\n", ictx->initdata->dimy, ictx->initdata->dimx);
} }
ictx->state = STATE_NULL; ictx->state = STATE_NULL;
return 2;
}else{ }else{
ictx->state = STATE_NULL; ictx->state = STATE_NULL;
} }
@ -1373,6 +1379,7 @@ pump_control_read(inputctx* ictx, unsigned char c){
case STATE_SDA_DRAIN: case STATE_SDA_DRAIN:
if(c == 'c'){ if(c == 'c'){
ictx->state = STATE_NULL; ictx->state = STATE_NULL;
return 2;
} }
break; break;
// primary device attributes and XTSMGRAPHICS replies are generally // primary device attributes and XTSMGRAPHICS replies are generally
@ -1480,6 +1487,8 @@ pump_control_read(inputctx* ictx, unsigned char c){
ictx->initdata->sixelx = ictx->p4; ictx->initdata->sixelx = ictx->p4;
ictx->initdata->sixely = ictx->numeric; ictx->initdata->sixely = ictx->numeric;
loginfo("max sixel geometry: %dx%d\n", ictx->initdata->sixely, ictx->initdata->sixelx); loginfo("max sixel geometry: %dx%d\n", ictx->initdata->sixely, ictx->initdata->sixelx);
ictx->state = STATE_NULL;
return 2;
} }
}else if(c >= 0x40 && c <= 0x7E){ }else if(c >= 0x40 && c <= 0x7E){
ictx->state = STATE_NULL; ictx->state = STATE_NULL;
@ -1499,6 +1508,7 @@ pump_control_read(inputctx* ictx, unsigned char c){
case STATE_APPSYNC_REPORT_DRAIN: case STATE_APPSYNC_REPORT_DRAIN:
if(c == 'y'){ if(c == 'y'){
ictx->state = STATE_NULL; ictx->state = STATE_NULL;
return 2;
} }
break; break;
default: default:
@ -1526,7 +1536,6 @@ handoff_initial_responses(inputctx* ictx){
static int static int
process_escape(inputctx* ictx, const unsigned char* buf, int buflen){ process_escape(inputctx* ictx, const unsigned char* buf, int buflen){
assert(1 <= buflen); assert(1 <= buflen);
ictx->midescape = 0;
// FIXME given that we keep our state across invocations, we want buf offset // FIXME given that we keep our state across invocations, we want buf offset
// by the amount we handled the last iteration, if any was left over... // by the amount we handled the last iteration, if any was left over...
// until then, we reset the state on entry. remove that once we preserve! // until then, we reset the state on entry. remove that once we preserve!
@ -1610,7 +1619,8 @@ process_escapes(inputctx* ictx, unsigned char* buf, int* bufused){
// the end of the tbuf, in which case we really do try reading more. if // the end of the tbuf, in which case we really do try reading more. if
// this was not a sequence, we'll catch it on the next read. // this was not a sequence, we'll catch it on the next read.
if(consumed < 0){ if(consumed < 0){
if(!ictx->midescape){ int tavailable = sizeof(ictx->tbuf) - (offset + *bufused - consumed);
if(!ictx->midescape || tavailable){
consumed = -consumed; consumed = -consumed;
int available = sizeof(ictx->ibuf) - ictx->ibufvalid; int available = sizeof(ictx->ibuf) - ictx->ibufvalid;
if(available){ if(available){
@ -1622,6 +1632,7 @@ process_escapes(inputctx* ictx, unsigned char* buf, int* bufused){
} }
*bufused -= consumed; *bufused -= consumed;
offset += consumed; offset += consumed;
ictx->midescape = 0;
} }
break; break;
} }
@ -1741,9 +1752,10 @@ process_melange(inputctx* ictx, const unsigned char* buf, int* bufused){
consumed = process_escape(ictx, buf + offset, *bufused); consumed = process_escape(ictx, buf + offset, *bufused);
if(consumed < 0){ if(consumed < 0){
if(ictx->midescape){ if(ictx->midescape){
if(-consumed != *bufused){ // not at the end; treat it as input if(offset + *bufused - consumed != sizeof(ictx->ibuf)){
// no need to move between buffers; simply ensure we process it as // not at the end; treat it as input. no need to move between
// input, and don't mark anything as consumed. // buffers; simply ensure we process it as input, and don't mark
// anything as consumed.
ictx->midescape = 0; ictx->midescape = 0;
} }
} }
@ -1796,14 +1808,22 @@ int ncinput_shovel(inputctx* ictx, const void* buf, int len){
return 0; return 0;
} }
// FIXME if ictx->midescape is set, need a nonblocking read! // here, we always block for an arbitrarily long time, or not at all,
// doing the latter only when ictx->midescape is set. |rtfd| and/or |rifd|
// are set high iff they are ready for reading, and otherwise cleared.
static int static int
block_on_input(inputctx* ictx){ block_on_input(inputctx* ictx, unsigned* rtfd, unsigned* rifd){
struct timespec* ts = NULL; // FIXME *rtfd = *rifd = 0;
unsigned nonblock = ictx->midescape;
if(nonblock){
loginfo("nonblocking read to check for completion\n");
ictx->midescape = 0;
}
#ifdef __MINGW64__ #ifdef __MINGW64__
int timeoutms = ts ? ts->tv_sec * 1000 + ts->tv_nsec / 1000000 : -1; int timeoutms = nonblock ? 0 : -1;
DWORD d = WaitForMultipleObjects(1, &ictx->stdinhandle, FALSE, timeoutms); DWORD d = WaitForMultipleObjects(1, &ictx->stdinhandle, FALSE, timeoutms);
if(d == WAIT_TIMEOUT){ if(d == WAIT_TIMEOUT){
*rifd = 1;
return 0; return 0;
}else if(d == WAIT_FAILED){ }else if(d == WAIT_FAILED){
return -1; return -1;
@ -1832,14 +1852,16 @@ block_on_input(inputctx* ictx){
} }
int events; int events;
#if defined(__APPLE__) || defined(__MINGW64__) #if defined(__APPLE__) || defined(__MINGW64__)
int timeoutms = ts ? ts->tv_sec * 1000 + ts->tv_nsec / 1000000 : -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; sigset_t smask;
sigfillset(&smask); sigfillset(&smask);
sigdelset(&smask, SIGCONT); sigdelset(&smask, SIGCONT);
sigdelset(&smask, SIGWINCH); sigdelset(&smask, SIGWINCH);
while((events = ppoll(pfds, pfdcount, ts, &smask)) < 0){ struct timespec ts = { .tv_sec = 0, .tv_nsec = 0, };
struct timespec* pts = nonblock ? &ts : NULL;
while((events = ppoll(pfds, pfdcount, pts, &smask)) < 0){
#endif #endif
if(errno != EAGAIN && errno != EBUSY && errno != EWOULDBLOCK){ if(errno != EAGAIN && errno != EBUSY && errno != EWOULDBLOCK){
return -1; return -1;
@ -1847,6 +1869,15 @@ block_on_input(inputctx* ictx){
return resize_seen; return resize_seen;
} }
} }
loginfo("got events: %d\n", events);
if(pfds[0].revents){
*rifd = 1;
if(events == 2){
*rtfd = 1;
}
}else{
*rtfd = 1;
}
return events; return events;
#endif #endif
} }
@ -1855,16 +1886,21 @@ block_on_input(inputctx* ictx){
// don't loop around this call without some kind of readiness notification. // don't loop around this call without some kind of readiness notification.
static void static void
read_inputs_nblock(inputctx* ictx){ read_inputs_nblock(inputctx* ictx){
unsigned rtfd, rifd;
// FIXME also need to wake up if our output queues have space that has // FIXME also need to wake up if our output queues have space that has
// opened up for us to write into, lest we deadlock with full buffers... // opened up for us to write into, lest we deadlock with full buffers...
block_on_input(ictx); block_on_input(ictx, &rtfd, &rifd);
// first we read from the terminal, if that's a distinct source. // first we read from the terminal, if that's a distinct source.
read_input_nblock(ictx->termfd, ictx->tbuf, sizeof(ictx->tbuf), if(rtfd){
&ictx->tbufvalid); read_input_nblock(ictx->termfd, ictx->tbuf, sizeof(ictx->tbuf),
&ictx->tbufvalid);
}
// 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).
read_input_nblock(ictx->stdinfd, ictx->ibuf, sizeof(ictx->ibuf), if(rifd){
&ictx->ibufvalid); read_input_nblock(ictx->stdinfd, ictx->ibuf, sizeof(ictx->ibuf),
&ictx->ibufvalid);
}
} }
static void* static void*

@ -86,6 +86,7 @@ reset_terminal(){
tios.c_lflag |= ISIG | ICANON | ECHO; tios.c_lflag |= ISIG | ICANON | ECHO;
tcsetattr(fd, TCSADRAIN, &tios); tcsetattr(fd, TCSADRAIN, &tios);
} }
printf("\x1b[<u"); // pop any kitty keyboard state we set
char* str = tigetstr("sgr0"); char* str = tigetstr("sgr0");
if(str != (char*)-1){ if(str != (char*)-1){
printf("%s", str); printf("%s", str);

Loading…
Cancel
Save