Skip to content
This repository has been archived by the owner on May 4, 2018. It is now read-only.

Commit

Permalink
windows: emit SIGWINCH when the console size changes
Browse files Browse the repository at this point in the history
  • Loading branch information
piscisaureus committed Aug 21, 2012
1 parent b12b649 commit 564e7c7
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 4 deletions.
1 change: 1 addition & 0 deletions include/uv-private/uv-win.h
Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions include/uv.h
Expand Up @@ -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.
Expand Down
8 changes: 8 additions & 0 deletions src/win/signal.c
Expand Up @@ -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:
Expand All @@ -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:
Expand Down
41 changes: 37 additions & 4 deletions src/win/tty.c
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand All @@ -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);
}
}


Expand Down

1 comment on commit 564e7c7

@TooTallNate
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:)

Please sign in to comment.