windows: emit SIGWINCH when the console size changes
This commit is contained in:
parent
b12b6498d6
commit
564e7c765c
@ -65,6 +65,7 @@ typedef intptr_t ssize_t;
|
||||
*/
|
||||
#define SIGHUP 1
|
||||
#define SIGKILL 9
|
||||
#define SIGWINCH 28
|
||||
|
||||
/*
|
||||
* Guids and typedefs for winsock extension functions
|
||||
|
||||
@ -1608,6 +1608,13 @@ UV_EXTERN int uv_fs_poll_stop(uv_fs_poll_t* handle);
|
||||
* program is given approximately 10 seconds to perform cleanup. After that
|
||||
* Windows will unconditionally terminate it.
|
||||
*
|
||||
* SIGWINCH is raised whenever libuv detects that the console has been
|
||||
* resized. SIGWINCH is emulated by libuv when the program uses an uv_tty_t
|
||||
* handle to write to the console. SIGWINCH may not always be delivered in a
|
||||
* timely manner; libuv will only detect size changes when the cursor is
|
||||
* being moved. When a readable uv_tty_handle is used in raw mode, resizing
|
||||
* the console buffer will also trigger a SIGWINCH signal.
|
||||
*
|
||||
* Watchers for other signals can be successfully created, but these signals
|
||||
* are never generated. These signals are: SIGILL, SIGABRT, SIGFPE, SIGSEGV,
|
||||
* SIGTERM and SIGKILL.
|
||||
|
||||
@ -169,6 +169,10 @@ static uv_err_t uv__signal_register(int signum) {
|
||||
case SIGHUP:
|
||||
return uv__signal_register_control_handler();
|
||||
|
||||
case SIGWINCH:
|
||||
/* SIGWINCH is generated in tty.c. No need to register anything. */
|
||||
return uv_ok_;
|
||||
|
||||
case SIGILL:
|
||||
case SIGABRT_COMPAT:
|
||||
case SIGFPE:
|
||||
@ -193,6 +197,10 @@ static void uv__signal_unregister(int signum) {
|
||||
uv__signal_unregister_control_handler();
|
||||
return;
|
||||
|
||||
case SIGWINCH:
|
||||
/* SIGWINCH is generated in tty.c. No need to unregister anything. */
|
||||
return;
|
||||
|
||||
case SIGILL:
|
||||
case SIGABRT_COMPAT:
|
||||
case SIGFPE:
|
||||
|
||||
@ -82,6 +82,8 @@ static int uv_tty_virtual_width = -1;
|
||||
|
||||
static CRITICAL_SECTION uv_tty_output_lock;
|
||||
|
||||
static HANDLE uv_tty_output_handle = INVALID_HANDLE_VALUE;
|
||||
|
||||
|
||||
void uv_console_init() {
|
||||
InitializeCriticalSection(&uv_tty_output_lock);
|
||||
@ -113,10 +115,17 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Update the virtual window. We must hold the tty_output_lock because the */
|
||||
/* virtual window state is shared between all uv_tty handles. */
|
||||
/* Obtain the the tty_output_lock because the virtual window state is */
|
||||
/* shared between all uv_tty_t handles. */
|
||||
EnterCriticalSection(&uv_tty_output_lock);
|
||||
|
||||
/* Store the global tty output handle. This handle is used by TTY read */
|
||||
/* streams to update the virtual window when a CONSOLE_BUFFER_SIZE_EVENT */
|
||||
/* is received. */
|
||||
uv_tty_output_handle = handle;
|
||||
|
||||
uv_tty_update_virtual_window(&screen_buffer_info);
|
||||
|
||||
LeaveCriticalSection(&uv_tty_output_lock);
|
||||
}
|
||||
|
||||
@ -513,7 +522,20 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
|
||||
}
|
||||
records_left--;
|
||||
|
||||
/* Ignore events that are not keyboard events */
|
||||
/* If the window was resized, recompute the virtual window size. This */
|
||||
/* will trigger a SIGWINCH signal if the window size changed in an */
|
||||
/* way that matters to libuv. */
|
||||
if (handle->last_input_record.EventType == WINDOW_BUFFER_SIZE_EVENT) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
if (uv_tty_output_handle == INVALID_HANDLE_VALUE)
|
||||
continue;
|
||||
if (!GetConsoleScreenBufferInfo(uv_tty_output_handle, &info))
|
||||
continue;
|
||||
uv_tty_update_virtual_window(&info);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Ignore other events that are not key or resize events. */
|
||||
if (handle->last_input_record.EventType != KEY_EVENT) {
|
||||
continue;
|
||||
}
|
||||
@ -835,8 +857,11 @@ int uv_tty_read_stop(uv_tty_t* handle) {
|
||||
|
||||
|
||||
static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) {
|
||||
uv_tty_virtual_height = info->srWindow.Bottom - info->srWindow.Top + 1;
|
||||
int old_virtual_width = uv_tty_virtual_width;
|
||||
int old_virtual_height = uv_tty_virtual_height;
|
||||
|
||||
uv_tty_virtual_width = info->dwSize.X;
|
||||
uv_tty_virtual_height = info->srWindow.Bottom - info->srWindow.Top + 1;
|
||||
|
||||
/* Recompute virtual window offset row. */
|
||||
if (uv_tty_virtual_offset == -1) {
|
||||
@ -854,6 +879,14 @@ static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) {
|
||||
if (uv_tty_virtual_offset < 0) {
|
||||
uv_tty_virtual_offset = 0;
|
||||
}
|
||||
|
||||
/* If the virtual window size changed, emit a SIGWINCH signal. Don't emit */
|
||||
/* if this was the first time the virtual window size was computed. */
|
||||
if (old_virtual_width != -1 && old_virtual_height != -1 &&
|
||||
(uv_tty_virtual_width != old_virtual_width ||
|
||||
uv_tty_virtual_height != old_virtual_height)) {
|
||||
uv__signal_dispatch(SIGWINCH);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user