@@ -157,6 +157,98 @@ void guac_vnc_copyrect(rfbClient* client, int src_x, int src_y, int w, int h, in
157157
158158#ifdef ENABLE_VNC_DESKTOP_SIZE
159159
160+ /**
161+ * This function does the actual work of sending the message to the RFB/VNC
162+ * server to request the resize, and then makes sure that the client frame
163+ * buffer is updated, as well.
164+ *
165+ * @param client
166+ * The remote frame buffer client that is triggering the resize
167+ * request.
168+ *
169+ * @param width
170+ * The updated width of the screen.
171+ *
172+ * @param height
173+ * The updated height of the screen.
174+ *
175+ * @return
176+ * TRUE if the screen update was sent to the server, otherwise false. Note
177+ * that a successful send of the resize message to the server does NOT mean
178+ * that the server has any obligation to resize the display - it only
179+ * indicates that the VNC library has successfully sent the request.
180+ */
181+ static rfbBool guac_vnc_send_desktop_size (rfbClient * client , int width , int height ) {
182+
183+ /* Get the Guacamole client data */
184+ guac_client * gc = rfbClientGetClientData (client , GUAC_VNC_CLIENT_KEY );
185+
186+ /* Don't send an update if the sreen appears to be uninitialized. */
187+ if (client -> screen .width == 0 || client -> screen .height == 0 ) {
188+ guac_client_log (gc , GUAC_LOG_ERROR , "Screen has not been initialized, cannot send resize." );
189+ return FALSE;
190+ }
191+
192+ /* Don't send an update if the requested dimensions are identical to current dimensions. */
193+ if (client -> screen .width == rfbClientSwap16IfLE (width ) && client -> screen .height == rfbClientSwap16IfLE (height )) {
194+ guac_client_log (gc , GUAC_LOG_WARNING , "Screen size has not changed, not sending update." );
195+ return FALSE;
196+ }
197+
198+ /**
199+ * Note: The RFB protocol requires two message types to be sent during a
200+ * resize request - the first for the desktop size (total size of all
201+ * monitors), and then a message for each screen that is attached to the
202+ * remote server. Both libvncclient and Guacamole only support a single
203+ * screen, so we send the desktop resize and screen resize with (nearly)
204+ * identical data, but if one or both of these components is updated in the
205+ * future to support multiple screens, this will need to be re-worked.
206+ */
207+
208+ /* Set up the messages. */
209+ rfbSetDesktopSizeMsg size_msg ;
210+ rfbExtDesktopScreen new_screen ;
211+
212+ /* Configure the desktop size update message. */
213+ size_msg .type = rfbSetDesktopSize ;
214+ size_msg .width = rfbClientSwap16IfLE (width );
215+ size_msg .height = rfbClientSwap16IfLE (height );
216+ size_msg .numberOfScreens = 1 ;
217+
218+ /* Configure the screen update message. */
219+ new_screen .id = client -> screen .id ;
220+ new_screen .x = client -> screen .x ;
221+ new_screen .y = client -> screen .y ;
222+ new_screen .flags = client -> screen .flags ;
223+ new_screen .width = rfbClientSwap16IfLE (width );
224+ new_screen .height = rfbClientSwap16IfLE (height );
225+
226+ /* Stop updates while the resize is in progress. */
227+ client -> requestedResize = TRUE;
228+
229+ /* Send the resize messages to the remote server. */
230+ if (!WriteToRFBServer (client , (char * )& size_msg , sz_rfbSetDesktopSizeMsg )
231+ || !WriteToRFBServer (client , (char * )& new_screen , sz_rfbExtDesktopScreen )) {
232+
233+ guac_client_log (gc , GUAC_LOG_ERROR , "Failed to send new desktop and screen size to the VNC server." );
234+ return FALSE;
235+
236+ }
237+
238+ /* Update the client frame buffer with the requested size. */
239+ client -> screen .width = rfbClientSwap16IfLE (width );
240+ client -> screen .height = rfbClientSwap16IfLE (height );
241+
242+ /* Request a full screen update. */
243+ client -> requestedResize = FALSE;
244+ if (!SendFramebufferUpdateRequest (client , 0 , 0 , width , height , FALSE)) {
245+ guac_client_log (gc , GUAC_LOG_WARNING , "Failed to request a full screen update." );
246+ }
247+
248+ /* Update should be successful. */
249+ return TRUE;
250+ }
251+
160252void guac_vnc_display_set_size (rfbClient * client , int width , int height ) {
161253
162254 /* Get the VNC client */
@@ -171,7 +263,11 @@ void guac_vnc_display_set_size(rfbClient* client, int width, int height) {
171263
172264 /* Send the display size update. */
173265 pthread_mutex_lock (& (vnc_client -> message_lock ));
174- SendExtDesktopSize (client , width , height );
266+ guac_client_log (gc , GUAC_LOG_TRACE , "Setting VNC display size." );
267+ if (guac_vnc_send_desktop_size (client , width , height ))
268+ guac_client_log (gc , GUAC_LOG_TRACE , "Successfully sent desktop size message." );
269+ else
270+ guac_client_log (gc , GUAC_LOG_TRACE , "Failed to send desktop size message." );
175271 pthread_mutex_unlock (& (vnc_client -> message_lock ));
176272
177273}
0 commit comments