File 4542.patch of Package mutter

From 7f06505516ba3cde4e87de96e15fbd074e870c4d Mon Sep 17 00:00:00 2001
From: Carlos Garnacho <carlosg@gnome.org>
Date: Fri, 2 May 2025 11:40:49 +0200
Subject: [PATCH 1/6] core: Add setter/getter for a11y properties in MetaWindow

We at the moment save the object path relative to the toplevel in
the a11y bus. This is an implementation detail of the existing
framework, so the specific data that we have to store relative to
a toplevel is expected to change in the future.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4542>
---
 src/core/window-private.h | 10 ++++++++
 src/core/window.c         | 53 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/src/core/window-private.h b/src/core/window-private.h
index a76fe1ef770..75b880778aa 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -268,6 +268,8 @@ struct _MetaWindow
   char *gtk_window_object_path;
   char *gtk_app_menu_object_path;
   char *gtk_menubar_object_path;
+  char *a11y_dbus_name;
+  char *a11y_object_path;
 
   MetaWindow *transient_for;
 
@@ -942,3 +944,11 @@ gboolean meta_window_apply_external_constraints (MetaWindow                  *wi
                                                  MetaGravity                  resize_gravity,
                                                  MtkRectangle                *constrained_rect,
                                                  MetaExternalConstraintFlags  constraint_flags);
+
+void meta_window_set_a11y_properties (MetaWindow *window,
+                                      const char *a11y_dbus_name,
+                                      const char *toplevel_object_path);
+
+gboolean meta_window_get_a11y_properties (MetaWindow  *window,
+                                          const char **a11y_dbus_name,
+                                          const char **toplevel_object_path);
diff --git a/src/core/window.c b/src/core/window.c
index d45f3caadc9..3a37450de23 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -228,6 +228,8 @@ enum
   PROP_MAPPED,
   PROP_MAIN_MONITOR,
   PROP_TAG,
+  PROP_A11Y_DBUS_NAME,
+  PROP_A11Y_OBJECT_PATH,
 
   PROP_LAST,
 };
@@ -406,6 +408,8 @@ meta_window_finalize (GObject *object)
   g_free (window->gtk_window_object_path);
   g_free (window->gtk_app_menu_object_path);
   g_free (window->gtk_menubar_object_path);
+  g_free (window->a11y_dbus_name);
+  g_free (window->a11y_object_path);
   g_free (window->placement.rule);
   g_free (window->tag);
 
@@ -518,6 +522,12 @@ meta_window_get_property (GObject         *object,
     case PROP_TAG:
       g_value_set_string (value, window->tag);
       break;
+    case PROP_A11Y_DBUS_NAME:
+      g_value_set_string (value, window->a11y_dbus_name);
+      break;
+    case PROP_A11Y_OBJECT_PATH:
+      g_value_set_string (value, window->a11y_object_path);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -700,6 +710,18 @@ meta_window_class_init (MetaWindowClass *klass)
                          G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY |
                          G_PARAM_STATIC_STRINGS);
 
+  obj_props[PROP_A11Y_DBUS_NAME] =
+    g_param_spec_string ("a11y-dbus-name", NULL, NULL,
+                         NULL,
+                         G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY |
+                         G_PARAM_STATIC_STRINGS);
+
+  obj_props[PROP_A11Y_OBJECT_PATH] =
+    g_param_spec_string ("a11y-object-path", NULL, NULL,
+                         NULL,
+                         G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY |
+                         G_PARAM_STATIC_STRINGS);
+
   g_object_class_install_properties (object_class, PROP_LAST, obj_props);
 
   window_signals[WORKSPACE_CHANGED] =
@@ -8806,3 +8828,34 @@ meta_window_apply_external_constraints (MetaWindow                  *window,
 
   return constraint_satisfied;
 }
