[mutter] backends/native: Apply per-output scales when moving across outputs



commit 420311b46348dd75922fdee40346c854f398c3c6
Author: Carlos Garnacho <carlosg gnome org>
Date:   Fri Mar 17 16:12:37 2017 +0100

    backends/native: Apply per-output scales when moving across outputs
    
    Quick motions can come across as too fast (or slow) if it crosses outputs
    with different scales. If this happens, rebuild the motion delta applying
    the scale that applies to each logical monitor the pointer is crossing.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=778119

 src/backends/native/meta-backend-native.c |   97 ++++++++++++++++++++++++++++-
 1 files changed, 95 insertions(+), 2 deletions(-)
---
diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c
index 90ab1e2..7b02efe 100644
--- a/src/backends/native/meta-backend-native.c
+++ b/src/backends/native/meta-backend-native.c
@@ -34,6 +34,7 @@
 #include "clutter/egl/clutter-egl.h"
 #include "clutter/evdev/clutter-evdev.h"
 #include "meta-barrier-native.h"
+#include "meta-border.h"
 #include "meta-idle-monitor-native.h"
 #include "meta-monitor-manager-kms.h"
 #include "meta-cursor-renderer-native.h"
@@ -256,6 +257,78 @@ pointer_constrain_callback (ClutterInputDevice *device,
 }
 
 static void
+relative_motion_across_outputs (MetaMonitorManager *monitor_manager,
+                                MetaLogicalMonitor *current,
+                                float               cur_x,
+                                float               cur_y,
+                                float              *dx_inout,
+                                float              *dy_inout)
+{
+  MetaLogicalMonitor *cur = current;
+  float x = cur_x, y = cur_y;
+  float dx = *dx_inout, dy = *dy_inout;
+  MetaScreenDirection direction = -1;
+
+  while (cur)
+    {
+      MetaLine2 left, right, top, bottom, motion;
+      MetaVector2 intersection;
+
+      motion = (MetaLine2) {
+        .a = { x, y },
+        .b = { x + (dx * cur->scale), y + (dy * cur->scale) }
+      };
+      left = (MetaLine2) {
+        { cur->rect.x, cur->rect.y },
+        { cur->rect.x, cur->rect.y + cur->rect.height }
+      };
+      right = (MetaLine2) {
+        { cur->rect.x + cur->rect.width, cur->rect.y },
+        { cur->rect.x + cur->rect.width, cur->rect.y + cur->rect.height }
+      };
+      top = (MetaLine2) {
+        { cur->rect.x, cur->rect.y },
+        { cur->rect.x + cur->rect.width, cur->rect.y }
+      };
+      bottom = (MetaLine2) {
+        { cur->rect.x, cur->rect.y + cur->rect.height },
+        { cur->rect.x + cur->rect.width, cur->rect.y + cur->rect.height }
+      };
+
+      if (direction != META_SCREEN_RIGHT &&
+          meta_line2_intersects_with (&motion, &left, &intersection))
+        direction = META_SCREEN_LEFT;
+      else if (direction != META_SCREEN_LEFT &&
+               meta_line2_intersects_with (&motion, &right, &intersection))
+        direction = META_SCREEN_RIGHT;
+      else if (direction != META_SCREEN_DOWN &&
+               meta_line2_intersects_with (&motion, &top, &intersection))
+        direction = META_SCREEN_UP;
+      else if (direction != META_SCREEN_UP &&
+               meta_line2_intersects_with (&motion, &bottom, &intersection))
+        direction = META_SCREEN_DOWN;
+      else
+        {
+          /* We reached the dest logical monitor */
+          x = motion.b.x;
+          y = motion.b.y;
+          break;
+        }
+
+      x = intersection.x;
+      y = intersection.y;
+      dx -= intersection.x - motion.a.x;
+      dy -= intersection.y - motion.a.y;
+
+      cur = meta_monitor_manager_get_logical_monitor_neighbor (monitor_manager,
+                                                               cur, direction);
+    }
+
+  *dx_inout = x - cur_x;
+  *dy_inout = y - cur_y;
+}
+
+static void
 relative_motion_filter (ClutterInputDevice *device,
                         float               x,
                         float               y,
@@ -264,14 +337,34 @@ relative_motion_filter (ClutterInputDevice *device,
                         gpointer            user_data)
 {
   MetaMonitorManager *monitor_manager = user_data;
+  MetaLogicalMonitor *logical_monitor, *dest_logical_monitor;
+  float new_dx, new_dy;
 
   logical_monitor = meta_monitor_manager_get_logical_monitor_at (monitor_manager,
                                                                  x, y);
   if (!logical_monitor)
     return;
 
-  *dx *= logical_monitor->scale;
-  *dy *= logical_monitor->scale;
+  new_dx = (*dx) * logical_monitor->scale;
+  new_dy = (*dy) * logical_monitor->scale;
+
+  dest_logical_monitor = meta_monitor_manager_get_logical_monitor_at (monitor_manager,
+                                                                      x + new_dx,
+                                                                      y + new_dy);
+  if (dest_logical_monitor &&
+      dest_logical_monitor != logical_monitor)
+    {
+      /* If we are crossing monitors, attempt to bisect the distance on each
+       * axis and apply the relative scale for each of them.
+       */
+      new_dx = *dx;
+      new_dy = *dy;
+      relative_motion_across_outputs (monitor_manager, logical_monitor,
+                                      x, y, &new_dx, &new_dy);
+    }
+
+  *dx = new_dx;
+  *dy = new_dy;
 }
 
 static ClutterBackend *


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