[ScreenCapturerX11] Fix update-region for monitors with offsets.

This CL ensures that each DesktopFrame's updated-region is expressed in
the frame's own coordinates, where the top-left is always (0, 0).
For example, DesktopFrame::GetFrameDataAtPos() and its callers use
this coordinate system.

Previously, whenever a RANDR monitor with a non-zero offset was
selected, ScreenCapturerX11 would hit some DCHECKs when trying to
copy pixels from previous frames, or when capturing new pixels into
them from XDAMAGE regions.

Bug: None
Change-Id: I7b2e8d0449359ee7b263ad60af193e2bf89aa1f4
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/232085
Reviewed-by: Joe Downing <joedow@chromium.org>
Commit-Queue: Joe Downing <joedow@chromium.org>
Cr-Commit-Position: refs/heads/main@{#35017}
diff --git a/modules/desktop_capture/linux/screen_capturer_x11.cc b/modules/desktop_capture/linux/screen_capturer_x11.cc
index ab1bd7f..e05f7bf 100644
--- a/modules/desktop_capture/linux/screen_capturer_x11.cc
+++ b/modules/desktop_capture/linux/screen_capturer_x11.cc
@@ -355,6 +355,7 @@
 std::unique_ptr<DesktopFrame> ScreenCapturerX11::CaptureScreen() {
   std::unique_ptr<SharedDesktopFrame> frame = queue_.current_frame()->Share();
   RTC_DCHECK(selected_monitor_rect_.size().equals(frame->size()));
+  RTC_DCHECK(selected_monitor_rect_.top_left().equals(frame->top_left()));
 
   // Pass the screen size to the helper, so it can clip the invalid region if it
   // expands that region to a grid.
@@ -378,19 +379,30 @@
     XRectangle* rects = XFixesFetchRegionAndBounds(display(), damage_region_,
                                                    &rects_num, &bounds);
     for (int i = 0; i < rects_num; ++i) {
-      updated_region->AddRect(DesktopRect::MakeXYWH(
-          rects[i].x, rects[i].y, rects[i].width, rects[i].height));
+      auto damage_rect = DesktopRect::MakeXYWH(rects[i].x, rects[i].y,
+                                               rects[i].width, rects[i].height);
+
+      // Damage regions are in the same coordinate-system as
+      // ```selected_monitor_rect_```, but may fall outside of it.
+      damage_rect.IntersectWith(selected_monitor_rect_);
+      if (!damage_rect.is_empty()) {
+        // Convert to DesktopFrame coordinates where the top-left is
+        // always (0, 0), before adding to the frame's update_region.
+        damage_rect.Translate(-frame->top_left());
+        updated_region->AddRect(damage_rect);
+      }
     }
     XFree(rects);
     helper_.InvalidateRegion(*updated_region);
 
     // Capture the damaged portions of the desktop.
     helper_.TakeInvalidRegion(updated_region);
-    updated_region->IntersectWith(selected_monitor_rect_);
 
     for (DesktopRegion::Iterator it(*updated_region); !it.IsAtEnd();
          it.Advance()) {
-      if (!x_server_pixel_buffer_.CaptureRect(it.rect(), frame.get()))
+      auto rect = it.rect();
+      rect.Translate(frame->top_left());
+      if (!x_server_pixel_buffer_.CaptureRect(rect, frame.get()))
         return nullptr;
     }
   } else {
@@ -400,7 +412,7 @@
                                             frame.get())) {
       return nullptr;
     }
-    updated_region->SetRect(selected_monitor_rect_);
+    updated_region->SetRect(DesktopRect::MakeSize(frame->size()));
   }
 
   return std::move(frame);
@@ -445,11 +457,8 @@
   RTC_DCHECK(current != last);
   for (DesktopRegion::Iterator it(last_invalid_region_); !it.IsAtEnd();
        it.Advance()) {
-    if (selected_monitor_rect_.ContainsRect(it.rect())) {
-      DesktopRect r = it.rect();
-      r.Translate(-selected_monitor_rect_.top_left());
-      current->CopyPixelsFrom(*last, r.top_left(), r);
-    }
+    const DesktopRect& r = it.rect();
+    current->CopyPixelsFrom(*last, r.top_left(), r);
   }
 }