+
+void
+meta_window_set_a11y_properties (MetaWindow *window,
+                                 const char *a11y_dbus_name,
+                                 const char *toplevel_object_path)
+{
+  if (g_set_str (&window->a11y_dbus_name, a11y_dbus_name))
+    {
+      g_object_notify_by_pspec (G_OBJECT (window),
+                                obj_props[PROP_A11Y_DBUS_NAME]);
+    }
+
+  if (g_set_str (&window->a11y_object_path, toplevel_object_path))
+    {
+      g_object_notify_by_pspec (G_OBJECT (window),
+                                obj_props[PROP_A11Y_OBJECT_PATH]);
+    }
+}
+
+gboolean
+meta_window_get_a11y_properties (MetaWindow  *window,
+                                 const char **a11y_dbus_name,
+                                 const char **toplevel_object_path)
+{
+  if (a11y_dbus_name)
+    *a11y_dbus_name = window->a11y_dbus_name;
+  if (toplevel_object_path)
+    *toplevel_object_path = window->a11y_object_path;
+
+  return window->a11y_dbus_name && window->a11y_object_path;
+}
-- 
GitLab


From 5ac8788c2eea29cc6050cb8ca8a0d7eeb0dc9117 Mon Sep 17 00:00:00 2001
From: Carlos Garnacho <carlosg@gnome.org>
Date: Fri, 2 May 2025 12:17:52 +0200
Subject: [PATCH 2/6] compositor: Add call to query a11y details under the
 pointer

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4542>
---
 src/compositor/compositor-private.h |  4 ++
 src/compositor/compositor.c         | 83 +++++++++++++++++++++++++++++
 src/wayland/meta-wayland.c          | 26 +++++++++
 src/wayland/meta-wayland.h          |  4 ++
 4 files changed, 117 insertions(+)

diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h
index 55e7dc66db5..1fa954438d0 100644
--- a/src/compositor/compositor-private.h
+++ b/src/compositor/compositor-private.h
@@ -203,3 +203,7 @@ meta_translate_to_high_res_xserver_time (int64_t time_us)
 
   return ms2us (ms & 0xffffffff) + us;
 }
+
+gboolean meta_compositor_query_pointer_a11y (MetaCompositor    *compositor,
+                                             GVariant         **data_out,
+                                             graphene_point_t  *rel_coords);
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index 8d051ce39c9..85d6dfa4833 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -1685,3 +1685,86 @@ meta_compositor_notify_mapping_change (MetaCompositor   *compositor,
 
   return klass->notify_mapping_change (compositor, type, state);
 }
