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



commit 47f47f25617fadbca4545b004e7e1a59ba65bc29
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 |  123 ++++++++++++++++++++++++++++++++++-
 src/wayland/meta-wayland-pointer.h |    3 +-
 src/wayland/meta-wayland-private.h |    2 +-
 src/wayland/meta-wayland-seat.c    |    2 +-
 4 files changed, 123 insertions(+), 7 deletions(-)
---
diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index 758d60a..4518930 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 <string.h>
@@ -119,9 +122,114 @@ 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,
+                           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;
@@ -130,9 +238,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 db6d3bf..b51706f 100644
--- a/src/wayland/meta-wayland-pointer.h
+++ b/src/wayland/meta-wayland-pointer.h
@@ -25,7 +25,8 @@
 #include "meta-wayland-seat.h"
 
 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-private.h b/src/wayland/meta-wayland-private.h
index 437a551..93071b6 100644
--- a/src/wayland/meta-wayland-private.h
+++ b/src/wayland/meta-wayland-private.h
@@ -195,7 +195,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;
diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c
index c577562..2442c78 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]