[mutter/cherry-pick-70e44c28-2] backends/native: Ensure pointer is onscreen in input thread




commit 921461a4661e83bc2ae3a62eb5b44eafa2fa18c6
Author: Carlos Garnacho <carlosg gnome org>
Date:   Fri Jan 14 20:29:45 2022 +0100

    backends/native: Ensure pointer is onscreen in input thread
    
    It's slightly racy to have the main thread update the views and warp
    the pointer, since the input thread may not be aware yet of the new
    viewport layout.
    
    Make the input thread clamp the pointer so it remains onscreen
    instead, when the new viewports are obtained.
    
    Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/64
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2237>
    
    
    (cherry picked from commit 70e44c281cb90d4f2dd23cd8b842bf0842e7407f)

 src/backends/native/meta-seat-impl.c | 55 ++++++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)
---
diff --git a/src/backends/native/meta-seat-impl.c b/src/backends/native/meta-seat-impl.c
index a7613627f3..0be4e7a307 100644
--- a/src/backends/native/meta-seat-impl.c
+++ b/src/backends/native/meta-seat-impl.c
@@ -3477,6 +3477,59 @@ meta_seat_impl_set_pointer_constraint (MetaSeatImpl              *seat_impl,
   g_object_unref (task);
 }
 
+static void
+ensure_pointer_onscreen (MetaSeatImpl *seat_impl)
+{
+  int i, candidate = -1;
+  int nearest_monitor_x, nearest_monitor_y, min_distance = G_MAXINT;
+  cairo_rectangle_int_t monitor_rect;
+  graphene_point_t coords;
+
+  if (!meta_seat_impl_query_state (seat_impl,
+                                   seat_impl->core_pointer, NULL,
+                                   &coords, NULL))
+    return;
+
+  /* Pointer is in a view */
+  if (meta_viewport_info_get_view_at (seat_impl->viewports,
+                                      coords.x, coords.y) >= 0)
+    return;
+
+  /* Find nearest view */
+  for (i = 0; i < meta_viewport_info_get_num_views (seat_impl->viewports); i++)
+    {
+      meta_viewport_info_get_view_info (seat_impl->viewports, i,
+                                        &monitor_rect, NULL);
+      nearest_monitor_x = MIN (ABS (coords.x - monitor_rect.x),
+                               ABS (coords.x -
+                                    monitor_rect.x + monitor_rect.width));
+      nearest_monitor_y = MIN (ABS (coords.y - monitor_rect.y),
+                               ABS (coords.y -
+                                    monitor_rect.y + monitor_rect.height));
+      if (nearest_monitor_x < min_distance ||
+          nearest_monitor_y < min_distance)
+        {
+          min_distance = MIN (nearest_monitor_x, nearest_monitor_y);
+          candidate = i;
+        }
+    }
+
+  if (candidate < 0)
+    return;
+
+  /* Calculate new coordinates on nearest view */
+  meta_viewport_info_get_view_info (seat_impl->viewports,
+                                    candidate,
+                                    &monitor_rect, NULL);
+  coords.x = CLAMP (coords.x, monitor_rect.x,
+                    monitor_rect.x + monitor_rect.width - 1);
+  coords.y = CLAMP (coords.y, monitor_rect.y,
+                    monitor_rect.y + monitor_rect.height - 1);
+
+  notify_absolute_motion_in_impl (seat_impl->core_pointer, 0,
+                                  coords.x, coords.y, NULL);
+}
+
 static gboolean
 set_viewports (GTask *task)
 {
@@ -3486,6 +3539,8 @@ set_viewports (GTask *task)
   g_set_object (&seat_impl->viewports, viewports);
   g_task_return_boolean (task, TRUE);
 
+  ensure_pointer_onscreen (seat_impl);
+
   return G_SOURCE_REMOVE;
 }
 


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