+
+gboolean
+meta_compositor_query_pointer_a11y (MetaCompositor    *compositor,
+                                    GVariant         **data_out,
+                                    graphene_point_t  *rel_coords_out)
+{
+  MetaCompositorPrivate *priv =
+    meta_compositor_get_instance_private (compositor);
+  MetaContext *context = meta_backend_get_context (priv->backend);
+  MetaWaylandCompositor *wayland_compositor =
+    meta_context_get_wayland_compositor (context);
+  ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (priv->backend));
+  ClutterBackend *clutter_backend =
+    meta_backend_get_clutter_backend (priv->backend);
+  ClutterSprite *sprite;
+  g_autoptr (GSList) windows = NULL;
+  graphene_point_t rel_coords;
+  MetaWindow *window;
+
+  sprite = clutter_backend_get_pointer_sprite (clutter_backend, stage);
+
+  window = meta_wayland_compositor_get_current_window (wayland_compositor,
+                                                       sprite, &rel_coords);
+
+  if (window)
+    {
+      const char *dbus_name = NULL, *object_path = NULL;
+      GVariantBuilder app_data_builder;
+      int rel_x, rel_y;
+      pid_t pid;
+
+      meta_window_stage_to_protocol_point (window,
+                                           (int) rel_coords.x,
+                                           (int) rel_coords.y,
+                                           &rel_x, &rel_y);
+
+      g_variant_builder_init (&app_data_builder, G_VARIANT_TYPE ("a{sv}"));
+
+      pid = meta_window_get_pid (window);
+
+      if (meta_window_get_a11y_properties (window,
+                                           &dbus_name,
+                                           &object_path))
+        {
+          if (dbus_name)
+            {
+              g_variant_builder_add (&app_data_builder, "{sv}",
+                                     "app-dbus-name",
+                                     g_variant_new_string (dbus_name));
+            }
+
+          if (object_path)
+            {
+              g_variant_builder_add (&app_data_builder, "{sv}",
+                                     "toplevel-object-path",
+                                     g_variant_new_object_path (object_path));
+            }
+
+          *data_out = g_variant_builder_end (&app_data_builder);
+          *rel_coords_out = GRAPHENE_POINT_INIT (rel_x, rel_y);
+          return TRUE;
+        }
+      else if (pid != 0)
+        {
+          g_variant_builder_add (&app_data_builder, "{sv}",
+                                 "pid",
+                                 g_variant_new_int32 (pid));
+
+          *data_out = g_variant_builder_end (&app_data_builder);
+          *rel_coords_out = GRAPHENE_POINT_INIT (rel_x, rel_y);
+
+          return pid != 0;
+        }
+      else
+        {
+          return FALSE;
+        }
+    }
+
+  /* Respond for our own chrome */
+  clutter_sprite_get_coords (sprite, rel_coords_out);
+  return TRUE;
+}
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index d5af568a66f..8c467e68799 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -1327,3 +1327,29 @@ meta_wayland_compositor_get_cursor (MetaWaylandCompositor *compositor,
 {
   return meta_wayland_seat_get_cursor (compositor->seat, sprite);
 }
+
+MetaWindow *
+meta_wayland_compositor_get_current_window (MetaWaylandCompositor *compositor,
+                                            ClutterSprite         *sprite,
+                                            graphene_point_t      *rel_coords)
+{
+  MetaWaylandSurface *surface;
+
+  surface = meta_wayland_seat_get_current_surface (compositor->seat,
+                                                   CLUTTER_FOCUS (sprite));
+  if (!surface)
+    return NULL;
+
+  if (rel_coords)
+    {
+      graphene_point_t pos;
+      float x, y;
+
+      clutter_sprite_get_coords (sprite, &pos);
+      meta_wayland_surface_get_relative_coordinates (surface, pos.x, pos.y,
+                                                     &x, &y);
+      *rel_coords = GRAPHENE_POINT_INIT (x, y);
+    }
+
+  return meta_wayland_surface_get_toplevel_window (surface);
+}
diff --git a/src/wayland/meta-wayland.h b/src/wayland/meta-wayland.h
index 764687c7fba..4ad3eca0dff 100644
--- a/src/wayland/meta-wayland.h
+++ b/src/wayland/meta-wayland.h
@@ -118,6 +118,10 @@ void meta_wayland_compositor_sync_focus (MetaWaylandCompositor *compositor);
 ClutterCursor * meta_wayland_compositor_get_cursor (MetaWaylandCompositor *compositor,
                                                     ClutterSprite         *sprite);
 
+MetaWindow * meta_wayland_compositor_get_current_window (MetaWaylandCompositor *compositor,
+                                                         ClutterSprite         *sprite,
+                                                         graphene_point_t      *rel_coords);
+
 static inline gboolean
 meta_wayland_compositor_serial_is_later (uint32_t serial1,
                                          uint32_t serial2)
-- 
GitLab


From ad24b770b22fcf83106eb42bd5e70e6986090262 Mon Sep 17 00:00:00 2001
From: Carlos Garnacho <carlosg@gnome.org>
Date: Fri, 2 May 2025 11:37:58 +0200
Subject: [PATCH 3/6] wayland: Update gtk-shell protocol

Add call to pass the a11y object path relative to the toplevel,
so it is known to Mutter. This information may be useful to the
screen reader.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4542>
---
 src/wayland/protocol/gtk-shell.xml | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/wayland/protocol/gtk-shell.xml b/src/wayland/protocol/gtk-shell.xml
index 3629fb41ec0..f514478471f 100644
--- a/src/wayland/protocol/gtk-shell.xml
+++ b/src/wayland/protocol/gtk-shell.xml
@@ -1,6 +1,6 @@
 <protocol name="gtk">
 
-  <interface name="gtk_shell1" version="6">
+  <interface name="gtk_shell1" version="7">
     <description summary="gtk specific extensions">
       gtk_shell is a protocol extension providing additional features for
       clients implementing it.
@@ -37,7 +37,7 @@
     <!-- Version 6 does not add new API, but asserts that surface offsets are implemented -->
   </interface>
 
-  <interface name="gtk_surface1" version="6">
+  <interface name="gtk_surface1" version="7">
     <request name="set_dbus_properties">
       <arg name="application_id" type="string" allow-null="true"/>
       <arg name="app_menu_path" type="string" allow-null="true"/>
@@ -106,6 +106,11 @@
     </request>
 
     <!-- Version 6 does not add new API, but asserts that surface offsets are implemented -->
+
+    <request name="set_a11y_properties" since="7">
+      <arg name="a11y_dbus_name" type="string" />
+      <arg name="toplevel_object_path" type="string" />
+    </request>
   </interface>
 
 </protocol>
-- 
GitLab


From 6ac844dbc6794fb723227bea45c10c334eab4cd7 Mon Sep 17 00:00:00 2001
From: Carlos Garnacho <carlosg@gnome.org>
Date: Fri, 2 May 2025 11:48:10 +0200
Subject: [PATCH 4/6] wayland: Hook a11y properties from gtk-shell to
 MetaWindow

Implement v7 of gtk-shell, and propagate the a11y properties so
they are stored in MetaWindow.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4542>
---
 src/wayland/meta-wayland-gtk-shell.c | 25 ++++++++++++++++++++++++-
 src/wayland/meta-wayland-versions.h  |  2 +-
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/src/wayland/meta-wayland-gtk-shell.c b/src/wayland/meta-wayland-gtk-shell.c
index a1f33c398c4..051e6890a4a 100644
--- a/src/wayland/meta-wayland-gtk-shell.c
+++ b/src/wayland/meta-wayland-gtk-shell.c
@@ -312,6 +312,28 @@ gtk_surface_titlebar_gesture (struct wl_client   *client,
     }
 }
 
