Commit c1303bd6 authored by Olivier Fourdan's avatar Olivier Fourdan

clutter/x11: Hook up pointer accessibility

Pointer accessibility features requires to receive all pointer events
regardless of X11 grabs.

Add XI2 raw events mask and hook up the pointer accessibility handlers
to the raw motion and button press/release events.

!512
parent db11a37a
......@@ -30,6 +30,7 @@
#include "clutter-backend-x11.h"
#include "clutter-input-device-xi2.h"
#include "clutter-input-device-tool-xi2.h"
#include "clutter-input-pointer-a11y-private.h"
#include "clutter-virtual-input-device-x11.h"
#include "clutter-stage-x11.h"
......@@ -1273,6 +1274,60 @@ translate_pad_event (ClutterEvent *event,
return TRUE;
}
static void
handle_raw_event (ClutterDeviceManagerXI2 *manager_xi2,
XEvent *xevent)
{
ClutterInputDevice *device;
XGenericEventCookie *cookie;
XIEvent *xi_event;
XIRawEvent *xev;
float x,y;
cookie = &xevent->xcookie;
xi_event = (XIEvent *) cookie->data;
xev = (XIRawEvent *) xi_event;
device = g_hash_table_lookup (manager_xi2->devices_by_id,
GINT_TO_POINTER (xev->deviceid));
if (device == NULL)
return;
if (!_clutter_is_input_pointer_a11y_enabled (device))
return;
switch (cookie->evtype)
{
case XI_RawMotion:
CLUTTER_NOTE (EVENT,
"raw motion: device:%d '%s'",
device->id,
device->device_name);
/* We don't get actual pointer location with raw events, and we cannot
* rely on `clutter_input_device_get_coords()` either because of
* unreparented toplevels (like all client-side decoration windows),
* so we need to explicitely query the pointer here...
*/
if (clutter_input_device_xi2_get_pointer_location (device, &x, &y))
_clutter_input_pointer_a11y_on_motion_event (device, x, y);
break;
case XI_RawButtonPress:
case XI_RawButtonRelease:
CLUTTER_NOTE (EVENT,
"raw button %s: device:%d '%s' button %i",
cookie->evtype == XI_RawButtonPress
? "press "
: "release",
device->id,
device->device_name,
xev->detail);
_clutter_input_pointer_a11y_on_button_event (device,
xev->detail,
(cookie->evtype == XI_RawButtonPress));
break;
}
}
static ClutterTranslateReturn
clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
gpointer native,
......@@ -1303,6 +1358,14 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
if (!xi_event)
return CLUTTER_TRANSLATE_REMOVE;
if (cookie->evtype == XI_RawMotion ||
cookie->evtype == XI_RawButtonPress ||
cookie->evtype == XI_RawButtonRelease)
{
handle_raw_event (manager_xi2, xevent);
return CLUTTER_TRANSLATE_REMOVE;
}
if (!(xi_event->evtype == XI_HierarchyChanged ||
xi_event->evtype == XI_DeviceChanged ||
xi_event->evtype == XI_PropertyEvent))
......@@ -2031,7 +2094,7 @@ clutter_device_manager_xi2_constructed (GObject *gobject)
GHashTable *masters, *slaves;
XIDeviceInfo *info;
XIEventMask event_mask;
unsigned char mask[2] = { 0, };
unsigned char mask[(XI_LASTEVENT + 7) / 8] = { 0, };
int n_devices, i;
backend_x11 =
......@@ -2083,6 +2146,19 @@ clutter_device_manager_xi2_constructed (GObject *gobject)
event_mask.mask_len = sizeof (mask);
event_mask.mask = mask;
clutter_device_manager_xi2_select_events (manager,
clutter_x11_get_root_window (),
&event_mask);
memset(mask, 0, sizeof (mask));
XISetMask (mask, XI_RawMotion);
XISetMask (mask, XI_RawButtonPress);
XISetMask (mask, XI_RawButtonRelease);
event_mask.deviceid = XIAllMasterDevices;
event_mask.mask_len = sizeof (mask);
event_mask.mask = mask;
clutter_device_manager_xi2_select_events (manager,
clutter_x11_get_root_window (),
&event_mask);
......
......@@ -46,6 +46,11 @@ struct _ClutterInputDeviceXI2
gint device_id;
ClutterInputDeviceTool *current_tool;
guint inhibit_pointer_query_timer;
gboolean query_status;
float current_x;
float current_y;
#ifdef HAVE_LIBWACOM
WacomDevice *wacom_device;
GArray *group_modes;
......@@ -114,6 +119,9 @@ clutter_input_device_xi2_finalize (GObject *object)
g_array_unref (device_xi2->group_modes);
#endif
if (device_xi2->inhibit_pointer_query_timer)
g_source_remove (device_xi2->inhibit_pointer_query_timer);
G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->finalize (object);
}
......@@ -293,6 +301,75 @@ clutter_input_device_xi2_get_current_tool (ClutterInputDevice *device)
return device_xi2->current_tool;
}
static gboolean
clutter_input_device_xi2_query_pointer_location (ClutterInputDeviceXI2 *device_xi2)
{
Window xroot_window, xchild_window;
double xroot_x, xroot_y, xwin_x, xwin_y;
XIButtonState button_state;
XIModifierState mod_state;
XIGroupState group_state;
int result;
clutter_x11_trap_x_errors ();
result = XIQueryPointer (clutter_x11_get_default_display (),
device_xi2->device_id,
clutter_x11_get_root_window (),
&xroot_window,
&xchild_window,
&xroot_x, &xroot_y,
&xwin_x, &xwin_y,
&button_state,
&mod_state,
&group_state);
clutter_x11_untrap_x_errors ();
if (!result)
return FALSE;
device_xi2->current_x = (float) xroot_x;
device_xi2->current_y = (float) xroot_y;
return TRUE;
}
static gboolean
clear_inhibit_pointer_query_cb (gpointer data)
{
ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (data);
device_xi2->inhibit_pointer_query_timer = 0;
return G_SOURCE_REMOVE;
}
gboolean
clutter_input_device_xi2_get_pointer_location (ClutterInputDevice *device,
float *x,
float *y)
{
ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (device);
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE);
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE_XI2 (device_xi2), FALSE);
g_return_val_if_fail (device->device_type == CLUTTER_POINTER_DEVICE, FALSE);
/* Throttle XServer queries and roundtrips using an idle timeout */
if (device_xi2->inhibit_pointer_query_timer == 0)
{
device_xi2->query_status =
clutter_input_device_xi2_query_pointer_location (device_xi2);
device_xi2->inhibit_pointer_query_timer =
clutter_threads_add_idle (clear_inhibit_pointer_query_cb, device_xi2);
}
*x = device_xi2->current_x;
*y = device_xi2->current_y;
return device_xi2->query_status;
}
#ifdef HAVE_LIBWACOM
void
clutter_input_device_xi2_ensure_wacom_info (ClutterInputDevice *device,
......
......@@ -48,6 +48,9 @@ void _clutter_input_device_xi2_translate_state (ClutterEvent *event,
void clutter_input_device_xi2_update_tool (ClutterInputDevice *device,
ClutterInputDeviceTool *tool);
ClutterInputDeviceTool * clutter_input_device_xi2_get_current_tool (ClutterInputDevice *device);
gboolean clutter_input_device_xi2_get_pointer_location (ClutterInputDevice *device,
float *x,
float *y);
#ifdef HAVE_LIBWACOM
void clutter_input_device_xi2_ensure_wacom_info (ClutterInputDevice *device,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment