From 92643d686bed8f3e4f2c1aae194925b6dc9dea86 Mon Sep 17 00:00:00 2001
From: Jan Grulich <jgrulich@redhat.com>
Date: Fri, 28 Jun 2024 18:13:15 +0000
Subject: [PATCH] Bug 1905335 - WebRTC backport: PipeWire capture: hide cursor
 when it goes off screen or is not visible r=pehrsons,webrtc-reviewers

This is a simple backport of an WebRTC upstream change.

Upstream commit: e6ad337d633c145c48a5a4ae54968c14c16081c7

Differential Revision: https://phabricator.services.mozilla.com/D215197
---
 .../wayland/mouse_cursor_monitor_pipewire.cc  | 14 +++--
 .../linux/wayland/shared_screencast_stream.cc | 52 +++++++++++--------
 .../e6ad337d63.no-op-cherry-pick-msg          |  1 +
 3 files changed, 39 insertions(+), 28 deletions(-)
 create mode 100644 third_party/libwebrtc/moz-patch-stack/e6ad337d63.no-op-cherry-pick-msg

diff --git a/third_party/libwebrtc/modules/desktop_capture/linux/wayland/mouse_cursor_monitor_pipewire.cc b/third_party/libwebrtc/modules/desktop_capture/linux/wayland/mouse_cursor_monitor_pipewire.cc
index 3d33b0fbb8e6e..00b07f341b16a 100644
--- a/third_party/libwebrtc/modules/desktop_capture/linux/wayland/mouse_cursor_monitor_pipewire.cc
+++ b/third_party/libwebrtc/modules/desktop_capture/linux/wayland/mouse_cursor_monitor_pipewire.cc
@@ -40,6 +40,14 @@ void MouseCursorMonitorPipeWire::Capture() {
   RTC_DCHECK_RUN_ON(&sequence_checker_);
   RTC_DCHECK(callback_);
 
+  absl::optional<DesktopVector> mouse_cursor_position =
+      options_.screencast_stream()->CaptureCursorPosition();
+  // Invalid cursor or position
+  if (!mouse_cursor_position) {
+    callback_->OnMouseCursor(nullptr);
+    return;
+  }
+
   std::unique_ptr<MouseCursor> mouse_cursor =
       options_.screencast_stream()->CaptureCursor();
 
@@ -48,11 +56,7 @@ void MouseCursorMonitorPipeWire::Capture() {
   }
 
   if (mode_ == SHAPE_AND_POSITION) {
-    absl::optional<DesktopVector> mouse_cursor_position =
-        options_.screencast_stream()->CaptureCursorPosition();
-    if (mouse_cursor_position) {
-      callback_->OnMouseCursorPosition(mouse_cursor_position.value());
-    }
+    callback_->OnMouseCursorPosition(mouse_cursor_position.value());
   }
 }
 
diff --git a/third_party/libwebrtc/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc b/third_party/libwebrtc/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
index ab9054f1a1676..b8cac318ffeb9 100644
--- a/third_party/libwebrtc/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
+++ b/third_party/libwebrtc/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
@@ -690,32 +690,38 @@ void SharedScreenCastStreamPrivate::ProcessBuffer(pw_buffer* buffer) {
     const struct spa_meta_cursor* cursor =
         static_cast<struct spa_meta_cursor*>(spa_buffer_find_meta_data(
             spa_buffer, SPA_META_Cursor, sizeof(*cursor)));
-    if (cursor && spa_meta_cursor_is_valid(cursor)) {
-      struct spa_meta_bitmap* bitmap = nullptr;
-
-      if (cursor->bitmap_offset)
-        bitmap =
-            SPA_MEMBER(cursor, cursor->bitmap_offset, struct spa_meta_bitmap);
-
-      if (bitmap && bitmap->size.width > 0 && bitmap->size.height > 0) {
-        const uint8_t* bitmap_data =
-            SPA_MEMBER(bitmap, bitmap->offset, uint8_t);
-        BasicDesktopFrame* mouse_frame = new BasicDesktopFrame(
-            DesktopSize(bitmap->size.width, bitmap->size.height));
-        mouse_frame->CopyPixelsFrom(
-            bitmap_data, bitmap->stride,
-            DesktopRect::MakeWH(bitmap->size.width, bitmap->size.height));
-        mouse_cursor_ = std::make_unique<MouseCursor>(
-            mouse_frame, DesktopVector(cursor->hotspot.x, cursor->hotspot.y));
 
-        if (observer_) {
-          observer_->OnCursorShapeChanged();
+    if (cursor) {
+      if (spa_meta_cursor_is_valid(cursor)) {
+        struct spa_meta_bitmap* bitmap = nullptr;
+
+        if (cursor->bitmap_offset)
+          bitmap =
+              SPA_MEMBER(cursor, cursor->bitmap_offset, struct spa_meta_bitmap);
+
+        if (bitmap && bitmap->size.width > 0 && bitmap->size.height > 0) {
+          const uint8_t* bitmap_data =
+              SPA_MEMBER(bitmap, bitmap->offset, uint8_t);
+          BasicDesktopFrame* mouse_frame = new BasicDesktopFrame(
+              DesktopSize(bitmap->size.width, bitmap->size.height));
+          mouse_frame->CopyPixelsFrom(
+              bitmap_data, bitmap->stride,
+              DesktopRect::MakeWH(bitmap->size.width, bitmap->size.height));
+          mouse_cursor_ = std::make_unique<MouseCursor>(
+              mouse_frame, DesktopVector(cursor->hotspot.x, cursor->hotspot.y));
+
+          if (observer_) {
+            observer_->OnCursorShapeChanged();
+          }
         }
-      }
-      mouse_cursor_position_.set(cursor->position.x, cursor->position.y);
+        mouse_cursor_position_.set(cursor->position.x, cursor->position.y);
 
-      if (observer_) {
-        observer_->OnCursorPositionChanged();
+        if (observer_) {
+          observer_->OnCursorPositionChanged();
+        }
+      } else {
+        // Indicate an invalid cursor
+        mouse_cursor_position_.set(-1, -1);
       }
     }
   }