Add better handling of monitors

This patch makes FreeRDP announce the support for monitor layout PDU. It also
adds support for servers to announce the monitors layout.
This commit is contained in:
davewheel 2016-01-20 16:54:15 +01:00
parent ca9e908f3c
commit 121a234866
6 changed files with 53 additions and 14 deletions

View File

@ -148,6 +148,7 @@ typedef BOOL (*pSetKeyboardIndicators)(rdpContext* context, UINT16 led_flags);
typedef BOOL (*pRefreshRect)(rdpContext* context, BYTE count, RECTANGLE_16* areas);
typedef BOOL (*pSuppressOutput)(rdpContext* context, BYTE allow, RECTANGLE_16* area);
typedef BOOL (*pRemoteMonitors)(rdpContext* context, UINT32 count, const MONITOR_DEF *monitors);
typedef BOOL (*pSurfaceCommand)(rdpContext* context, wStream* s);
typedef BOOL (*pSurfaceBits)(rdpContext* context, SURFACE_BITS_COMMAND* surfaceBitsCommand);
@ -180,7 +181,8 @@ struct rdp_update
pRefreshRect RefreshRect; /* 48 */
pSuppressOutput SuppressOutput; /* 49 */
UINT32 paddingD[64 - 50]; /* 50 */
pRemoteMonitors RemoteMonitors; /* 50 */
UINT32 paddingD[64 - 51]; /* 51 */
pSurfaceCommand SurfaceCommand; /* 64 */
pSurfaceBits SurfaceBits; /* 65 */

View File

@ -364,9 +364,34 @@ BOOL rdp_server_accept_client_control_pdu(rdpRdp* rdp, wStream* s)
BOOL rdp_server_accept_client_font_list_pdu(rdpRdp* rdp, wStream* s)
{
rdpSettings *settings = rdp->settings;
if (!rdp_recv_client_font_list_pdu(s))
return FALSE;
if (settings->SupportMonitorLayoutPdu && settings->MonitorCount)
{
/* client supports the monitorLayout PDU, let's send him the monitors if any */
wStream *st;
BOOL r;
st = rdp_data_pdu_init(rdp);
if (!st)
return FALSE;
if (!rdp_write_monitor_layout_pdu(st, settings->MonitorCount, settings->MonitorDefArray))
{
Stream_Free(st, TRUE);
return FALSE;
}
r = rdp_send_data_pdu(rdp, st, DATA_PDU_TYPE_MONITOR_LAYOUT, 0);
Stream_Free(st, TRUE);
if (!r)
return FALSE;
}
if (!rdp_send_server_font_map_pdu(rdp))
return FALSE;

View File

@ -761,6 +761,9 @@ BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength)
if (settings->SupportDynamicTimeZone)
settings->SupportDynamicTimeZone = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE) ? TRUE : FALSE;
if (settings->SupportMonitorLayoutPdu)
settings->SupportMonitorLayoutPdu = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU) ? TRUE : FALSE;
if (!(earlyCapabilityFlags & RNS_UD_CS_VALID_CONNECTION_TYPE))
connectionType = 0;
@ -866,6 +869,9 @@ void gcc_write_client_core_data(wStream* s, rdpMcs* mcs)
if (settings->SupportDynamicTimeZone)
earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE;
if (settings->SupportMonitorLayoutPdu)
earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU;
Stream_Write_UINT16(s, highColorDepth); /* highColorDepth */
Stream_Write_UINT16(s, supportedColorDepths); /* supportedColorDepths */

View File

@ -706,13 +706,14 @@ BOOL rdp_recv_monitor_layout_pdu(rdpRdp* rdp, wStream* s)
UINT32 monitorCount;
MONITOR_DEF* monitor;
MONITOR_DEF* monitorDefArray;
BOOL ret = TRUE;
if (Stream_GetRemainingLength(s) < 4)
return FALSE;
Stream_Read_UINT32(s, monitorCount); /* monitorCount (4 bytes) */
if (Stream_GetRemainingLength(s) < (monitorCount * 20))
if ((Stream_GetRemainingLength(s) / 20) < monitorCount)
return FALSE;
monitorDefArray = (MONITOR_DEF*) calloc(monitorCount, sizeof(MONITOR_DEF));
@ -720,9 +721,8 @@ BOOL rdp_recv_monitor_layout_pdu(rdpRdp* rdp, wStream* s)
if (!monitorDefArray)
return FALSE;
for (index = 0; index < monitorCount; index++)
for (monitor = monitorDefArray, index = 0; index < monitorCount; index++, monitor++)
{
monitor = &(monitorDefArray[index]);
Stream_Read_UINT32(s, monitor->left); /* left (4 bytes) */
Stream_Read_UINT32(s, monitor->top); /* top (4 bytes) */
Stream_Read_UINT32(s, monitor->right); /* right (4 bytes) */
@ -730,27 +730,30 @@ BOOL rdp_recv_monitor_layout_pdu(rdpRdp* rdp, wStream* s)
Stream_Read_UINT32(s, monitor->flags); /* flags (4 bytes) */
}
IFCALLRET(rdp->update->RemoteMonitors, ret, rdp->context, monitorCount, monitorDefArray);
free(monitorDefArray);
return TRUE;
return ret;
}
BOOL rdp_write_monitor_layout_pdu(wStream* s, UINT32 monitorCount, MONITOR_DEF* monitorDefArray)
BOOL rdp_write_monitor_layout_pdu(wStream* s, UINT32 monitorCount, const rdpMonitor* monitorDefArray)
{
UINT32 index;
MONITOR_DEF* monitor;
const rdpMonitor* monitor;
if (!Stream_EnsureRemainingCapacity(s, 4 + (monitorCount * 20)))
return FALSE;
Stream_Write_UINT32(s, monitorCount); /* monitorCount (4 bytes) */
for (index = 0; index < monitorCount; index++)
for (index = 0, monitor = monitorDefArray; index < monitorCount; index++, monitor++)
{
monitor = &(monitorDefArray[index]);
Stream_Write_UINT32(s, monitor->left); /* left (4 bytes) */
Stream_Write_UINT32(s, monitor->top); /* top (4 bytes) */
Stream_Write_UINT32(s, monitor->right); /* right (4 bytes) */
Stream_Write_UINT32(s, monitor->bottom); /* bottom (4 bytes) */
Stream_Write_UINT32(s, monitor->flags); /* flags (4 bytes) */
Stream_Write_UINT32(s, monitor->x); /* left (4 bytes) */
Stream_Write_UINT32(s, monitor->y); /* top (4 bytes) */
Stream_Write_UINT32(s, monitor->x + monitor->width - 1); /* right (4 bytes) */
Stream_Write_UINT32(s, monitor->y + monitor->height - 1); /* bottom (4 bytes) */
Stream_Write_UINT32(s, monitor->is_primary ? 0x01 : 0x00); /* flags (4 bytes) */
}
return TRUE;

View File

@ -214,6 +214,8 @@ int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s);
void rdp_read_flow_control_pdu(wStream* s, UINT16* type);
BOOL rdp_write_monitor_layout_pdu(wStream* s, UINT32 monitorCount, const rdpMonitor* monitorDefArray);
int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra);
int rdp_check_fds(rdpRdp* rdp);

View File

@ -295,6 +295,7 @@ rdpSettings* freerdp_settings_new(DWORD flags)
if (!settings->ChannelDefArray)
goto out_fail;
settings->SupportMonitorLayoutPdu = TRUE;
settings->MonitorCount = 0;
settings->MonitorDefArraySize = 32;
settings->MonitorDefArray = (rdpMonitor*) calloc(settings->MonitorDefArraySize, sizeof(rdpMonitor));