+static void
+gtk_surface_set_a11y_properties (struct wl_client   *client,
+                                 struct wl_resource *resource,
+                                 const char         *a11y_dbus_name,
+                                 const char         *toplevel_object_path)
+{
+  MetaWaylandGtkSurface *gtk_surface = wl_resource_get_user_data (resource);
+  MetaWaylandSurface *surface = gtk_surface->surface;
+  MetaWindow *window;
+
+  if (!surface)
+    return;
+
+  window = meta_wayland_surface_get_window (surface);
+  if (!window)
+    return;
+
+  meta_window_set_a11y_properties (window,
+                                   a11y_dbus_name,
+                                   toplevel_object_path);
+}
+
 static void
 gtk_surface_release (struct wl_client   *client,
                      struct wl_resource *resource)
@@ -326,7 +348,8 @@ static const struct gtk_surface1_interface meta_wayland_gtk_surface_interface =
   gtk_surface_present,
   gtk_surface_request_focus,
   gtk_surface_release,
-  gtk_surface_titlebar_gesture
+  gtk_surface_titlebar_gesture,
+  gtk_surface_set_a11y_properties,
 };
 
 static void
diff --git a/src/wayland/meta-wayland-versions.h b/src/wayland/meta-wayland-versions.h
index 34d5099dede..bf87d1feffe 100644
--- a/src/wayland/meta-wayland-versions.h
+++ b/src/wayland/meta-wayland-versions.h
@@ -38,7 +38,7 @@
 #define META_WL_SEAT_VERSION                10
 #define META_WL_OUTPUT_VERSION              4
 #define META_XSERVER_VERSION                1
-#define META_GTK_SHELL1_VERSION             6
+#define META_GTK_SHELL1_VERSION             7
 #define META_WL_SUBCOMPOSITOR_VERSION       1
 #define META_ZWP_POINTER_GESTURES_V1_VERSION 3
 #define META_ZXDG_EXPORTER_V1_VERSION       1
-- 
GitLab


From 62f6fa2e0c8b7e6e42326651fa58c0f67646d42b Mon Sep 17 00:00:00 2001
From: Carlos Garnacho <carlosg@gnome.org>
Date: Fri, 2 May 2025 11:49:31 +0200
Subject: [PATCH 5/6] data: Add interface to let screen readers query pointer
 position

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4542>
---
 data/dbus-interfaces/org.freedesktop.a11y.xml | 66 +++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/data/dbus-interfaces/org.freedesktop.a11y.xml b/data/dbus-interfaces/org.freedesktop.a11y.xml
index 4f1d210423f..e05b07aa619 100644
--- a/data/dbus-interfaces/org.freedesktop.a11y.xml
+++ b/data/dbus-interfaces/org.freedesktop.a11y.xml
@@ -116,4 +116,70 @@
       <arg type="q" name="keycode" direction="in" />
     </signal>
   </interface>
