[gnome-remote-desktop] session-rdp: Don't submit pointer bitmaps for hidden mouse pointers



commit 1615f49fe7b4a8bda7a0281c7a626f4f7a70f41c
Author: Pascal Nowack <Pascal Nowack gmx de>
Date:   Mon Nov 30 18:42:26 2020 +0100

    session-rdp: Don't submit pointer bitmaps for hidden mouse pointers
    
    Currently, when a mouse pointer changes in a session, g-r-d sends an
    update of the new mouse pointer bitmap or use an already cached one
    when the client already has the pointer bitmap.
    This also applies to hidden mouse pointers, which are usually submitted
    when for example a video is being played in the remote session and the
    mouse pointer lies in the video area.
    In such cases it is just wasteful to submit a full pointer bitmap which
    is actually completely empty.
    With Firefox, for example, such pointer bitmap can have a size of
    64 * 64 * 4 Bytes.
    Moreover, it also creates a problem with mstsc, since mstsc can't
    handle such complete transparent pointer bitmaps.
    Instead of hiding the mouse pointer, mstsc turns the mouse pointer
    bitmap into a black square.
    
    To solve this issue, use the PointerSystem update to tell the client to
    hide the mouse pointer on the client side, instead of submitting a new
    pointer bitmap.
    This also has the advantage that the size of the transparent pointer
    bitmap doesn't matter, since such pointer bitmaps are filtered out
    first before submitting a pointer update and therefore also not
    pollute the pointer cache with empty data.
    
    To identify a hidden mouse pointer, check the alpha bits of the
    mouse pointer bitmap.
    In a bitmap of a hidden mouse pointer, all alpha bits are set to 0.

 src/grd-session-rdp.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)
---
diff --git a/src/grd-session-rdp.c b/src/grd-session-rdp.c
index 9ece1e8..c24dbef 100644
--- a/src/grd-session-rdp.c
+++ b/src/grd-session-rdp.c
@@ -70,6 +70,7 @@ struct _GrdSessionRdp
   uint8_t *last_frame;
   Pointer *last_pointer;
   GHashTable *pointer_cache;
+  PointerType pointer_type;
 
   GMutex pointer_mutex;
   uint16_t pointer_x;
@@ -212,6 +213,24 @@ grd_session_rdp_take_buffer (GrdSessionRdp *session_rdp,
   g_free (data);
 }
 
+static gboolean
+is_mouse_pointer_hidden (uint32_t  width,
+                         uint32_t  height,
+                         uint8_t  *data)
+{
+  uint8_t *src_data;
+  uint32_t i;
+
+  for (i = 0, src_data = data; i < height * width; ++i, ++src_data)
+    {
+      src_data += 3;
+      if (*src_data)
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
 static gboolean
 find_equal_pointer_bitmap (gpointer key,
                            gpointer value,
@@ -232,6 +251,7 @@ grd_session_rdp_update_pointer (GrdSessionRdp *session_rdp,
   RdpPeerContext *rdp_peer_context = (RdpPeerContext *) peer->context;
   rdpSettings *rdp_settings = peer->settings;
   rdpUpdate *rdp_update = peer->update;
+  POINTER_SYSTEM_UPDATE pointer_system = {0};
   POINTER_NEW_UPDATE pointer_new = {0};
   POINTER_LARGE_UPDATE pointer_large = {0};
   POINTER_CACHED_UPDATE pointer_cached = {0};
@@ -252,6 +272,21 @@ grd_session_rdp_update_pointer (GrdSessionRdp *session_rdp,
       return;
     }
 
+  if (is_mouse_pointer_hidden (width, height, data))
+    {
+      if (session_rdp->pointer_type != POINTER_TYPE_HIDDEN)
+        {
+          session_rdp->last_pointer = NULL;
+          session_rdp->pointer_type = POINTER_TYPE_HIDDEN;
+          pointer_system.type = SYSPTR_NULL;
+
+          rdp_update->pointer->PointerSystem (peer->context, &pointer_system);
+        }
+
+      g_free (data);
+      return;
+    }
+
   /* RDP only handles pointer bitmaps up to 384x384 pixels */
   if (width > 384 || height > 384)
     {
@@ -259,6 +294,8 @@ grd_session_rdp_update_pointer (GrdSessionRdp *session_rdp,
       return;
     }
 
+  session_rdp->pointer_type = POINTER_TYPE_NORMAL;
+
   stride = width * 4;
   if (session_rdp->last_pointer &&
       session_rdp->last_pointer->hotspot_x == hotspot_x &&


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