File mutter-a11y-mouse-review.patch of Package mutter
diff --git a/data/dbus-interfaces/org.freedesktop.a11y.xml b/data/dbus-interfaces/org.freedesktop.a11y.xml
index 4f1d210423..50912f98e3 100644
--- a/data/dbus-interfaces/org.freedesktop.a11y.xml
+++ b/data/dbus-interfaces/org.freedesktop.a11y.xml
@@ -116,4 +116,32 @@
<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 toplevel beneath the pointer, and the relative position in
+ the surface.
+ -->
+ <method name="QueryPointer">
+ <arg type="s" name="app_dbus_name" direction="out" />
+ <arg type="s" name="toplevel_object_path" direction="out" />
+ <arg type="d" name="rel_x" direction="out" />
+ <arg type="d" name="rel_y" direction="out" />
+ </method>
+
+ <signal name="PointerChanged"/>
+ </interface>
</node>
diff --git a/src/backends/meta-a11y-manager.c b/src/backends/meta-a11y-manager.c
index d8f02fc929..f0053427c0 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"
@@ -75,7 +77,9 @@ typedef struct _MetaA11yManager
GObject parent;
MetaBackend *backend;
guint dbus_name_id;
+ gboolean needs_motion_hint_emitted;
MetaDBusKeyboardMonitor *keyboard_monitor_skeleton;
+ MetaDBusPointerLocator *pointer_locator_skeleton;
GList *key_grabbers;
GHashTable *grabbed_keypresses;
@@ -306,6 +310,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);
+ const char *dbus_name = NULL, *object_path = NULL;
+ graphene_point_t rel_coords;
+
+ a11y_manager->needs_motion_hint_emitted = TRUE;
+
+ meta_compositor_query_pointer_a11y (compositor,
+ &dbus_name, &object_path,
+ &rel_coords);
+
+ if (!dbus_name || !object_path)
+ {
+ g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR,
+ G_DBUS_ERROR_FAILED,
+ "Unknown object path");
+ return G_DBUS_METHOD_INVOCATION_HANDLED;
+ }
+
+ meta_dbus_pointer_locator_complete_query_pointer (skeleton, invocation,
+ dbus_name, object_path,
+ rel_coords.x, rel_coords.y);
+ return G_DBUS_METHOD_INVOCATION_HANDLED;
+}
+
static void
on_bus_acquired (GDBusConnection *connection,
const char *name,
@@ -334,6 +370,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");
@@ -609,6 +657,34 @@ meta_a11y_manager_notify_clients (MetaA11yManager *a11y_manager,
return a11y_grabbed;
}
+void
+meta_a11y_manager_notify_motion (MetaA11yManager *a11y_manager)
+{
+ g_autoptr (GDBusConnection) connection = NULL;
+ g_autoptr (GError) error = NULL;
+
+ if (!a11y_manager->needs_motion_hint_emitted)
+ return;
+
+ a11y_manager->needs_motion_hint_emitted = FALSE;
+
+ connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+ if (!connection)
+ {
+ g_warning ("Could not get session bus: %s", error->message);
+ return;
+ }
+
+ if (!g_dbus_connection_emit_signal (connection,
+ NULL,
+ "/org/freedesktop/a11y/Manager",
+ "org.freedesktop.a11y.PointerLocator",
+ "PointerChanged",
+ NULL,
+ &error))
+ g_warning ("Could not emit a11y PointerChanged: %s", error->message);
+}
+
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 754cb65394..2b5c8a2040 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_notify_motion (MetaA11yManager *a11y_manager);
+
uint32_t * meta_a11y_manager_get_modifier_keysyms (MetaA11yManager *a11y_manager,
int *n_modifiers);
diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h
index 8bc8c2a1d9..9a398baefd 100644
--- a/src/compositor/compositor-private.h
+++ b/src/compositor/compositor-private.h
@@ -213,3 +213,8 @@ meta_translate_to_high_res_xserver_time (int64_t time_us)
return ms2us (ms & 0xffffffff) + us;
}
+
+void meta_compositor_query_pointer_a11y (MetaCompositor *compositor,
+ const char **dbus_name,
+ const char **toplevel_object_path,
+ graphene_point_t *rel_coords);
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index 146a52653e..e2739e6fbe 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -1642,3 +1642,44 @@ meta_compositor_notify_mapping_change (MetaCompositor *compositor,
return klass->notify_mapping_change (compositor, type, state);
}
+
+void
+meta_compositor_query_pointer_a11y (MetaCompositor *compositor,
+ const char **dbus_name,
+ const char **toplevel_object_path,
+ graphene_point_t *rel_coords)
+{
+ MetaCompositorPrivate *priv =
+ meta_compositor_get_instance_private (compositor);
+ ClutterSeat *seat = meta_backend_get_default_seat (priv->backend);
+ g_autoptr (GSList) windows = NULL;
+ graphene_point_t coords;
+ GSList *l;
+
+ clutter_seat_query_state (seat,
+ NULL, &coords, NULL);
+
+ windows = meta_display_list_windows (priv->display,
+ META_LIST_INCLUDE_OVERRIDE_REDIRECT);
+
+ for (l = windows; l; l = l->next)
+ {
+ int rel_x, rel_y;
+
+ if (!meta_window_has_pointer (l->data))
+ continue;
+
+ meta_window_get_a11y_properties (l->data,
+ dbus_name,
+ toplevel_object_path);
+
+ meta_window_stage_to_protocol_point (l->data,
+ (int) coords.x, (int) coords.y,
+ &rel_x, &rel_y);
+ if (rel_coords)
+ *rel_coords = GRAPHENE_POINT_INIT (rel_x, rel_y);
+ return;
+ }
+
+ /* FIXME: respond as well for our own chrome */
+}
diff --git a/src/core/events.c b/src/core/events.c
index 43c37e0991..db56e32326 100644
--- a/src/core/events.c
+++ b/src/core/events.c
@@ -209,6 +209,10 @@ meta_display_handle_event (MetaDisplay *display,
if (a11y_grabbed)
return CLUTTER_EVENT_STOP;
}
+ else if (event_type == CLUTTER_MOTION)
+ {
+ meta_a11y_manager_notify_motion (a11y_manager);
+ }
source_device = clutter_event_get_source_device (event);
seat = clutter_input_device_get_seat (clutter_event_get_source_device (event));
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 01f6679ac3..2d550b8a23 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;
@@ -937,3 +939,11 @@ void meta_window_set_tag (MetaWindow *window,
META_EXPORT_TEST
GPtrArray * meta_window_get_transient_children (MetaWindow *window);
+
+void meta_window_set_a11y_properties (MetaWindow *window,
+ const char *a11y_dbus_name,
+ const char *toplevel_object_path);
+
+void 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 8f44f60d22..66f88cc64f 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -232,6 +232,8 @@ enum
PROP_MAPPED,
PROP_MAIN_MONITOR,
PROP_TAG,
+ PROP_A11Y_DBUS_NAME,
+ PROP_A11Y_OBJECT_PATH,
PROP_LAST,
};
@@ -410,6 +412,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);
@@ -520,6 +524,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;
@@ -702,6 +712,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] =
@@ -8700,3 +8722,32 @@ meta_window_show_in_window_list (MetaWindow *window)
window->skip_from_window_list = FALSE;
meta_window_recalc_features (window);
}
+
+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]);
+ }
+}
+
+void
+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;
+}
diff --git a/src/wayland/meta-wayland-gtk-shell.c b/src/wayland/meta-wayland-gtk-shell.c
index a1f33c398c..051e6890a4 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 e9cf9856c2..f0b9329785 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
diff --git a/src/wayland/protocol/gtk-shell.xml b/src/wayland/protocol/gtk-shell.xml
index 3629fb41ec..f514478471 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>