+
+  <!--
+      org.freedesktop.a11y.PointerLocator:
+      @short_description: interface for locating the pointer position in the
+       accessibility tree
+
+      This interface is used by assistive technologies to query the pointer
+      position in the accessibility tree. The compositor is expected to listen on
+      the well-known bus name "org.freedesktop.a11y.Manager" at the object
+      path "/org/freedesktop/a11y/Manager".
+  -->
+  <interface name="org.freedesktop.a11y.PointerLocator">
+
+    <!--
+        QueryPointer:
+
+        Queries the a11y details about the toplevel beneath the mouse pointer,
+        together with the relative position of the mouse pointer on the surface.
+        The most up-to-date coordinates as known to the compositor are returned
+        by this method call.
+
+        Screen readers may use the given information to further query the
+        accessibility tree of the specific application, in order to identify
+        the application-side accessible elements directly underneath the mouse
+        pointer.
+
+        This request will also schedule the emission of a following
+        "PointerPositionChanged" signal, whenever mouse pointer motion would
+        happen.
+
+        The "data" argument is a generic container, so far the only handled keys
+        are relevant to AT-SPI:
+
+        - "app-dbus_name" (type: s): Application D-Bus name in the a11y D-Bus
+        - "toplevel-object-path" (type: o): Object path to the toplevel, in the
+          given D-Bus name.
+
+        If this data is not provided, the focused client will be considered to
+        be the desktop environment itself, and the provided coordinates will be
+        relative to its origin point.
+
+        A org.freedesktop.a11y.UnknownToplevel error will be returned if the
+        client under the pointer is non-introspectable.
+    -->
+    <method name="QueryPointer">
+      <arg type="a{sv}" name="app_data" direction="out" />
+      <arg type="d" name="rel_x" direction="out" />
+      <arg type="d" name="rel_y" direction="out" />
+    </method>
+
+    <!--
+        PointerPositionChanged:
+
+        This signal is emitted once when two conditions meet:
+        1. A "QueryPointer" method call happened before
+        2. Pointer motion happened after replying to that method call
+
+        The purpose of the signal is being used as a throttling mechanism, so
+        that a11y pointer handling is independent of device specifics like
+        frequency rate at which input is handled.
+
+        The expected response for a screen reader to this signal is scheduling
+        a following "QueryPointer" method call.
+    -->
+    <signal name="PointerPositionChanged"/>
+  </interface>
 </node>
-- 
GitLab


From 23a8205f47c7eb81bdc0c84134cbb7c5b33fa948 Mon Sep 17 00:00:00 2001
From: Carlos Garnacho <carlosg@gnome.org>
Date: Fri, 2 May 2025 12:45:49 +0200
Subject: [PATCH 6/6] backends: Implement a11y pointer locator D-Bus interface

This interface allows the screen reader to query the DBus name,
toplevel object path, and surface-relative pointer coordinates of
the surface beneath the pointer.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4542>
---
 src/backends/meta-a11y-manager.c | 105 +++++++++++++++++++++++++++++++
 src/backends/meta-a11y-manager.h |   2 +
 src/core/events.c                |   5 ++
 3 files changed, 112 insertions(+)

diff --git a/src/backends/meta-a11y-manager.c b/src/backends/meta-a11y-manager.c
index c56ce5a4120..2c9e002b15d 100644
--- a/src/backends/meta-a11y-manager.c
+++ b/src/backends/meta-a11y-manager.c
@@ -22,7 +22,9 @@
 
 #include "backends/meta-a11y-manager.h"
 #include "backends/meta-dbus-access-checker.h"
+#include "compositor/compositor-private.h"
 #include "core/meta-debug-control-private.h"
+#include "meta/display.h"
 #include "meta/meta-backend.h"
 #include "meta/meta-context.h"
 #include "meta/util.h"
@@ -35,6 +37,13 @@
                             CLUTTER_BUTTON4_MASK | \
                             CLUTTER_BUTTON5_MASK)
 
