conhost: Import window state update from wineconsole.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
7d48e0c564
commit
632676d071
|
@ -294,11 +294,6 @@ static void init_tty_output( struct console *console )
|
||||||
console->tty_cursor_visible = TRUE;
|
console->tty_cursor_visible = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void empty_update_rect( struct screen_buffer *screen_buffer, RECT *rect )
|
|
||||||
{
|
|
||||||
SetRect( rect, screen_buffer->width, screen_buffer->height, 0, 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void scroll_to_cursor( struct screen_buffer *screen_buffer )
|
static void scroll_to_cursor( struct screen_buffer *screen_buffer )
|
||||||
{
|
{
|
||||||
int w = screen_buffer->win.right - screen_buffer->win.left + 1;
|
int w = screen_buffer->win.right - screen_buffer->win.left + 1;
|
||||||
|
|
|
@ -133,4 +133,9 @@ struct screen_buffer
|
||||||
BOOL init_window( struct console *console );
|
BOOL init_window( struct console *console );
|
||||||
NTSTATUS change_screen_buffer_size( struct screen_buffer *screen_buffer, int new_width, int new_height );
|
NTSTATUS change_screen_buffer_size( struct screen_buffer *screen_buffer, int new_width, int new_height );
|
||||||
|
|
||||||
|
static inline void empty_update_rect( struct screen_buffer *screen_buffer, RECT *rect )
|
||||||
|
{
|
||||||
|
SetRect( rect, screen_buffer->width, screen_buffer->height, 0, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* RC_INVOKED */
|
#endif /* RC_INVOKED */
|
||||||
|
|
|
@ -29,11 +29,19 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(conhost);
|
WINE_DEFAULT_DEBUG_CHANNEL(conhost);
|
||||||
|
|
||||||
|
enum update_state
|
||||||
|
{
|
||||||
|
UPDATE_NONE,
|
||||||
|
UPDATE_PENDING,
|
||||||
|
UPDATE_BUSY
|
||||||
|
};
|
||||||
|
|
||||||
struct console_window
|
struct console_window
|
||||||
{
|
{
|
||||||
HDC mem_dc; /* memory DC holding the bitmap below */
|
HDC mem_dc; /* memory DC holding the bitmap below */
|
||||||
HBITMAP bitmap; /* bitmap of display window content */
|
HBITMAP bitmap; /* bitmap of display window content */
|
||||||
HFONT font; /* font used for rendering, usually fixed */
|
HFONT font; /* font used for rendering, usually fixed */
|
||||||
|
HBITMAP cursor_bitmap; /* bitmap used for the caret */
|
||||||
unsigned int ui_charset; /* default UI charset */
|
unsigned int ui_charset; /* default UI charset */
|
||||||
WCHAR *config_key; /* config registry key name */
|
WCHAR *config_key; /* config registry key name */
|
||||||
LONG ext_leading; /* external leading for font */
|
LONG ext_leading; /* external leading for font */
|
||||||
|
@ -48,6 +56,9 @@ struct console_window
|
||||||
unsigned int sb_width; /* active screen buffer width */
|
unsigned int sb_width; /* active screen buffer width */
|
||||||
unsigned int sb_height; /* active screen buffer height */
|
unsigned int sb_height; /* active screen buffer height */
|
||||||
COORD cursor_pos; /* cursor position */
|
COORD cursor_pos; /* cursor position */
|
||||||
|
|
||||||
|
RECT update; /* screen buffer update rect */
|
||||||
|
enum update_state update_state; /* update state */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct console_config
|
struct console_config
|
||||||
|
@ -356,6 +367,251 @@ static void save_config( const WCHAR *key_name, const struct console_config *con
|
||||||
RegCloseKey(key);
|
RegCloseKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* fill memory DC with current cells values */
|
||||||
|
static void fill_mem_dc( struct console *console, const RECT *update )
|
||||||
|
{
|
||||||
|
unsigned int i, j, k;
|
||||||
|
unsigned int attr;
|
||||||
|
char_info_t *cell;
|
||||||
|
HFONT old_font;
|
||||||
|
HBRUSH brush;
|
||||||
|
WCHAR *line;
|
||||||
|
INT *dx;
|
||||||
|
RECT r;
|
||||||
|
|
||||||
|
if (!console->window->font)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!(line = malloc( (update->right - update->left + 1) * sizeof(WCHAR))) ) return;
|
||||||
|
dx = malloc( (update->right - update->left + 1) * sizeof(*dx) );
|
||||||
|
|
||||||
|
old_font = SelectObject( console->window->mem_dc, console->window->font );
|
||||||
|
for (j = update->top; j <= update->bottom; j++)
|
||||||
|
{
|
||||||
|
cell = &console->active->data[j * console->active->width];
|
||||||
|
for (i = update->left; i <= update->right; i++)
|
||||||
|
{
|
||||||
|
attr = cell[i].attr;
|
||||||
|
SetBkColor( console->window->mem_dc, console->active->color_map[(attr >> 4) & 0x0F] );
|
||||||
|
SetTextColor( console->window->mem_dc, console->active->color_map[attr & 0x0F] );
|
||||||
|
for (k = i; k <= update->right && cell[k].attr == attr; k++)
|
||||||
|
{
|
||||||
|
line[k - i] = cell[k].ch;
|
||||||
|
dx[k - i] = console->active->font.width;
|
||||||
|
}
|
||||||
|
ExtTextOutW( console->window->mem_dc, i * console->active->font.width,
|
||||||
|
j * console->active->font.height, 0, NULL, line, k - i, dx );
|
||||||
|
if (console->window->ext_leading &&
|
||||||
|
(brush = CreateSolidBrush( console->active->color_map[(attr >> 4) & 0x0F] )))
|
||||||
|
{
|
||||||
|
r.left = i * console->active->font.width;
|
||||||
|
r.top = (j + 1) * console->active->font.height - console->window->ext_leading;
|
||||||
|
r.right = k * console->active->font.width;
|
||||||
|
r.bottom = (j + 1) * console->active->font.height;
|
||||||
|
FillRect( console->window->mem_dc, &r, brush );
|
||||||
|
DeleteObject( brush );
|
||||||
|
}
|
||||||
|
i = k - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SelectObject( console->window->mem_dc, old_font );
|
||||||
|
free( dx );
|
||||||
|
free( line );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set a new position for the cursor */
|
||||||
|
static void update_window_cursor( struct console *console )
|
||||||
|
{
|
||||||
|
if (console->win != GetFocus() || !console->active->cursor_visible) return;
|
||||||
|
|
||||||
|
SetCaretPos( (console->active->cursor_x - console->active->win.left) * console->active->font.width,
|
||||||
|
(console->active->cursor_y - console->active->win.top) * console->active->font.height );
|
||||||
|
ShowCaret( console->win );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sets a new shape for the cursor */
|
||||||
|
static void shape_cursor( struct console *console )
|
||||||
|
{
|
||||||
|
int size = console->active->cursor_size;
|
||||||
|
|
||||||
|
if (console->active->cursor_visible && console->win == GetFocus()) DestroyCaret();
|
||||||
|
if (console->window->cursor_bitmap) DeleteObject( console->window->cursor_bitmap );
|
||||||
|
console->window->cursor_bitmap = NULL;
|
||||||
|
console->window->cursor_visible = FALSE;
|
||||||
|
|
||||||
|
if (size != 100)
|
||||||
|
{
|
||||||
|
int w16b; /* number of bytes per row, aligned on word size */
|
||||||
|
int i, j, nbl;
|
||||||
|
BYTE *ptr;
|
||||||
|
|
||||||
|
w16b = ((console->active->font.width + 15) & ~15) / 8;
|
||||||
|
ptr = calloc( w16b, console->active->font.height );
|
||||||
|
if (!ptr) return;
|
||||||
|
nbl = max( (console->active->font.height * size) / 100, 1 );
|
||||||
|
for (j = console->active->font.height - nbl; j < console->active->font.height; j++)
|
||||||
|
{
|
||||||
|
for (i = 0; i < console->active->font.width; i++)
|
||||||
|
{
|
||||||
|
ptr[w16b * j + (i / 8)] |= 0x80 >> (i & 7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console->window->cursor_bitmap = CreateBitmap( console->active->font.width,
|
||||||
|
console->active->font.height, 1, 1, ptr );
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_window( struct console *console )
|
||||||
|
{
|
||||||
|
unsigned int win_width, win_height;
|
||||||
|
BOOL update_all = FALSE;
|
||||||
|
int dx, dy;
|
||||||
|
RECT r;
|
||||||
|
|
||||||
|
console->window->update_state = UPDATE_BUSY;
|
||||||
|
|
||||||
|
if (console->window->sb_width != console->active->width ||
|
||||||
|
console->window->sb_height != console->active->height ||
|
||||||
|
!console->window->bitmap)
|
||||||
|
{
|
||||||
|
console->window->sb_width = console->active->width;
|
||||||
|
console->window->sb_height = console->active->height;
|
||||||
|
|
||||||
|
if (console->active->width && console->active->height && console->window->font)
|
||||||
|
{
|
||||||
|
HBITMAP bitmap;
|
||||||
|
HDC dc;
|
||||||
|
RECT r;
|
||||||
|
|
||||||
|
if (!(dc = GetDC( console->win ))) return;
|
||||||
|
|
||||||
|
bitmap = CreateCompatibleBitmap( dc,
|
||||||
|
console->active->width * console->active->font.width,
|
||||||
|
console->active->height * console->active->font.height );
|
||||||
|
ReleaseDC( console->win, dc );
|
||||||
|
SelectObject( console->window->mem_dc, bitmap );
|
||||||
|
|
||||||
|
if (console->window->bitmap) DeleteObject( console->window->bitmap );
|
||||||
|
console->window->bitmap = bitmap;
|
||||||
|
SetRect( &r, 0, 0, console->active->width - 1, console->active->height - 1 );
|
||||||
|
fill_mem_dc( console, &r );
|
||||||
|
}
|
||||||
|
|
||||||
|
empty_update_rect( console->active, &console->window->update );
|
||||||
|
update_all = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compute window size from desired client size */
|
||||||
|
win_width = console->active->win.right - console->active->win.left + 1;
|
||||||
|
win_height = console->active->win.bottom - console->active->win.top + 1;
|
||||||
|
|
||||||
|
if (update_all || win_width != console->window->win_width ||
|
||||||
|
win_height != console->window->win_height)
|
||||||
|
{
|
||||||
|
console->window->win_width = win_width;
|
||||||
|
console->window->win_height = win_height;
|
||||||
|
|
||||||
|
r.left = r.top = 0;
|
||||||
|
r.right = win_width * console->active->font.width;
|
||||||
|
r.bottom = win_height * console->active->font.height;
|
||||||
|
AdjustWindowRect( &r, GetWindowLongW( console->win, GWL_STYLE ), FALSE );
|
||||||
|
|
||||||
|
dx = dy = 0;
|
||||||
|
if (console->active->width > win_width)
|
||||||
|
{
|
||||||
|
dy = GetSystemMetrics( SM_CYHSCROLL );
|
||||||
|
SetScrollRange( console->win, SB_HORZ, 0, console->active->width - win_width, FALSE );
|
||||||
|
SetScrollPos( console->win, SB_VERT, console->active->win.top, FALSE );
|
||||||
|
ShowScrollBar( console->win, SB_HORZ, TRUE );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ShowScrollBar( console->win, SB_HORZ, FALSE );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (console->active->height > win_height)
|
||||||
|
{
|
||||||
|
dx = GetSystemMetrics( SM_CXVSCROLL );
|
||||||
|
SetScrollRange( console->win, SB_VERT, 0, console->active->height - win_height, FALSE );
|
||||||
|
SetScrollPos( console->win, SB_VERT, console->active->win.top, FALSE );
|
||||||
|
ShowScrollBar( console->win, SB_VERT, TRUE );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ShowScrollBar( console->win, SB_VERT, FALSE );
|
||||||
|
|
||||||
|
dx += r.right - r.left;
|
||||||
|
dy += r.bottom - r.top;
|
||||||
|
SetWindowPos( console->win, 0, 0, 0, dx, dy, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
|
||||||
|
|
||||||
|
SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0 );
|
||||||
|
console->active->max_width = (r.right - r.left) / console->active->font.width;
|
||||||
|
console->active->max_height = (r.bottom - r.top - GetSystemMetrics( SM_CYCAPTION )) /
|
||||||
|
console->active->font.height;
|
||||||
|
|
||||||
|
InvalidateRect( console->win, NULL, FALSE );
|
||||||
|
UpdateWindow( console->win );
|
||||||
|
update_all = TRUE;
|
||||||
|
}
|
||||||
|
else if (console->active->win.left != console->window->win_pos.X ||
|
||||||
|
console->active->win.top != console->window->win_pos.Y)
|
||||||
|
{
|
||||||
|
ScrollWindow( console->win,
|
||||||
|
(console->window->win_pos.X - console->active->win.left) * console->active->font.width,
|
||||||
|
(console->window->win_pos.Y - console->active->win.top) * console->active->font.height,
|
||||||
|
NULL, NULL );
|
||||||
|
SetScrollPos( console->win, SB_HORZ, console->active->win.left, TRUE );
|
||||||
|
SetScrollPos( console->win, SB_VERT, console->active->win.top, TRUE );
|
||||||
|
InvalidateRect( console->win, NULL, FALSE );
|
||||||
|
}
|
||||||
|
|
||||||
|
console->window->win_pos.X = console->active->win.left;
|
||||||
|
console->window->win_pos.Y = console->active->win.top;
|
||||||
|
|
||||||
|
if (console->window->update.top <= console->window->update.bottom &&
|
||||||
|
console->window->update.left <= console->window->update.right)
|
||||||
|
{
|
||||||
|
RECT *update = &console->window->update;
|
||||||
|
r.left = (update->left - console->active->win.left) * console->active->font.width;
|
||||||
|
r.right = (update->right - console->active->win.left + 1) * console->active->font.width;
|
||||||
|
r.top = (update->top - console->active->win.top) * console->active->font.height;
|
||||||
|
r.bottom = (update->bottom - console->active->win.top + 1) * console->active->font.height;
|
||||||
|
fill_mem_dc( console, update );
|
||||||
|
empty_update_rect( console->active, &console->window->update );
|
||||||
|
InvalidateRect( console->win, &r, FALSE );
|
||||||
|
UpdateWindow( console->win );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (update_all || console->active->cursor_size != console->window->cursor_size)
|
||||||
|
{
|
||||||
|
console->window->cursor_size = console->active->cursor_size;
|
||||||
|
shape_cursor( console );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (console->active->cursor_visible != console->window->cursor_visible)
|
||||||
|
{
|
||||||
|
console->window->cursor_visible = console->active->cursor_visible;
|
||||||
|
if (console->win == GetFocus())
|
||||||
|
{
|
||||||
|
if (console->window->cursor_visible)
|
||||||
|
CreateCaret( console->win, console->window->cursor_bitmap,
|
||||||
|
console->active->font.width, console->active->font.height );
|
||||||
|
else
|
||||||
|
DestroyCaret();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (update_all || console->active->cursor_x != console->window->cursor_pos.X ||
|
||||||
|
console->active->cursor_y != console->window->cursor_pos.Y)
|
||||||
|
{
|
||||||
|
console->window->cursor_pos.X = console->active->cursor_x;
|
||||||
|
console->window->cursor_pos.Y = console->active->cursor_y;
|
||||||
|
update_window_cursor( console );
|
||||||
|
}
|
||||||
|
|
||||||
|
console->window->update_state = UPDATE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
static void fill_logfont( LOGFONTW *lf, const WCHAR *name, unsigned int height, unsigned int weight )
|
static void fill_logfont( LOGFONTW *lf, const WCHAR *name, unsigned int height, unsigned int weight )
|
||||||
{
|
{
|
||||||
lf->lfHeight = height;
|
lf->lfHeight = height;
|
||||||
|
@ -640,6 +896,8 @@ static void apply_config( struct console *console, const struct console_config *
|
||||||
{
|
{
|
||||||
update_console_font( console, config->face_name, config->cell_height, config->font_weight );
|
update_console_font( console, config->face_name, config->cell_height, config->font_weight );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_window( console );
|
||||||
}
|
}
|
||||||
|
|
||||||
static LRESULT window_create( HWND hwnd, const CREATESTRUCTW *create )
|
static LRESULT window_create( HWND hwnd, const CREATESTRUCTW *create )
|
||||||
|
@ -651,6 +909,7 @@ 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;
|
||||||
|
|
||||||
|
console->window->mem_dc = CreateCompatibleDC( 0 );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue