Skip to content

Instantly share code, notes, and snippets.

@adsr
Created November 30, 2021 01:18
Show Gist options
  • Select an option

  • Save adsr/0e670edf4e5a29e92d010a865c1f5b25 to your computer and use it in GitHub Desktop.

Select an option

Save adsr/0e670edf4e5a29e92d010a865c1f5b25 to your computer and use it in GitHub Desktop.
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