diff options
-rw-r--r-- | atspi/atspi-device-legacy.c | 91 | ||||
-rw-r--r-- | atspi/atspi-device-legacy.h | 59 | ||||
-rw-r--r-- | atspi/atspi-device-x11.c | 635 | ||||
-rw-r--r-- | atspi/atspi-device-x11.h | 59 | ||||
-rw-r--r-- | atspi/atspi-device.c | 400 | ||||
-rw-r--r-- | atspi/atspi-device.h | 103 | ||||
-rw-r--r-- | atspi/atspi-registry.c | 2 | ||||
-rw-r--r-- | atspi/atspi-types.h | 9 | ||||
-rw-r--r-- | atspi/meson.build | 12 |
9 files changed, 1368 insertions, 2 deletions
diff --git a/atspi/atspi-device-legacy.c b/atspi/atspi-device-legacy.c new file mode 100644 index 00000000..fbae5f03 --- /dev/null +++ b/atspi/atspi-device-legacy.c @@ -0,0 +1,91 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2020 SUSE LLC. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "atspi-private.h" +#include "atspi-device-legacy.h" + +typedef struct _AtspiDeviceLegacyPrivate AtspiDeviceLegacyPrivate; +struct _AtspiDeviceLegacyPrivate +{ + AtspiDeviceListener *listener; +}; + +GObjectClass *device_legacy_parent_class; + +G_DEFINE_TYPE_WITH_CODE (AtspiDeviceLegacy, atspi_device_legacy, + ATSPI_TYPE_DEVICE, + G_ADD_PRIVATE (AtspiDeviceLegacy)) + +gboolean +key_cb (const AtspiDeviceEvent *event, void *user_data) +{ + AtspiDeviceLegacy *device = ATSPI_DEVICE_LEGACY (user_data); + + return atspi_device_notify_key (ATSPI_DEVICE (device), event->type == (AtspiEventType)ATSPI_KEY_PRESS, event->hw_code, event->id, event->modifiers, event->event_string); +} + +static void +atspi_device_legacy_init (AtspiDeviceLegacy *device) +{ + AtspiDeviceLegacyPrivate *priv = atspi_device_legacy_get_instance_private (device); + gint i; + + priv->listener = atspi_device_listener_new (key_cb, device, NULL); + for (i = 0; i < 256; i++) + atspi_register_keystroke_listener (priv->listener, NULL, i, 3, ATSPI_KEYLISTENER_SYNCHRONOUS | ATSPI_KEYLISTENER_CANCONSUME, NULL); +} + +static void +atspi_device_legacy_finalize (GObject *object) +{ + AtspiDeviceLegacy *device = ATSPI_DEVICE_LEGACY (object); + AtspiDeviceLegacyPrivate *priv = atspi_device_legacy_get_instance_private (device); + + g_clear_object (&priv->listener); + device_legacy_parent_class->finalize (object); +} + + +static void +atspi_device_legacy_class_init (AtspiDeviceLegacyClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + + device_legacy_parent_class = g_type_class_peek_parent (klass); + object_class->finalize = atspi_device_legacy_finalize; +} + +/** + * atspi_device_legacy_new: + * + * Creates a new #AtspiDeviceLegacy. + * + * Returns: (transfer full): a pointer to a newly-created #AtspiDeviceLegacy. + * + **/ +AtspiDeviceLegacy * +atspi_device_legacy_new () +{ + AtspiDeviceLegacy *device = g_object_new (atspi_device_legacy_get_type (), NULL); + + return device; +} diff --git a/atspi/atspi-device-legacy.h b/atspi/atspi-device-legacy.h new file mode 100644 index 00000000..50f777e2 --- /dev/null +++ b/atspi/atspi-device-legacy.h @@ -0,0 +1,59 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2020 SUSE LLC. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _ATSPI_DEVICE_LEGACY_H_ +#define _ATSPI_DEVICE_LEGACY_H_ + +#include "glib-object.h" + +#include "atspi-types.h" +#include "atspi-device.h" + +G_BEGIN_DECLS + +#define ATSPI_TYPE_DEVICE_LEGACY (atspi_device_legacy_get_type ()) +#define ATSPI_DEVICE_LEGACY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_DEVICE_LEGACY, AtspiDeviceLegacy)) +#define ATSPI_DEVICE_LEGACY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_DEVICE_LEGACY, AtspiDeviceLegacyClass)) +#define ATSPI_IS_DEVICE_LEGACY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_DEVICE_LEGACY)) +#define ATSPI_IS_DEVICE_LEGACY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_DEVICE_LEGACY)) +#define ATSPI_DEVICE_LEGACY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_DEVICE_LEGACY, AtspiDeviceLegacyClass)) + +typedef struct _AtspiDeviceLegacy AtspiDeviceLegacy; +struct _AtspiDeviceLegacy +{ + AtspiDevice parent; +}; + +typedef struct _AtspiDeviceLegacyClass AtspiDeviceLegacyClass; +struct _AtspiDeviceLegacyClass +{ + AtspiDeviceClass parent_class; +}; + +GType atspi_device_legacy_get_type (void); + +AtspiDeviceLegacy *atspi_device_legacy_new (); + +G_END_DECLS + +#endif /* _ATSPI_DEVICE_LEGACY_H_ */ diff --git a/atspi/atspi-device-x11.c b/atspi/atspi-device-x11.c new file mode 100644 index 00000000..adc600be --- /dev/null +++ b/atspi/atspi-device-x11.c @@ -0,0 +1,635 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2020 SUSE LLC. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "atspi-private.h" +#include "atspi-device-x11.h" + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/extensions/XInput2.h> +#include <X11/XKBlib.h> + + +#define ATSPI_VIRTUAL_MODIFIER_MASK 0xffff0000 + +typedef struct _AtspiDeviceX11Private AtspiDeviceX11Private; +struct _AtspiDeviceX11Private +{ + Display *display; + Window window; + GSource *source; + int xi_opcode; + int device_id; + GSList *modifiers; + GSList *key_grabs; + guint virtual_mods_enabled; +}; + +GObjectClass *device_x11_parent_class; + +typedef struct _DisplaySource +{ + GSource source; + + Display *display; + GPollFD event_poll_fd; +} DisplaySource; + +typedef struct +{ + guint keycode; + guint modifier; +} AtspiX11KeyModifier; + +typedef struct +{ + AtspiKeyDefinition *kd; + gboolean enabled; +} AtspiX11KeyGrab; + +static gboolean +event_prepare (GSource *source, gint *timeout) +{ + Display *display = ((DisplaySource *)source)->display; + gboolean retval; + + *timeout = -1; + retval = XPending (display); + + return retval; +} + +static gboolean +event_check (GSource *source) +{ + DisplaySource *display_source = (DisplaySource*)source; + gboolean retval; + + if (display_source->event_poll_fd.revents & G_IO_IN) + retval = XPending (display_source->display); + else + retval = FALSE; + + return retval; +} + +static void +xi2keyevent (XIDeviceEvent *xievent, XEvent *xkeyevent) +{ + memset (xkeyevent, 0, sizeof (*xkeyevent)); + + switch (xievent->evtype) + { + case XI_KeyPress: + xkeyevent->type = KeyPress; + break; + case XI_KeyRelease: + xkeyevent->type = KeyRelease; + break; + default: + break; + } + xkeyevent->xkey.serial = xievent->serial; + xkeyevent->xkey.send_event = xievent->send_event; + xkeyevent->xkey.display = xievent->display; + xkeyevent->xkey.window = xievent->event; + xkeyevent->xkey.root = xievent->root; + xkeyevent->xkey.subwindow = xievent->child; + xkeyevent->xkey.time = xievent->time; + xkeyevent->xkey.x = xievent->event_x; + xkeyevent->xkey.y = xievent->event_y; + xkeyevent->xkey.x_root = xievent->root_x; + xkeyevent->xkey.y_root = xievent->root_y; + xkeyevent->xkey.state = xievent->mods.effective; + xkeyevent->xkey.keycode = xievent->detail; + xkeyevent->xkey.same_screen = 1; +} + +G_DEFINE_TYPE_WITH_CODE (AtspiDeviceX11, atspi_device_x11, + ATSPI_TYPE_DEVICE, + G_ADD_PRIVATE (AtspiDeviceX11)) + + +static guint +find_virtual_mapping (AtspiDeviceX11 *x11_device, gint keycode) +{ + AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (x11_device); + GSList *l; + + for (l = priv->modifiers; l; l = l->next) + { + AtspiX11KeyModifier *entry = l->data; + if (entry->keycode == keycode) + return entry->modifier; + } + + return 0; +} + +static gboolean +grab_should_be_enabled (AtspiDeviceX11 *x11_device, AtspiX11KeyGrab *grab) +{ + AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (x11_device); + guint virtual_mods_used = grab->kd->modifiers & ATSPI_VIRTUAL_MODIFIER_MASK; + return ((priv->virtual_mods_enabled & virtual_mods_used) == virtual_mods_used); +} + +static gboolean +grab_has_active_duplicate (AtspiDeviceX11 *x11_device, AtspiX11KeyGrab *grab) +{ + AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (x11_device); + GSList *l; + + for (l = priv->key_grabs; l; l = l->next) + { + AtspiX11KeyGrab *other = l->data; + if (other != grab && other->enabled && other->kd->keycode == grab->kd->keycode && (other->kd->modifiers & ~ATSPI_VIRTUAL_MODIFIER_MASK) == (grab->kd->modifiers & ~ATSPI_VIRTUAL_MODIFIER_MASK)) + return TRUE; + } + return FALSE; +} + +static void +enable_key_grab (AtspiDeviceX11 *x11_device, AtspiX11KeyGrab *grab) +{ + AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (x11_device); + XIGrabModifiers xi_modifiers; + XIEventMask eventmask; + unsigned char mask[XIMaskLen (XI_LASTEVENT)] = { 0 }; + + g_return_if_fail (priv->display != NULL); + + xi_modifiers.modifiers = grab->kd->modifiers & ~ATSPI_VIRTUAL_MODIFIER_MASK; + xi_modifiers.status = 0; + + eventmask.deviceid = XIAllDevices; + eventmask.mask_len = sizeof(mask); + eventmask.mask = mask; + + XISetMask (mask, XI_KeyPress); + XISetMask (mask, XI_KeyRelease); + + if (!grab_has_active_duplicate (x11_device, grab)) + XIGrabKeycode (priv->display, XIAllMasterDevices, grab->kd->keycode, priv->window, XIGrabModeSync, XIGrabModeAsync, False, &eventmask, 1, &xi_modifiers); + grab->enabled = TRUE; +} + +static void +disable_key_grab (AtspiDeviceX11 *x11_device, AtspiX11KeyGrab *grab) +{ + AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (x11_device); + XIGrabModifiers xi_modifiers; + + g_return_if_fail (priv->display != NULL); + + if (!grab->enabled) + return; + + grab->enabled = FALSE; + + if (grab_has_active_duplicate (x11_device, grab)) + return; + + xi_modifiers.modifiers = grab->kd->modifiers & ~ATSPI_VIRTUAL_MODIFIER_MASK; + xi_modifiers.status = 0; + + XIUngrabKeycode (priv->display, XIAllMasterDevices, grab->kd->keycode, priv->window, sizeof(xi_modifiers), &xi_modifiers); +} + +static void +set_virtual_modifier (AtspiDeviceX11 *x11_device, gint keycode, gboolean enabled) +{ + AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (x11_device); + guint modifier = find_virtual_mapping (x11_device, keycode); + GSList *l; + + if (!modifier) + return; + + if (enabled) + { + if (priv->virtual_mods_enabled & modifier) + return; + priv->virtual_mods_enabled |= modifier; + } + else + { + if (!(priv->virtual_mods_enabled & modifier)) + return; + priv->virtual_mods_enabled &= ~modifier; + } + + for (l = priv->key_grabs; l; l = l->next) + { + AtspiX11KeyGrab *grab = l->data; + gboolean new_enabled = grab_should_be_enabled (x11_device, grab); + if (new_enabled && !grab->enabled) + enable_key_grab (x11_device, grab); + else if (grab->enabled && !new_enabled) + disable_key_grab (x11_device, grab); + } +} + +static gboolean +do_event_dispatch (gpointer user_data) +{ + AtspiDeviceX11 *device = user_data; + AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (device); + Display *display = priv->display; + XEvent xevent; + char text[10]; + KeySym keysym; + XComposeStatus status; + + while (XPending (display)) + { + XNextEvent (display, &xevent); + XEvent keyevent; + + switch (xevent.type) + { + case KeyPress: + case KeyRelease: + XLookupString(&xevent.xkey, text, sizeof (text), &keysym, &status); + atspi_device_notify_key (ATSPI_DEVICE (device), (xevent.type == KeyPress), xevent.xkey.keycode, keysym, xevent.xkey.state & priv->virtual_mods_enabled, text); + break; + case GenericEvent: + if (xevent.xcookie.extension == priv->xi_opcode) + { + XGetEventData(priv->display, &xevent.xcookie); + XIRawEvent *xiRawEv = (XIRawEvent *) xevent.xcookie.data; + XIDeviceEvent *xiDevEv = (XIDeviceEvent *) xevent.xcookie.data; + switch (xevent.xcookie.evtype) + { + case XI_KeyPress: + case XI_KeyRelease: + xi2keyevent (xiDevEv, &keyevent); + XLookupString((XKeyEvent *)&keyevent, text, sizeof (text), &keysym, &status); + if (text[0] < ' ') + text[0] = '\0'; + if (!priv->device_id) + priv->device_id = xiDevEv->deviceid; + set_virtual_modifier (device, xiRawEv->detail, xevent.xcookie.evtype == XI_KeyPress); + if (xiDevEv->deviceid == priv->device_id) + atspi_device_notify_key (ATSPI_DEVICE (device), (xevent.xcookie.evtype == XI_KeyPress), xiRawEv->detail, keysym, keyevent.xkey.state, text); + XFreeEventData (priv->display, &xevent.xcookie); + break; + } + } + default: + if (XFilterEvent (&xevent, None)) + continue; + } + } + return TRUE; +} + +static gboolean +event_dispatch (GSource *source, GSourceFunc callback, gpointer user_data) +{ + if (callback) + callback (user_data); + return G_SOURCE_CONTINUE; +} + +static GSourceFuncs event_funcs = { + event_prepare, + event_check, + event_dispatch, + NULL +}; + +static GSource * +display_source_new (Display *display) +{ + GSource *source = g_source_new (&event_funcs, sizeof (DisplaySource)); + DisplaySource *display_source = (DisplaySource *) source; + g_source_set_name (source, "[at-spi2-core] display_source_funcs"); + + display_source->display = display; + + return source; +} + +static void +create_event_source (AtspiDeviceX11 *device) +{ + AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (device); + DisplaySource *display_source; + + int connection_number = ConnectionNumber (priv->display); + + priv->source = display_source_new (priv->display); + display_source = (DisplaySource *)priv->source; + + g_source_set_priority (priv->source, G_PRIORITY_DEFAULT); + + display_source->event_poll_fd.fd = connection_number; + display_source->event_poll_fd.events = G_IO_IN; + + g_source_add_poll (priv->source, &display_source->event_poll_fd); + g_source_set_can_recurse (priv->source, TRUE); + g_source_set_callback (priv->source, do_event_dispatch, device, NULL); + g_source_attach (priv->source, NULL); +} + +static gboolean +check_virtual_modifier (AtspiDeviceX11 *x11_device, guint modifier) +{ + AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (x11_device); + GSList *l; + + for (l = priv->modifiers; l; l = l->next) + { + AtspiX11KeyModifier *entry = l->data; + if (entry->modifier == modifier) + return TRUE; + } + + return FALSE; +} + +static guint +get_unused_virtual_modifier (AtspiDeviceX11 *x11_device) +{ + guint ret = 0x10000; + + while (ret) + { + if (!check_virtual_modifier (x11_device, ret)) + return ret; + ret <<= 1; + } + + return 0; +} + +static guint +atspi_device_x11_map_modifier (AtspiDevice *device, gint keycode) +{ + AtspiDeviceX11 *x11_device = ATSPI_DEVICE_X11 (device); + AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (x11_device); + XkbDescPtr desc; + guint ret; + AtspiX11KeyModifier *entry; + + desc = XkbGetMap (priv->display, XkbModifierMapMask, XkbUseCoreKbd); + + if (keycode < desc->min_key_code || keycode >= desc->max_key_code) + { + XkbFreeKeyboard (desc, XkbModifierMapMask, TRUE); + g_warning ("Passed invalid keycode %d", keycode); + return 0; + } + + ret = desc->map->modmap[keycode]; + XkbFreeKeyboard (desc, XkbModifierMapMask, TRUE); + if (ret & (ShiftMask | ControlMask)) + return ret; + + ret = find_virtual_mapping (x11_device, keycode); + if (ret) + return ret; + + ret = get_unused_virtual_modifier (x11_device); + + entry = g_new (AtspiX11KeyModifier, 1); + entry->keycode = keycode; + entry->modifier = ret; + priv->modifiers = g_slist_append (priv->modifiers, entry); + + return ret; +} + +static void +atspi_device_x11_unmap_modifier (AtspiDevice *device, gint keycode) +{ + AtspiDeviceX11 *x11_device = ATSPI_DEVICE_X11 (device); + AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (x11_device); + GSList *l; + + for (l = priv->modifiers; l; l = l->next) + { + AtspiX11KeyModifier *entry = l->data; + if (entry->keycode == keycode) + { + g_free (entry); + priv->modifiers = g_slist_remove (priv->modifiers, entry); + return; + } + } +} + +static guint +atspi_device_x11_get_modifier (AtspiDevice *device, gint keycode) +{ + AtspiDeviceX11 *x11_device = ATSPI_DEVICE_X11 (device); + AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (x11_device); + XkbDescPtr desc; + guint ret; + + desc = XkbGetMap (priv->display, XkbModifierMapMask, XkbUseCoreKbd); + + if (keycode < desc->min_key_code || keycode >= desc->max_key_code) + { + XkbFreeKeyboard (desc, XkbModifierMapMask, TRUE); + g_warning ("Passed invalid keycode %d", keycode); + return 0; + } + + ret = desc->map->modmap[keycode]; + XkbFreeKeyboard (desc, XkbModifierMapMask, TRUE); + if (ret) + return ret; + + return find_virtual_mapping (x11_device, keycode); +} + +static void +atspi_device_x11_init (AtspiDeviceX11 *device) +{ + AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (device); + int first_event, first_error; + + priv->display=XOpenDisplay(""); + g_return_if_fail (priv->display != NULL); + priv->window = DefaultRootWindow(priv->display); + + if (XQueryExtension(priv->display, "XInputExtension", &priv->xi_opcode, &first_event, &first_error)) + { + int major = 2; + int minor = 1; + if (XIQueryVersion(priv->display, &major, &minor) != BadRequest) + { + XIEventMask eventmask; + unsigned char mask[XIMaskLen (XI_LASTEVENT)] = { 0 }; + + eventmask.deviceid = XIAllDevices; + eventmask.mask_len = sizeof(mask); + eventmask.mask = mask; + + XISetMask (mask, XI_KeyPress); + XISetMask (mask, XI_KeyRelease); + XISetMask (mask, XI_ButtonPress); + XISetMask (mask, XI_ButtonRelease); + XISetMask (mask, XI_Motion); + XISelectEvents (priv->display, priv->window, &eventmask, 1); + create_event_source (device); + } + } +} + +static void +atspi_device_x11_finalize (GObject *object) +{ + AtspiDeviceX11 *device = ATSPI_DEVICE_X11 (object); + AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (device); + GSList *l; + + for (l = priv->key_grabs; l; l = l->next) + { + AtspiX11KeyGrab *grab = l->data; + disable_key_grab (device, grab); + g_boxed_free (ATSPI_TYPE_KEY_DEFINITION, grab->kd); + g_free (grab); + } + g_slist_free (priv->key_grabs); + priv->key_grabs = NULL; + + g_slist_free_full (priv->modifiers, g_free); + priv->modifiers = NULL; + + if (priv->source) + { + g_source_destroy ((GSource *) priv->source); + g_source_unref ((GSource *) priv->source); + priv->source = NULL; + } + + device_x11_parent_class->finalize (object); +} + + +static void +atspi_device_x11_add_key_grab (AtspiDevice *device, AtspiKeyDefinition *kd) +{ + AtspiDeviceX11 *x11_device = ATSPI_DEVICE_X11 (device); + AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (x11_device); + AtspiX11KeyGrab *grab; + + grab = g_new (AtspiX11KeyGrab, 1); + grab->kd = g_boxed_copy (ATSPI_TYPE_KEY_DEFINITION, kd); + grab->enabled = FALSE; + priv->key_grabs = g_slist_append (priv->key_grabs, grab); + if (grab_should_be_enabled (x11_device, grab)) + enable_key_grab (x11_device, grab); +} + +static void +atspi_device_x11_remove_key_grab (AtspiDevice *device, guint id) +{ + AtspiDeviceX11 *x11_device = ATSPI_DEVICE_X11 (device); + AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (x11_device); + AtspiKeyDefinition *kd; + GSList *l; + + kd = atspi_device_get_grab_by_id (device, id); + + for (l = priv->key_grabs; l; l = g_slist_next (l)) + { + AtspiX11KeyGrab *other = l->data; + if (other->kd->keycode == kd->keycode && other->kd->modifiers == kd->modifiers) + { + disable_key_grab (x11_device, other); + priv->key_grabs = g_slist_remove (priv->key_grabs, other); + return; + } + } +} + +static guint +atspi_device_x11_get_locked_modifiers (AtspiDevice *device) +{ + AtspiDeviceX11 *x11_device = ATSPI_DEVICE_X11 (device); + AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (x11_device); + XkbStateRec state_rec; + + memset (&state_rec, 0, sizeof (state_rec)); + XkbGetState (priv->display, XkbUseCoreKbd, &state_rec); + return state_rec.locked_mods; +} + +static gboolean +atspi_device_x11_grab_keyboard (AtspiDevice *device) +{ + AtspiDeviceX11 *x11_device = ATSPI_DEVICE_X11 (device); + AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (x11_device); + int result; + + g_return_val_if_fail (priv->display != NULL, FALSE); + result = XGrabKeyboard (priv->display, priv->window, TRUE, GrabModeAsync, GrabModeSync, CurrentTime); + return (result == 0); +} + +static void +atspi_device_x11_ungrab_keyboard (AtspiDevice *device) +{ + AtspiDeviceX11 *x11_device = ATSPI_DEVICE_X11 (device); + AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (x11_device); + + g_return_if_fail (priv->display != NULL); + XUngrabKeyboard (priv->display, CurrentTime); +} + +static void +atspi_device_x11_class_init (AtspiDeviceX11Class *klass) +{ + AtspiDeviceClass *device_class = ATSPI_DEVICE_CLASS (klass); + GObjectClass *object_class = (GObjectClass *) klass; + + device_x11_parent_class = g_type_class_peek_parent (klass); + device_class->add_key_grab = atspi_device_x11_add_key_grab; + device_class->map_modifier = atspi_device_x11_map_modifier; + device_class->unmap_modifier = atspi_device_x11_unmap_modifier; + device_class->get_modifier = atspi_device_x11_get_modifier; + device_class->remove_key_grab = atspi_device_x11_remove_key_grab; + device_class->get_locked_modifiers = atspi_device_x11_get_locked_modifiers; + device_class->grab_keyboard = atspi_device_x11_grab_keyboard; + device_class->ungrab_keyboard = atspi_device_x11_ungrab_keyboard; + object_class->finalize = atspi_device_x11_finalize; +} + +/** + * atspi_device_x11_new: + * + * Creates a new #AtspiDeviceX11. + * + * Returns: (transfer full): a pointer to a newly-created #AtspiDeviceX11. + * + **/ +AtspiDeviceX11 * +atspi_device_x11_new () +{ + AtspiDeviceX11 *device = g_object_new (atspi_device_x11_get_type (), NULL); + + return device; +} diff --git a/atspi/atspi-device-x11.h b/atspi/atspi-device-x11.h new file mode 100644 index 00000000..3a91edca --- /dev/null +++ b/atspi/atspi-device-x11.h @@ -0,0 +1,59 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2020 SUSE LLC. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _ATSPI_DEVICE_X11_H_ +#define _ATSPI_DEVICE_X11_H_ + +#include "glib-object.h" + +#include "atspi-types.h" +#include "atspi-device.h" + +G_BEGIN_DECLS + +#define ATSPI_TYPE_DEVICE_X11 (atspi_device_x11_get_type ()) +#define ATSPI_DEVICE_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_DEVICE_X11, AtspiDeviceX11)) +#define ATSPI_DEVICE_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_DEVICE_X11, AtspiDeviceX11Class)) +#define ATSPI_IS_DEVICE_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_DEVICE_X11)) +#define ATSPI_IS_DEVICE_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_DEVICE_X11)) +#define ATSPI_DEVICE_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_DEVICE_X11, AtspiDeviceX11Class)) + +typedef struct _AtspiDeviceX11 AtspiDeviceX11; +struct _AtspiDeviceX11 +{ + AtspiDevice parent; +}; + +typedef struct _AtspiDeviceX11Class AtspiDeviceX11Class; +struct _AtspiDeviceX11Class +{ + AtspiDeviceClass parent_class; +}; + +GType atspi_device_x11_get_type (void); + +AtspiDeviceX11 *atspi_device_x11_new (); + +G_END_DECLS + +#endif /* _ATSPI_DEVICE_X11_H_ */ diff --git a/atspi/atspi-device.c b/atspi/atspi-device.c new file mode 100644 index 00000000..abf6138d --- /dev/null +++ b/atspi/atspi-device.c @@ -0,0 +1,400 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2020 SUSE LLC. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "atspi-private.h" +#include "atspi-device.h" +#include "atspi-device-legacy.h" +#include "atspi-device-x11.h" + +typedef struct +{ + guint id; + guint keycode; + guint keysym; + guint modifiers; + AtspiKeyCallback callback; + void *callback_data; + GDestroyNotify callback_destroyed; +} AtspiKeyGrab; + +typedef struct _AtspiDevicePrivate AtspiDevicePrivate; +struct _AtspiDevicePrivate +{ + GSList *key_watchers; + GSList *keygrabs; + guint last_grab_id; +}; + +GObjectClass *device_parent_class; + +static void +atspi_device_init (AtspiDevice *device) +{ +} + +G_DEFINE_TYPE_WITH_CODE (AtspiDevice, atspi_device, + G_TYPE_OBJECT, + G_ADD_PRIVATE (AtspiDevice)) + +static void +atspi_device_finalize (GObject *object) +{ + AtspiDevice *device = (AtspiDevice *) object; + AtspiDevicePrivate *priv = atspi_device_get_instance_private (device); + + g_slist_free_full (priv->keygrabs, g_free); + priv->keygrabs = NULL; + + device_parent_class->finalize (object); +} + +static void +atspi_device_real_add_key_grab (AtspiDevice *device, AtspiKeyDefinition *kd) +{ +} + +static void +atspi_device_real_remove_key_grab (AtspiDevice *device, guint id) +{ +} + +static void +atspi_device_class_init (AtspiDeviceClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + + device_parent_class = g_type_class_peek_parent (klass); + klass->add_key_grab = atspi_device_real_add_key_grab; + klass->remove_key_grab = atspi_device_real_remove_key_grab; + object_class->finalize = atspi_device_finalize; +} + +/** + * atspi_device_new: + * + * Creates a new #AtspiDevice with a specified callback function. + * + * Returns: (transfer full): a pointer to a newly-created #AtspiDevice. + * + **/ +AtspiDevice * +atspi_device_new () +{ + //if (!g_getenv ("WAYLAND_DISPLAY") && !g_getenv ("ATSPI_USE_LEGACY_DEVICE")) +#ifdef HAVE_X11 + if (!g_getenv ("ATSPI_USE_LEGACY_DEVICE")) + return ATSPI_DEVICE (atspi_device_x11_new ()); +#endif + + return ATSPI_DEVICE (atspi_device_legacy_new ()); +} + +gboolean +atspi_device_notify_key (AtspiDevice *device, gboolean pressed, int keycode, int keysym, gint state, gchar *text) +{ + AtspiDevicePrivate *priv = atspi_device_get_instance_private (device); + GSList *l; + gboolean ret = FALSE; + + for (l = priv->key_watchers; l; l = l->next) + { + AtspiKeyGrab *grab = l->data; + grab->callback (device, pressed, keycode, keysym, state, text, grab->callback_data); + } + + for (l = priv->keygrabs; l; l = l->next) + { + AtspiKeyGrab *grab = l->data; + //if (keycode == grab->keycode && (grab->modifiers & state) == grab->modifiers) + if (keycode == grab->keycode && grab->modifiers == state) + { + if (grab->callback) + grab->callback (device, pressed, keycode, keysym, state, text, grab->callback_data); + ret = TRUE; + } + } + + return ret; +} + +static gboolean +is_id_used (AtspiDevice *device, guint id) +{ + AtspiDevicePrivate *priv = atspi_device_get_instance_private (device); + GSList *l; + + for (l = priv->key_watchers; l; l = l->next) + { + AtspiKeyGrab *grab = l->data; + if (grab->id == id) + return TRUE; + } + + for (l = priv->keygrabs; l; l = l->next) + { + AtspiKeyGrab *grab = l->data; + if (grab->id == id) + return TRUE; + } + + return FALSE; +} + +static guint +get_grab_id (AtspiDevice *device) +{ + AtspiDevicePrivate *priv = atspi_device_get_instance_private (device); + + while (is_id_used (device, priv->last_grab_id)) priv->last_grab_id++; + return priv->last_grab_id++; +} + +static gboolean +grab_has_duplicate (AtspiDevice *device, AtspiKeyGrab *grab) +{ + AtspiDevicePrivate *priv = atspi_device_get_instance_private (device); + GSList *l; + + for (l = priv->keygrabs; l; l = l->next) + { + AtspiKeyGrab *other_grab = l->data; + if (other_grab->id != grab->id && other_grab->keycode == grab->keycode && other_grab->modifiers == grab->modifiers) + return TRUE; + } + + return FALSE; +} + +/** + *atspi_device_add_key_grab: +* @device: the device. + * @kd: a #AtspiKeyDefinition specifying the key code to grab. + * @callback: (scope notified) (allow-none): the function to call when the + * given key is pressed. + * @user_data: Data to be passed to @callback. + * @callback_destroyed: callback function to be called when @callback is + * destroyed. + * + * Returns: an identifier that can be later used to remove the grab. + * Add a key grab for the given key/modifier combination. + */ +guint +atspi_device_add_key_grab (AtspiDevice *device, AtspiKeyDefinition *kd, AtspiKeyCallback callback, void *user_data, GDestroyNotify callback_destroyed) +{ + AtspiDevicePrivate *priv = atspi_device_get_instance_private (device); + AtspiKeyGrab *grab = g_new (AtspiKeyGrab, 1); + grab->keycode = kd->keycode; + grab->keysym = kd->keysym; + grab->modifiers = kd->modifiers; + grab->callback = callback; + grab->callback_data = user_data; + grab->callback_destroyed = callback_destroyed; + grab->id = get_grab_id (device); + priv->keygrabs = g_slist_append (priv->keygrabs, grab); + + if (!grab_has_duplicate (device, grab)) + ATSPI_DEVICE_GET_CLASS (device)->add_key_grab (device, kd); + return grab->id; +} + +/** + * atspi_device_remove_key_grab: + * @device: the device. + * @id: the identifier of the grab to be removed. + * + * Removes the key grab specified by @id. + */ +void +atspi_device_remove_key_grab (AtspiDevice *device, guint id) +{ + AtspiDevicePrivate *priv = atspi_device_get_instance_private (device); + GSList *l; + + for (l = priv->keygrabs; l; l = l->next) + { + AtspiKeyGrab *grab = l->data; + if (grab->id == id) + { + if (!grab_has_duplicate (device, grab)) + ATSPI_DEVICE_GET_CLASS (device)->remove_key_grab (device, id); + priv->keygrabs = g_slist_remove (priv->keygrabs, grab); + if (grab->callback_destroyed) + (*grab->callback_destroyed) (grab->callback); + g_free (grab); + return; + } + } +} + +/** + *atspi_device_add_key_watcher: +* @device: the device. + * @callback: (scope notified): the function to call when the given key is + * pressed. + * @user_data: (closure callback): Data to be passed to @callback. + * @callback_destroyed: (destroy callback): callback function to be called + * when @callback is destroyed. + * + * Add a callback that will receive a notification whenever a key is + * pressed or released. + */ +void +atspi_device_add_key_watcher (AtspiDevice *device, AtspiKeyCallback callback, void *user_data, GDestroyNotify callback_destroyed) +{ + AtspiDevicePrivate *priv = atspi_device_get_instance_private (device); + AtspiKeyGrab *grab = g_new0 (AtspiKeyGrab, 1); + grab->id = get_grab_id (device); + grab->callback = callback; + grab->callback_data = user_data; + grab->callback_destroyed = callback_destroyed; + priv->key_watchers = g_slist_append (priv->key_watchers, grab); +} + +AtspiKeyDefinition * +atspi_device_get_grab_by_id (AtspiDevice *device, guint id) +{ + AtspiDevicePrivate *priv = atspi_device_get_instance_private (device); + GSList *l; + + for (l = priv->keygrabs; l; l = l->next) + { + AtspiKeyGrab *grab = l->data; + if (grab->id == id) + { + AtspiKeyDefinition *kd = g_new0 (AtspiKeyDefinition, 1); + kd->keycode = grab->keycode;\ + kd->modifiers = grab->modifiers; + return kd; + } + } + return NULL; +} + +/** + * atspi_device_map_modifier: + * @device: the device. + * @keycode: the keycode to map. + * + * Maps the specified key code to a modifier so that it can be used in + * conjunction with other keys to create a key grab. If the given keycode is + * already mapped, then this function will return the modifier that is + * currently mapped to the keycode, without doing anything else. Otherwise, + * it will use the last modifier that AT-SPI used to map a key. If no keys + * have yet been mapped using this device, then it will look for a modifier + * that is not currently being used. If no unused modifier can be found, + * then it will use the first modifier by default. + * + * Returns: the modifier that is now mapped to this keycode. This return + * value can be passed to atspi_device_add_key_grab. + */ +guint +atspi_device_map_modifier (AtspiDevice *device, gint keycode) +{ + if (ATSPI_DEVICE_GET_CLASS (device)->map_modifier) + return ATSPI_DEVICE_GET_CLASS (device)->map_modifier (device, keycode); + + return 0; +} + +/** + * atspi_device_unmap_modifier: + * @device: the device. + * @keycode: the keycode to unmap. + * + * Removes a mapped modifier from the given keycode. + */ +void +atspi_device_unmap_modifier (AtspiDevice *device, gint keycode) +{ + if (ATSPI_DEVICE_GET_CLASS (device)->unmap_modifier) + ATSPI_DEVICE_GET_CLASS (device)->unmap_modifier (device, keycode); +} + +/** + * atspi_device_get_modifier: + * @device: the device. + * @keycode: the keycode to map. + * + * Gets the modifier for a given keycode, if one exists. Does not creatt a new + * mapping. This function should be used when the intention is to query a + * locking modifier such as num lock via atspi_device_get_locked_modifiers, + * rather than to add key grabs. + * + * Returns: the modifier that is mapped to this keycode. + */ +guint +atspi_device_get_modifier (AtspiDevice *device, gint keycode) +{ + if (ATSPI_DEVICE_GET_CLASS (device)->get_modifier) + return ATSPI_DEVICE_GET_CLASS (device)->get_modifier (device, keycode); + + return 0; +} + +/** + * atspi_device_get_locked_modifiers: + * @device: the device. + * + * Returns the locked modifiers (ie, num lock, caps lock) associated with this + * keyboard. + * + * Returns: a guint of modifier flags. + */ +guint +atspi_device_get_locked_modifiers (AtspiDevice *device) +{ + if (ATSPI_DEVICE_GET_CLASS (device)->get_locked_modifiers) + return ATSPI_DEVICE_GET_CLASS (device)->get_locked_modifiers (device); + + return 0; +} + +/** + * atspi_device_grab_keyboard: + * + * Attempts to grab the entire keyboard. This should only be done + * temporarily, as it may conflict with other applications that also want to + * grab the keyboard. + * + * Returns: #TRUE if successful, #FALSE otherwise. + */ +gboolean +atspi_device_grab_keyboard (AtspiDevice *device) +{ + if (ATSPI_DEVICE_GET_CLASS (device)->grab_keyboard) + return ATSPI_DEVICE_GET_CLASS (device)->grab_keyboard (device); + + return FALSE; +} + +/** + * atspi_device_ungrab_keyboard: + * + * Removes a keyboard grab added via a call to atspi_device_add_keyboard. + */ +void +atspi_device_ungrab_keyboard (AtspiDevice *device) +{ + if (ATSPI_DEVICE_GET_CLASS (device)->ungrab_keyboard) + ATSPI_DEVICE_GET_CLASS (device)->ungrab_keyboard (device); +} + diff --git a/atspi/atspi-device.h b/atspi/atspi-device.h new file mode 100644 index 00000000..a246842a --- /dev/null +++ b/atspi/atspi-device.h @@ -0,0 +1,103 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2020 SUSE LLC. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _ATSPI_DEVICE_H_ +#define _ATSPI_DEVICE_H_ + +#include "glib-object.h" + +#include "atspi-types.h" + +G_BEGIN_DECLS + +#define ATSPI_TYPE_DEVICE (atspi_device_get_type ()) +#define ATSPI_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_DEVICE, AtspiDevice)) +#define ATSPI_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_DEVICE, AtspiDeviceClass)) +#define ATSPI_IS_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_DEVICE)) +#define ATSPI_IS_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_DEVICE)) +#define ATSPI_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_DEVICE, AtspiDeviceClass)) + +typedef struct _AtspiDevice AtspiDevice; +struct _AtspiDevice +{ + GObject parent; +}; + +typedef struct _AtspiDeviceClass AtspiDeviceClass; +struct _AtspiDeviceClass +{ + GObjectClass parent_class; + + void (*add_key_grab) (AtspiDevice *device, AtspiKeyDefinition *kd); + void (*remove_key_grab) (AtspiDevice *device, guint id); + guint (*map_modifier) (AtspiDevice *device, gint keycode); + void (*unmap_modifier) (AtspiDevice *device, gint keycode); + guint (*get_modifier) (AtspiDevice *device, gint keycode); + gboolean (*grab_keyboard) (AtspiDevice *device); + void (*ungrab_keyboard) (AtspiDevice *device); + guint (*get_locked_modifiers) (AtspiDevice *device); +}; + +GType atspi_device_get_type (void); + +/** + * AtspiKeyCallback: + * @device: the device. + * @pressed: TRUE if the key is being pressed, FALSE if being released. + * @keycode: the hardware code for the key. + * @keysym: the keysym for the key. + * @modifiers: a bitflag indicating which key modifiers are active. + * @keystring: the text corresponding to the keypress. + * @user_data: (closure): user-supplied data + * + * A callback that will be invoked when a key is pressed. + */ +typedef void (*AtspiKeyCallback) (AtspiDevice *device, gboolean pressed, guint keycode, guint keysym, guint modifiers, const gchar *keystring, void *user_data); + +AtspiDevice *atspi_device_new (); + +gboolean atspi_device_notify_key (AtspiDevice *device, gboolean pressed, int keycode, int keysym, gint state, gchar *text); + +guint atspi_device_add_key_grab (AtspiDevice *device, AtspiKeyDefinition *kd, AtspiKeyCallback callback, void *user_data, GDestroyNotify callback_destroyed); + +void atspi_device_remove_key_grab (AtspiDevice *device, guint id); + +void atspi_device_add_key_watcher (AtspiDevice *device, AtspiKeyCallback callback, void *user_data, GDestroyNotify callback_destroyed); + +AtspiKeyDefinition *atspi_device_get_grab_by_id (AtspiDevice *device, guint id); + +guint atspi_device_map_modifier (AtspiDevice *device, gint keycode); + +void atspi_device_unmap_modifier (AtspiDevice *device, gint keycode); + +guint atspi_device_get_modifier (AtspiDevice *device, gint keycode); + +guint atspi_device_get_locked_modifiers (AtspiDevice *device); + +gboolean atspi_device_grab_keyboard (AtspiDevice *device); + +void atspi_device_ungrab_keyboard (AtspiDevice *device); + +G_END_DECLS + +#endif /* _ATSPI_DEVICE_H_ */ diff --git a/atspi/atspi-registry.c b/atspi/atspi-registry.c index ca2a6c3e..dea5878e 100644 --- a/atspi/atspi-registry.c +++ b/atspi/atspi-registry.c @@ -556,7 +556,7 @@ atspi_key_definition_copy (AtspiKeyDefinition *src) dst->keysym = src->keysym; if (src->keystring) dst->keystring = g_strdup (src->keystring); - dst->unused = src->unused; + dst->modifiers = src->modifiers; return dst; } diff --git a/atspi/atspi-types.h b/atspi/atspi-types.h index 2631baf7..ab43ca8c 100644 --- a/atspi/atspi-types.h +++ b/atspi/atspi-types.h @@ -78,9 +78,16 @@ struct _AtspiKeyDefinition gint keycode; gint keysym; gchar *keystring; - gint unused; + guint modifiers; }; +/** + * ATSPI_TYPE_KEY_DEFINITION: + * + * The #GType for a boxed type holding a #AtspiKeyDefinition. + */ +#define ATSPI_TYPE_KEY_DEFINITION (atspi_key_definition_get_type ()) + typedef struct _AtspiEvent AtspiEvent; struct _AtspiEvent { diff --git a/atspi/meson.build b/atspi/meson.build index 5797f73a..a6f12384 100644 --- a/atspi/meson.build +++ b/atspi/meson.build @@ -4,6 +4,8 @@ atspi_sources = [ 'atspi-application.c', 'atspi-collection.c', 'atspi-component.c', + 'atspi-device.c', + 'atspi-device-legacy.c', 'atspi-device-listener.c', 'atspi-document.c', 'atspi-editabletext.c', @@ -26,6 +28,13 @@ atspi_sources = [ 'atspi-value.c', ] +x11_option = get_option('x11') +if x11_option != 'no' + if x11_dep.found() + atspi_sources += ['atspi-device-x11.c'] + endif +endif + atspi_headers = [ 'atspi.h', 'atspi-accessible.h', @@ -34,7 +43,10 @@ atspi_headers = [ 'atspi-collection.h', 'atspi-component.h', 'atspi-constants.h', + 'atspi-device.h', + 'atspi-device-legacy.h', 'atspi-device-listener.h', + 'atspi-device-x11.h', 'atspi-document.h', 'atspi-editabletext.h', 'atspi-event-listener.h', |