Merge pull request #1820 from Nexarian/dynamic_monitor_xrdp_master
Resolution switching without reconnecting.
This commit is contained in:
commit
5f618207dd
14
README.md
14
README.md
@ -9,9 +9,15 @@
|
||||
## Overview
|
||||
|
||||
**xrdp** provides a graphical login to remote machines using Microsoft
|
||||
Remote Desktop Protocol (RDP). xrdp accepts connections from a variety of
|
||||
RDP clients: FreeRDP, rdesktop, KRDC, NeutrinoRDP and Microsoft Remote Desktop
|
||||
Client (for Windows, Mac OS, iOS and Android).
|
||||
Remote Desktop Protocol (RDP). xrdp accepts connections from a variety of RDP clients:
|
||||
- FreeRDP
|
||||
- rdesktop
|
||||
- KRDC
|
||||
- NeutrinoRDP
|
||||
- Windows MSTSC (Microsoft Terminal Services Client)
|
||||
- Microsoft Remote Desktop (which is distinct from MSTSC)
|
||||
|
||||
Many of these work on some or all of Windows, Mac OS, iOS, and/or Android.
|
||||
|
||||
RDP transport is encrypted using TLS by default.
|
||||
|
||||
@ -24,7 +30,7 @@ RDP transport is encrypted using TLS by default.
|
||||
* Connect to a Linux desktop using RDP from anywhere (requires
|
||||
[xorgxrdp](https://github.com/neutrinolabs/xorgxrdp) Xorg module)
|
||||
* Reconnect to an existing session
|
||||
* Session resizing
|
||||
* Session resizing on connect and while an existing session is active.
|
||||
* RDP/VNC proxy (connect to another RDP/VNC server via xrdp)
|
||||
|
||||
### Access to Remote Resources
|
||||
|
@ -14,6 +14,7 @@ include_HEADERS = \
|
||||
ms-rdpegdi.h \
|
||||
ms-rdpele.h \
|
||||
ms-rdperp.h \
|
||||
ms-rdpedisp.h \
|
||||
ms-smb2.h \
|
||||
xrdp_client_info.h \
|
||||
xrdp_constants.h \
|
||||
|
@ -78,7 +78,12 @@
|
||||
/* This isn't explicitly named in MS-RDPBCGR */
|
||||
#define CHANNEL_NAME_LEN 7
|
||||
|
||||
/* Oprions field */
|
||||
/* 2.2.1.3.6 Client Monitor Data - */
|
||||
/* monitorCount (4 bytes): A 32-bit, unsigned integer. The number of display */
|
||||
/* monitor definitions in the monitorDefArray field (the maximum allowed is 16). */
|
||||
#define CLIENT_MONITOR_DATA_MAXIMUM_MONITORS 16
|
||||
|
||||
/* Options field */
|
||||
/* NOTE: XR_ prefixed to avoid conflict with FreeRDP */
|
||||
#define XR_CHANNEL_OPTION_INITIALIZED 0x80000000
|
||||
#define XR_CHANNEL_OPTION_ENCRYPT_RDP 0x40000000
|
||||
|
29
common/ms-rdpedisp.h
Normal file
29
common/ms-rdpedisp.h
Normal file
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* MS-RDPEDISP : Definitions from [MS-RDPEDISP]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* References to MS-RDPEDISP are currently correct for v20201030 of that
|
||||
* document
|
||||
*/
|
||||
|
||||
#if !defined(MS_RDPEDISP_H)
|
||||
#define MS_RDPEDISP_H
|
||||
|
||||
/* Display Control Messages: Display Virtual Channel Extension (2.2.2) */
|
||||
#define DISPLAYCONTROL_PDU_TYPE_MONITOR_LAYOUT 0x00000002
|
||||
#define DISPLAYCONTROL_PDU_TYPE_CAPS 0x00000005
|
||||
|
||||
#endif /* MS_RDPEDISP_H */
|
@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "xrdp_constants.h"
|
||||
#include "ms-rdpbcgr.h"
|
||||
|
||||
#if !defined(XRDP_CLIENT_INFO_H)
|
||||
#define XRDP_CLIENT_INFO_H
|
||||
@ -120,8 +121,8 @@ struct xrdp_client_info
|
||||
int security_layer; /* 0 = rdp, 1 = tls , 2 = hybrid */
|
||||
int multimon; /* 0 = deny , 1 = allow */
|
||||
int monitorCount; /* number of monitors detected (max = 16) */
|
||||
struct monitor_info minfo[16]; /* client monitor data */
|
||||
struct monitor_info minfo_wm[16]; /* client monitor data, non-negative values */
|
||||
struct monitor_info minfo[CLIENT_MONITOR_DATA_MAXIMUM_MONITORS]; /* client monitor data */
|
||||
struct monitor_info minfo_wm[CLIENT_MONITOR_DATA_MAXIMUM_MONITORS]; /* client monitor data, non-negative values */
|
||||
|
||||
int keyboard_type;
|
||||
int keyboard_subtype;
|
||||
|
@ -776,7 +776,12 @@ xrdp_channel_drdynvc_start(struct xrdp_channel *self)
|
||||
struct mcs_channel_item *ci;
|
||||
struct mcs_channel_item *dci;
|
||||
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_channel_drdynvc_start: drdynvc_channel_id %d", self->drdynvc_channel_id);
|
||||
if (self->drdynvc_channel_id != -1)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_channel_drdynvc_start: already started");
|
||||
return 0;
|
||||
}
|
||||
dci = NULL;
|
||||
count = self->mcs_layer->channel_list->count;
|
||||
for (index = 0; index < count; index++)
|
||||
|
@ -492,6 +492,10 @@ lxrdp_set_param(struct mod *mod, const char *name, const char *value)
|
||||
{
|
||||
settings->nla_security = g_text2bool(value);
|
||||
}
|
||||
else if (g_strcmp(name, "enable_dynamic_resizing") == 0)
|
||||
{
|
||||
settings->desktop_resize = g_text2bool(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "lxrdp_set_param: unknown name [%s] value [%s]", name, value);
|
||||
@ -599,6 +603,27 @@ lxrdp_suppress_output(struct mod *mod, int suppress,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
lxrdp_server_version_message(struct mod *mod)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
lxrdp_server_monitor_resize(struct mod *mod, int width, int height)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
lxrdp_server_monitor_full_invalidate(struct mod *mod, int width, int height)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static void
|
||||
lfreerdp_begin_paint(rdpContext *context)
|
||||
@ -2074,6 +2099,9 @@ mod_init(void)
|
||||
mod->mod_check_wait_objs = lxrdp_check_wait_objs;
|
||||
mod->mod_frame_ack = lxrdp_frame_ack;
|
||||
mod->mod_suppress_output = lxrdp_suppress_output;
|
||||
mod->mod_server_version_message = lxrdp_server_version_message;
|
||||
mod->mod_server_monitor_resize = lxrdp_server_monitor_resize;
|
||||
mod->mod_server_monitor_full_invalidate = lxrdp_server_monitor_full_invalidate;
|
||||
|
||||
mod->inst = freerdp_new();
|
||||
mod->inst->PreConnect = lfreerdp_pre_connect;
|
||||
|
@ -82,8 +82,13 @@ struct mod
|
||||
int (*mod_frame_ack)(struct mod *mod, int flags, int frame_id);
|
||||
int (*mod_suppress_output)(struct mod *mod, int suppress,
|
||||
int left, int top, int right, int bottom);
|
||||
tintptr mod_dumby[100 - 11]; /* align, 100 minus the number of mod
|
||||
functions above */
|
||||
int (*mod_server_monitor_resize)(struct mod *mod,
|
||||
int width, int height);
|
||||
int (*mod_server_monitor_full_invalidate)(struct mod *mod,
|
||||
int width, int height);
|
||||
int (*mod_server_version_message)(struct mod *mod);
|
||||
tintptr mod_dumby[100 - 14]; /* align, 100 minus the number of mod
|
||||
functions above */
|
||||
/* server functions */
|
||||
int (*server_begin_update)(struct mod *v);
|
||||
int (*server_end_update)(struct mod *v);
|
||||
|
45
vnc/vnc.c
45
vnc/vnc.c
@ -1224,7 +1224,7 @@ send_update_request_for_resize_status(struct vnc *v)
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
|
||||
switch (v->initial_resize_status)
|
||||
switch (v->resize_status)
|
||||
{
|
||||
case VRS_WAITING_FOR_FIRST_UPDATE:
|
||||
/*
|
||||
@ -1364,14 +1364,14 @@ lib_framebuffer_first_update(struct vnc *v)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "Server layout is the same "
|
||||
"as the client layout");
|
||||
v->initial_resize_status = VRS_DONE;
|
||||
v->resize_status = VRS_DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "Server layout differs from "
|
||||
"the client layout. Changing server layout");
|
||||
error = send_set_desktop_size(v, &v->client_layout);
|
||||
v->initial_resize_status = VRS_WAITING_FOR_RESIZE_CONFIRM;
|
||||
v->resize_status = VRS_WAITING_FOR_RESIZE_CONFIRM;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1382,7 +1382,7 @@ lib_framebuffer_first_update(struct vnc *v)
|
||||
LOG(LOG_LEVEL_DEBUG, "Resizing client to server %dx%d",
|
||||
v->server_width, v->server_height);
|
||||
error = resize_client(v, 0, v->server_width, v->server_height);
|
||||
v->initial_resize_status = VRS_DONE;
|
||||
v->resize_status = VRS_DONE;
|
||||
}
|
||||
|
||||
g_free(layout.s);
|
||||
@ -1437,7 +1437,7 @@ lib_framebuffer_waiting_for_resize_confirm(struct vnc *v)
|
||||
v->server_width, v->server_height);
|
||||
error = resize_client(v, 0, v->server_width, v->server_height);
|
||||
}
|
||||
v->initial_resize_status = VRS_DONE;
|
||||
v->resize_status = VRS_DONE;
|
||||
}
|
||||
|
||||
g_free(layout.s);
|
||||
@ -1777,7 +1777,7 @@ lib_mod_process_message(struct vnc *v, struct stream *s)
|
||||
{
|
||||
if (type == S2C_FRAMEBUFFER_UPDATE)
|
||||
{
|
||||
switch (v->initial_resize_status)
|
||||
switch (v->resize_status)
|
||||
{
|
||||
case VRS_WAITING_FOR_FIRST_UPDATE:
|
||||
error = lib_framebuffer_first_update(v);
|
||||
@ -2237,7 +2237,7 @@ lib_mod_connect(struct vnc *v)
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
v->initial_resize_status = VRS_WAITING_FOR_FIRST_UPDATE;
|
||||
v->resize_status = VRS_WAITING_FOR_FIRST_UPDATE;
|
||||
error = send_update_request_for_resize_status(v);
|
||||
}
|
||||
|
||||
@ -2465,6 +2465,34 @@ lib_mod_suppress_output(struct vnc *v, int suppress,
|
||||
return error;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* return error */
|
||||
int
|
||||
lib_mod_server_version_message(struct vnc *v)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* return error */
|
||||
int
|
||||
lib_mod_server_monitor_resize(struct vnc *v, int width, int height)
|
||||
{
|
||||
int error = 0;
|
||||
set_single_screen_layout(&v->client_layout, width, height);
|
||||
v->resize_status = VRS_WAITING_FOR_FIRST_UPDATE;
|
||||
error = send_update_request_for_resize_status(v);
|
||||
return error;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* return error */
|
||||
int
|
||||
lib_mod_server_monitor_full_invalidate(struct vnc *v, int param1, int param2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
tintptr EXPORT_CC
|
||||
mod_init(void)
|
||||
@ -2486,6 +2514,9 @@ mod_init(void)
|
||||
v->mod_check_wait_objs = lib_mod_check_wait_objs;
|
||||
v->mod_frame_ack = lib_mod_frame_ack;
|
||||
v->mod_suppress_output = lib_mod_suppress_output;
|
||||
v->mod_server_monitor_resize = lib_mod_server_monitor_resize;
|
||||
v->mod_server_monitor_full_invalidate = lib_mod_server_monitor_full_invalidate;
|
||||
v->mod_server_version_message = lib_mod_server_version_message;
|
||||
|
||||
/* Member variables */
|
||||
v->enabled_encodings_mask = -1;
|
||||
|
@ -77,7 +77,12 @@ struct vnc
|
||||
int (*mod_frame_ack)(struct vnc *v, int flags, int frame_id);
|
||||
int (*mod_suppress_output)(struct vnc *v, int suppress,
|
||||
int left, int top, int right, int bottom);
|
||||
tintptr mod_dumby[100 - 11]; /* align, 100 minus the number of mod
|
||||
int (*mod_server_monitor_resize)(struct vnc *v,
|
||||
int width, int height);
|
||||
int (*mod_server_monitor_full_invalidate)(struct vnc *v,
|
||||
int width, int height);
|
||||
int (*mod_server_version_message)(struct vnc *v);
|
||||
tintptr mod_dumby[100 - 14]; /* align, 100 minus the number of mod
|
||||
functions above */
|
||||
/* server functions */
|
||||
int (*server_begin_update)(struct vnc *v);
|
||||
@ -152,5 +157,5 @@ struct vnc
|
||||
unsigned int enabled_encodings_mask;
|
||||
/* Resizeable support */
|
||||
struct vnc_screen_layout client_layout;
|
||||
enum vnc_resize_status initial_resize_status;
|
||||
enum vnc_resize_status resize_status;
|
||||
};
|
||||
|
15
xrdp/xrdp.h
15
xrdp/xrdp.h
@ -367,6 +367,21 @@ xrdp_bitmap_compress(char *in_data, int width, int height,
|
||||
int e);
|
||||
|
||||
/* xrdp_mm.c */
|
||||
|
||||
struct dynamic_monitor_layout
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
int
|
||||
xrdp_mm_drdynvc_up(struct xrdp_mm *self);
|
||||
int
|
||||
|
@ -235,6 +235,9 @@ ip=ask
|
||||
port=ask3389
|
||||
username=ask
|
||||
password=ask
|
||||
; Currently NeutrinoRDP doesn't support dynamic resizing. Uncomment
|
||||
; this line if you're using a client which does.
|
||||
#enable_dynamic_resizing=false
|
||||
|
||||
; You can override the common channel settings for each session type
|
||||
#channel.rdpdr=true
|
||||
|
202
xrdp/xrdp_mm.c
202
xrdp/xrdp_mm.c
@ -24,6 +24,8 @@
|
||||
#include "xrdp.h"
|
||||
#include "log.h"
|
||||
#include "string_calls.h"
|
||||
#include "ms-rdpedisp.h"
|
||||
#include "ms-rdpbcgr.h"
|
||||
|
||||
#ifdef USE_PAM
|
||||
#if defined(HAVE__PAM_TYPES_H)
|
||||
@ -992,12 +994,208 @@ xrdp_mm_process_rail_drawing_orders(struct xrdp_mm *self, struct stream *s)
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
dynamic_monitor_open_response(intptr_t id, int chan_id, int creation_status)
|
||||
{
|
||||
struct xrdp_process *pro;
|
||||
struct xrdp_wm *wm;
|
||||
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);
|
||||
if (creation_status != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "dynamic_monitor_open_response: error");
|
||||
return 1;
|
||||
}
|
||||
pro = (struct xrdp_process *) id;
|
||||
wm = pro->wm;
|
||||
make_stream(s);
|
||||
init_stream(s, 1024);
|
||||
out_uint32_le(s, 5); /* DISPLAYCONTROL_PDU_TYPE_CAPS */
|
||||
out_uint32_le(s, 8 + 12);
|
||||
out_uint32_le(s, CLIENT_MONITOR_DATA_MAXIMUM_MONITORS); /* MaxNumMonitors */
|
||||
out_uint32_le(s, 4096); /* MaxMonitorAreaFactorA */
|
||||
out_uint32_le(s, 2048); /* MaxMonitorAreaFactorB */
|
||||
s_mark_end(s);
|
||||
bytes = (int) (s->end - s->data);
|
||||
libxrdp_drdynvc_data(wm->session, chan_id, s->data, bytes);
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
dynamic_monitor_close_response(intptr_t id, int chan_id)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "dynamic_monitor_close_response:");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
dynamic_monitor_data_first(intptr_t id, int chan_id, char *data, int bytes,
|
||||
int total_bytes)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "dynamic_monitor_data_first:");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
dynamic_monitor_data(intptr_t id, int chan_id, char *data, int bytes)
|
||||
{
|
||||
struct stream ls;
|
||||
struct stream *s;
|
||||
int msg_type;
|
||||
int msg_length;
|
||||
int monitor_index;
|
||||
struct xrdp_process *pro;
|
||||
struct xrdp_wm *wm;
|
||||
|
||||
int MonitorLayoutSize;
|
||||
int NumMonitor;
|
||||
|
||||
struct dynamic_monitor_layout monitor_layouts[CLIENT_MONITOR_DATA_MAXIMUM_MONITORS];
|
||||
struct dynamic_monitor_layout *monitor_layout;
|
||||
|
||||
struct xrdp_rect rect;
|
||||
int session_width;
|
||||
int session_height;
|
||||
|
||||
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);
|
||||
|
||||
rect.left = 8192;
|
||||
rect.top = 8192;
|
||||
rect.right = -8192;
|
||||
rect.bottom = -8192;
|
||||
|
||||
if (msg_type == DISPLAYCONTROL_PDU_TYPE_MONITOR_LAYOUT)
|
||||
{
|
||||
in_uint32_le(s, MonitorLayoutSize);
|
||||
in_uint32_le(s, NumMonitor);
|
||||
LOG(LOG_LEVEL_DEBUG, " MonitorLayoutSize %d NumMonitor %d",
|
||||
MonitorLayoutSize, NumMonitor);
|
||||
for (monitor_index = 0; monitor_index < NumMonitor; monitor_index++)
|
||||
{
|
||||
monitor_layout = monitor_layouts + monitor_index;
|
||||
in_uint32_le(s, monitor_layout->flags);
|
||||
in_uint32_le(s, monitor_layout->left);
|
||||
in_uint32_le(s, monitor_layout->top);
|
||||
in_uint32_le(s, monitor_layout->width);
|
||||
in_uint32_le(s, monitor_layout->height);
|
||||
in_uint32_le(s, monitor_layout->physical_width);
|
||||
in_uint32_le(s, monitor_layout->physical_height);
|
||||
in_uint32_le(s, monitor_layout->orientation);
|
||||
in_uint32_le(s, monitor_layout->desktop_scale_factor);
|
||||
in_uint32_le(s, monitor_layout->device_scale_factor);
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " Flags 0x%8.8x Left %d Top %d "
|
||||
"Width %d Height %d PhysicalWidth %d PhysicalHeight %d "
|
||||
"Orientation %d DesktopScaleFactor %d DeviceScaleFactor %d",
|
||||
monitor_layout->flags, monitor_layout->left, monitor_layout->top,
|
||||
monitor_layout->width, monitor_layout->height,
|
||||
monitor_layout->physical_width, monitor_layout->physical_height,
|
||||
monitor_layout->orientation, monitor_layout->desktop_scale_factor,
|
||||
monitor_layout->device_scale_factor);
|
||||
|
||||
rect.left = MIN(monitor_layout->left, rect.left);
|
||||
rect.top = MIN(monitor_layout->top, rect.top);
|
||||
rect.right = MAX(rect.right, monitor_layout->left + monitor_layout->width);
|
||||
rect.bottom = MAX(rect.bottom, monitor_layout->top + monitor_layout->height);
|
||||
}
|
||||
}
|
||||
session_width = rect.right - rect.left;
|
||||
session_height = rect.bottom - rect.top;
|
||||
if ((session_width > 0) && (session_height > 0))
|
||||
{
|
||||
// TODO: Unify this logic with server_reset
|
||||
libxrdp_reset(wm->session, session_width, session_height, wm->screen->bpp);
|
||||
/* reset cache */
|
||||
xrdp_cache_reset(wm->cache, wm->client_info);
|
||||
/* resize the main window */
|
||||
xrdp_bitmap_resize(wm->screen, session_width, session_height);
|
||||
/* load some stuff */
|
||||
xrdp_wm_load_static_colors_plus(wm, 0);
|
||||
xrdp_wm_load_static_pointers(wm);
|
||||
/* redraw */
|
||||
xrdp_bitmap_invalidate(wm->screen, 0);
|
||||
|
||||
struct xrdp_mod* v = wm->mm->mod;
|
||||
if (v != 0) {
|
||||
v->mod_server_version_message(v);
|
||||
v->mod_server_monitor_resize(v, session_width, session_height);
|
||||
v->mod_server_monitor_full_invalidate(v, session_width, session_height);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
dynamic_monitor_initialize(struct xrdp_mm *self)
|
||||
{
|
||||
struct xrdp_drdynvc_procs d_procs;
|
||||
int flags;
|
||||
int error;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "dynamic_monitor_initialize:");
|
||||
|
||||
g_memset(&d_procs, 0, sizeof(d_procs));
|
||||
d_procs.open_response = dynamic_monitor_open_response;
|
||||
d_procs.close_response = dynamic_monitor_close_response;
|
||||
d_procs.data_first = dynamic_monitor_data_first;
|
||||
d_procs.data = dynamic_monitor_data;
|
||||
flags = 0;
|
||||
error = libxrdp_drdynvc_open(self->wm->session,
|
||||
"Microsoft::Windows::RDS::DisplayControl",
|
||||
flags, &d_procs,
|
||||
&(self->dynamic_monitor_chanid));
|
||||
if (error != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_mm_drdynvc_up: "
|
||||
"libxrdp_drdynvc_open failed %d", error);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
xrdp_mm_drdynvc_up(struct xrdp_mm *self)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_mm_drdynvc_up:");
|
||||
return 0;
|
||||
char enable_dynamic_resize[32];
|
||||
int error = 0;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mm_drdynvc_up:");
|
||||
|
||||
xrdp_mm_get_value(self, "enable_dynamic_resizing",
|
||||
enable_dynamic_resize,
|
||||
sizeof(enable_dynamic_resize) - 1);
|
||||
|
||||
/*
|
||||
* User can disable dynamic resizing if necessary
|
||||
*/
|
||||
if (enable_dynamic_resize[0] != '\0' && !g_text2bool(enable_dynamic_resize))
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "User has disabled dynamic resizing.");
|
||||
}
|
||||
else
|
||||
{
|
||||
error = dynamic_monitor_initialize(self);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -53,7 +53,12 @@ struct xrdp_mod
|
||||
int (*mod_frame_ack)(struct xrdp_mod *v, int flags, int frame_id);
|
||||
int (*mod_suppress_output)(struct xrdp_mod *v, int suppress,
|
||||
int left, int top, int right, int bottom);
|
||||
tintptr mod_dumby[100 - 11]; /* align, 100 minus the number of mod
|
||||
int (*mod_server_monitor_resize)(struct xrdp_mod* v,
|
||||
int width, int height);
|
||||
int (*mod_server_monitor_full_invalidate)(struct xrdp_mod* v,
|
||||
int width, int height);
|
||||
int (*mod_server_version_message)(struct xrdp_mod* v);
|
||||
tintptr mod_dumby[100 - 14]; /* align, 100 minus the number of mod
|
||||
functions above */
|
||||
/* server functions */
|
||||
int (*server_begin_update)(struct xrdp_mod *v);
|
||||
@ -302,6 +307,7 @@ struct xrdp_mm
|
||||
struct xrdp_encoder *encoder;
|
||||
int cs2xr_cid_map[256];
|
||||
int xr2cr_cid_map[256];
|
||||
int dynamic_monitor_chanid;
|
||||
};
|
||||
|
||||
struct xrdp_key_info
|
||||
|
179
xup/xup.c
179
xup/xup.c
@ -27,6 +27,15 @@
|
||||
#include "trans.h"
|
||||
#include "string_calls.h"
|
||||
|
||||
static int
|
||||
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);
|
||||
|
||||
static int
|
||||
send_server_version_message(struct mod *v, struct stream *s);
|
||||
|
||||
static int
|
||||
lib_mod_process_message(struct mod *mod, struct stream *s);
|
||||
|
||||
@ -139,7 +148,6 @@ int
|
||||
lib_mod_connect(struct mod *mod)
|
||||
{
|
||||
int error;
|
||||
int len;
|
||||
int i;
|
||||
int use_uds;
|
||||
struct stream *s;
|
||||
@ -243,60 +251,18 @@ lib_mod_connect(struct mod *mod)
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
/* send version message */
|
||||
init_stream(s, 8192);
|
||||
s_push_layer(s, iso_hdr, 4);
|
||||
out_uint16_le(s, 103);
|
||||
out_uint32_le(s, 301);
|
||||
out_uint32_le(s, 0);
|
||||
out_uint32_le(s, 0);
|
||||
out_uint32_le(s, 0);
|
||||
out_uint32_le(s, 1);
|
||||
s_mark_end(s);
|
||||
len = (int)(s->end - s->data);
|
||||
s_pop_layer(s, iso_hdr);
|
||||
out_uint32_le(s, len);
|
||||
lib_send_copy(mod, s);
|
||||
error = send_server_version_message(mod, s);
|
||||
}
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
/* send screen size message */
|
||||
init_stream(s, 8192);
|
||||
s_push_layer(s, iso_hdr, 4);
|
||||
out_uint16_le(s, 103);
|
||||
out_uint32_le(s, 300);
|
||||
out_uint32_le(s, mod->width);
|
||||
out_uint32_le(s, mod->height);
|
||||
out_uint32_le(s, mod->bpp);
|
||||
out_uint32_le(s, 0);
|
||||
s_mark_end(s);
|
||||
len = (int)(s->end - s->data);
|
||||
s_pop_layer(s, iso_hdr);
|
||||
out_uint32_le(s, len);
|
||||
lib_send_copy(mod, s);
|
||||
error = send_server_monitor_resize(mod, s, mod->width, mod->height, mod->bpp);
|
||||
}
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
/* send invalidate message */
|
||||
init_stream(s, 8192);
|
||||
s_push_layer(s, iso_hdr, 4);
|
||||
out_uint16_le(s, 103);
|
||||
out_uint32_le(s, 200);
|
||||
/* x and y */
|
||||
i = 0;
|
||||
out_uint32_le(s, i);
|
||||
/* width and height */
|
||||
i = ((mod->width & 0xffff) << 16) | mod->height;
|
||||
out_uint32_le(s, i);
|
||||
out_uint32_le(s, 0);
|
||||
out_uint32_le(s, 0);
|
||||
s_mark_end(s);
|
||||
len = (int)(s->end - s->data);
|
||||
s_pop_layer(s, iso_hdr);
|
||||
out_uint32_le(s, len);
|
||||
lib_send_copy(mod, s);
|
||||
error = send_server_monitor_full_invalidate(mod, s, mod->width, mod->height);
|
||||
}
|
||||
|
||||
free_stream(s);
|
||||
@ -1292,6 +1258,124 @@ process_server_paint_rect_shmem_ex(struct mod *amod, struct stream *s)
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* return error */
|
||||
static int
|
||||
send_server_version_message(struct mod *mod, struct stream *s)
|
||||
{
|
||||
/* send version message */
|
||||
init_stream(s, 8192);
|
||||
s_push_layer(s, iso_hdr, 4);
|
||||
out_uint16_le(s, 103);
|
||||
out_uint32_le(s, 301);
|
||||
out_uint32_le(s, 0);
|
||||
out_uint32_le(s, 0);
|
||||
out_uint32_le(s, 0);
|
||||
out_uint32_le(s, 1);
|
||||
s_mark_end(s);
|
||||
int len = (int)(s->end - s->data);
|
||||
s_pop_layer(s, iso_hdr);
|
||||
out_uint32_le(s, len);
|
||||
int rv = lib_send_copy(mod, s);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* return error */
|
||||
static int
|
||||
send_server_monitor_resize(struct mod *mod, struct stream *s, int width, int height, int bpp)
|
||||
{
|
||||
/* send screen size message */
|
||||
init_stream(s, 8192);
|
||||
s_push_layer(s, iso_hdr, 4);
|
||||
out_uint16_le(s, 103);
|
||||
out_uint32_le(s, 300);
|
||||
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
|
||||
the bpp on resize.
|
||||
*/
|
||||
out_uint32_le(s, bpp);
|
||||
out_uint32_le(s, 0);
|
||||
s_mark_end(s);
|
||||
int len = (int)(s->end - s->data);
|
||||
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",
|
||||
width, height, bpp, rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int
|
||||
send_server_monitor_full_invalidate(struct mod *mod, struct stream *s, int width, int height)
|
||||
{
|
||||
/* send invalidate message */
|
||||
init_stream(s, 8192);
|
||||
s_push_layer(s, iso_hdr, 4);
|
||||
out_uint16_le(s, 103);
|
||||
out_uint32_le(s, 200);
|
||||
/* x and y */
|
||||
int i = 0;
|
||||
out_uint32_le(s, i);
|
||||
/* width and height */
|
||||
i = ((width & 0xffff) << 16) | height;
|
||||
out_uint32_le(s, i);
|
||||
out_uint32_le(s, 0);
|
||||
out_uint32_le(s, 0);
|
||||
s_mark_end(s);
|
||||
int len = (int)(s->end - s->data);
|
||||
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",
|
||||
width, height, rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* return error */
|
||||
static int
|
||||
lib_send_server_version_message(struct mod *mod)
|
||||
{
|
||||
/* send server version message */
|
||||
struct stream *s;
|
||||
make_stream(s);
|
||||
int rv = send_server_version_message(mod, s);
|
||||
free_stream(s);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* return error */
|
||||
static int
|
||||
lib_send_server_monitor_resize(struct mod *mod, int width, int height)
|
||||
{
|
||||
/* send screen size message */
|
||||
struct stream *s;
|
||||
make_stream(s);
|
||||
int rv = send_server_monitor_resize(mod, s, width, height, mod->bpp);
|
||||
free_stream(s);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* return error */
|
||||
static int
|
||||
lib_send_server_monitor_full_invalidate(struct mod *mod, int width, int height)
|
||||
{
|
||||
/* send invalidate message */
|
||||
struct stream *s;
|
||||
make_stream(s);
|
||||
int rv = send_server_monitor_full_invalidate(mod, s, width, height);
|
||||
free_stream(s);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* return error */
|
||||
static int
|
||||
@ -1636,6 +1720,9 @@ mod_init(void)
|
||||
mod->mod_check_wait_objs = lib_mod_check_wait_objs;
|
||||
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_version_message = lib_send_server_version_message;
|
||||
return (tintptr) mod;
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,12 @@ struct mod
|
||||
int (*mod_frame_ack)(struct mod *v, int flags, int frame_id);
|
||||
int (*mod_suppress_output)(struct mod *v, int suppress,
|
||||
int left, int top, int right, int bottom);
|
||||
tintptr mod_dumby[100 - 11]; /* align, 100 minus the number of mod
|
||||
int (*mod_server_monitor_resize)(struct mod* v,
|
||||
int width, int height);
|
||||
int (*mod_server_monitor_full_invalidate)(struct mod* v,
|
||||
int width, int height);
|
||||
int (*mod_server_version_message)(struct mod* v);
|
||||
tintptr mod_dumby[100 - 14]; /* align, 100 minus the number of mod
|
||||
functions above */
|
||||
/* server functions */
|
||||
int (*server_begin_update)(struct mod *v);
|
||||
|
Loading…
Reference in New Issue
Block a user