[mutter/wayland] wayland: constraint the pointer onto visible monitors when running on evdev



commit a6dc454c4957190f9cf95df42aaf432b300c77f4
Author: Giovanni Campagna <gcampagn redhat com>
Date:   Fri Aug 23 13:57:58 2013 +0200

    wayland: constraint the pointer onto visible monitors when running on evdev
    
    Use the new Clutter hook to make sure the pointer never enters
    the dead area caused by the different monitor sizes.
    
    You don't realize how much X is doing for you until you lose it...
    
    https://bugzilla.gnome.org/show_bug.cgi?id=706655

 src/wayland/meta-wayland-pointer.c |  124 ++++++++++++++++++++++++++++++++++-
 src/wayland/meta-wayland-pointer.h |    5 +-
 src/wayland/meta-wayland-seat.c    |    2 +-
 3 files changed, 124 insertions(+), 7 deletions(-)
---
diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index aaa003e..cc4192c 100644
--- a/src/wayland/meta-wayland-pointer.c
+++ b/src/wayland/meta-wayland-pointer.c
@@ -43,6 +43,9 @@
 
 #include "config.h"
 
+#include <clutter/clutter.h>
+#include <clutter/evdev/clutter-evdev.h>
+
 #include "meta-wayland-pointer.h"
 #include "meta-wayland-private.h"
 
@@ -120,9 +123,115 @@ static const MetaWaylandPointerGrabInterface default_pointer_grab_interface = {
   default_grab_button
 };
 
+/*
+ * The pointer constrain code is mostly a rip-off of the XRandR code from Xorg.
+ * (from xserver/randr/rrcrtc.c, RRConstrainCursorHarder)
+ *
+ * Copyright © 2006 Keith Packard
+ * Copyright 2010 Red Hat, Inc
+ *
+ */
+
+static gboolean
+check_all_screen_monitors(MetaMonitorInfo *monitors,
+                         unsigned         n_monitors,
+                         float            x,
+                         float            y)
+{
+  unsigned int i;
+
+  for (i = 0; i < n_monitors; i++)
+    {
+      MetaMonitorInfo *monitor = &monitors[i];
+      int left, right, top, bottom;
+
+      left = monitor->rect.x;
+      right = left + monitor->rect.width;
+      top = monitor->rect.y;
+      bottom = left + monitor->rect.height;
+
+      if ((x >= left) && (x < right) && (y >= top) && (y < bottom))
+       return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+constrain_all_screen_monitors (ClutterInputDevice *device,
+                              MetaMonitorInfo    *monitors,
+                              unsigned            n_monitors,
+                              float              *x,
+                              float              *y)
+{
+  ClutterPoint current;
+  unsigned int i;
+
+  clutter_input_device_get_coords (device, NULL, &current);
+
+  /* if we're trying to escape, clamp to the CRTC we're coming from */
+  for (i = 0; i < n_monitors; i++)
+    {
+      MetaMonitorInfo *monitor = &monitors[i];
+      int left, right, top, bottom;
+      float nx, ny;
+
+      left = monitor->rect.x;
+      right = left + monitor->rect.width;
+      top = monitor->rect.y;
+      bottom = left + monitor->rect.height;
+
+      nx = current.x;
+      ny = current.y;
+
+      if ((nx >= left) && (nx < right) && (ny >= top) && (ny < bottom))
+       {
+         if (*x < left)
+           *x = left;
+         if (*x >= right)
+           *x = right - 1;
+         if (*y < top)
+           *y = top;
+         if (*y >= bottom)
+           *y = bottom - 1;
+
+         return;
+        }
+    }
+}
+
+static void
+pointer_constrain_callback (ClutterInputDevice *device,
+                           guint32             time,
+                           float              *new_x,
+                           float              *new_y,
+                           gpointer            user_data)
+{
+  MetaMonitorManager *monitor_manager;
+  MetaMonitorInfo *monitors;
+  unsigned int n_monitors;
+  gboolean ret;
+
+  monitor_manager = meta_monitor_manager_get ();
+  monitors = meta_monitor_manager_get_monitor_infos (monitor_manager, &n_monitors);
+
+  /* if we're moving inside a monitor, we're fine */
+  ret = check_all_screen_monitors(monitors, n_monitors, *new_x, *new_y);
+  if (ret == TRUE)
+    return;
+
+  /* if we're trying to escape, clamp to the CRTC we're coming from */
+  constrain_all_screen_monitors(device, monitors, n_monitors, new_x, new_y);
+}
+
 void
-meta_wayland_pointer_init (MetaWaylandPointer *pointer)
+meta_wayland_pointer_init (MetaWaylandPointer *pointer,
+                          gboolean            is_native)
 {
+  ClutterDeviceManager *manager;
+  ClutterInputDevice *device;
+  ClutterPoint current;
+
   memset (pointer, 0, sizeof *pointer);
   wl_list_init (&pointer->resource_list);
   pointer->focus_listener.notify = lose_pointer_focus;
@@ -131,9 +240,16 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer)
   pointer->grab = &pointer->default_grab;
   wl_signal_init (&pointer->focus_signal);
 
-  /* FIXME: Pick better co-ords. */
-  pointer->x = wl_fixed_from_int (100);
-  pointer->y = wl_fixed_from_int (100);
+  manager = clutter_device_manager_get_default ();
+  device = clutter_device_manager_get_core_device (manager, CLUTTER_POINTER_DEVICE);
+
+  if (is_native)
+    clutter_evdev_set_pointer_constrain_callback (manager, pointer_constrain_callback,
+                                                 pointer, NULL);
+
+  clutter_input_device_get_coords (device, NULL, &current);
+  pointer->x = wl_fixed_from_double (current.x);
+  pointer->y = wl_fixed_from_double (current.y);
 }
 
 void
diff --git a/src/wayland/meta-wayland-pointer.h b/src/wayland/meta-wayland-pointer.h
index 7ab3bd3..4c4aaff 100644
--- a/src/wayland/meta-wayland-pointer.h
+++ b/src/wayland/meta-wayland-pointer.h
@@ -60,7 +60,7 @@ struct _MetaWaylandPointer
   guint32 grab_serial;
   guint32 grab_time;
 
-  wl_fixed_t x, y;
+  wl_fixed_t x, y; /* TODO: remove, use ClutterInputDevice instead */
   MetaWaylandSurface *current;
   struct wl_listener current_listener;
   wl_fixed_t current_x, current_y;
@@ -69,7 +69,8 @@ struct _MetaWaylandPointer
 };
 
 void
-meta_wayland_pointer_init (MetaWaylandPointer *pointer);
+meta_wayland_pointer_init (MetaWaylandPointer *pointer,
+                          gboolean            is_native);
 
 void
 meta_wayland_pointer_release (MetaWaylandPointer *pointer);
diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c
index 3720919..b701e9e 100644
--- a/src/wayland/meta-wayland-seat.c
+++ b/src/wayland/meta-wayland-seat.c
@@ -284,7 +284,7 @@ meta_wayland_seat_new (struct wl_display *display,
   wl_list_init (&seat->drag_resource_list);
   wl_signal_init (&seat->drag_icon_signal);
 
-  meta_wayland_pointer_init (&seat->pointer);
+  meta_wayland_pointer_init (&seat->pointer, is_native);
 
   meta_wayland_keyboard_init (&seat->keyboard, display, is_native);
 


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