Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/neutrinolabs/xrdp.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Pitstick <cmp@pitstick.net>2022-03-15 07:45:26 +0300
committerChristopher Pitstick <cmp@pitstick.net>2022-07-11 06:42:30 +0300
commit6f461aa54c9ab3092b25ffd079060cd45b7c7285 (patch)
treeb27759baa637e1c610d7edc8b728142436a7ce18
parent771197871338f0b3d2caec9657494a440588230b (diff)
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.
-rw-r--r--xrdp/xrdp.h20
-rw-r--r--xrdp/xrdp_mm.c527
-rw-r--r--xrdp/xrdp_types.h29
-rw-r--r--xrdp/xrdp_wm.c23
-rw-r--r--xup/xup.c62
5 files changed, 466 insertions, 195 deletions
diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h
index 88ec8814..d1ae20fb 100644
--- a/xrdp/xrdp.h
+++ b/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
diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c
index 3d65675a..89aa108c 100644
--- a/xrdp/xrdp_mm.c
+++ b/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,207 +1046,386 @@ sync_dynamic_monitor_data(struct xrdp_wm *wm,
MAXIMUM_MONITOR_SIZE);
}
+int
+advance_resize_state_machine(struct xrdp_mm *mm,
+ enum display_resize_state new_state)
+{
+ 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;
+}
+
/******************************************************************************/
static int
-process_dynamic_monitor_description(struct xrdp_wm *wm,
- struct display_size_description *description)
+dynamic_monitor_data(intptr_t id, int chan_id, char *data, int bytes)
{
int error = 0;
- struct xrdp_mm *mm = wm->mm;
- struct xrdp_mod *module = mm->mod;
+ struct stream ls;
+ struct stream *s;
+ int msg_type;
+ int msg_length;
+ struct xrdp_process *pro;
+ struct xrdp_wm *wm;
+ int monitor_layout_size;
+ struct display_size_description *display_size_data;
- LOG_DEVEL(LOG_LEVEL_TRACE, "process_dynamic_monitor_description:");
+ 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_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;
+ LOG(LOG_LEVEL_INFO, "dynamic_monitor_data: Not allowing resize."
+ " Suppress output is active.");
+ return error;
}
- if (description->session_width <= 0 || description->session_height <= 0)
+
+ g_memset(&ls, 0, sizeof(ls));
+ ls.data = data;
+ ls.p = ls.data;
+ ls.size = bytes;
+ ls.end = ls.data + bytes;
+ s = &ls;
+ in_uint32_le(s, msg_type);
+ in_uint32_le(s, 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
+ && msg_length >= 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);
+ // 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;
}
- if (description->session_width
- == wm->client_info->display_sizes.session_width
- && description->session_height
- == wm->client_info->display_sizes.session_height)
+ in_uint32_le(s, monitor_layout_size);
+ if (monitor_layout_size != 40)
{
- 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;
+ /* 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.",
+ monitor_layout_size);
+ return 1;
}
- // 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)
+ display_size_data = (struct display_size_description *)
+ g_malloc(sizeof(struct display_size_description), 1);
+ if (!display_size_data)
{
- LOG_DEVEL(LOG_LEVEL_ERROR,
- "process_dynamic_monitor_description: xrdp_cache_reset"
- " failed %d", error);
- return error;
+ return 1;
}
- /* load some stuff */
- error = xrdp_wm_load_static_colors_plus(wm, 0);
- if (error != 0)
+ error = libxrdp_process_monitor_stream(s, display_size_data, 1);
+ if (error)
{
- LOG_DEVEL(LOG_LEVEL_ERROR, "process_dynamic_monitor_description:"
- " xrdp_wm_load_static_colors_plus failed %d", 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;
+}
- error = xrdp_wm_load_static_pointers(wm);
- if (error != 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)
{
- LOG_DEVEL(LOG_LEVEL_ERROR, "process_dynamic_monitor_description:"
- " xrdp_wm_load_static_pointers failed %d", error);
- return error;
+ return 1;
}
- /* resize the main window */
- error = xrdp_bitmap_resize(wm->screen,
- description->session_width,
- description->session_height);
- if (error != 0)
+ mm = wm->mm;
+ if (mm == NULL)
{
- LOG_DEVEL(LOG_LEVEL_ERROR, "process_dynamic_monitor_description:"
- " xrdp_bitmap_resize failed %d", error);
- return error;
+ return 1;
}
- /* redraw */
- error = xrdp_bitmap_invalidate(wm->screen, 0);
- if (error != 0)
+ module = mm->mod;
+ if (module == NULL)
{
- LOG_DEVEL(LOG_LEVEL_ERROR,
- "process_dynamic_monitor_description:"
- " xrdp_bitmap_invalidate failed %d", error);
- return error;
+ return 1;
}
- if (module != 0)
+ if (!xrdp_wm_can_resize(wm))
{
- 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;
- }
+ return 0;
}
- // 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)
+ 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)
{
- mm->encoder = xrdp_encoder_create(mm);
- }
+ 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);
+ }
- sync_dynamic_monitor_data(wm, description);
+ 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_data(intptr_t id, int chan_id, char *data, int bytes)
+dynamic_monitor_process_queue(struct xrdp_mm *self)
{
- int error = 0;
- struct stream ls;
- struct stream *s;
- int msg_type;
- int msg_length;
- struct xrdp_process *pro;
- struct xrdp_wm *wm;
- int monitor_layout_size;
+ LOG_DEVEL(LOG_LEVEL_TRACE, "dynamic_monitor_process_queue:");
- LOG_DEVEL(LOG_LEVEL_TRACE, "dynamic_monitor_data:");
- pro = (struct xrdp_process *) id;
- wm = pro->wm;
- g_memset(&ls, 0, sizeof(ls));
- ls.data = data;
- ls.p = ls.data;
- ls.size = bytes;
- ls.end = ls.data + 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);
-
- if (msg_type != DISPLAYCONTROL_PDU_TYPE_MONITOR_LAYOUT)
+ if (self == 0)
{
return 0;
}
- in_uint32_le(s, monitor_layout_size);
- if (monitor_layout_size != 40)
+
+ struct xrdp_wm *wm = self->wm;
+
+ if (!xrdp_wm_can_resize(wm))
{
- 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.",
- monitor_layout_size);
- return 1;
+ return 0;
}
- struct display_size_description *description =
- (struct display_size_description *)
- g_malloc(sizeof(struct display_size_description), 1);
+ 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.");
+ }
- error = libxrdp_process_monitor_stream(s, description, 1);
- if (error == 0)
+ if (self->resize_data->state == WMRZ_COMPLETE)
{
- error = process_dynamic_monitor_description(wm, description);
+ 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);
}
- g_free(description);
- return error;
+ 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;
}
/******************************************************************************/
@@ -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;
}
diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h
index d800370c..41d109a0 100644
--- a/xrdp/xrdp_types.h
+++ b/xrdp/xrdp_types.h
@@ -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
diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c
index 6d5f1b89..ff37deb7 100644
--- a/xrdp/xrdp_wm.c
+++ b/xrdp/xrdp_wm.c
@@ -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;
+}
diff --git a/xup/xup.c b/xup/xup.c
index cae29100..fcb65d75 100644
--- a/xup/xup.c
+++ b/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;
}