Created
November 30, 2021 01:18
-
-
Save adsr/0e670edf4e5a29e92d010a865c1f5b25 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/termbox.h b/termbox.h | |
| index b4ce055..81dfc3a 100644 | |
| --- a/termbox.h | |
| +++ b/termbox.h | |
| @@ -534,21 +534,22 @@ struct tb_global_t { | |
| const char *caps[TB_CAP__COUNT]; | |
| struct cap_trie_t cap_trie; | |
| struct bytebuf_t in; | |
| struct bytebuf_t out; | |
| struct cellbuf_t back; | |
| struct cellbuf_t front; | |
| struct termios orig_tios; | |
| int has_orig_tios; | |
| int last_errno; | |
| int initialized; | |
| - int need_resize; | |
| + int pending_resize; | |
| + int received_resize; | |
| int (*fn_extract_esc_pre)(struct tb_event *, size_t *); | |
| int (*fn_extract_esc_post)(struct tb_event *, size_t *); | |
| }; | |
| struct tb_global_t global = {0}; | |
| /* BEGIN codegen c */ | |
| /* Produced by ./codegen.sh on Sun, 19 Sep 2021 01:02:03 +0000 */ | |
| static const int16_t terminfo_cap_indexes[] = { | |
| @@ -2243,21 +2244,28 @@ static int wait_event(struct tb_event *event, struct timeval *timeout) { | |
| FD_SET(global.rfd, &rfds); | |
| FD_SET(global.resize_pipefd[0], &rfds); | |
| int maxfd = global.resize_pipefd[0] > global.rfd | |
| ? global.resize_pipefd[0] | |
| : global.rfd; | |
| int select_rv = select(maxfd + 1, &rfds, NULL, NULL, timeout); | |
| if (select_rv < 0) { | |
| - // Let EINTR/EAGAIN bubble up | |
| + // If we were interrupted by a resize signal, try again. On the next | |
| + // select call, we should see activity on resize_pipefd. | |
| + // | |
| + // For all other errors, return to caller. | |
| + if (errno == EINTR && global.received_resize) { | |
| + global.received_resize = 0; | |
| + continue; | |
| + } | |
| global.last_errno = errno; | |
| return TB_ERR_SELECT; | |
| } else if (select_rv == 0) { | |
| return TB_ERR_NO_EVENT; | |
| } | |
| if (FD_ISSET(global.rfd, &rfds)) { | |
| ssize_t read_rv = read(global.rfd, buf, sizeof(buf)); | |
| if (read_rv < 0) { | |
| global.last_errno = errno; | |
| @@ -2267,21 +2275,22 @@ static int wait_event(struct tb_event *event, struct timeval *timeout) { | |
| } | |
| } | |
| if (FD_ISSET(global.resize_pipefd[0], &rfds)) { | |
| int ignore = 0; | |
| read(global.resize_pipefd[0], &ignore, sizeof(ignore)); | |
| if_err_return(rv, update_term_size()); | |
| event->type = TB_EVENT_RESIZE; | |
| event->w = global.width; | |
| event->h = global.height; | |
| - global.need_resize = 1; | |
| + global.received_resize = 0; | |
| + global.pending_resize = 1; | |
| return TB_OK; | |
| } | |
| memset(event, 0, sizeof(*event)); | |
| if_ok_return(rv, extract_event(event)); | |
| } while (!timeout || timeout->tv_sec > 0 || timeout->tv_usec > 0); | |
| return TB_ERR_NO_EVENT; | |
| } | |
| @@ -2552,33 +2561,34 @@ static int extract_esc_mouse(struct tb_event *event) { | |
| return mi + 1; | |
| } | |
| return 0; | |
| */ | |
| } | |
| static int resize_if_needed() { | |
| int rv; | |
| - if (!global.need_resize) { | |
| + if (!global.pending_resize) { | |
| return TB_OK; | |
| } | |
| if_err_return(rv, update_term_size()); // TODO is this needed? | |
| if_err_return(rv, cellbuf_resize(&global.back, global.width, global.height)); | |
| if_err_return(rv, cellbuf_resize(&global.front, global.width, global.height)); | |
| if_err_return(rv, cellbuf_clear(&global.front)); | |
| if_err_return(rv, send_clear()); | |
| - global.need_resize = 0; | |
| + global.pending_resize = 0; | |
| return TB_OK; | |
| } | |
| static void handle_resize(int sig) { | |
| + global.received_resize = 1; | |
| write(global.resize_pipefd[1], &sig, sizeof(sig)); | |
| } | |
| static int send_attr(uintattr_t fg, uintattr_t bg) { | |
| int rv; | |
| if (fg == global.last_fg && bg == global.last_bg) { | |
| return TB_OK; | |
| } | |
| diff --git a/tests/run.sh b/tests/run.sh | |
| index aef325d..7f20602 100755 | |
| --- a/tests/run.sh | |
| +++ b/tests/run.sh | |
| @@ -45,28 +45,31 @@ main() { | |
| while ! test -e $xvfb_pipe; do | |
| echo -n . | |
| max_wait=$((max_wait-1)) | |
| [ "$max_wait" -le 0 ] && break | |
| sleep 1 | |
| done | |
| echo | |
| # run test_bin in xterm in Xvfb | |
| echo ' running test in xterm' | |
| + php_cmd="php -d auto_prepend_file=$this_dir/test_ffi.php $test_php $test_log_cmd &>$test_log_php" | |
| + # echo " php_cmd=$php_cmd" | |
| xterm -display $x_display \ | |
| -u8 -geometry $xterm_geom -bg $xterm_bg -fg $xterm_fg \ | |
| -xrm 'xterm*metaSendsEscape:true' \ | |
| + -xrm 'xterm*allowWindowOps:true' \ | |
| -xrm 'xterm*translations:#override\nShift <Key>Home:print-immediate()' \ | |
| -xrm 'xterm*printOptsImmediate:1' \ | |
| -xrm 'xterm*printModeImmediate:2' \ | |
| -xrm "xterm*printFileImmediate:$test_log_xterm" \ | |
| - -e "php -d auto_prepend_file=$this_dir/test_ffi.php $test_php $test_log_cmd &>$test_log_php" \ | |
| + -e "$php_cmd" \ | |
| &>/dev/null & | |
| local xterm_pid=$! | |
| # tail test_log_cmd until we see 'screencap' | |
| local test_log_cursor=0 | |
| local test_log_size=0 | |
| local test_end_ts=$(($(date +%s) + $timeout_s)) | |
| while true; do | |
| test_log_size=$(stat --format=%s $test_log_cmd 2>/dev/null) | |
| [ -z "$test_log_size" ] && break # stat failed or deleted | |
| diff --git a/tests/test_ffi.php b/tests/test_ffi.php | |
| index 2194c1c..5fbaaf6 100644 | |
| --- a/tests/test_ffi.php | |
| +++ b/tests/test_ffi.php | |
| @@ -76,20 +76,27 @@ $test = new class() { | |
| $sh_cmd = sprintf( | |
| 'sh -c %s >/dev/null 2>&1', | |
| escapeshellarg($cmd) | |
| ); | |
| $output = []; | |
| $exit_code = 1; | |
| exec($sh_cmd, $output, $exit_code); | |
| return $exit_code; | |
| } | |
| + public function resize(int $w, int $h): void { | |
| + file_put_contents( | |
| + '/dev/tty', | |
| + sprintf("\x1b[8;%d;%dt", $h, $w) | |
| + ); | |
| + } | |
| + | |
| public function log(string $str): void { | |
| $lines = explode("\n", $str); | |
| foreach ($lines as $line) { | |
| file_put_contents($this->test_log, " $line\n", FILE_APPEND); | |
| } | |
| } | |
| public function screencap(): void { | |
| $this->log('screencap'); | |
| sleep(PHP_INT_MAX); | |
| diff --git a/tests/test_resize/expected.ansi b/tests/test_resize/expected.ansi | |
| new file mode 100644 | |
| index 0000000..7dde896 | |
| Binary files /dev/null and b/tests/test_resize/expected.ansi differ | |
| diff --git a/tests/test_resize/test.php b/tests/test_resize/test.php | |
| new file mode 100755 | |
| index 0000000..42886a5 | |
| --- /dev/null | |
| +++ b/tests/test_resize/test.php | |
| @@ -0,0 +1,23 @@ | |
| +<?php | |
| +declare(strict_types=1); | |
| + | |
| +$test->ffi->tb_init(); | |
| + | |
| +$orig_w = $test->ffi->tb_width(); | |
| +$orig_h = $test->ffi->tb_height(); | |
| + | |
| +$test->resize($orig_w - 1, $orig_h - 1); | |
| +$event = $test->ffi->new('struct tb_event'); | |
| +$rv = $test->ffi->tb_poll_event(FFI::addr($event)); | |
| + | |
| +$new_w = $test->ffi->tb_width(); | |
| +$new_h = $test->ffi->tb_height(); | |
| + | |
| +$test->ffi->tb_printf(0, 0, 0, 0, | |
| + 'orig_w,h=%d,%d new_w,h=%d,%d rv=%d event_type=%d', | |
| + $orig_w, $orig_h, $new_w, $new_h, $rv, $event->type | |
| +); | |
| + | |
| +$test->ffi->tb_present(); | |
| + | |
| +$test->screencap(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment