From da86e50e2936789c9e9a963d67e1207504c16784 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Tue, 17 Aug 2021 12:29:23 +0200 Subject: [PATCH] conhost: Use message window to return a window for windowless consoles. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=38640 Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- dlls/kernel32/tests/console.c | 4 ++ programs/conhost/conhost.c | 7 ++-- programs/conhost/conhost.h | 1 + programs/conhost/window.c | 71 +++++++++++++++++++++++++---------- 4 files changed, 60 insertions(+), 23 deletions(-) diff --git a/dlls/kernel32/tests/console.c b/dlls/kernel32/tests/console.c index bd5cad428bc..759a0572b13 100644 --- a/dlls/kernel32/tests/console.c +++ b/dlls/kernel32/tests/console.c @@ -4355,6 +4355,7 @@ static void test_pseudo_console_child(HANDLE input, HANDLE output) CONSOLE_SCREEN_BUFFER_INFO sb_info; CONSOLE_CURSOR_INFO cursor_info; DWORD mode; + HWND hwnd; BOOL ret; ret = GetConsoleMode(input, &mode); @@ -4408,6 +4409,9 @@ static void test_pseudo_console_child(HANDLE input, HANDLE output) ok(cursor_info.dwSize == 25, "dwSize = %u\n", cursor_info.dwSize); ok(cursor_info.bVisible == TRUE, "bVisible = %x\n", cursor_info.bVisible); + hwnd = GetConsoleWindow(); + ok(IsWindow(hwnd), "no console window\n"); + test_console_title(); test_WriteConsoleInputW(input); } diff --git a/programs/conhost/conhost.c b/programs/conhost/conhost.c index eeca9e62a3f..9bfc5f84242 100644 --- a/programs/conhost/conhost.c +++ b/programs/conhost/conhost.c @@ -349,7 +349,7 @@ static void update_output( struct screen_buffer *screen_buffer, RECT *rect ) TRACE( "%s\n", wine_dbgstr_rect( rect )); - if (screen_buffer->console->win) + if (screen_buffer->console->window) { update_window_region( screen_buffer->console, rect ); return; @@ -2529,6 +2529,7 @@ static NTSTATUS console_input_ioctl( struct console *console, unsigned int code, TRACE( "get window\n" ); if (in_size || *out_size != sizeof(*result)) return STATUS_INVALID_PARAMETER; if (!(result = alloc_ioctl_buffer( sizeof(*result )))) return STATUS_NO_MEMORY; + if (!console->win) init_message_window( console ); *result = condrv_handle( console->win ); return STATUS_SUCCESS; } @@ -2664,7 +2665,6 @@ static int main_loop( struct console *console, HANDLE signal ) unsigned short signal_id; IO_STATUS_BLOCK signal_io; NTSTATUS status; - BOOL pump_msgs; DWORD res; if (signal) @@ -2680,11 +2680,10 @@ static int main_loop( struct console *console, HANDLE signal ) wait_handles[wait_cnt++] = console->server; if (signal) wait_handles[wait_cnt++] = signal_event; if (console->input_thread) wait_handles[wait_cnt++] = console->input_thread; - pump_msgs = console->win != NULL; for (;;) { - if (pump_msgs) + if (console->win) res = MsgWaitForMultipleObjects( wait_cnt, wait_handles, FALSE, INFINITE, QS_ALLINPUT ); else res = WaitForMultipleObjects( wait_cnt, wait_handles, FALSE, INFINITE ); diff --git a/programs/conhost/conhost.h b/programs/conhost/conhost.h index 1813676dc72..5e9b999380c 100644 --- a/programs/conhost/conhost.h +++ b/programs/conhost/conhost.h @@ -131,6 +131,7 @@ struct screen_buffer }; BOOL init_window( struct console *console ); +void init_message_window( struct console *console ); void update_window_region( struct console *console, const RECT *update ); void update_window_config( struct console *console, BOOL delay ); diff --git a/programs/conhost/window.c b/programs/conhost/window.c index 5881ad9c3ad..3ce36fe2c3d 100644 --- a/programs/conhost/window.c +++ b/programs/conhost/window.c @@ -429,7 +429,7 @@ static void fill_mem_dc( struct console *console, const RECT *update ) /* set a new position for the cursor */ static void update_window_cursor( struct console *console ) { - if (console->win != GetFocus() || !console->active->cursor_visible) return; + if (!console->active->cursor_visible || console->win != GetFocus()) return; SetCaretPos( (get_bounded_cursor_x( console->active ) - console->active->win.left) * console->active->font.width, (console->active->cursor_y - console->active->win.top) * console->active->font.height ); @@ -2143,15 +2143,18 @@ static LRESULT window_create( HWND hwnd, const CREATESTRUCTW *create ) SetWindowLongPtrW( hwnd, 0, (DWORD_PTR)console ); console->win = hwnd; - sys_menu = GetSystemMenu( hwnd, FALSE ); - if (!sys_menu) return 0; - console->window->popup_menu = CreatePopupMenu(); - if (!console->window->popup_menu) return 0; + if (console->window) + { + sys_menu = GetSystemMenu( hwnd, FALSE ); + if (!sys_menu) return 0; + console->window->popup_menu = CreatePopupMenu(); + if (!console->window->popup_menu) return 0; - fill_menu( sys_menu, TRUE ); - fill_menu( console->window->popup_menu, FALSE ); + fill_menu( sys_menu, TRUE ); + fill_menu( console->window->popup_menu, FALSE ); - console->window->mem_dc = CreateCompatibleDC( 0 ); + console->window->mem_dc = CreateCompatibleDC( 0 ); + } return 0; } @@ -2171,7 +2174,7 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp case WM_TIMER: case WM_UPDATE_CONFIG: - if (console->window->update_state == UPDATE_PENDING) + if (console->window && console->window->update_state == UPDATE_PENDING) update_window( console ); break; @@ -2179,6 +2182,8 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp { PAINTSTRUCT ps; + if (!console->window) break; + BeginPaint( console->win, &ps ); BitBlt( ps.hdc, 0, 0, (console->active->win.right - console->active->win.left + 1) * console->active->font.width, @@ -2193,6 +2198,7 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp } case WM_SHOWWINDOW: + if (!console->window) break; if (wparam) update_window( console ); else @@ -2204,7 +2210,7 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp case WM_KEYDOWN: case WM_KEYUP: - if (console->window->in_selection) + if (console->window && console->window->in_selection) handle_selection_key( console, msg == WM_KEYDOWN, wparam, lparam ); else record_key_input( console, msg == WM_KEYDOWN, wparam, lparam ); @@ -2216,7 +2222,7 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp break; case WM_LBUTTONDOWN: - if (console->window->quick_edit || console->window->in_selection) + if (console->window && (console->window->quick_edit || console->window->in_selection)) { if (console->window->in_selection) update_selection( console, 0 ); @@ -2241,7 +2247,7 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp break; case WM_MOUSEMOVE: - if (console->window->quick_edit || console->window->in_selection) + if (console->window && (console->window->quick_edit || console->window->in_selection)) { if (GetCapture() == console->win && console->window->in_selection && (wparam & MK_LBUTTON)) @@ -2257,7 +2263,7 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp break; case WM_LBUTTONUP: - if (console->window->quick_edit || console->window->in_selection) + if (console->window && (console->window->quick_edit || console->window->in_selection)) { if (GetCapture() == console->win && console->window->in_selection) { @@ -2273,7 +2279,7 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp break; case WM_RBUTTONDOWN: - if ((wparam & (MK_CONTROL|MK_SHIFT)) == console->window->menu_mask) + if (console->window && (wparam & (MK_CONTROL|MK_SHIFT)) == console->window->menu_mask) { POINT pt; pt.x = (short)LOWORD(lparam); @@ -2304,7 +2310,7 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp break; case WM_SETFOCUS: - if (console->active->cursor_visible) + if (console->window && console->active->cursor_visible) { CreateCaret( console->win, console->window->cursor_bitmap, console->active->font.width, console->active->font.height ); @@ -2313,12 +2319,12 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp break; case WM_KILLFOCUS: - if (console->active->cursor_visible) + if (console->window && console->active->cursor_visible) DestroyCaret(); break; case WM_SIZE: - if (console->window->update_state != UPDATE_BUSY) + if (console->window && console->window->update_state != UPDATE_BUSY) resize_window( console, max( LOWORD(lparam) / console->active->font.width, 20 ), max( HIWORD(lparam) / console->active->font.height, 20 )); @@ -2329,6 +2335,7 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp int win_width = console->active->win.right - console->active->win.left + 1; int x = console->active->win.left; + if (!console->window) break; switch (LOWORD(wparam)) { case SB_PAGEUP: x -= 8; break; @@ -2360,6 +2367,8 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp int win_height = console->active->win.bottom - console->active->win.top + 1; int y = console->active->win.top; + if (!console->window) break; + if (msg == WM_MOUSEWHEEL) { UINT scroll_lines = 3; @@ -2391,6 +2400,7 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp } case WM_SYSCOMMAND: + if (!console->window) break; switch (wparam) { case IDS_DEFAULT: @@ -2405,6 +2415,7 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp break; case WM_COMMAND: + if (!console->window) break; switch (wparam) { case IDS_DEFAULT: @@ -2447,7 +2458,7 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp break; case WM_INITMENUPOPUP: - if (!HIWORD(lparam)) return DefWindowProcW( hwnd, msg, wparam, lparam ); + if (!console->window || !HIWORD(lparam)) return DefWindowProcW( hwnd, msg, wparam, lparam ); set_menu_details( console, GetSystemMenu(console->win, FALSE) ); break; @@ -2462,7 +2473,7 @@ void update_window_config( struct console *console, BOOL delay ) { const int delay_timeout = 50; - if (!console->win || console->window->update_state != UPDATE_NONE) return; + if (!console->window || console->window->update_state != UPDATE_NONE) return; console->window->update_state = UPDATE_PENDING; if (delay) SetTimer( console->win, 1, delay_timeout, NULL ); @@ -2536,3 +2547,25 @@ BOOL init_window( struct console *console ) apply_config( console, &config ); return TRUE; } + +void init_message_window( struct console *console ) +{ + WNDCLASSW wndclass; + + wndclass.style = CS_DBLCLKS; + wndclass.lpfnWndProc = window_proc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = sizeof(DWORD_PTR); + wndclass.hInstance = GetModuleHandleW( NULL ); + wndclass.hIcon = 0; + wndclass.hCursor = 0; + wndclass.hbrBackground = GetStockObject( BLACK_BRUSH ); + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = L"WineConsoleClass"; + RegisterClassW(&wndclass); + + CreateWindowW( wndclass.lpszClassName, NULL, + WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX| + WS_MAXIMIZEBOX|WS_HSCROLL|WS_VSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, + 0, 0, HWND_MESSAGE, 0, wndclass.hInstance, console ); +}