Jacek Caban : server: Introduce IOCTL_CONDRV_SET_OUTPUT_INFO ioctl.

Alexandre Julliard julliard at winehq.org
Fri Jul 10 16:30:31 CDT 2020


Module: wine
Branch: master
Commit: 86acbd0122ddad629f4ac55595782f2c704d54dc
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=86acbd0122ddad629f4ac55595782f2c704d54dc

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Jul 10 17:07:03 2020 +0200

server: Introduce IOCTL_CONDRV_SET_OUTPUT_INFO ioctl.

Based on set_console_output_info request.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 include/wine/condrv.h |  10 ++-
 server/console.c      | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 206 insertions(+), 1 deletion(-)

diff --git a/include/wine/condrv.h b/include/wine/condrv.h
index 4d681f6ea7..49eb3459c0 100644
--- a/include/wine/condrv.h
+++ b/include/wine/condrv.h
@@ -30,7 +30,8 @@
 #define IOCTL_CONDRV_GET_INPUT_INFO        CTL_CODE(FILE_DEVICE_CONSOLE, 13, METHOD_BUFFERED, FILE_READ_PROPERTIES)
 
 /* console output ioctls */
-#define IOCTL_CONDRV_GET_OUTPUT_INFO       CTL_CODE(FILE_DEVICE_CONSOLE, 32, METHOD_BUFFERED, FILE_WRITE_PROPERTIES)
+#define IOCTL_CONDRV_GET_OUTPUT_INFO       CTL_CODE(FILE_DEVICE_CONSOLE, 32, METHOD_BUFFERED, FILE_READ_PROPERTIES)
+#define IOCTL_CONDRV_SET_OUTPUT_INFO       CTL_CODE(FILE_DEVICE_CONSOLE, 33, METHOD_BUFFERED, FILE_WRITE_PROPERTIES)
 
 /* console renderer ioctls */
 #define IOCTL_CONDRV_GET_RENDERER_EVENTS   CTL_CODE(FILE_DEVICE_CONSOLE, 70, METHOD_BUFFERED, FILE_READ_PROPERTIES)
@@ -68,6 +69,13 @@ struct condrv_output_info
     unsigned int  color_map[16];      /* color table */
 };
 
