Jacek Caban : conhost: Update tty output in IOCTL_CONDRV_ACTIVATE.
Alexandre Julliard
julliard at winehq.org
Fri Sep 4 15:47:32 CDT 2020
Module: wine
Branch: master
Commit: 3885b32bc8995bbb171ffdc7af7d402df1b0534e
URL: https://source.winehq.org/git/wine.git/?a=commit;h=3885b32bc8995bbb171ffdc7af7d402df1b0534e
Author: Jacek Caban <jacek at codeweavers.com>
Date: Fri Sep 4 13:52:01 2020 +0200
conhost: Update tty output in IOCTL_CONDRV_ACTIVATE.
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
programs/conhost/conhost.c | 14 ++++++-
programs/conhost/tests/tty.c | 97 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 109 insertions(+), 2 deletions(-)
diff --git a/programs/conhost/conhost.c b/programs/conhost/conhost.c
index 9edd5971b8..9830ff0182 100644
--- a/programs/conhost/conhost.c
+++ b/programs/conhost/conhost.c
@@ -451,6 +451,17 @@ static NTSTATUS write_console_input( struct console *console, const INPUT_RECORD
return STATUS_SUCCESS;
}
+static NTSTATUS screen_buffer_activate( struct screen_buffer *screen_buffer )
+{
+ RECT update_rect;
+ TRACE( "%p\n", screen_buffer );
+ screen_buffer->console->active = screen_buffer;
+ SetRect( &update_rect, 0, 0, screen_buffer->width - 1, screen_buffer->height - 1);
+ update_output( screen_buffer, &update_rect );
+ tty_sync( screen_buffer->console );
+ return STATUS_SUCCESS;
+}
+
static NTSTATUS get_output_info( struct screen_buffer *screen_buffer, size_t *out_size )
{
struct condrv_output_info *info;
@@ -1043,8 +1054,7 @@ static NTSTATUS screen_buffer_ioctl( struct screen_buffer *screen_buffer, unsign
case IOCTL_CONDRV_ACTIVATE:
if (in_size || *out_size) return STATUS_INVALID_PARAMETER;
- screen_buffer->console->active = screen_buffer;
- return STATUS_SUCCESS;
+ return screen_buffer_activate( screen_buffer );
case IOCTL_CONDRV_GET_MODE:
{
diff --git a/programs/conhost/tests/tty.c b/programs/conhost/tests/tty.c
index c28928701f..9c0ec8493b 100644
--- a/programs/conhost/tests/tty.c
+++ b/programs/conhost/tests/tty.c
@@ -145,8 +145,10 @@ static BOOL expect_erase_line_(unsigned line, unsigned int cnt)
enum req_type
{
+ REQ_CREATE_SCREEN_BUFFER,
REQ_FILL_CHAR,
REQ_SCROLL,
+ REQ_SET_ACTIVE,
REQ_SET_CURSOR,
REQ_SET_TITLE,
REQ_WRITE_CHARACTERS,
@@ -160,6 +162,7 @@ struct pseudoconsole_req
{
WCHAR string[1];
COORD coord;
+ HANDLE handle;
struct
{
COORD coord;
@@ -234,6 +237,33 @@ static void child_set_cursor(const unsigned int x, unsigned int y)
ok(ret, "WriteFile failed: %u\n", GetLastError());
}
+static HANDLE child_create_screen_buffer(void)
+{
+ struct pseudoconsole_req req;
+ HANDLE handle;
+ DWORD count;
+ BOOL ret;
+
+ req.type = REQ_CREATE_SCREEN_BUFFER;
+ ret = WriteFile(child_pipe, &req, sizeof(req), &count, NULL);
+ ok(ret, "WriteFile failed: %u\n", GetLastError());
+ ret = ReadFile(child_pipe, &handle, sizeof(handle), &count, NULL);
+ ok(ret, "ReadFile failed: %u\n", GetLastError());
+ return handle;
+}
+
+static void child_set_active(HANDLE handle)
+{
+ struct pseudoconsole_req req;
+ DWORD count;
+ BOOL ret;
+
+ req.type = REQ_SET_ACTIVE;
+ req.u.handle = handle;
+ ret = WriteFile(child_pipe, &req, sizeof(req), &count, NULL);
+ ok(ret, "WriteFile failed: %u\n", GetLastError());
+}
+
#define child_write_output(a,b,c,d,e,f,g,h,j,k,l,m,n) child_write_output_(__LINE__,a,b,c,d,e,f,g,h,j,k,l,m,n)
static void child_write_output_(unsigned int line, CHAR_INFO *buf, unsigned int size_x, unsigned int size_y,
unsigned int coord_x, unsigned int coord_y, unsigned int left,
@@ -303,6 +333,7 @@ static void child_fill_character(WCHAR ch, DWORD count, int x, int y)
static void test_tty_output(void)
{
CHAR_INFO char_info_buf[2048], char_info;
+ HANDLE sb, sb2;
unsigned int i;
/* simple write chars */
@@ -532,6 +563,52 @@ static void test_tty_output(void)
expect_output_sequence("\x1b[4;3H"); /* set cursor */
expect_output_sequence("\x1b[?25h"); /* show cursor */
expect_empty_output();
+
+ sb = child_create_screen_buffer();
+ child_set_active(sb);
+ expect_hide_cursor();
+ expect_output_sequence("\x1b[H"); /* set cursor */
+ for (i = 0; i < 40; i++)
+ {
+ expect_erase_line(30);
+ if (i != 39) expect_output_sequence("\r\n");
+ }
+ expect_output_sequence("\x1b[H"); /* set cursor */
+ expect_output_sequence("\x1b[?25h"); /* show cursor */
+ expect_empty_output();
+
+ child_write_characters(L"new sb", 0, 0);
+ skip_hide_cursor();
+ expect_output_sequence("new sb");
+ ok(skip_sequence("\x1b[H") || skip_sequence("\r"), "expected set cursor\n");
+ skip_sequence("\x1b[?25h"); /* show cursor */
+ expect_empty_output();
+
+ sb2 = child_create_screen_buffer();
+ child_set_active(sb2);
+ expect_hide_cursor();
+ for (i = 0; i < 40; i++)
+ {
+ expect_erase_line(30);
+ if (i != 39) expect_output_sequence("\r\n");
+ }
+ expect_output_sequence("\x1b[H"); /* set cursor */
+ expect_output_sequence("\x1b[?25h"); /* show cursor */
+ expect_empty_output();
+
+ child_set_active(sb);
+ expect_hide_cursor();
+ expect_output_sequence("new sb");
+ expect_erase_line(24);
+ expect_output_sequence("\r\n");
+ for (i = 1; i < 40; i++)
+ {
+ expect_erase_line(30);
+ if (i != 39) expect_output_sequence("\r\n");
+ }
+ expect_output_sequence("\x1b[H"); /* set cursor */
+ expect_output_sequence("\x1b[?25h"); /* show cursor */
+ expect_empty_output();
}
static void child_process(HANDLE pipe)
@@ -552,6 +629,20 @@ static void child_process(HANDLE pipe)
const struct pseudoconsole_req *req = (void *)buf;
switch (req->type)
{
+ case REQ_CREATE_SCREEN_BUFFER:
+ {
+ HANDLE handle;
+ DWORD count;
+ SetLastError(0xdeadbeef);
+ handle = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ CONSOLE_TEXTMODE_BUFFER, NULL);
+ ok(handle != INVALID_HANDLE_VALUE, "CreateConsoleScreenBuffer failed: %u\n", GetLastError());
+ ret = WriteFile(pipe, &handle, sizeof(handle), &count, NULL);
+ ok(ret, "WriteFile failed: %u\n", GetLastError());
+ break;
+ }
+
case REQ_SCROLL:
ret = ScrollConsoleScreenBufferW(output, &req->u.scroll.rect, NULL, req->u.scroll.dst, &req->u.scroll.fill);
ok(ret, "ScrollConsoleScreenBuffer failed: %u\n", GetLastError());
@@ -563,6 +654,12 @@ static void child_process(HANDLE pipe)
ok(count == req->u.fill.count, "count = %u, expected %u\n", count, req->u.fill.count);
break;
+ case REQ_SET_ACTIVE:
+ output = req->u.handle;
+ ret = SetConsoleActiveScreenBuffer(output);
+ ok(ret, "SetConsoleActiveScreenBuffer failed: %u\n", GetLastError());
+ break;
+
case REQ_SET_CURSOR:
ret = SetConsoleCursorPosition(output, req->u.coord);
ok(ret, "SetConsoleCursorPosition failed: %u\n", GetLastError());
More information about the wine-cvs
mailing list