+#define META_A11Y_ERROR (meta_a11y_error_quark ())
+
+typedef enum
+{
+  META_A11Y_ERROR_UNKNOWN_TOPLEVEL,
+} MetaA11yError;
+
 enum
 {
   A11Y_MODIFIERS_CHANGED,
@@ -75,7 +84,10 @@ typedef struct _MetaA11yManager
   GObject parent;
   MetaBackend *backend;
   guint dbus_name_id;
+  GHashTable *query_pointer_requesters;
   MetaDBusKeyboardMonitor *keyboard_monitor_skeleton;
+  MetaDBusPointerLocator *pointer_locator_skeleton;
+  GDBusConnection *connection;
 
   GList *key_grabbers;
   GHashTable *grabbed_keypresses;
@@ -86,6 +98,20 @@ typedef struct _MetaA11yManager
 
 G_DEFINE_TYPE (MetaA11yManager, meta_a11y_manager, G_TYPE_OBJECT)
 
+static GQuark
+meta_a11y_error_quark (void)
+{
+  GDBusErrorEntry entries[] = {
+    { META_A11Y_ERROR_UNKNOWN_TOPLEVEL, "org.freedesktop.a11y.UnknownToplevel" },
+  };
+  size_t quark;
+
+  g_dbus_error_register_error_domain ("-meta-a11y-error-quark", &quark,
+                                      entries, G_N_ELEMENTS (entries));
+
+  return (GQuark) quark;
+}
+
 static void
 key_grabber_free (MetaA11yKeyGrabber *grabber)
 {
@@ -306,6 +332,38 @@ handle_set_key_grabs (MetaDBusKeyboardMonitor *skeleton,
   return G_DBUS_METHOD_INVOCATION_HANDLED;
 }
 
+static gboolean
+handle_query_pointer (MetaDBusPointerLocator *skeleton,
+                      GDBusMethodInvocation  *invocation,
+                      MetaA11yManager        *a11y_manager)
+{
+  MetaContext *context =
+    meta_backend_get_context (a11y_manager->backend);
+  MetaDisplay *display = meta_context_get_display (context);
+  MetaCompositor *compositor = meta_display_get_compositor (display);
+  GVariant *app_data;
+  graphene_point_t rel_coords;
+  const char *sender;
+
+  sender = g_dbus_method_invocation_get_sender (invocation);
+
+  g_hash_table_add (a11y_manager->query_pointer_requesters, g_strdup (sender));
+
+  if (!meta_compositor_query_pointer_a11y (compositor, &app_data, &rel_coords))
+    {
+      g_dbus_method_invocation_return_error_literal (invocation,
+                                                     META_A11Y_ERROR,
+                                                     META_A11Y_ERROR_UNKNOWN_TOPLEVEL,
+                                                     "Cannot get client a11y information");
+      return G_DBUS_METHOD_INVOCATION_HANDLED;
+    }
+
+  meta_dbus_pointer_locator_complete_query_pointer (skeleton, invocation,
+                                                    app_data,
+                                                    rel_coords.x, rel_coords.y);
+  return G_DBUS_METHOD_INVOCATION_HANDLED;
+}
+
 static void
 on_bus_acquired (GDBusConnection *connection,
                  const char      *name,
@@ -314,6 +372,8 @@ on_bus_acquired (GDBusConnection *connection,
   MetaA11yManager *manager = user_data;
   MetaContext *context = meta_backend_get_context (manager->backend);
 
+  manager->connection = connection;
+
   manager->keyboard_monitor_skeleton = meta_dbus_keyboard_monitor_skeleton_new ();
 
   g_signal_connect (manager->keyboard_monitor_skeleton, "g-authorize-method",
@@ -334,6 +394,18 @@ on_bus_acquired (GDBusConnection *connection,
                                     "/org/freedesktop/a11y/Manager",
                                     NULL);
 
+  manager->pointer_locator_skeleton = meta_dbus_pointer_locator_skeleton_new ();
+
+  g_signal_connect (manager->pointer_locator_skeleton, "g-authorize-method",
+                    G_CALLBACK (check_access), manager);
+  g_signal_connect (manager->pointer_locator_skeleton, "handle-query-pointer",
+                    G_CALLBACK (handle_query_pointer), manager);
+
+  g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (manager->pointer_locator_skeleton),
+                                    connection,
+                                    "/org/freedesktop/a11y/Manager",
+                                    NULL);
+
   manager->access_checker = meta_dbus_access_checker_new (connection, context);
   meta_dbus_access_checker_allow_sender (manager->access_checker,
                                          "org.gnome.Orca.KeyboardMonitor");
@@ -345,6 +417,7 @@ on_name_acquired (GDBusConnection *connection,
                   gpointer         user_data)
 {
   meta_topic (META_DEBUG_DBUS, "Acquired name %s", name);
+
 }
 
 static void
@@ -366,6 +439,7 @@ meta_a11y_manager_finalize (GObject *object)
   g_clear_object (&a11y_manager->access_checker);
   g_clear_pointer (&a11y_manager->grabbed_keypresses, g_hash_table_destroy);
   g_clear_pointer (&a11y_manager->all_grabbed_modifiers, g_hash_table_destroy);
+  g_clear_pointer (&a11y_manager->query_pointer_requesters, g_hash_table_destroy);
   g_bus_unown_name (a11y_manager->dbus_name_id);
 
   G_OBJECT_CLASS (meta_a11y_manager_parent_class)->finalize (object);
@@ -397,6 +471,8 @@ meta_a11y_manager_constructed (GObject *object)
 
   a11y_manager->grabbed_keypresses = g_hash_table_new (NULL, NULL);
   a11y_manager->all_grabbed_modifiers = g_hash_table_new (NULL, NULL);
+  a11y_manager->query_pointer_requesters =
+    g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
 
   a11y_manager->dbus_name_id =
     g_bus_own_name (G_BUS_TYPE_SESSION,
@@ -603,6 +679,35 @@ meta_a11y_manager_notify_clients (MetaA11yManager    *a11y_manager,
   return a11y_grabbed;
 }
 
+void
+meta_a11y_manager_maybe_notify_motion (MetaA11yManager *a11y_manager)
+{
+  g_autoptr (GDBusConnection) connection = NULL;
+  GHashTableIter iter;
+  const char *dest;
+
+  if (!a11y_manager->connection)
+    return;
+
+  g_hash_table_iter_init (&iter, a11y_manager->query_pointer_requesters);
+
+  while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &dest))
+    {
+      g_autoptr (GError) error = NULL;
+
+      if (!g_dbus_connection_emit_signal (a11y_manager->connection,
+                                          dest,
+                                          "/org/freedesktop/a11y/Manager",
+                                          "org.freedesktop.a11y.PointerLocator",
+                                          "PointerPositionChanged",
+                                          NULL,
+                                          &error))
+        g_warning ("Could not emit a11y PointerPositionChanged: %s", error->message);
+
+      g_hash_table_iter_remove (&iter);
+    }
+}
+
 uint32_t *
 meta_a11y_manager_get_modifier_keysyms (MetaA11yManager *a11y_manager,
                                         int             *n_modifiers)
diff --git a/src/backends/meta-a11y-manager.h b/src/backends/meta-a11y-manager.h
index 754cb65394c..9d90560b587 100644
--- a/src/backends/meta-a11y-manager.h
+++ b/src/backends/meta-a11y-manager.h
@@ -31,5 +31,7 @@ MetaA11yManager * meta_a11y_manager_new (MetaBackend *backend);
 gboolean meta_a11y_manager_notify_clients (MetaA11yManager    *a11y_manager,
                                            const ClutterEvent *event);
 
+void meta_a11y_manager_maybe_notify_motion (MetaA11yManager *a11y_manager);
+
 uint32_t * meta_a11y_manager_get_modifier_keysyms (MetaA11yManager *a11y_manager,
                                                    int             *n_modifiers);
diff --git a/src/core/events.c b/src/core/events.c
index d27b802fb22..0d6f06a6d4d 100644
--- a/src/core/events.c
+++ b/src/core/events.c
@@ -155,6 +155,11 @@ meta_display_handle_event (MetaDisplay        *display,
       if (a11y_grabbed)
         return CLUTTER_EVENT_STOP;
     }
+  else if (event_type == CLUTTER_MOTION &&
+           !clutter_event_get_device_tool (event))
+    {
+      meta_a11y_manager_maybe_notify_motion (a11y_manager);
+    }
 
   source_device = clutter_event_get_source_device (event);
   seat = clutter_input_device_get_seat (clutter_event_get_source_device (event));
-- 
GitLab

openSUSE Build Service is sponsored by