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 <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2021-08-17 12:29:23 +02:00 committed by Alexandre Julliard
parent 365e99c022
commit da86e50e29
4 changed files with 60 additions and 23 deletions

View file

@ -4355,6 +4355,7 @@ static void test_pseudo_console_child(HANDLE input, HANDLE output)
CONSOLE_SCREEN_BUFFER_INFO sb_info; CONSOLE_SCREEN_BUFFER_INFO sb_info;
CONSOLE_CURSOR_INFO cursor_info; CONSOLE_CURSOR_INFO cursor_info;
DWORD mode; DWORD mode;
HWND hwnd;
BOOL ret; BOOL ret;
ret = GetConsoleMode(input, &mode); 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.dwSize == 25, "dwSize = %u\n", cursor_info.dwSize);
ok(cursor_info.bVisible == TRUE, "bVisible = %x\n", cursor_info.bVisible); ok(cursor_info.bVisible == TRUE, "bVisible = %x\n", cursor_info.bVisible);
hwnd = GetConsoleWindow();
ok(IsWindow(hwnd), "no console window\n");
test_console_title(); test_console_title();
test_WriteConsoleInputW(input); test_WriteConsoleInputW(input);
} }

View file

@ -349,7 +349,7 @@ static void update_output( struct screen_buffer *screen_buffer, RECT *rect )
TRACE( "%s\n", wine_dbgstr_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 ); update_window_region( screen_buffer->console, rect );
return; return;
@ -2529,6 +2529,7 @@ static NTSTATUS console_input_ioctl( struct console *console, unsigned int code,
TRACE( "get window\n" ); TRACE( "get window\n" );
if (in_size || *out_size != sizeof(*result)) return STATUS_INVALID_PARAMETER; if (in_size || *out_size != sizeof(*result)) return STATUS_INVALID_PARAMETER;
if (!(result = alloc_ioctl_buffer( sizeof(*result )))) return STATUS_NO_MEMORY; if (!(result = alloc_ioctl_buffer( sizeof(*result )))) return STATUS_NO_MEMORY;
if (!console->win) init_message_window( console );
*result = condrv_handle( console->win ); *result = condrv_handle( console->win );
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -2664,7 +2665,6 @@ static int main_loop( struct console *console, HANDLE signal )
unsigned short signal_id; unsigned short signal_id;
IO_STATUS_BLOCK signal_io; IO_STATUS_BLOCK signal_io;
NTSTATUS status; NTSTATUS status;
BOOL pump_msgs;
DWORD res; DWORD res;
if (signal) if (signal)
@ -2680,11 +2680,10 @@ static int main_loop( struct console *console, HANDLE signal )
wait_handles[wait_cnt++] = console->server; wait_handles[wait_cnt++] = console->server;
if (signal) wait_handles[wait_cnt++] = signal_event; if (signal) wait_handles[wait_cnt++] = signal_event;
if (console->input_thread) wait_handles[wait_cnt++] = console->input_thread; if (console->input_thread) wait_handles[wait_cnt++] = console->input_thread;
pump_msgs = console->win != NULL;
for (;;) for (;;)
{ {
if (pump_msgs) if (console->win)
res = MsgWaitForMultipleObjects( wait_cnt, wait_handles, FALSE, INFINITE, QS_ALLINPUT ); res = MsgWaitForMultipleObjects( wait_cnt, wait_handles, FALSE, INFINITE, QS_ALLINPUT );
else else
res = WaitForMultipleObjects( wait_cnt, wait_handles, FALSE, INFINITE ); res = WaitForMultipleObjects( wait_cnt, wait_handles, FALSE, INFINITE );

View file

@ -131,6 +131,7 @@ struct screen_buffer
}; };
BOOL init_window( struct console *console ); 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_region( struct console *console, const RECT *update );
void update_window_config( struct console *console, BOOL delay ); void update_window_config( struct console *console, BOOL delay );

View file

@ -429,7 +429,7 @@ static void fill_mem_dc( struct console *console, const RECT *update )
/* set a new position for the cursor */ /* set a new position for the cursor */
static void update_window_cursor( struct console *console ) 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, 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 ); (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 ); SetWindowLongPtrW( hwnd, 0, (DWORD_PTR)console );
console->win = hwnd; console->win = hwnd;
sys_menu = GetSystemMenu( hwnd, FALSE ); if (console->window)
if (!sys_menu) return 0; {
console->window->popup_menu = CreatePopupMenu(); sys_menu = GetSystemMenu( hwnd, FALSE );
if (!console->window->popup_menu) return 0; if (!sys_menu) return 0;
console->window->popup_menu = CreatePopupMenu();
if (!console->window->popup_menu) return 0;
fill_menu( sys_menu, TRUE ); fill_menu( sys_menu, TRUE );
fill_menu( console->window->popup_menu, FALSE ); fill_menu( console->window->popup_menu, FALSE );
console->window->mem_dc = CreateCompatibleDC( 0 ); console->window->mem_dc = CreateCompatibleDC( 0 );
}
return 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_TIMER:
case WM_UPDATE_CONFIG: case WM_UPDATE_CONFIG:
if (console->window->update_state == UPDATE_PENDING) if (console->window && console->window->update_state == UPDATE_PENDING)
update_window( console ); update_window( console );
break; break;
@ -2179,6 +2182,8 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp
{ {
PAINTSTRUCT ps; PAINTSTRUCT ps;
if (!console->window) break;
BeginPaint( console->win, &ps ); BeginPaint( console->win, &ps );
BitBlt( ps.hdc, 0, 0, BitBlt( ps.hdc, 0, 0,
(console->active->win.right - console->active->win.left + 1) * console->active->font.width, (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: case WM_SHOWWINDOW:
if (!console->window) break;
if (wparam) if (wparam)
update_window( console ); update_window( console );
else else
@ -2204,7 +2210,7 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp
case WM_KEYDOWN: case WM_KEYDOWN:
case WM_KEYUP: case WM_KEYUP:
if (console->window->in_selection) if (console->window && console->window->in_selection)
handle_selection_key( console, msg == WM_KEYDOWN, wparam, lparam ); handle_selection_key( console, msg == WM_KEYDOWN, wparam, lparam );
else else
record_key_input( console, msg == WM_KEYDOWN, wparam, lparam ); 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; break;
case WM_LBUTTONDOWN: 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) if (console->window->in_selection)
update_selection( console, 0 ); update_selection( console, 0 );
@ -2241,7 +2247,7 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp
break; break;
case WM_MOUSEMOVE: 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 && if (GetCapture() == console->win && console->window->in_selection &&
(wparam & MK_LBUTTON)) (wparam & MK_LBUTTON))
@ -2257,7 +2263,7 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp
break; break;
case WM_LBUTTONUP: 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) 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; break;
case WM_RBUTTONDOWN: 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; POINT pt;
pt.x = (short)LOWORD(lparam); pt.x = (short)LOWORD(lparam);
@ -2304,7 +2310,7 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp
break; break;
case WM_SETFOCUS: case WM_SETFOCUS:
if (console->active->cursor_visible) if (console->window && console->active->cursor_visible)
{ {
CreateCaret( console->win, console->window->cursor_bitmap, CreateCaret( console->win, console->window->cursor_bitmap,
console->active->font.width, console->active->font.height ); 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; break;
case WM_KILLFOCUS: case WM_KILLFOCUS:
if (console->active->cursor_visible) if (console->window && console->active->cursor_visible)
DestroyCaret(); DestroyCaret();
break; break;
case WM_SIZE: case WM_SIZE:
if (console->window->update_state != UPDATE_BUSY) if (console->window && console->window->update_state != UPDATE_BUSY)
resize_window( console, resize_window( console,
max( LOWORD(lparam) / console->active->font.width, 20 ), max( LOWORD(lparam) / console->active->font.width, 20 ),
max( HIWORD(lparam) / console->active->font.height, 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 win_width = console->active->win.right - console->active->win.left + 1;
int x = console->active->win.left; int x = console->active->win.left;
if (!console->window) break;
switch (LOWORD(wparam)) switch (LOWORD(wparam))
{ {
case SB_PAGEUP: x -= 8; break; 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 win_height = console->active->win.bottom - console->active->win.top + 1;
int y = console->active->win.top; int y = console->active->win.top;
if (!console->window) break;
if (msg == WM_MOUSEWHEEL) if (msg == WM_MOUSEWHEEL)
{ {
UINT scroll_lines = 3; UINT scroll_lines = 3;
@ -2391,6 +2400,7 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp
} }
case WM_SYSCOMMAND: case WM_SYSCOMMAND:
if (!console->window) break;
switch (wparam) switch (wparam)
{ {
case IDS_DEFAULT: case IDS_DEFAULT:
@ -2405,6 +2415,7 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp
break; break;
case WM_COMMAND: case WM_COMMAND:
if (!console->window) break;
switch (wparam) switch (wparam)
{ {
case IDS_DEFAULT: case IDS_DEFAULT:
@ -2447,7 +2458,7 @@ static LRESULT WINAPI window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp
break; break;
case WM_INITMENUPOPUP: 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) ); set_menu_details( console, GetSystemMenu(console->win, FALSE) );
break; break;
@ -2462,7 +2473,7 @@ void update_window_config( struct console *console, BOOL delay )
{ {
const int delay_timeout = 50; 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; console->window->update_state = UPDATE_PENDING;
if (delay) if (delay)
SetTimer( console->win, 1, delay_timeout, NULL ); SetTimer( console->win, 1, delay_timeout, NULL );
@ -2536,3 +2547,25 @@ BOOL init_window( struct console *console )
apply_config( console, &config ); apply_config( console, &config );
return TRUE; 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 );
}