From eeee7bed1dbc58f159ecc4ef84848237452b87b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 29 Jul 2020 11:22:19 +0200 Subject: [PATCH] cursor-tracker: Add way to force tracking cursor position On X11 we won't always receive cursor positions, as some other client might have grabbed the pointer (e.g. for implementing a popup menu). To make screen casting show a somewhat correct cursor position, we need to actively poll the X server about the current cursor position. We only really want to do this when screen casting or taking a screenshot, so add an API that forces the cursor tracker to track the cursor position. On the native backend this is a no-op as we by default always track the cursor position anyway. https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1391 --- clutter/clutter/clutter-private.h | 6 ++ src/backends/meta-cursor-renderer.c | 2 - src/backends/meta-cursor-tracker-private.h | 7 +++ src/backends/meta-cursor-tracker.c | 47 ++++++++++++++- src/backends/x11/meta-cursor-tracker-x11.c | 70 ++++++++++++++++++++++ 5 files changed, 128 insertions(+), 4 deletions(-) diff --git a/clutter/clutter/clutter-private.h b/clutter/clutter/clutter-private.h index e3f89ed09..e4119b99f 100644 --- a/clutter/clutter/clutter-private.h +++ b/clutter/clutter/clutter-private.h @@ -313,6 +313,12 @@ us (uint64_t us) return us; } +static inline uint32_t +ms (uint32_t ms) +{ + return ms; +} + static inline uint64_t ms2us (uint64_t ms) { diff --git a/src/backends/meta-cursor-renderer.c b/src/backends/meta-cursor-renderer.c index c4d680235..c8bf6578d 100644 --- a/src/backends/meta-cursor-renderer.c +++ b/src/backends/meta-cursor-renderer.c @@ -383,8 +383,6 @@ meta_cursor_renderer_set_position (MetaCursorRenderer *renderer, { MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); - g_assert (meta_is_wayland_compositor ()); - priv->current_x = x; priv->current_y = y; diff --git a/src/backends/meta-cursor-tracker-private.h b/src/backends/meta-cursor-tracker-private.h index 54cdb588e..2a3d99a13 100644 --- a/src/backends/meta-cursor-tracker-private.h +++ b/src/backends/meta-cursor-tracker-private.h @@ -30,6 +30,9 @@ struct _MetaCursorTrackerClass { GObjectClass parent_class; + + void (* set_force_track_position) (MetaCursorTracker *tracker, + gboolean is_enabled); }; gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker, @@ -45,6 +48,10 @@ void meta_cursor_tracker_update_position (MetaCursorTracker *tracker, float new_x, float new_y); +void meta_cursor_tracker_track_position (MetaCursorTracker *tracker); + +void meta_cursor_tracker_untrack_position (MetaCursorTracker *tracker); + MetaCursorSprite * meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker); #endif diff --git a/src/backends/meta-cursor-tracker.c b/src/backends/meta-cursor-tracker.c index f9331b6f6..a411413e2 100644 --- a/src/backends/meta-cursor-tracker.c +++ b/src/backends/meta-cursor-tracker.c @@ -62,6 +62,8 @@ typedef struct _MetaCursorTrackerPrivate gboolean is_showing; + int track_position_count; + float x; float y; @@ -175,6 +177,12 @@ sync_cursor (MetaCursorTracker *tracker) g_signal_emit (tracker, signals[CURSOR_CHANGED], 0); } +static void +meta_cursor_tracker_real_set_force_track_position (MetaCursorTracker *tracker, + gboolean is_enabled) +{ +} + static void meta_cursor_tracker_init (MetaCursorTracker *tracker) { @@ -251,6 +259,9 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass) object_class->set_property = meta_cursor_tracker_set_property; object_class->finalize = meta_cursor_tracker_finalize; + klass->set_force_track_position = + meta_cursor_tracker_real_set_force_track_position; + obj_props[PROP_BACKEND] = g_param_spec_object ("backend", "backend", @@ -491,8 +502,6 @@ meta_cursor_tracker_update_position (MetaCursorTracker *tracker, meta_backend_get_cursor_renderer (priv->backend); gboolean position_changed; - g_assert (meta_is_wayland_compositor ()); - if (priv->x != new_x || priv->y != new_y) { position_changed = TRUE; @@ -567,6 +576,40 @@ meta_cursor_tracker_get_pointer (MetaCursorTracker *tracker, get_pointer_position_gdk (x, y, (int*)mods); } +void +meta_cursor_tracker_track_position (MetaCursorTracker *tracker) +{ + MetaCursorTrackerPrivate *priv = + meta_cursor_tracker_get_instance_private (tracker); + + priv->track_position_count++; + if (priv->track_position_count == 1) + { + MetaCursorTrackerClass *klass = + META_CURSOR_TRACKER_GET_CLASS (tracker); + + klass->set_force_track_position (tracker, TRUE); + } +} + +void +meta_cursor_tracker_untrack_position (MetaCursorTracker *tracker) +{ + MetaCursorTrackerPrivate *priv = + meta_cursor_tracker_get_instance_private (tracker); + + g_return_if_fail (priv->track_position_count <= 0); + + priv->track_position_count--; + if (priv->track_position_count == 0) + { + MetaCursorTrackerClass *klass = + META_CURSOR_TRACKER_GET_CLASS (tracker); + + klass->set_force_track_position (tracker, FALSE); + } +} + gboolean meta_cursor_tracker_get_pointer_visible (MetaCursorTracker *tracker) { diff --git a/src/backends/x11/meta-cursor-tracker-x11.c b/src/backends/x11/meta-cursor-tracker-x11.c index 7072275a6..f47ca9c23 100644 --- a/src/backends/x11/meta-cursor-tracker-x11.c +++ b/src/backends/x11/meta-cursor-tracker-x11.c @@ -22,14 +22,77 @@ #include "backends/x11/meta-cursor-tracker-x11.h" +#include "clutter/clutter-private.h" + +#define UPDATE_POSITION_TIMEOUT_MS (ms (100)) + struct _MetaCursorTrackerX11 { MetaCursorTracker parent; + + gboolean is_force_track_position_enabled; + guint update_position_timeout_id; }; G_DEFINE_TYPE (MetaCursorTrackerX11, meta_cursor_tracker_x11, META_TYPE_CURSOR_TRACKER) +static void +update_position (MetaCursorTrackerX11 *tracker_x11) +{ + MetaCursorTracker *tracker = META_CURSOR_TRACKER (tracker_x11); + int x, y; + + meta_cursor_tracker_get_pointer (tracker, &x, &y, NULL); + meta_cursor_tracker_update_position (tracker, x, y); +} + +static gboolean +update_position_timeout (gpointer user_data) +{ + MetaCursorTrackerX11 *tracker_x11 = user_data; + + update_position (tracker_x11); + + return G_SOURCE_CONTINUE; +} + +static void +meta_cursor_tracker_x11_set_force_track_position (MetaCursorTracker *tracker, + gboolean is_enabled) +{ + MetaCursorTrackerX11 *tracker_x11 = META_CURSOR_TRACKER_X11 (tracker); + + if (tracker_x11->is_force_track_position_enabled == is_enabled) + return; + + tracker_x11->is_force_track_position_enabled = is_enabled; + + if (is_enabled) + { + tracker_x11->update_position_timeout_id = + g_timeout_add (UPDATE_POSITION_TIMEOUT_MS, + update_position_timeout, + tracker_x11); + update_position (tracker_x11); + } + else + { + g_clear_handle_id (&tracker_x11->update_position_timeout_id, + g_source_remove); + } +} + +static void +meta_cursor_tracker_x11_dispose (GObject *object) +{ + MetaCursorTrackerX11 *tracker_x11 = META_CURSOR_TRACKER_X11 (object); + + g_clear_handle_id (&tracker_x11->update_position_timeout_id, g_source_remove); + + G_OBJECT_CLASS (meta_cursor_tracker_x11_parent_class)->dispose (object); +} + static void meta_cursor_tracker_x11_init (MetaCursorTrackerX11 *tracker_x11) { @@ -38,4 +101,11 @@ meta_cursor_tracker_x11_init (MetaCursorTrackerX11 *tracker_x11) static void meta_cursor_tracker_x11_class_init (MetaCursorTrackerX11Class *klass) { + GObjectClass *object_class = G_OBJECT_CLASS (klass); + MetaCursorTrackerClass *tracker_class = META_CURSOR_TRACKER_CLASS (klass); + + object_class->dispose = meta_cursor_tracker_x11_dispose; + + tracker_class->set_force_track_position = + meta_cursor_tracker_x11_set_force_track_position; }