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



commit 5d990b3450129eb057cb544c640db256f075a98f
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 |    5 +-
 src/wayland/meta-wayland-seat.c    |    2 +-
 3 files changed, 123 insertions(+), 7 deletions(-)
---
diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index aaa003e..8c74375 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,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;
@@ -131,9 +239,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 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]