[gnome-remote-desktop] vnc: Add ability to resize virtual monitors during a session



commit c59d20961cef86725bc6cebdd110fa6c22eb1c62
Author: Vasilis Liaskovitis <vliaskovitis suse com>
Date:   Thu Jul 14 20:29:57 2022 +0200

    vnc: Add ability to resize virtual monitors during a session
    
    Add the setDesktopSize hook that informs PipeWire about the new
    desktop size requested by the VNC client.
    
    Based on RDP virtual monitor commits by Pascal Nowack <Pascal Nowack gmx de>
    https://gitlab.gnome.org/GNOME/gnome-remote-desktop/-/merge_requests/69

 src/grd-session-vnc.c         | 30 ++++++++++++++++++++++++++++++
 src/grd-vnc-pipewire-stream.c | 27 +++++++++++++++++++++++++++
 src/grd-vnc-pipewire-stream.h |  4 ++++
 3 files changed, 61 insertions(+)
---
diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c
index aa7fafe1..ed4a4289 100644
--- a/src/grd-session-vnc.c
+++ b/src/grd-session-vnc.c
@@ -505,6 +505,35 @@ handle_pointer_event (int          button_mask,
   rfbDefaultPtrAddEvent (button_mask, x, y, rfb_client);
 }
 
+static int
+handle_set_desktop_size (int                         width,
+                         int                         height,
+                         int                         num_screens,
+                         struct rfbExtDesktopScreen *screens,
+                         rfbClientPtr                rfb_client)
+{
+  GrdSessionVnc *session_vnc = rfb_client->screen->screenData;
+  GrdVncVirtualMonitor *monitor;
+
+  if (!session_vnc->monitor_config->is_virtual)
+    {
+      g_warning ("[VNC] Ignoring SetDesktopSize request, mirror-primary mode is used");
+      return rfbExtDesktopSize_ResizeProhibited;
+    }
+
+  g_debug ("[VNC] Trying to set new size %dx%d", width, height);
+
+  g_assert (session_vnc->monitor_config->monitor_count == 1);
+  g_assert (session_vnc->monitor_config->virtual_monitors);
+
+  monitor = session_vnc->monitor_config->virtual_monitors;
+  monitor->width = GRD_VNC_CLAMP_DESKTOP_SIZE (width);
+  monitor->height = GRD_VNC_CLAMP_DESKTOP_SIZE (height);
+  grd_vnc_pipewire_stream_resize (session_vnc->pipewire_stream, monitor);
+
+  return rfbExtDesktopSize_Success;
+}
+
 static rfbBool
 check_rfb_password (rfbClientPtr  rfb_client,
                     const char   *response_encrypted,
@@ -596,6 +625,7 @@ init_vnc_session (GrdSessionVnc *session_vnc)
   rfb_screen->kbdReleaseAllKeys = handle_release_all_keys;
   rfb_screen->setXCutText = handle_set_clipboard_text;
   rfb_screen->ptrAddEvent = handle_pointer_event;
+  rfb_screen->setDesktopSizeHook = handle_set_desktop_size;
 
   rfb_screen->frameBuffer = g_malloc0 (screen_width * screen_height * 4);
   memset (rfb_screen->frameBuffer, 0x1f, screen_width * screen_height * 4);
diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c
index 85be4878..4dd5562d 100644
--- a/src/grd-vnc-pipewire-stream.c
+++ b/src/grd-vnc-pipewire-stream.c
@@ -214,6 +214,9 @@ on_stream_param_changed (void                 *user_data,
   width = stream->spa_format.size.width;
   height = stream->spa_format.size.height;
 
+  g_debug ("[VNC] Stream parameters changed. New monitor size: [%u, %u]",
+           width, height);
+
   grd_session_vnc_queue_resize_framebuffer (stream->session, width, height);
 
   allowed_buffer_types = 1 << SPA_DATA_MemFd;
@@ -997,3 +1000,27 @@ grd_vnc_pipewire_stream_class_init (GrdVncPipeWireStreamClass *klass)
                                   NULL, NULL, NULL,
                                   G_TYPE_NONE, 0);
 }
+
+void
+grd_vnc_pipewire_stream_resize (GrdVncPipeWireStream *stream,
+                                GrdVncVirtualMonitor *virtual_monitor)
+{
+  struct spa_rectangle virtual_monitor_rect;
+  uint8_t params_buffer[1024];
+  struct spa_pod_builder pod_builder;
+  const struct spa_pod *params[1];
+
+  virtual_monitor_rect = SPA_RECTANGLE (virtual_monitor->width,
+                                        virtual_monitor->height);
+
+  pod_builder = SPA_POD_BUILDER_INIT (params_buffer, sizeof (params_buffer));
+
+  params[0] = spa_pod_builder_add_object (
+    &pod_builder,
+    SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
+    SPA_FORMAT_VIDEO_size, SPA_POD_Rectangle (&virtual_monitor_rect),
+    0);
+
+  pw_stream_update_params (stream->pipewire_stream,
+                           params, G_N_ELEMENTS (params));
+}
diff --git a/src/grd-vnc-pipewire-stream.h b/src/grd-vnc-pipewire-stream.h
index 47aef5f7..0fed1bdd 100644
--- a/src/grd-vnc-pipewire-stream.h
+++ b/src/grd-vnc-pipewire-stream.h
@@ -37,4 +37,8 @@ GrdVncPipeWireStream * grd_vnc_pipewire_stream_new (GrdSessionVnc              *
                                                     const GrdVncVirtualMonitor *virtual_monitor,
                                                     GError                    **error);
 
+void
+grd_vnc_pipewire_stream_resize (GrdVncPipeWireStream *stream,
+                                GrdVncVirtualMonitor *virtual_monitor);
+
 #endif /* GRD_VNC_PIPEWIRE_STREAM_H */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]