+/* IOCTL_CONDRV_SET_OUTPUT_INFO params */
+struct condrv_output_info_params
+{
+    unsigned int  mask;               /* setting mask */
+    struct condrv_output_info info;   /* output info */
+};
+
 /* IOCTL_CONDRV_GET_RENDERER_EVENTS result */
 struct condrv_renderer_event
 {
diff --git a/server/console.c b/server/console.c
index ba2e4c776d..89f6fae863 100644
--- a/server/console.c
+++ b/server/console.c
@@ -1196,6 +1196,187 @@ static int set_console_output_info( struct screen_buffer *screen_buffer,
     return 1;
 }
 
+static int set_output_info( struct screen_buffer *screen_buffer,
+                            const struct condrv_output_info_params *params, data_size_t extra_size )
+{
+    const struct condrv_output_info *info = &params->info;
+    struct condrv_renderer_event evt;
+    WCHAR *font_name;
+
+    if (params->mask & SET_CONSOLE_OUTPUT_INFO_CURSOR_GEOM)
+    {
+        if (info->cursor_size < 1 || info->cursor_size > 100)
+        {
+            set_error( STATUS_INVALID_PARAMETER );
+            return 0;
+        }
+        if (screen_buffer->cursor_size != info->cursor_size ||
+            screen_buffer->cursor_visible != info->cursor_visible)
+        {
+            screen_buffer->cursor_size    = info->cursor_size;
+            screen_buffer->cursor_visible = info->cursor_visible;
+            evt.event = CONSOLE_RENDERER_CURSOR_GEOM_EVENT;
+            memset( &evt.u, 0, sizeof(evt.u) );
+            evt.u.cursor_geom.size    = info->cursor_size;
+            evt.u.cursor_geom.visible = info->cursor_visible;
+            console_input_events_append( screen_buffer->input, &evt );
+        }
+    }
+    if (params->mask & SET_CONSOLE_OUTPUT_INFO_CURSOR_POS)
+    {
+        if (info->cursor_x < 0 || info->cursor_x >= screen_buffer->width ||
+            info->cursor_y < 0 || info->cursor_y >= screen_buffer->height)
+        {
+            set_error( STATUS_INVALID_PARAMETER );
+            return 0;
+        }
+        if (screen_buffer->cursor_x != info->cursor_x || screen_buffer->cursor_y != info->cursor_y)
+        {
+            screen_buffer->cursor_x       = info->cursor_x;
+            screen_buffer->cursor_y       = info->cursor_y;
+            evt.event = CONSOLE_RENDERER_CURSOR_POS_EVENT;
+            memset( &evt.u, 0, sizeof(evt.u) );
+            evt.u.cursor_pos.x = info->cursor_x;
+            evt.u.cursor_pos.y = info->cursor_y;
+            console_input_events_append( screen_buffer->input, &evt );
+        }
+    }
+    if (params->mask & SET_CONSOLE_OUTPUT_INFO_SIZE)
+    {
+        unsigned cc;
+
+        /* new screen-buffer cannot be smaller than actual window */
+        if (info->width < screen_buffer->win.right - screen_buffer->win.left + 1 ||
+            info->height < screen_buffer->win.bottom - screen_buffer->win.top + 1)
+        {
+            set_error( STATUS_INVALID_PARAMETER );
+            return 0;
+        }
+        /* FIXME: there are also some basic minimum and max size to deal with */
+        if (!change_screen_buffer_size( screen_buffer, info->width, info->height )) return 0;
+
+        evt.event = CONSOLE_RENDERER_SB_RESIZE_EVENT;
+        memset(  &evt.u, 0, sizeof(evt.u) );
+        evt.u.resize.width  = info->width;
+        evt.u.resize.height = info->height;
+        console_input_events_append( screen_buffer->input, &evt );
+
+        evt.event = CONSOLE_RENDERER_UPDATE_EVENT;
+        memset( &evt.u, 0, sizeof(evt.u) );
+        evt.u.update.top    = 0;
+        evt.u.update.bottom = screen_buffer->height - 1;
+        console_input_events_append( screen_buffer->input, &evt );
+
+        /* scroll window to display sb */
+        if (screen_buffer->win.right >= info->width)
+        {
+            screen_buffer->win.right -= screen_buffer->win.left;
+            screen_buffer->win.left = 0;
+        }
+        if (screen_buffer->win.bottom >= info->height)
+        {
+            screen_buffer->win.bottom -= screen_buffer->win.top;
+            screen_buffer->win.top = 0;
+        }
+        /* reset cursor if needed (normally, if cursor was outside of new sb, the
+         * window has been shifted so that the new position of the cursor will be
+         * visible */
+        cc = 0;
+        if (screen_buffer->cursor_x >= info->width)
+        {
+            screen_buffer->cursor_x = info->width - 1;
+            cc++;
+        }
+        if (screen_buffer->cursor_y >= info->height)
+        {
+            screen_buffer->cursor_y = info->height - 1;
+            cc++;
+        }
+        if (cc)
+        {
+            evt.event = CONSOLE_RENDERER_CURSOR_POS_EVENT;
+            memset( &evt.u, 0, sizeof(evt.u) );
+            evt.u.cursor_pos.x = info->cursor_x;
+            evt.u.cursor_pos.y = info->cursor_y;
+            console_input_events_append( screen_buffer->input, &evt );
+        }
+
+        if (screen_buffer == screen_buffer->input->active &&
+            screen_buffer->input->mode & ENABLE_WINDOW_INPUT)
+        {
+            INPUT_RECORD ir;
+            ir.EventType = WINDOW_BUFFER_SIZE_EVENT;
+            ir.Event.WindowBufferSizeEvent.dwSize.X = info->width;
+            ir.Event.WindowBufferSizeEvent.dwSize.Y = info->height;
+            write_console_input( screen_buffer->input, 1, &ir );
+        }
+    }
+    if (params->mask & SET_CONSOLE_OUTPUT_INFO_ATTR)
+    {
+        screen_buffer->attr = info->attr;
+    }
+    if (params->mask & SET_CONSOLE_OUTPUT_INFO_POPUP_ATTR)
+    {
+        screen_buffer->popup_attr = info->popup_attr;
+    }
+    if (params->mask & SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW)
+    {
+        if (info->win_left < 0 || info->win_left > info->win_right ||
+            info->win_right >= screen_buffer->width ||
+            info->win_top < 0  || info->win_top > info->win_bottom ||
+            info->win_bottom >= screen_buffer->height)
+        {
+            set_error( STATUS_INVALID_PARAMETER );
+            return 0;
+        }
+        if (screen_buffer->win.left != info->win_left || screen_buffer->win.top != info->win_top ||
+            screen_buffer->win.right != info->win_right || screen_buffer->win.bottom != info->win_bottom)
+        {
+            screen_buffer->win.left   = info->win_left;
+            screen_buffer->win.top    = info->win_top;
+            screen_buffer->win.right  = info->win_right;
+            screen_buffer->win.bottom = info->win_bottom;
+            evt.event = CONSOLE_RENDERER_DISPLAY_EVENT;
+            memset( &evt.u, 0, sizeof(evt.u) );
+            evt.u.display.left   = info->win_left;
+            evt.u.display.top    = info->win_top;
+            evt.u.display.width  = info->win_right - info->win_left + 1;
+            evt.u.display.height = info->win_bottom - info->win_top + 1;
+            console_input_events_append( screen_buffer->input, &evt );
+        }
+    }
+    if (params->mask & SET_CONSOLE_OUTPUT_INFO_MAX_SIZE)
+    {
+        screen_buffer->max_width  = info->max_width;
+        screen_buffer->max_height = info->max_height;
+    }
+    if (params->mask & SET_CONSOLE_OUTPUT_INFO_COLORTABLE)
+    {
+        memcpy( screen_buffer->color_map, info->color_map, sizeof(info->color_map) );
+    }
+    if (params->mask & SET_CONSOLE_OUTPUT_INFO_FONT)
+    {
+        screen_buffer->font.width  = info->font_width;
+        screen_buffer->font.height = info->font_height;
+        screen_buffer->font.weight = info->font_weight;
+        screen_buffer->font.pitch_family = info->font_pitch_family;
+        if (extra_size)
+        {
+            extra_size = extra_size / sizeof(WCHAR) * sizeof(WCHAR);
+            font_name = mem_alloc( extra_size );
+            if (font_name)
+            {
+                memcpy( font_name, info + 1, extra_size );
+                free( screen_buffer->font.face_name );
+                screen_buffer->font.face_name = font_name;
+                screen_buffer->font.face_len  = extra_size;
+            }
+        }
+    }
+
+    return 1;
+}
+
 /* appends a new line to history (history is a fixed size array) */
 static void console_input_append_hist( struct console_input* console, const WCHAR* buf, data_size_t len )
 {
@@ -1675,6 +1856,22 @@ static int screen_buffer_ioctl( struct fd *fd, ioctl_code_t code, struct async *
             return 1;
         }
 
+    case IOCTL_CONDRV_SET_OUTPUT_INFO:
+        {
+            const struct condrv_output_info_params *params = get_req_data();
+            if (get_req_data_size() < sizeof(*params))
+            {
+                set_error( STATUS_INVALID_PARAMETER );
+                return 0;
+            }
+            if (!screen_buffer->input)
+            {
+                set_error( STATUS_INVALID_HANDLE );
+                return 0;
+            }
+            return set_output_info( screen_buffer, params, get_req_data_size() - sizeof(*params) );
+        }
+
     default:
         set_error( STATUS_INVALID_HANDLE );
         return 0;




More information about the wine-cvs mailing list