server: Introduce IOCTL_CONDRV_SCROLL ioctl.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
fbe3db1197
commit
7ae370a549
|
@ -22,6 +22,7 @@
|
||||||
#define _INC_CONDRV
|
#define _INC_CONDRV
|
||||||
|
|
||||||
#include "winioctl.h"
|
#include "winioctl.h"
|
||||||
|
#include "wincon.h"
|
||||||
|
|
||||||
/* common console input and output ioctls */
|
/* common console input and output ioctls */
|
||||||
#define IOCTL_CONDRV_GET_MODE CTL_CODE(FILE_DEVICE_CONSOLE, 0, METHOD_BUFFERED, FILE_READ_PROPERTIES)
|
#define IOCTL_CONDRV_GET_MODE CTL_CODE(FILE_DEVICE_CONSOLE, 0, METHOD_BUFFERED, FILE_READ_PROPERTIES)
|
||||||
|
@ -43,6 +44,7 @@
|
||||||
#define IOCTL_CONDRV_SET_OUTPUT_INFO CTL_CODE(FILE_DEVICE_CONSOLE, 33, METHOD_BUFFERED, FILE_WRITE_PROPERTIES)
|
#define IOCTL_CONDRV_SET_OUTPUT_INFO CTL_CODE(FILE_DEVICE_CONSOLE, 33, METHOD_BUFFERED, FILE_WRITE_PROPERTIES)
|
||||||
#define IOCTL_CONDRV_ACTIVATE CTL_CODE(FILE_DEVICE_CONSOLE, 34, METHOD_BUFFERED, FILE_WRITE_DATA)
|
#define IOCTL_CONDRV_ACTIVATE CTL_CODE(FILE_DEVICE_CONSOLE, 34, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||||
#define IOCTL_CONDRV_FILL_OUTPUT CTL_CODE(FILE_DEVICE_CONSOLE, 35, METHOD_BUFFERED, FILE_WRITE_DATA)
|
#define IOCTL_CONDRV_FILL_OUTPUT CTL_CODE(FILE_DEVICE_CONSOLE, 35, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||||
|
#define IOCTL_CONDRV_SCROLL CTL_CODE(FILE_DEVICE_CONSOLE, 36, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||||
|
|
||||||
/* console renderer ioctls */
|
/* console renderer ioctls */
|
||||||
#define IOCTL_CONDRV_GET_RENDERER_EVENTS CTL_CODE(FILE_DEVICE_CONSOLE, 70, METHOD_BUFFERED, FILE_READ_PROPERTIES)
|
#define IOCTL_CONDRV_GET_RENDERER_EVENTS CTL_CODE(FILE_DEVICE_CONSOLE, 70, METHOD_BUFFERED, FILE_READ_PROPERTIES)
|
||||||
|
@ -133,6 +135,16 @@ struct condrv_output_info_params
|
||||||
struct condrv_output_info info; /* output info */
|
struct condrv_output_info info; /* output info */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define SET_CONSOLE_OUTPUT_INFO_CURSOR_GEOM 0x0001
|
||||||
|
#define SET_CONSOLE_OUTPUT_INFO_CURSOR_POS 0x0002
|
||||||
|
#define SET_CONSOLE_OUTPUT_INFO_SIZE 0x0004
|
||||||
|
#define SET_CONSOLE_OUTPUT_INFO_ATTR 0x0008
|
||||||
|
#define SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW 0x0010
|
||||||
|
#define SET_CONSOLE_OUTPUT_INFO_MAX_SIZE 0x0020
|
||||||
|
#define SET_CONSOLE_OUTPUT_INFO_FONT 0x0040
|
||||||
|
#define SET_CONSOLE_OUTPUT_INFO_COLORTABLE 0x0080
|
||||||
|
#define SET_CONSOLE_OUTPUT_INFO_POPUP_ATTR 0x0100
|
||||||
|
|
||||||
/* IOCTL_CONDRV_FILL_OUTPUT params */
|
/* IOCTL_CONDRV_FILL_OUTPUT params */
|
||||||
struct condrv_fill_output_params
|
struct condrv_fill_output_params
|
||||||
{
|
{
|
||||||
|
@ -145,15 +157,14 @@ struct condrv_fill_output_params
|
||||||
unsigned short attr; /* attribute to write */
|
unsigned short attr; /* attribute to write */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SET_CONSOLE_OUTPUT_INFO_CURSOR_GEOM 0x0001
|
/* IOCTL_CONDRV_SCROLL params */
|
||||||
#define SET_CONSOLE_OUTPUT_INFO_CURSOR_POS 0x0002
|
struct condrv_scroll_params
|
||||||
#define SET_CONSOLE_OUTPUT_INFO_SIZE 0x0004
|
{
|
||||||
#define SET_CONSOLE_OUTPUT_INFO_ATTR 0x0008
|
SMALL_RECT scroll; /* source rectangle */
|
||||||
#define SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW 0x0010
|
COORD origin; /* destination coordinates */
|
||||||
#define SET_CONSOLE_OUTPUT_INFO_MAX_SIZE 0x0020
|
SMALL_RECT clip; /* clipping rectangle */
|
||||||
#define SET_CONSOLE_OUTPUT_INFO_FONT 0x0040
|
char_info_t fill; /* empty character info */
|
||||||
#define SET_CONSOLE_OUTPUT_INFO_COLORTABLE 0x0080
|
};
|
||||||
#define SET_CONSOLE_OUTPUT_INFO_POPUP_ATTR 0x0100
|
|
||||||
|
|
||||||
/* IOCTL_CONDRV_GET_RENDERER_EVENTS result */
|
/* IOCTL_CONDRV_GET_RENDERER_EVENTS result */
|
||||||
struct condrv_renderer_event
|
struct condrv_renderer_event
|
||||||
|
|
118
server/console.c
118
server/console.c
|
@ -1446,7 +1446,85 @@ static int fill_console_output( struct screen_buffer *screen_buffer, char_info_t
|
||||||
|
|
||||||
/* scroll parts of a screen buffer */
|
/* scroll parts of a screen buffer */
|
||||||
static void scroll_console_output( struct screen_buffer *screen_buffer, int xsrc, int ysrc, int xdst, int ydst,
|
static void scroll_console_output( struct screen_buffer *screen_buffer, int xsrc, int ysrc, int xdst, int ydst,
|
||||||
int w, int h )
|
int w, int h, const rectangle_t *clip, char_info_t fill )
|
||||||
|
{
|
||||||
|
struct condrv_renderer_event evt;
|
||||||
|
rectangle_t src, dst;
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
src.left = max( xsrc, clip->left );
|
||||||
|
src.top = max( ysrc, clip->top );
|
||||||
|
src.right = min( xsrc + w - 1, clip->right );
|
||||||
|
src.bottom = min( ysrc + h - 1, clip->bottom );
|
||||||
|
|
||||||
|
dst.left = xdst;
|
||||||
|
dst.top = ydst;
|
||||||
|
dst.right = xdst + w - 1;
|
||||||
|
dst.bottom = ydst + h - 1;
|
||||||
|
|
||||||
|
if (dst.left < clip->left)
|
||||||
|
{
|
||||||
|
xsrc += clip->left - dst.left;
|
||||||
|
w -= clip->left - dst.left;
|
||||||
|
dst.left = clip->left;
|
||||||
|
}
|
||||||
|
if (dst.top < clip->top)
|
||||||
|
{
|
||||||
|
ysrc += clip->top - dst.top;
|
||||||
|
h -= clip->top - dst.top;
|
||||||
|
dst.top = clip->top;
|
||||||
|
}
|
||||||
|
if (dst.right > clip->right) w -= dst.right - clip->right;
|
||||||
|
if (dst.bottom > clip->bottom) h -= dst.bottom - clip->bottom;
|
||||||
|
|
||||||
|
if (w > 0 && h > 0)
|
||||||
|
{
|
||||||
|
if (ysrc < ydst)
|
||||||
|
{
|
||||||
|
for (y = h; y > 0; y--)
|
||||||
|
{
|
||||||
|
memcpy( &screen_buffer->data[(dst.top + y - 1) * screen_buffer->width + dst.left],
|
||||||
|
&screen_buffer->data[(ysrc + y - 1) * screen_buffer->width + xsrc],
|
||||||
|
w * sizeof(screen_buffer->data[0]) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (y = 0; y < h; y++)
|
||||||
|
{
|
||||||
|
/* we use memmove here because when psrc and pdst are the same,
|
||||||
|
* copies are done on the same row, so the dst and src blocks
|
||||||
|
* can overlap */
|
||||||
|
memmove( &screen_buffer->data[(dst.top + y) * screen_buffer->width + dst.left],
|
||||||
|
&screen_buffer->data[(ysrc + y) * screen_buffer->width + xsrc],
|
||||||
|
w * sizeof(screen_buffer->data[0]) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (y = src.top; y <= src.bottom; y++)
|
||||||
|
{
|
||||||
|
int left = src.left;
|
||||||
|
int right = src.right;
|
||||||
|
if (dst.top <= y && y <= dst.bottom)
|
||||||
|
{
|
||||||
|
if (dst.left <= src.left) left = max( left, dst.right + 1 );
|
||||||
|
if (dst.left >= src.left) right = min( right, dst.left - 1 );
|
||||||
|
}
|
||||||
|
for (x = left; x <= right; x++) screen_buffer->data[y * screen_buffer->width + x] = fill;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: this could be enhanced, by signalling scroll */
|
||||||
|
evt.event = CONSOLE_RENDERER_UPDATE_EVENT;
|
||||||
|
memset(&evt.u, 0, sizeof(evt.u));
|
||||||
|
evt.u.update.top = min( src.top, dst.top );
|
||||||
|
evt.u.update.bottom = max( src.bottom, dst.bottom );
|
||||||
|
console_input_events_append( screen_buffer->input, &evt );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* scroll parts of a screen buffer */
|
||||||
|
static void scroll_console_output_req( struct screen_buffer *screen_buffer, int xsrc, int ysrc, int xdst, int ydst,
|
||||||
|
int w, int h )
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
char_info_t *psrc, *pdst;
|
char_info_t *psrc, *pdst;
|
||||||
|
@ -1811,6 +1889,40 @@ static int screen_buffer_ioctl( struct fd *fd, ioctl_code_t code, struct async *
|
||||||
return !get_error();
|
return !get_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case IOCTL_CONDRV_SCROLL:
|
||||||
|
{
|
||||||
|
const struct condrv_scroll_params *params = get_req_data();
|
||||||
|
rectangle_t clip;
|
||||||
|
if (get_req_data_size() != sizeof(*params))
|
||||||
|
{
|
||||||
|
set_error( STATUS_INVALID_PARAMETER );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (console_input_is_bare( screen_buffer->input ) || !screen_buffer->input)
|
||||||
|
{
|
||||||
|
set_error( STATUS_OBJECT_TYPE_MISMATCH );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
clip.left = max( params->clip.Left, 0 );
|
||||||
|
clip.top = max( params->clip.Top, 0 );
|
||||||
|
clip.right = min( params->clip.Right, screen_buffer->width - 1 );
|
||||||
|
clip.bottom = min( params->clip.Bottom, screen_buffer->height - 1 );
|
||||||
|
if (clip.left > clip.right || clip.top > clip.bottom || params->scroll.Left < 0 || params->scroll.Top < 0 ||
|
||||||
|
params->scroll.Right >= screen_buffer->width || params->scroll.Bottom >= screen_buffer->height ||
|
||||||
|
params->scroll.Right < params->scroll.Left || params->scroll.Top > params->scroll.Bottom ||
|
||||||
|
params->origin.X < 0 || params->origin.X >= screen_buffer->width || params->origin.Y < 0 ||
|
||||||
|
params->origin.Y >= screen_buffer->height)
|
||||||
|
{
|
||||||
|
set_error( STATUS_INVALID_PARAMETER );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
scroll_console_output( screen_buffer, params->scroll.Left, params->scroll.Top, params->origin.X, params->origin.Y,
|
||||||
|
params->scroll.Right - params->scroll.Left + 1, params->scroll.Bottom - params->scroll.Top + 1,
|
||||||
|
&clip, params->fill );
|
||||||
|
return !get_error();
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
set_error( STATUS_INVALID_HANDLE );
|
set_error( STATUS_INVALID_HANDLE );
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2182,8 +2294,8 @@ DECL_HANDLER(move_console_output)
|
||||||
release_object( screen_buffer );
|
release_object( screen_buffer );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scroll_console_output( screen_buffer, req->x_src, req->y_src, req->x_dst, req->y_dst,
|
scroll_console_output_req( screen_buffer, req->x_src, req->y_src, req->x_dst, req->y_dst,
|
||||||
req->w, req->h );
|
req->w, req->h );
|
||||||
release_object( screen_buffer );
|
release_object( screen_buffer );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue