Skip to content

Commit b3c1351

Browse files
GUACAMOLE-288: Handle multiple monitors in RDP via resize display updates.
1 parent fa0f71d commit b3c1351

File tree

4 files changed

+56
-30
lines changed

4 files changed

+56
-30
lines changed

src/protocols/rdp/channels/disp.c

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,10 @@ guac_rdp_disp* guac_rdp_disp_alloc(guac_client* client) {
4444

4545
/* No requests have been made */
4646
disp->last_request = guac_timestamp_current();
47-
disp->requested_width = 0;
48-
disp->requested_height = 0;
49-
disp->reconnect_needed = 0;
47+
disp->requested_width = 0;
48+
disp->requested_height = 0;
49+
disp->reconnect_needed = 0;
50+
disp->requested_monitors = 1;
5051

5152
return disp;
5253

@@ -88,7 +89,7 @@ static void guac_rdp_disp_channel_connected(rdpContext* context,
8889
/* Init module with current display size */
8990
guac_rdp_disp_set_size(guac_disp, rdp_client->settings,
9091
context->instance, guac_rdp_get_width(context->instance),
91-
guac_rdp_get_height(context->instance));
92+
guac_rdp_get_height(context->instance), 1);
9293

9394
/* Store reference to the display update plugin once it's connected */
9495
DispClientContext* disp = (DispClientContext*) args->pInterface;
@@ -180,6 +181,7 @@ void guac_rdp_disp_set_size(guac_rdp_disp* disp, guac_rdp_settings* settings,
180181
/* Store deferred size */
181182
disp->requested_width = width;
182183
disp->requested_height = height;
184+
disp->requested_monitors = monitors;
183185

184186
/* Send display update notification if possible */
185187
guac_rdp_disp_update_size(disp, settings, rdp_inst);
@@ -191,6 +193,7 @@ void guac_rdp_disp_update_size(guac_rdp_disp* disp,
191193

192194
int width = disp->requested_width;
193195
int height = disp->requested_height;
196+
int monitors_count = disp->requested_monitors;
194197

195198
/* Do not update size if no requests have been received */
196199
if (width == 0 || height == 0)
@@ -204,7 +207,7 @@ void guac_rdp_disp_update_size(guac_rdp_disp* disp,
204207

205208
/* Do NOT send requests unless the size will change */
206209
if (rdp_inst != NULL
207-
&& width == guac_rdp_get_width(rdp_inst)
210+
&& width * monitors_count == guac_rdp_get_width(rdp_inst)
208211
&& height == guac_rdp_get_height(rdp_inst))
209212
return;
210213

@@ -221,32 +224,46 @@ void guac_rdp_disp_update_size(guac_rdp_disp* disp,
221224

222225
}
223226

224-
else if (settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE) {
225-
DISPLAY_CONTROL_MONITOR_LAYOUT monitors[1] = {{
226-
.Flags = 0x1, /* DISPLAYCONTROL_MONITOR_PRIMARY */
227-
.Left = 0,
228-
.Top = 0,
229-
.Width = width,
230-
.Height = height,
231-
.PhysicalWidth = 0,
232-
.PhysicalHeight = 0,
233-
.Orientation = 0,
234-
.DesktopScaleFactor = 0,
235-
.DeviceScaleFactor = 0
236-
}};
237-
238-
/* Send display update notification if display channel is connected */
239-
if (disp->disp != NULL) {
240-
241-
guac_client* client = disp->client;
242-
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
243-
244-
pthread_mutex_lock(&(rdp_client->message_lock));
245-
disp->disp->SendMonitorLayout(disp->disp, 1, monitors);
246-
pthread_mutex_unlock(&(rdp_client->message_lock));
227+
/* Send display update notification if display channel is connected */
228+
else if (settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE
229+
&& disp->disp != NULL) {
230+
231+
/* Init monitors layout */
232+
DISPLAY_CONTROL_MONITOR_LAYOUT* monitors;
233+
monitors = guac_mem_alloc(monitors_count * sizeof(DISPLAY_CONTROL_MONITOR_LAYOUT));
234+
235+
for (int i = 0; i < monitors_count; i++) {
236+
237+
/* First monitor is the primary */
238+
int primary_monitor = (i == 0 ? 1 : 0);
239+
240+
/* Shift each monitor to the right */
241+
int monitor_left = i * width;
247242

243+
/* Get current monitor */
244+
DISPLAY_CONTROL_MONITOR_LAYOUT* monitor = &monitors[i];
245+
246+
/* Set current monitor properties */
247+
monitor->Flags = primary_monitor;
248+
monitor->Left = monitor_left;
249+
monitor->Top = 0;
250+
monitor->Width = width;
251+
monitor->Height = height;
252+
monitor->Orientation = 0;
253+
monitor->PhysicalWidth = 0;
254+
monitor->PhysicalHeight = 0;
248255
}
249256

257+
/* Send display update notification */
258+
guac_client* client = disp->client;
259+
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
260+
261+
pthread_mutex_lock(&(rdp_client->message_lock));
262+
disp->disp->SendMonitorLayout(disp->disp, monitors_count, monitors);
263+
pthread_mutex_unlock(&(rdp_client->message_lock));
264+
265+
guac_mem_free(monitors);
266+
250267
}
251268

252269
}

src/protocols/rdp/channels/disp.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ typedef struct guac_rdp_disp {
7474
*/
7575
int requested_height;
7676

77+
/**
78+
* The number of monitors requested.
79+
*/
80+
int requested_monitors;
81+
7782
/**
7883
* Whether the size has changed and the RDP connection must be closed and
7984
* reestablished.
@@ -154,9 +159,12 @@ void guac_rdp_disp_load_plugin(rdpContext* context);
154159
* The desired display height, in pixels. Due to the restrictions of the
155160
* RDP display update channel, this will be constrained to the range of 200
156161
* through 8192 inclusive.
162+
*
163+
* @param monitors
164+
* The count of monitors.
157165
*/
158166
void guac_rdp_disp_set_size(guac_rdp_disp* disp, guac_rdp_settings* settings,
159-
freerdp* rdp_inst, int width, int height);
167+
freerdp* rdp_inst, int width, int height, int monitors);
160168

161169
/**
162170
* Sends an actual display update request to the RDP server based on previous

src/protocols/rdp/rdp.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,6 @@ static int guac_rdp_handle_connection(guac_client* client) {
607607
guac_rdp_disp_update_size(rdp_client->disp, settings, rdp_inst);
608608

609609
/* Wait for data and construct a reasonable frame */
610-
611610
int wait_result = rdp_guac_client_wait_for_messages(client, GUAC_RDP_MESSAGE_CHECK_INTERVAL);
612611
if (wait_result < 0)
613612
break;

src/protocols/rdp/settings.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1729,6 +1729,7 @@ void guac_rdp_push_settings(guac_client* client,
17291729
freerdp_settings_set_uint32(rdp_settings, FreeRDP_OsMajorType, OSMAJORTYPE_UNSPECIFIED);
17301730
freerdp_settings_set_uint32(rdp_settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED);
17311731
freerdp_settings_set_bool(rdp_settings, FreeRDP_DesktopResize, TRUE);
1732+
freerdp_settings_set_bool(rdp_settings, FreeRDP_UseMultimon, TRUE);
17321733

17331734
/* Claim support only for specific updates, independent of FreeRDP defaults */
17341735
BYTE* order_support = freerdp_settings_get_pointer_writable(rdp_settings, FreeRDP_OrderSupport);
@@ -1975,6 +1976,7 @@ void guac_rdp_push_settings(guac_client* client,
19751976
rdp_settings->OsMajorType = OSMAJORTYPE_UNSPECIFIED;
19761977
rdp_settings->OsMinorType = OSMINORTYPE_UNSPECIFIED;
19771978
rdp_settings->DesktopResize = TRUE;
1979+
rdp_settings->UseMultimon = TRUE;
19781980

19791981
/* Claim support only for specific updates, independent of FreeRDP defaults */
19801982
ZeroMemory(rdp_settings->OrderSupport, GUAC_RDP_ORDER_SUPPORT_LENGTH);

0 commit comments

Comments
 (0)