From e6ad337d633c145c48a5a4ae54968c14c16081c7 Mon Sep 17 00:00:00 2001 From: Jan Grulich Date: Wed, 19 Jun 2024 10:26:37 +0200 Subject: [PATCH] PipeWire capture: hide cursor when it goes off screen or is not visible Set cursor position to (-1,-1) to indicate it's not valid when it goes off the screen or it gets hidden by the compositor. Compositors indicate invalid or hidden cursor by unsetting the cursor id in cursor metadata and using spa_meta_cursor_is_valid() will tell us the needed information for this. Bug: chromium:346608851 Change-Id: I71b3222ca161b7fd8e964f4f4e12b9983179beba Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/355080 Reviewed-by: Alexander Cooper Commit-Queue: Jan Grulich Cr-Commit-Position: refs/heads/main@{#42548} --- .../wayland/mouse_cursor_monitor_pipewire.cc | 14 ++++-- .../linux/wayland/shared_screencast_stream.cc | 48 +++++++++++-------- 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/modules/desktop_capture/linux/wayland/mouse_cursor_monitor_pipewire.cc b/modules/desktop_capture/linux/wayland/mouse_cursor_monitor_pipewire.cc index 3d33b0fbb8..00b07f341b 100644 --- a/modules/desktop_capture/linux/wayland/mouse_cursor_monitor_pipewire.cc +++ b/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 mouse_cursor_position = + options_.screencast_stream()->CaptureCursorPosition(); + // Invalid cursor or position + if (!mouse_cursor_position) { + callback_->OnMouseCursor(nullptr); + return; + } + std::unique_ptr mouse_cursor = options_.screencast_stream()->CaptureCursor(); @@ -48,11 +56,7 @@ void MouseCursorMonitorPipeWire::Capture() { } if (mode_ == SHAPE_AND_POSITION) { - absl::optional 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/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc b/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc index 90273aba3e..047ad5a857 100644 --- a/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc +++ b/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc @@ -680,32 +680,38 @@ void SharedScreenCastStreamPrivate::ProcessBuffer(pw_buffer* buffer) { const struct spa_meta_cursor* cursor = static_cast(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 (cursor) { + if (spa_meta_cursor_is_valid(cursor)) { + struct spa_meta_bitmap* bitmap = nullptr; - 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( - mouse_frame, DesktopVector(cursor->hotspot.x, cursor->hotspot.y)); + 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( + mouse_frame, DesktopVector(cursor->hotspot.x, cursor->hotspot.y)); + + if (observer_) { + observer_->OnCursorShapeChanged(); + } + } + mouse_cursor_position_.set(cursor->position.x, cursor->position.y); if (observer_) { - observer_->OnCursorShapeChanged(); + observer_->OnCursorPositionChanged(); } - } - mouse_cursor_position_.set(cursor->position.x, cursor->position.y); - - if (observer_) { - observer_->OnCursorPositionChanged(); + } else { + // Indicate an invalid cursor + mouse_cursor_position_.set(-1, -1); } } }