Jacek Caban : server: Introduce IOCTL_CONDRV_SCROLL ioctl.
Alexandre Julliard
julliard at winehq.org
Wed Jul 29 15:47:00 CDT 2020
Module: wine
Branch: master
Commit: 7ae370a5491b58eeec03961b09dcf5ae5e53e411
URL: https://source.winehq.org/git/wine.git/?a=commit;h=7ae370a5491b58eeec03961b09dcf5ae5e53e411
Author: Jacek Caban <jacek at codeweavers.com>
Date: Wed Jul 29 12:36:05 2020 +0200
server: Introduce IOCTL_CONDRV_SCROLL ioctl.
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
include/wine/condrv.h | 29 +++++++++----
server/console.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 135 insertions(+), 12 deletions(-)
diff --git a/include/wine/condrv.h b/include/wine/condrv.h
index 839db84ea5..a6df63155c 100644
--- a/include/wine/condrv.h
+++ b/include/wine/condrv.h
@@ -22,6 +22,7 @@
#define _INC_CONDRV
#include "winioctl.h"
+#include "wincon.h"
/* common console input and output ioctls */
#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_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_SCROLL CTL_CODE(FILE_DEVICE_CONSOLE, 36, METHOD_BUFFERED, FILE_WRITE_DATA)
/* console renderer ioctls */
#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 */
};
+#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 */
struct condrv_fill_output_params
{
@@ -145,15 +157,14 @@ struct condrv_fill_output_params
unsigned short attr; /* attribute to write */
};
-#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_SCROLL params */
+struct condrv_scroll_params
+{
+ SMALL_RECT scroll; /* source rectangle */
+ COORD origin; /* destination coordinates */
+ SMALL_RECT clip; /* clipping rectangle */
+ char_info_t fill; /* empty character info */
+};
/* IOCTL_CONDRV_GET_RENDERER_EVENTS result */
struct condrv_renderer_event
diff --git a/server/console.c b/server/console.c
index 8bd3e94e65..f924ddc06b 100644
--- a/server/console.c
+++ b/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 */
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;
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();
}
+ 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:
set_error( STATUS_INVALID_HANDLE );
return 0;
@@ -2182,8 +2294,8 @@ DECL_HANDLER(move_console_output)
release_object( screen_buffer );
return;
}
- scroll_console_output( screen_buffer, req->x_src, req->y_src, req->x_dst, req->y_dst,
- req->w, req->h );
+ scroll_console_output_req( screen_buffer, req->x_src, req->y_src, req->x_dst, req->y_dst,
+ req->w, req->h );
release_object( screen_buffer );
}
}
More information about the wine-cvs
mailing list