mirror of https://github.com/neutrinolabs/xrdp
Refactoring resizing into state machine.
- Fixes MSTSC resizing (with RFX as well). - Queue system so that resizes are processed when XRDP and the X server are ready, not immediately. - Deletes and recreates the encoder (RFX fix) - Introduces a dynamic_monitor_description struct that is used for the queue system. - Fix some lines previously introduced by the original resizing code to be 80 chars long, as is the standard for XRDP.
This commit is contained in:
parent
7711978713
commit
6f461aa54c
20
xrdp/xrdp.h
20
xrdp/xrdp.h
|
@ -147,8 +147,12 @@ xrdp_wm_get_wait_objs(struct xrdp_wm *self, tbus *robjs, int *rc,
|
|||
tbus *wobjs, int *wc, int *timeout);
|
||||
int
|
||||
xrdp_wm_check_wait_objs(struct xrdp_wm *self);
|
||||
const char *
|
||||
xrdp_wm_login_state_to_str(enum wm_login_state login_state);
|
||||
int
|
||||
xrdp_wm_set_login_state(struct xrdp_wm *self, enum wm_login_state login_state);
|
||||
int
|
||||
xrdp_wm_can_resize(struct xrdp_wm *self);
|
||||
void
|
||||
xrdp_wm_mod_connect_done(struct xrdp_wm *self, int status);
|
||||
|
||||
|
@ -397,18 +401,12 @@ xrdp_bitmap_compress(char *in_data, int width, int height,
|
|||
|
||||
/* xrdp_mm.c */
|
||||
|
||||
struct dynamic_monitor_layout
|
||||
struct display_control_monitor_layout_data
|
||||
{
|
||||
int flags;
|
||||
int left;
|
||||
int top;
|
||||
int width;
|
||||
int height;
|
||||
int physical_width;
|
||||
int physical_height;
|
||||
int orientation;
|
||||
int desktop_scale_factor;
|
||||
int device_scale_factor;
|
||||
struct display_size_description description;
|
||||
enum display_resize_state state;
|
||||
int last_state_update_timestamp;
|
||||
int start_time;
|
||||
};
|
||||
|
||||
int
|
||||
|
|
535
xrdp/xrdp_mm.c
535
xrdp/xrdp_mm.c
|
@ -43,6 +43,7 @@
|
|||
|
||||
#include "xrdp_encoder.h"
|
||||
#include "xrdp_sockets.h"
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
|
@ -65,6 +66,8 @@ struct xrdp_mm *
|
|||
xrdp_mm_create(struct xrdp_wm *owner)
|
||||
{
|
||||
struct xrdp_mm *self;
|
||||
char buf[1024];
|
||||
int pid;
|
||||
|
||||
self = (struct xrdp_mm *)g_malloc(sizeof(struct xrdp_mm), 1);
|
||||
self->wm = owner;
|
||||
|
@ -72,6 +75,14 @@ xrdp_mm_create(struct xrdp_wm *owner)
|
|||
self->login_names->auto_free = 1;
|
||||
self->login_values = list_create();
|
||||
self->login_values->auto_free = 1;
|
||||
self->resize_queue = list_create();
|
||||
self->resize_queue->auto_free = 1;
|
||||
|
||||
pid = g_getpid();
|
||||
/* setup wait objects for signalling */
|
||||
g_snprintf(buf, sizeof(buf), "xrdp_%8.8x_resize_ready", pid);
|
||||
self->resize_ready = g_create_wait_obj(buf);
|
||||
self->resize_data = NULL;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_mm_create: bpp %d mcs_connection_type %d "
|
||||
"jpeg_codec_id %d v3_codec_id %d rfx_codec_id %d "
|
||||
|
@ -165,6 +176,9 @@ xrdp_mm_delete(struct xrdp_mm *self)
|
|||
self->sesman_trans = 0;
|
||||
list_delete(self->login_names);
|
||||
list_delete(self->login_values);
|
||||
list_delete(self->resize_queue);
|
||||
g_free(self->resize_data);
|
||||
g_delete_wait_obj(self->resize_ready);
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
|
@ -969,7 +983,8 @@ dynamic_monitor_open_response(intptr_t id, int chan_id, int creation_status)
|
|||
struct stream *s;
|
||||
int bytes;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "dynamic_monitor_open_response: chan_id %d creation_status 0x%8.8x", chan_id, creation_status);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "dynamic_monitor_open_response: chan_id %d "
|
||||
"creation_status 0x%8.8x", chan_id, creation_status);
|
||||
if (creation_status != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "dynamic_monitor_open_response: error");
|
||||
|
@ -1031,152 +1046,24 @@ sync_dynamic_monitor_data(struct xrdp_wm *wm,
|
|||
MAXIMUM_MONITOR_SIZE);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
process_dynamic_monitor_description(struct xrdp_wm *wm,
|
||||
struct display_size_description *description)
|
||||
int
|
||||
advance_resize_state_machine(struct xrdp_mm *mm,
|
||||
enum display_resize_state new_state)
|
||||
{
|
||||
int error = 0;
|
||||
struct xrdp_mm *mm = wm->mm;
|
||||
struct xrdp_mod *module = mm->mod;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "process_dynamic_monitor_description:");
|
||||
|
||||
if (wm->client_info->suppress_output == 1)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"process_dynamic_monitor_description:"
|
||||
" Not allowing resize. Suppress output is active.");
|
||||
return 0;
|
||||
}
|
||||
if (description == NULL)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_ERROR,
|
||||
"process_dynamic_monitor_description:"
|
||||
" description is null.");
|
||||
return 0;
|
||||
}
|
||||
if (description->session_width <= 0 || description->session_height <= 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"process_dynamic_monitor_description: Not allowing resize due to"
|
||||
" invalid dimensions (w: %d x h: %d)",
|
||||
description->session_width, description->session_height);
|
||||
return 0;
|
||||
}
|
||||
if (description->session_width
|
||||
== wm->client_info->display_sizes.session_width
|
||||
&& description->session_height
|
||||
== wm->client_info->display_sizes.session_height)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "process_dynamic_monitor_description:"
|
||||
" Not resizing. Already this size. (w: %d x h: %d)",
|
||||
description->session_width,
|
||||
description->session_height);
|
||||
sync_dynamic_monitor_data(wm, description);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: Unify this logic with server_reset
|
||||
error = libxrdp_reset(wm->session,
|
||||
description->session_width,
|
||||
description->session_height,
|
||||
wm->screen->bpp);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_ERROR,
|
||||
"process_dynamic_monitor_description:"
|
||||
" libxrdp_reset failed %d", error);
|
||||
return error;
|
||||
}
|
||||
/* reset cache */
|
||||
error = xrdp_cache_reset(wm->cache, wm->client_info);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_ERROR,
|
||||
"process_dynamic_monitor_description: xrdp_cache_reset"
|
||||
" failed %d", error);
|
||||
return error;
|
||||
}
|
||||
/* load some stuff */
|
||||
error = xrdp_wm_load_static_colors_plus(wm, 0);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_ERROR, "process_dynamic_monitor_description:"
|
||||
" xrdp_wm_load_static_colors_plus failed %d", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = xrdp_wm_load_static_pointers(wm);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_ERROR, "process_dynamic_monitor_description:"
|
||||
" xrdp_wm_load_static_pointers failed %d", error);
|
||||
return error;
|
||||
}
|
||||
/* resize the main window */
|
||||
error = xrdp_bitmap_resize(wm->screen,
|
||||
description->session_width,
|
||||
description->session_height);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_ERROR, "process_dynamic_monitor_description:"
|
||||
" xrdp_bitmap_resize failed %d", error);
|
||||
return error;
|
||||
}
|
||||
/* redraw */
|
||||
error = xrdp_bitmap_invalidate(wm->screen, 0);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_ERROR,
|
||||
"process_dynamic_monitor_description:"
|
||||
" xrdp_bitmap_invalidate failed %d", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
if (module != 0)
|
||||
{
|
||||
error = module->mod_server_version_message(module);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_ERROR, "process_dynamic_monitor_description:"
|
||||
" mod_server_version_message failed %d", error);
|
||||
return error;
|
||||
}
|
||||
error = module->mod_server_monitor_resize(
|
||||
module,
|
||||
description->session_width,
|
||||
description->session_height);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_ERROR, "process_dynamic_monitor_description:"
|
||||
"mod_server_monitor_resize failed %d", error);
|
||||
return error;
|
||||
}
|
||||
error = module->mod_server_monitor_full_invalidate(
|
||||
module,
|
||||
description->session_width,
|
||||
description->session_height);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_ERROR, "process_dynamic_monitor_description:"
|
||||
"mod_server_monitor_full_invalidate failed %d", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
// Need to recreate the encoder for connections that use it.
|
||||
if (mm->encoder != NULL)
|
||||
{
|
||||
xrdp_encoder_delete(mm->encoder);
|
||||
mm->encoder = NULL;
|
||||
}
|
||||
if (mm->encoder == NULL)
|
||||
{
|
||||
mm->encoder = xrdp_encoder_create(mm);
|
||||
}
|
||||
|
||||
sync_dynamic_monitor_data(wm, description);
|
||||
struct display_control_monitor_layout_data *description = mm->resize_data;
|
||||
LOG_DEVEL(LOG_LEVEL_INFO,
|
||||
"advance_resize_state_machine:"
|
||||
" Processing resize to: %d x %d."
|
||||
" Advancing state from %s to %s."
|
||||
" Previous state took %d MS.",
|
||||
description->description.session_width,
|
||||
description->description.session_height,
|
||||
XRDP_DISPLAY_RESIZE_STATE_TO_STR(description->state),
|
||||
XRDP_DISPLAY_RESIZE_STATE_TO_STR(new_state),
|
||||
g_time3() - description->last_state_update_timestamp);
|
||||
description->state = new_state;
|
||||
description->last_state_update_timestamp = g_time3();
|
||||
g_set_wait_obj(mm->resize_ready);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1192,10 +1079,19 @@ dynamic_monitor_data(intptr_t id, int chan_id, char *data, int bytes)
|
|||
struct xrdp_process *pro;
|
||||
struct xrdp_wm *wm;
|
||||
int monitor_layout_size;
|
||||
struct display_size_description *display_size_data;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "dynamic_monitor_data:");
|
||||
pro = (struct xrdp_process *) id;
|
||||
wm = pro->wm;
|
||||
|
||||
if (wm->client_info->suppress_output == 1)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "dynamic_monitor_data: Not allowing resize."
|
||||
" Suppress output is active.");
|
||||
return error;
|
||||
}
|
||||
|
||||
g_memset(&ls, 0, sizeof(ls));
|
||||
ls.data = data;
|
||||
ls.p = ls.data;
|
||||
|
@ -1204,16 +1100,33 @@ dynamic_monitor_data(intptr_t id, int chan_id, char *data, int bytes)
|
|||
s = &ls;
|
||||
in_uint32_le(s, msg_type);
|
||||
in_uint32_le(s, msg_length);
|
||||
LOG(LOG_LEVEL_DEBUG, "dynamic_monitor_data: msg_type %d msg_length %d",
|
||||
msg_type, msg_length);
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG,
|
||||
"dynamic_monitor_data: msg_type %d msg_length %d",
|
||||
msg_type, msg_length);
|
||||
|
||||
if (msg_type != DISPLAYCONTROL_PDU_TYPE_MONITOR_LAYOUT)
|
||||
if (msg_type != DISPLAYCONTROL_PDU_TYPE_MONITOR_LAYOUT
|
||||
&& msg_length >= 0)
|
||||
{
|
||||
// Unsupported message types
|
||||
switch (msg_type)
|
||||
{
|
||||
case DISPLAYCONTROL_PDU_TYPE_CAPS:
|
||||
LOG(LOG_LEVEL_ERROR, "dynamic_monitor_data: Received"
|
||||
" DISPLAYCONTROL_PDU_TYPE_CAPS. Per MS-RDPEDISP 2.2.2.1,"
|
||||
" this is a server-to-client message, client should never"
|
||||
" send this. Ignoring message");
|
||||
break;
|
||||
default:
|
||||
LOG(LOG_LEVEL_ERROR, "dynamic_monitor_data: Received neither"
|
||||
" nor DISPLAYCONTROL_PDU_TYPE_CAPS. Ignoring message.");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
in_uint32_le(s, monitor_layout_size);
|
||||
if (monitor_layout_size != 40)
|
||||
{
|
||||
/* 2.2.2.2 DISPLAYCONTROL_MONITOR_LAYOUT_PDU */
|
||||
LOG(LOG_LEVEL_ERROR, "dynamic_monitor_data: monitor_layout_size"
|
||||
" is %d. Per spec ([MS-RDPEDISP] 2.2.2.2"
|
||||
" DISPLAYCONTROL_MONITOR_LAYOUT_PDU) it must be 40.",
|
||||
|
@ -1221,19 +1134,300 @@ dynamic_monitor_data(intptr_t id, int chan_id, char *data, int bytes)
|
|||
return 1;
|
||||
}
|
||||
|
||||
struct display_size_description *description =
|
||||
(struct display_size_description *)
|
||||
g_malloc(sizeof(struct display_size_description), 1);
|
||||
|
||||
error = libxrdp_process_monitor_stream(s, description, 1);
|
||||
if (error == 0)
|
||||
display_size_data = (struct display_size_description *)
|
||||
g_malloc(sizeof(struct display_size_description), 1);
|
||||
if (!display_size_data)
|
||||
{
|
||||
error = process_dynamic_monitor_description(wm, description);
|
||||
return 1;
|
||||
}
|
||||
g_free(description);
|
||||
error = libxrdp_process_monitor_stream(s, display_size_data, 1);
|
||||
if (error)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "dynamic_monitor_data:"
|
||||
" libxrdp_process_monitor_stream"
|
||||
" failed with error %d.", error);
|
||||
g_free(display_size_data);
|
||||
return error;
|
||||
}
|
||||
list_add_item(wm->mm->resize_queue, (tintptr)display_size_data);
|
||||
g_set_wait_obj(wm->mm->resize_ready);
|
||||
LOG(LOG_LEVEL_DEBUG, "dynamic_monitor_data:"
|
||||
" received width %d, received height %d.", display_size_data->session_width, display_size_data->session_height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
advance_error(int error,
|
||||
struct xrdp_mm *mm)
|
||||
{
|
||||
advance_resize_state_machine(mm, WMRZ_ERROR);
|
||||
return error;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
process_display_control_monitor_layout_data(struct xrdp_wm *wm)
|
||||
{
|
||||
int error = 0;
|
||||
struct xrdp_mm *mm;
|
||||
struct xrdp_mod *module;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "process_display_control_monitor_layout_data:");
|
||||
|
||||
if (wm == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
mm = wm->mm;
|
||||
if (mm == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
module = mm->mod;
|
||||
if (module == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!xrdp_wm_can_resize(wm))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct display_control_monitor_layout_data *description
|
||||
= mm->resize_data;
|
||||
const unsigned int desc_width = description->description.session_width;
|
||||
const unsigned int desc_height = description->description.session_height;
|
||||
|
||||
switch (description->state)
|
||||
{
|
||||
case WMRZ_ENCODER_DELETE:
|
||||
// Disable the encoder until the resize is complete.
|
||||
if (mm->encoder != NULL)
|
||||
{
|
||||
xrdp_encoder_delete(mm->encoder);
|
||||
mm->encoder = NULL;
|
||||
}
|
||||
advance_resize_state_machine(mm, WMRZ_SERVER_MONITOR_RESIZE);
|
||||
break;
|
||||
case WMRZ_SERVER_MONITOR_RESIZE:
|
||||
error = module->mod_server_monitor_resize(
|
||||
module, desc_width, desc_height);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_INFO,
|
||||
"process_display_control_monitor_layout_data:"
|
||||
" mod_server_monitor_resize failed %d", error);
|
||||
return advance_error(error, mm);
|
||||
}
|
||||
advance_resize_state_machine(mm, WMRZ_SERVER_VERSION_MESSAGE);
|
||||
break;
|
||||
case WMRZ_SERVER_VERSION_MESSAGE:
|
||||
error = module->mod_server_version_message(module);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_INFO,
|
||||
"process_display_control_monitor_layout_data:"
|
||||
" mod_server_version_message failed %d", error);
|
||||
return advance_error(error, mm);
|
||||
}
|
||||
advance_resize_state_machine(mm, WMRZ_XRDP_CORE_RESIZE);
|
||||
break;
|
||||
case WMRZ_XRDP_CORE_RESIZE:
|
||||
// TODO: Unify this logic with server_reset
|
||||
error = libxrdp_reset(
|
||||
wm->session, desc_width, desc_height, wm->screen->bpp);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_INFO,
|
||||
"process_display_control_monitor_layout_data:"
|
||||
" libxrdp_reset failed %d", error);
|
||||
return advance_error(error, mm);
|
||||
}
|
||||
/* reset cache */
|
||||
error = xrdp_cache_reset(wm->cache, wm->client_info);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_INFO,
|
||||
"process_display_control_monitor_layout_data:"
|
||||
" xrdp_cache_reset failed %d", error);
|
||||
return advance_error(error, mm);
|
||||
}
|
||||
/* load some stuff */
|
||||
error = xrdp_wm_load_static_colors_plus(wm, 0);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_INFO,
|
||||
"process_display_control_monitor_layout_data:"
|
||||
" xrdp_wm_load_static_colors_plus failed %d", error);
|
||||
return advance_error(error, mm);
|
||||
}
|
||||
|
||||
error = xrdp_wm_load_static_pointers(wm);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_INFO,
|
||||
"process_display_control_monitor_layout_data:"
|
||||
" xrdp_wm_load_static_pointers failed %d", error);
|
||||
return advance_error(error, mm);
|
||||
}
|
||||
/* resize the main window */
|
||||
error = xrdp_bitmap_resize(
|
||||
wm->screen, desc_width, desc_height);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_INFO,
|
||||
"process_display_control_monitor_layout_data:"
|
||||
" xrdp_bitmap_resize failed %d", error);
|
||||
return advance_error(error, mm);
|
||||
}
|
||||
sync_dynamic_monitor_data(wm, &(description->description));
|
||||
advance_resize_state_machine(mm, WMRZ_ENCODER_CREATE);
|
||||
break;
|
||||
case WMRZ_ENCODER_CREATE:
|
||||
if (mm->encoder == NULL)
|
||||
{
|
||||
mm->encoder = xrdp_encoder_create(mm);
|
||||
}
|
||||
advance_resize_state_machine(mm, WMRZ_SERVER_INVALIDATE);
|
||||
break;
|
||||
case WMRZ_SERVER_INVALIDATE:
|
||||
/* redraw */
|
||||
error = xrdp_bitmap_invalidate(wm->screen, 0);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_INFO,
|
||||
"process_display_control_monitor_layout_data:"
|
||||
" xrdp_bitmap_invalidate failed %d", error);
|
||||
return advance_error(error, mm);
|
||||
}
|
||||
if (module != 0)
|
||||
{
|
||||
// Ack all frames to speed up resize.
|
||||
module->mod_frame_ack(module, 0, INT_MAX);
|
||||
}
|
||||
advance_resize_state_machine(mm, WMRZ_COMPLETE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
dynamic_monitor_process_queue(struct xrdp_mm *self)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "dynamic_monitor_process_queue:");
|
||||
|
||||
if (self == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct xrdp_wm *wm = self->wm;
|
||||
|
||||
if (!xrdp_wm_can_resize(wm))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (self->resize_data == NULL)
|
||||
{
|
||||
if (self->resize_queue->count <= 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "Resize queue is empty.");
|
||||
return 0;
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "dynamic_monitor_process_queue: Queue is"
|
||||
" not empty. Filling out description.");
|
||||
const struct display_size_description *queue_head =
|
||||
(struct display_size_description *)
|
||||
list_get_item(self->resize_queue, 0);
|
||||
|
||||
const int invalid_dimensions = queue_head->session_width <= 0
|
||||
|| queue_head->session_height <= 0;
|
||||
|
||||
if (invalid_dimensions)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"dynamic_monitor_process_queue: Not allowing"
|
||||
" resize due to invalid dimensions (w: %d x h: %d)",
|
||||
queue_head->session_width,
|
||||
queue_head->session_height);
|
||||
}
|
||||
|
||||
const struct display_size_description *current_size
|
||||
= &wm->client_info->display_sizes;
|
||||
|
||||
const int already_this_size = queue_head->session_width
|
||||
== current_size->session_width
|
||||
&& queue_head->session_height
|
||||
== current_size->session_height;
|
||||
|
||||
if (already_this_size)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"dynamic_monitor_process_queue: Not resizing."
|
||||
" Already this size. (w: %d x h: %d)",
|
||||
queue_head->session_width,
|
||||
queue_head->session_height);
|
||||
}
|
||||
|
||||
if (!invalid_dimensions && !already_this_size)
|
||||
{
|
||||
const int LAYOUT_DATA_SIZE =
|
||||
sizeof(struct display_control_monitor_layout_data);
|
||||
self->resize_data = (struct display_control_monitor_layout_data *)
|
||||
g_malloc(LAYOUT_DATA_SIZE, 1);
|
||||
g_memcpy(&(self->resize_data->description), queue_head,
|
||||
sizeof(struct display_size_description));
|
||||
const int time = g_time3();
|
||||
self->resize_data->start_time = time;
|
||||
self->resize_data->last_state_update_timestamp = time;
|
||||
advance_resize_state_machine(self, WMRZ_ENCODER_DELETE);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_set_wait_obj(self->resize_ready);
|
||||
}
|
||||
list_remove_item(self->resize_queue, 0);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "dynamic_monitor_process_queue:"
|
||||
" Resize data is not null.");
|
||||
}
|
||||
|
||||
if (self->resize_data->state == WMRZ_COMPLETE)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "dynamic_monitor_process_queue: Clearing"
|
||||
" completed resize (w: %d x h: %d). It took %d milliseconds.",
|
||||
self->resize_data->description.session_width,
|
||||
self->resize_data->description.session_height,
|
||||
g_time3() - self->resize_data->start_time);
|
||||
g_set_wait_obj(self->resize_ready);
|
||||
}
|
||||
else if (self->resize_data->state == WMRZ_ERROR)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "dynamic_monitor_process_queue: Clearing"
|
||||
" failed request to resize to: (w: %d x h: %d)",
|
||||
self->resize_data->description.session_width,
|
||||
self->resize_data->description.session_height);
|
||||
g_set_wait_obj(self->resize_ready);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No errors, process it!
|
||||
return process_display_control_monitor_layout_data(self->wm);
|
||||
}
|
||||
g_free(self->resize_data);
|
||||
self->resize_data = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
dynamic_monitor_initialize(struct xrdp_mm *self)
|
||||
|
@ -1266,6 +1460,7 @@ dynamic_monitor_initialize(struct xrdp_mm *self)
|
|||
int
|
||||
xrdp_mm_drdynvc_up(struct xrdp_mm *self)
|
||||
{
|
||||
struct display_control_monitor_layout_data *ignore_marker;
|
||||
const char *enable_dynamic_resize;
|
||||
int error = 0;
|
||||
|
||||
|
@ -1279,11 +1474,12 @@ xrdp_mm_drdynvc_up(struct xrdp_mm *self)
|
|||
!g_text2bool(enable_dynamic_resize))
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "User has disabled dynamic resizing.");
|
||||
return error;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = dynamic_monitor_initialize(self);
|
||||
}
|
||||
ignore_marker = (struct display_control_monitor_layout_data *)
|
||||
g_malloc(sizeof(struct display_control_monitor_layout_data), 1);
|
||||
list_add_item(self->resize_queue, (tintptr)ignore_marker);
|
||||
error = dynamic_monitor_initialize(self);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -1317,7 +1513,8 @@ xrdp_mm_drdynvc_open_response(intptr_t id, int chan_id, int creation_status)
|
|||
struct xrdp_process *pro;
|
||||
int chansrv_chan_id;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_mm_drdynvc_open_response: chan_id %d creation_status %d",
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_mm_drdynvc_open_response: "
|
||||
" chan_id %d creation_status %d",
|
||||
chan_id, creation_status);
|
||||
pro = (struct xrdp_process *) id;
|
||||
wm = pro->wm;
|
||||
|
@ -2684,6 +2881,11 @@ xrdp_mm_get_wait_objs(struct xrdp_mm *self,
|
|||
read_objs[(*rcount)++] = self->encoder->xrdp_encoder_event_processed;
|
||||
}
|
||||
|
||||
if (self->resize_queue != 0)
|
||||
{
|
||||
read_objs[(*rcount)++] = self->resize_ready;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -2908,6 +3110,12 @@ xrdp_mm_check_wait_objs(struct xrdp_mm *self)
|
|||
}
|
||||
}
|
||||
|
||||
if (g_is_wait_obj_set(self->resize_ready))
|
||||
{
|
||||
g_reset_wait_obj(self->resize_ready);
|
||||
dynamic_monitor_process_queue(self);
|
||||
}
|
||||
|
||||
if (self->encoder != NULL)
|
||||
{
|
||||
if (g_is_wait_obj_set(self->encoder->xrdp_encoder_event_processed))
|
||||
|
@ -3557,7 +3765,8 @@ server_reset(struct xrdp_mod *mod, int width, int height, int bpp)
|
|||
if (wm->client_info->display_sizes.session_width == (uint32_t)width &&
|
||||
wm->client_info->display_sizes.session_height == (uint32_t)height &&
|
||||
wm->client_info->bpp == bpp &&
|
||||
(wm->client_info->display_sizes.monitorCount == 0 || wm->client_info->multimon == 0))
|
||||
(wm->client_info->display_sizes.monitorCount == 0 ||
|
||||
wm->client_info->multimon == 0))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -311,6 +311,30 @@ enum mm_connect_state
|
|||
MMCS_DONE
|
||||
};
|
||||
|
||||
enum display_resize_state
|
||||
{
|
||||
WMRZ_ENCODER_DELETE = 0,
|
||||
WMRZ_SERVER_MONITOR_RESIZE,
|
||||
WMRZ_SERVER_VERSION_MESSAGE,
|
||||
WMRZ_XRDP_CORE_RESIZE,
|
||||
WMRZ_ENCODER_CREATE,
|
||||
WMRZ_SERVER_INVALIDATE,
|
||||
WMRZ_COMPLETE,
|
||||
WMRZ_ERROR
|
||||
};
|
||||
|
||||
#define XRDP_DISPLAY_RESIZE_STATE_TO_STR(status) \
|
||||
((status) == WMRZ_ENCODER_DELETE ? "WMRZ_ENCODER_DELETE" : \
|
||||
(status) == WMRZ_SERVER_MONITOR_RESIZE ? "WMRZ_SERVER_MONITOR_RESIZE" : \
|
||||
(status) == WMRZ_SERVER_VERSION_MESSAGE ? "WMRZ_SERVER_VERSION_MESSAGE" : \
|
||||
(status) == WMRZ_XRDP_CORE_RESIZE ? "WMRZ_XRDP_CORE_RESIZE" : \
|
||||
(status) == WMRZ_ENCODER_CREATE ? "WMRZ_ENCODER_CREATE" : \
|
||||
(status) == WMRZ_SERVER_INVALIDATE ? "WMRZ_SERVER_INVALIDATE" : \
|
||||
(status) == WMRZ_COMPLETE ? "WMRZ_COMPLETE" : \
|
||||
(status) == WMRZ_ERROR ? "WMRZ_ERROR" : \
|
||||
"unknown" \
|
||||
)
|
||||
|
||||
struct xrdp_mm
|
||||
{
|
||||
struct xrdp_wm *wm; /* owner */
|
||||
|
@ -344,6 +368,11 @@ struct xrdp_mm
|
|||
int cs2xr_cid_map[256];
|
||||
int xr2cr_cid_map[256];
|
||||
int dynamic_monitor_chanid;
|
||||
|
||||
/* Resize on-the-fly control */
|
||||
struct display_control_monitor_layout_data *resize_data;
|
||||
struct list *resize_queue;
|
||||
tbus resize_ready;
|
||||
};
|
||||
|
||||
struct xrdp_key_info
|
||||
|
|
|
@ -2230,9 +2230,8 @@ xrdp_wm_check_wait_objs(struct xrdp_wm *self)
|
|||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static const char *
|
||||
wm_login_state_to_str(enum wm_login_state login_state)
|
||||
const char *
|
||||
xrdp_wm_login_state_to_str(enum wm_login_state login_state)
|
||||
{
|
||||
const char *result = "unknown";
|
||||
/* Use a switch for this, as some compilers will warn about missing states
|
||||
|
@ -2266,10 +2265,24 @@ int
|
|||
xrdp_wm_set_login_state(struct xrdp_wm *self, enum wm_login_state login_state)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "Login state change request %s -> %s",
|
||||
wm_login_state_to_str(self->login_state),
|
||||
wm_login_state_to_str(login_state));
|
||||
xrdp_wm_login_state_to_str(self->login_state),
|
||||
xrdp_wm_login_state_to_str(login_state));
|
||||
|
||||
self->login_state = login_state;
|
||||
g_set_wait_obj(self->login_state_event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
xrdp_wm_can_resize(struct xrdp_wm *self)
|
||||
{
|
||||
if (self->login_state != WMLS_CLEANUP
|
||||
&& self->login_state != WMLS_INACTIVE)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "Not allowing resize. Login in progress.");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO,
|
||||
"State is %s", xrdp_wm_login_state_to_str(self->login_state));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
62
xup/xup.c
62
xup/xup.c
|
@ -28,10 +28,12 @@
|
|||
#include "string_calls.h"
|
||||
|
||||
static int
|
||||
send_server_monitor_resize(struct mod *mod, struct stream *s, int width, int height, int bpp);
|
||||
send_server_monitor_resize(
|
||||
struct mod *mod, struct stream *s, int width, int height, int bpp);
|
||||
|
||||
static int
|
||||
send_server_monitor_full_invalidate(struct mod *mod, struct stream *s, int width, int height);
|
||||
send_server_monitor_full_invalidate(
|
||||
struct mod *mod, struct stream *s, int width, int height);
|
||||
|
||||
static int
|
||||
send_server_version_message(struct mod *v, struct stream *s);
|
||||
|
@ -154,10 +156,15 @@ lib_mod_connect(struct mod *mod)
|
|||
mod->server_msg(mod, "started connecting", 0);
|
||||
|
||||
/* only support 8, 15, 16, 24, and 32 bpp connections from rdp client */
|
||||
if (mod->bpp != 8 && mod->bpp != 15 && mod->bpp != 16 && mod->bpp != 24 && mod->bpp != 32)
|
||||
if (mod->bpp != 8
|
||||
&& mod->bpp != 15
|
||||
&& mod->bpp != 16
|
||||
&& mod->bpp != 24
|
||||
&& mod->bpp != 32)
|
||||
{
|
||||
mod->server_msg(mod,
|
||||
"error - only supporting 8, 15, 16, 24, and 32 bpp rdp connections", 0);
|
||||
"error - only supporting 8, 15, 16, 24, and 32"
|
||||
" bpp rdp connections", 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -220,12 +227,14 @@ lib_mod_connect(struct mod *mod)
|
|||
if (error == 0)
|
||||
{
|
||||
/* send screen size message */
|
||||
error = send_server_monitor_resize(mod, s, mod->width, mod->height, mod->bpp);
|
||||
error = send_server_monitor_resize(
|
||||
mod, s, mod->width, mod->height, mod->bpp);
|
||||
}
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
error = send_server_monitor_full_invalidate(mod, s, mod->width, mod->height);
|
||||
error = send_server_monitor_full_invalidate(
|
||||
mod, s, mod->width, mod->height);
|
||||
}
|
||||
|
||||
free_stream(s);
|
||||
|
@ -1261,7 +1270,8 @@ send_server_version_message(struct mod *mod, struct stream *s)
|
|||
/******************************************************************************/
|
||||
/* return error */
|
||||
static int
|
||||
send_server_monitor_resize(struct mod *mod, struct stream *s, int width, int height, int bpp)
|
||||
send_server_monitor_resize(
|
||||
struct mod *mod, struct stream *s, int width, int height, int bpp)
|
||||
{
|
||||
/* send screen size message */
|
||||
init_stream(s, 8192);
|
||||
|
@ -1271,8 +1281,9 @@ send_server_monitor_resize(struct mod *mod, struct stream *s, int width, int hei
|
|||
out_uint32_le(s, width);
|
||||
out_uint32_le(s, height);
|
||||
/*
|
||||
TODO: The bpp here is only necessary for initial creation. We should modify XUP to require this
|
||||
only on server initialization, but not on resize. Microsoft's RDP protocol does not support changing
|
||||
TODO: The bpp here is only necessary for initial creation. We should
|
||||
modify XUP to require this only on server initialization, but not on
|
||||
resize. Microsoft's RDP protocol does not support changing
|
||||
the bpp on resize.
|
||||
*/
|
||||
out_uint32_le(s, bpp);
|
||||
|
@ -1282,14 +1293,16 @@ send_server_monitor_resize(struct mod *mod, struct stream *s, int width, int hei
|
|||
s_pop_layer(s, iso_hdr);
|
||||
out_uint32_le(s, len);
|
||||
int rv = lib_send_copy(mod, s);
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "send_server_monitor_resize: sent resize message with following properties to xorgxrdp backend "
|
||||
"width=%d, height=%d, bpp=%d, return value=%d",
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "send_server_monitor_resize:"
|
||||
" sent resize message with following properties to"
|
||||
" xorgxrdp backend width=%d, height=%d, bpp=%d, return value=%d",
|
||||
width, height, bpp, rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int
|
||||
send_server_monitor_full_invalidate(struct mod *mod, struct stream *s, int width, int height)
|
||||
send_server_monitor_full_invalidate(
|
||||
struct mod *mod, struct stream *s, int width, int height)
|
||||
{
|
||||
/* send invalidate message */
|
||||
init_stream(s, 8192);
|
||||
|
@ -1309,8 +1322,10 @@ send_server_monitor_full_invalidate(struct mod *mod, struct stream *s, int width
|
|||
s_pop_layer(s, iso_hdr);
|
||||
out_uint32_le(s, len);
|
||||
int rv = lib_send_copy(mod, s);
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "send_server_monitor_full_invalidate: sent invalidate message with following properties to xorgxrdp backend "
|
||||
"width=%d, height=%d, return value=%d",
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "send_server_monitor_full_invalidate:"
|
||||
" sent invalidate message with following"
|
||||
" properties to xorgxrdp backend"
|
||||
" width=%d, height=%d, return value=%d",
|
||||
width, height, rv);
|
||||
return rv;
|
||||
}
|
||||
|
@ -1456,7 +1471,8 @@ lib_mod_process_orders(struct mod *mod, int type, struct stream *s)
|
|||
rv = process_server_paint_rect_shmem_ex(mod, s);
|
||||
break;
|
||||
default:
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING, "lib_mod_process_orders: unknown order type %d", type);
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING,
|
||||
"lib_mod_process_orders: unknown order type %d", type);
|
||||
rv = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -1523,7 +1539,8 @@ lib_mod_process_message(struct mod *mod, struct stream *s)
|
|||
}
|
||||
else if (type == 2) /* caps */
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "lib_mod_process_message: type 2 len %d", len);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE,
|
||||
"lib_mod_process_message: type 2 len %d", len);
|
||||
for (index = 0; index < num_orders; index++)
|
||||
{
|
||||
phold = s->p;
|
||||
|
@ -1533,7 +1550,9 @@ lib_mod_process_message(struct mod *mod, struct stream *s)
|
|||
switch (type)
|
||||
{
|
||||
default:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "lib_mod_process_message: unknown cap type %d len %d",
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE,
|
||||
"lib_mod_process_message: unknown"
|
||||
" cap type %d len %d",
|
||||
type, len);
|
||||
break;
|
||||
}
|
||||
|
@ -1661,7 +1680,8 @@ lib_mod_check_wait_objs(struct mod *mod)
|
|||
int
|
||||
lib_mod_frame_ack(struct mod *amod, int flags, int frame_id)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "lib_mod_frame_ack: flags 0x%8.8x frame_id %d", flags, frame_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE,
|
||||
"lib_mod_frame_ack: flags 0x%8.8x frame_id %d", flags, frame_id);
|
||||
send_paint_rect_ex_ack(amod, flags, frame_id);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1672,7 +1692,8 @@ int
|
|||
lib_mod_suppress_output(struct mod *amod, int suppress,
|
||||
int left, int top, int right, int bottom)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "lib_mod_suppress_output: suppress 0x%8.8x left %d top %d "
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE,
|
||||
"lib_mod_suppress_output: suppress 0x%8.8x left %d top %d "
|
||||
"right %d bottom %d", suppress, left, top, right, bottom);
|
||||
send_suppress_output(amod, suppress, left, top, right, bottom);
|
||||
return 0;
|
||||
|
@ -1699,7 +1720,8 @@ mod_init(void)
|
|||
mod->mod_frame_ack = lib_mod_frame_ack;
|
||||
mod->mod_suppress_output = lib_mod_suppress_output;
|
||||
mod->mod_server_monitor_resize = lib_send_server_monitor_resize;
|
||||
mod->mod_server_monitor_full_invalidate = lib_send_server_monitor_full_invalidate;
|
||||
mod->mod_server_monitor_full_invalidate
|
||||
= lib_send_server_monitor_full_invalidate;
|
||||
mod->mod_server_version_message = lib_send_server_version_message;
|
||||
return (tintptr) mod;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue