*
* (other object events)
*
-- * object:state-changed
++ * object:state-changed
* object:children-changed
* object:visible-data-changed
* object:selection-changed
* mouse:b3p
* mouse:b3r
*
-- * NOTE: this character string may be UTF-8, but should not contain byte
++ * NOTE: this character string may be UTF-8, but should not contain byte
* value 56
* (ascii ':'), except as a delimiter, since non-UTF-8 string
* delimiting functions are used internally.
/**
* atspi_event_listener_register_from_callback:
-- * @callback: (scope notified): the #AtspiEventListenerCB to be registered
++ * @callback: (scope notified): the #AtspiEventListenerCB to be registered
* against an event type.
* @user_data: (closure): User data to be passed to the callback.
* @callback_destroyed: A #GDestroyNotify called when the callback is destroyed.
* @event_type: a character string indicating the type of events for which
* notification is requested. See #atspi_event_listener_register
* for a description of the format.
-- *
++ *
* Registers an #AtspiEventListenerCB against an @event_type.
*
* Returns: #TRUE if successfull, otherwise #FALSE.
* and toolkit events (e.g. "Gtk", "AWT").
* Examples: "focus:", "Gtk:GtkWidget:button_press_event".
*
-- * Registers an #AtspiEventListenetSimpleCB. The method is similar to
++ * Registers an #AtspiEventListenetSimpleCB. The method is similar to
* #atspi_event_listener_register, but @callback takes no user_data.
*
* Returns: #TRUE if successfull, otherwise #FALSE.
{
return FALSE;
}
+ path = _atspi_device_listener_get_path (listener);
+ dbus_error_init (&d_error);
+
+ path = _atspi_device_listener_get_path (listener);
+
/* copy the keyval filter values from the C api into the DBind KeySet */
if (key_set)
{
{
return retval;
}
+ path = _atspi_device_listener_get_path (listener);
+ dbus_error_init (&d_error);
+
+ path = _atspi_device_listener_get_path (listener);
+
dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "RegisterDeviceEventListener", &d_error, "ou=>b", path, d_event_types, &retval);
if (dbus_error_is_set (&d_error))
{
{
return FALSE;
}
+ path = _atspi_device_listener_get_path (listener);
+ dbus_error_init (&d_error);
+
+ path = _atspi_device_listener_get_path (listener);
+
event_types |= (1 << ATSPI_BUTTON_PRESSED_EVENT);
event_types |= (1 << ATSPI_BUTTON_RELEASED_EVENT);
#ifdef DBUS_BROKER
#include <systemd/sd-login.h>
#endif
+ #include <sys/stat.h>
+//TODO: move to vconf/vconf-internal-setting-keys.h?
+#define VCONFKEY_SETAPPL_ACCESSIBILITY_UNIVERSAL_SWITCH_CONFIGURATION_SERVICE "db/setting/accessibility/universal-switch/configuration-service"
+#define VCONFKEY_SETAPPL_ACCESSIBILITY_UNIVERSAL_SWITCH_INTERACTION_SERVICE "db/setting/accessibility/universal-switch/interaction-service"
+
+#define MAX_NUMBER_OF_KEYS_PER_CLIENT 2
+
+#define APP_CONTROL_OPERATION_SCREEN_READ "http://tizen.org/appcontrol/operation/read_screen"
+#define APP_CONTROL_OPERATION_UNIVERSAL_SWITCH "http://tizen.org/appcontrol/operation/universal_switch"
+#include <appsvc.h>
+#include <vconf.h>
+
+//uncomment if you want debug
+//#ifndef TIZEN_ENGINEER_MODE
+//#define TIZEN_ENGINEER_MODE
+//#endif
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "ATSPI_BUS_LAUNCHER"
+
+#include <dlog.h>
+#include <aul.h>
+
+//uncomment this if you want log suring startup
+//seems like dlog is not working at startup time
+#define ATSPI_BUS_LAUNCHER_LOG_TO_FILE
+
+#ifdef ATSPI_BUS_LAUNCHER_LOG_TO_FILE
+FILE *log_file;
+#ifdef LOGD
+#undef LOGD
+#endif
+#define LOGD(arg...) do {if (log_file) {fprintf(log_file, ##arg);fprintf(log_file, "\n"); fflush(log_file);}} while(0)
+#endif
+
+static gboolean _launch_process_repeat_until_success(gpointer user_data);
+
typedef enum {
A11Y_BUS_STATE_IDLE = 0,
A11Y_BUS_STATE_READING_ADDRESS,
GDBusProxy *client_proxy;
A11yBusState state;
+
/* -1 == error, 0 == pending, > 0 == running */
- int a11y_bus_pid;
+ GPid a11y_bus_pid;
+ char *socket_name;
char *a11y_bus_address;
#ifdef HAVE_X11
gboolean x11_prop_set;
static gboolean
ensure_a11y_bus_daemon (A11yBusLauncher *app, char *config_path)
{
- char *argv[] = { DBUS_DAEMON, config_path, "--nofork", "--print-address", "3", NULL };
- GPid pid;
- char addr_buf[2048];
- GError *error = NULL;
+ char *address_param;
+
+ if (app->socket_name)
+ {
+ gchar *escaped_address = g_dbus_address_escape_value (app->socket_name);
+ address_param = g_strconcat ("--address=unix:path=", escaped_address, NULL);
+ g_free (escaped_address);
+ }
+ else
+ {
+ address_param = NULL;
+ }
- argv[1] = (char*)config_path;
-
+ if (app->a11y_bus_pid != 0)
+ return FALSE;
+
if (pipe (app->pipefd) < 0)
- g_error ("Failed to create pipe: %s", strerror (errno));
+ {
+ char buf[4096] = { 0 };
+ strerror_r (errno, buf, sizeof(buf));
+ g_error ("Failed to create pipe: %s", buf);
+ }
+ char *print_address_fd_param = g_strdup_printf ("%d", app->pipefd[1]);
+
+ char *argv[] = { DBUS_DAEMON, config_path, "--nofork", "--print-address", print_address_fd_param, address_param, NULL };
+ gint source_fds[1] = { app->pipefd[1] };
+ gint target_fds[1] = { app->pipefd[1] };
+ G_STATIC_ASSERT (G_N_ELEMENTS (source_fds) == G_N_ELEMENTS (target_fds));
+ GPid pid;
+ char addr_buf[2048];
+ GError *error = NULL;
+ char *error_from_read;
+
g_clear_pointer (&app->a11y_launch_error_message, g_free);
- if (!g_spawn_async (NULL,
- argv,
- NULL,
- G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
- setup_bus_child_daemon,
- app,
- &pid,
- &error))
+ if (!g_spawn_async_with_pipes_and_fds (NULL,
+ (const gchar * const *) argv,
+ NULL,
+ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_LEAVE_DESCRIPTORS_OPEN,
+ NULL, /* child_setup */
+ app,
+ -1, /* stdin_fd */
+ -1, /* stdout_fd */
+ -1, /* stdout_fd */
+ source_fds,
+ target_fds,
+ G_N_ELEMENTS (source_fds), /* n_fds in source_fds and target_fds */
+ &pid,
+ NULL, /* stdin_pipe_out */
+ NULL, /* stdout_pipe_out */
+ NULL, /* stderr_pipe_out */
+ &error))
{
app->a11y_bus_pid = -1;
app->a11y_launch_error_message = g_strdup (error->message);
}
if ((app->listenfd = socket (PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0)) < 0)
- g_error ("Failed to create listening socket: %s", strerror (errno));
+ {
+ char buf[4096] = { 0 };
+ strerror_r (errno, buf, sizeof(buf));
+ g_error ("Failed to create listening socket: %s", buf);
+ }
- if (bind (app->listenfd, (struct sockaddr *)&addr, sizeof(sa_family_t)) < 0)
- {
- char buf[4096] = { 0 };
- strerror_r (errno, buf, sizeof(buf));
- g_error ("Failed to bind listening socket: %s", buf);
- }
+ if (bind (app->listenfd, (struct sockaddr *)&addr, addr_len) < 0)
+ g_error ("Failed to bind listening socket: %s", strerror (errno));
- if (getsockname (app->listenfd, (struct sockaddr *)&addr, &addr_len) < 0)
- {
- char buf[4096] = { 0 };
- strerror_r (errno, buf, sizeof(buf));
- g_error ("Failed to get socket name for listening socket: %s", buf);
- }
+ if (!app->socket_name &&
+ getsockname (app->listenfd, (struct sockaddr *)&addr, &addr_len) < 0)
+ g_error ("Failed to get socket name for listening socket: %s", strerror(errno));
if (listen (app->listenfd, 1024) < 0)
- g_error ("Failed to listen on socket: %s", strerror(errno));
+ {
+ char buf[4096] = { 0 };
+ strerror_r (errno, buf, sizeof(buf));
+ g_error ("Failed to listen on socket: %s", buf);
+ }
g_clear_pointer (&app->a11y_launch_error_message, g_free);
{
#if GLIB_CHECK_VERSION (2, 32, 0)
GSettingsSchemaSource *source = g_settings_schema_source_get_default ();
- if (!source) return NULL;
+ if (!source)
+ {
- g_error ("Cannot get the default GSettingsSchemaSource - is the gsettings-desktop-schemas package installed?");
++ g_critical ("Cannot get the default GSettingsSchemaSource - is the gsettings-desktop-schemas package installed?");
+ }
GSettingsSchema *schema = g_settings_schema_source_lookup (source, name, FALSE);
gboolean screen_reader_set = FALSE;
gint i;
- _global_app = g_slice_new0 (A11yBusLauncher);
+ _global_app = g_new0 (A11yBusLauncher, 1);
_global_app->loop = g_main_loop_new (NULL, FALSE);
+ _global_app->client_watcher_id = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+
+ _global_app->screen_reader.name = "screen-reader";
+ _global_app->screen_reader.app_control_operation = APP_CONTROL_OPERATION_SCREEN_READ;
+ _global_app->screen_reader.vconf_key[0] = VCONFKEY_SETAPPL_ACCESSIBILITY_TTS;
+ _global_app->screen_reader.number_of_keys = 1;
+
+ _global_app->universal_switch.name = "universal-switch";
+ _global_app->universal_switch.app_control_operation = APP_CONTROL_OPERATION_UNIVERSAL_SWITCH;
+ _global_app->universal_switch.vconf_key[0] = VCONFKEY_SETAPPL_ACCESSIBILITY_UNIVERSAL_SWITCH_CONFIGURATION_SERVICE;
+ _global_app->universal_switch.vconf_key[1] = VCONFKEY_SETAPPL_ACCESSIBILITY_UNIVERSAL_SWITCH_INTERACTION_SERVICE;
+ _global_app->universal_switch.number_of_keys = 2;
for (i = 1; i < argc; i++)
{
g_main_loop_run (_global_app->loop);
if (_global_app->a11y_bus_pid > 0)
- kill (_global_app->a11y_bus_pid, SIGTERM);
+ {
+ kill (_global_app->a11y_bus_pid, SIGTERM);
+ g_spawn_close_pid (_global_app->a11y_bus_pid);
+ _global_app->a11y_bus_pid = -1;
+ }
- /* Clear the X property if our bus is gone; in the case where e.g.
+ /* Clear the X property if our bus is gone; in the case where e.g.
* GDM is launching a login on an X server it was using before,
* we don't want early login processes to pick up the stale address.
*/
glib_req_version = '>= 2.62.0'
gobject_req_version = '>= 2.0.0'
gio_req_version = '>= 2.28.0'
+ gir_req_version = '>= 0.6.7'
+app_svc_req_version = '>= 0.0.0'
libdbus_dep = dependency('dbus-1', version: libdbus_req_version)
glib_dep = dependency('glib-2.0', version: glib_req_version)
--- /dev/null
- Version: 2.42.0
+%bcond_with x
+
+Name: at-spi2-core
- %doc AUTHORS README
++Version: 2.44.1
+Release: 1
+Summary: Assistive Technology Service Provider Interface - D-Bus based implementation
+License: LGPL-2.1+
+Group: System/Libraries
+Url: http://www.gnome.org/
+Source: http://ftp.gnome.org/pub/GNOME/sources/at-spi2-core/2.31/%{name}-%{version}.tar.xz
+Source1001: %{name}.manifest
+Requires: dbus
+BuildRequires: python-devel
+BuildRequires: python-xml
+BuildRequires: intltool
+BuildRequires: dbus-devel
+BuildRequires: glib2-devel
+BuildRequires: gettext
+BuildRequires: gtk-doc
+%if %{with x}
+BuildRequires: libX11-devel
+BuildRequires: libXtst-devel
+BuildRequires: libXi-devel
+%endif
+BuildRequires: pkgconfig(vconf)
+BuildRequires: pkgconfig(appsvc)
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(aul)
+BuildRequires: gobject-introspection
+BuildRequires: meson
+BuildRequires: app-svc-devel
+
+%description
+AT-SPI is a general interface for applications to make use of the
+accessibility toolkit. This version is based on dbus.
+
+This package contains the AT-SPI registry daemon. It provides a
+mechanism for all assistive technologies to discover and interact
+with applications running on the desktop.
+
+%package -n libatspi0
+Summary: An Accessibility ToolKit -- Library
+Group: System/Libraries
+
+%description -n libatspi0
+AT-SPI is a general interface for applications to make use of the
+accessibility toolkit. This version is based on dbus.
+
+%package -n typelib-1_0-Atspi-2_0
+Summary: An Accessibility ToolKit -- Introspection bindings
+Group: System/Libraries
+
+%description -n typelib-1_0-Atspi-2_0
+AT-SPI is a general interface for applications to make use of the
+accessibility toolkit. This version is based on dbus.
+
+This package provides the GObject Introspection bindings for the
+libatspi library.
+
+%package devel
+Summary: Include Files and Libraries mandatory for Development
+Group: Development/Libraries
+Requires: %{name} = %{version}
+Requires: libatspi0 = %{version}
+Requires: typelib-1_0-Atspi-2_0 = %{version}
+
+%description devel
+This package contains all necessary include files and libraries needed
+to develop applications that require these.
+
+%prep
+%setup -q
+cp %{SOURCE1001} .
+
+%build
+meson setup \
+ --prefix=/usr \
+ --libdir=%{_libdir} \
+ --default-library=shared \
+ -Ddbus_daemon=/usr/bin/dbus-daemon \
+ -Dx11=no \
+ build
+
+meson compile -C build
+
+%install
+find %{buildroot} -name '*.la' -or -name '*.a' | xargs rm -f
+
+export DESTDIR=%{buildroot}
+meson install -C build
+
+%find_lang %{name}
+
+%clean
+rm -fr %{buildroot}
+
+%post -n libatspi0 -p /sbin/ldconfig
+
+%postun -n libatspi0 -p /sbin/ldconfig
+
+%files -f %{name}.lang
+%manifest %{name}.manifest
+%defattr(-,root,root)
+%{_bindir}/at_spi2_tool
+
++%doc AUTHORS README.md
+%license COPYING
+%{_libexecdir}/at-spi-bus-launcher
+%{_libexecdir}/at-spi2-registryd
+%{_datadir}/defaults/at-spi2/accessibility.conf
+%{_sysconfdir}/xdg/autostart/at-spi-dbus-bus.desktop
+%{_datadir}/dbus-1/accessibility-services/org.a11y.atspi.Registry.service
+%{_datadir}/dbus-1/services/org.a11y.Bus.service
+%{_prefix}/lib/systemd/user/at-spi-dbus-bus.service
+%files -n libatspi0
+%manifest %{name}.manifest
+%defattr(-, root, root)
+%{_libdir}/libatspi.so.0*
+
+%files -n typelib-1_0-Atspi-2_0
+%manifest %{name}.manifest
+%defattr(-, root, root)
+
+%files devel
+%manifest %{name}.manifest
+%defattr(-, root, root)
+%{_includedir}/at-spi-2.0
+%{_libdir}/libatspi.so
+%{_libdir}/pkgconfig/atspi-2.pc
}
static guint
--spi_dec_plat_mouse_check (SpiDEController *controller,
++spi_dec_plat_mouse_check (SpiDEController *controller,
int *x, int *y, gboolean *moved)
{
SpiDEControllerClass *klass;
}
static void
--spi_dec_plat_emit_modifier_event (SpiDEController *controller, guint prev_mask,
++spi_dec_plat_emit_modifier_event (SpiDEController *controller, guint prev_mask,
guint current_mask)
{
SpiDEControllerClass *klass;
return 0;
}
else
-- {
++ {
return ((l1->mod_mask != l2->mod_mask) || (l1->key_val != l2->key_val));
}
}
mask_return = spi_dec_plat_mouse_check (controller, &x, &y, &moved);
if ((mask_return & key_modifier_mask) !=
-- (mouse_mask_state & key_modifier_mask))
++ (mouse_mask_state & key_modifier_mask))
{
spi_dec_plat_emit_modifier_event (controller, mouse_mask_state, mask_return);
mouse_mask_state = mask_return;
guint id;
id = g_timeout_add (20, spi_dec_poll_mouse_moving, data);
g_source_set_name_by_id (id, "[at-spi2-core] spi_dec_poll_mouse_moving");
-- return FALSE;
++ return FALSE;
}
}
/**
* Eventually we can use this to make the marshalling of mask types
-- * more sane, but for now we just use this to detect
++ * more sane, but for now we just use this to detect
* the use of 'virtual' masks such as numlock and convert them to
* system-specific mask values (i.e. ModMask).
-- *
++ *
**/
static Accessibility_ControllerEventMask
spi_dec_translate_mask (Accessibility_ControllerEventMask mask)
tmp_mask = mask ^ SPI_KEYMASK_NUMLOCK;
tmp_mask |= _numlock_physical_mask;
}
--
++
return tmp_mask;
}
(int) (key_listener->keys ? g_slist_length(key_listener->keys) : 0));
#endif
-- return key_listener;
++ return key_listener;
}
static DEControllerListener *
listener->path = g_strdup(path);
listener->type = SPI_DEVICE_TYPE_MOUSE;
listener->types = types;
-- return listener;
++ return listener;
}
static DEControllerListener *
static void
spi_dec_listener_free (DEControllerListener *listener)
{
-- if (listener->type == SPI_DEVICE_TYPE_KBD)
++ if (listener->type == SPI_DEVICE_TYPE_KBD)
spi_key_listener_data_free ((DEControllerKeyListener *) listener);
else
{
{
DEControllerKeyListener *key_listener;
gboolean retval;
--
++
switch (listener->type) {
case SPI_DEVICE_TYPE_KBD:
key_listener = (DEControllerKeyListener *) listener;
}
len = g_slist_length (key_set);
--
++
if (len == 0) /* special case, means "all keys/any key" */
{
#ifdef SPI_DEBUG
-- g_print ("anykey\n");
++ g_print ("anykey\n");
#endif
return TRUE;
}
for (l = key_set,i = 0; l; l = g_slist_next(l),i++)
{
Accessibility_KeyDefinition *kd = l->data;
--#ifdef SPI_KEYEVENT_DEBUG
++#ifdef SPI_KEYEVENT_DEBUG
g_print ("key_set[%d] event = %d, code = %d; key_event %d, code %d, string %s\n",
i,
(int) kd->keysym,
(int) kd->keycode,
(int) key_event->id,
(int) key_event->hw_code,
-- key_event->event_string);
++ key_event->event_string);
#endif
if (kd->keysym == (dbus_uint32_t) key_event->id)
{
{
if (((key_event->modifiers & 0xFF) == (dbus_uint16_t) (listener->mask & 0xFF)) &&
key_set_contains_key (listener->keys, key_event) &&
-- eventtype_seq_contains_event (listener->listener.types, key_event) &&
++ eventtype_seq_contains_event (listener->listener.types, key_event) &&
(is_system_global == listener->mode->global))
{
return TRUE;
is_consumed = FALSE;
for (l2 = notify; l2 && !is_consumed; l2 = l2->next)
{
-- DEControllerKeyListener *key_listener = l2->data;
++ DEControllerKeyListener *key_listener = l2->data;
is_consumed = Accessibility_DeviceEventListener_NotifyEvent (controller, controller->registry, &key_listener->listener, key_event) &&
key_listener->mode->preemptive;
for (; l2; l2 = l2->next)
{
-- DEControllerKeyListener *key_listener = l2->data;
++ DEControllerKeyListener *key_listener = l2->data;
spi_key_listener_clone_free (key_listener);
/* clone doesn't have its own ref, so don't use spi_dec_listener_free */
}
GList *l, *next;
gboolean update_failed = FALSE;
long keycode = 0;
--
++
g_return_val_if_fail (controller != NULL, FALSE);
/*
spi_grab_mask_free (grab_mask);
}
-- }
++ }
return ! update_failed;
}
!strcmp(ctx->listener->path, key_listener->listener.path))
{
/* TODO: FIXME aggregate keys in case the listener is registered twice */
-- DEControllerKeyListener *ctx_key_listener =
-- (DEControllerKeyListener *) ctx->listener;
-- keylist_free (ctx_key_listener->keys);
++ DEControllerKeyListener *ctx_key_listener =
++ (DEControllerKeyListener *) ctx->listener;
++ keylist_free (ctx_key_listener->keys);
ctx_key_listener->keys = keylist_clone(key_listener->keys);
}
* TODO: when initializing, query for XTest extension before using,
* and fall back to XSendEvent() if XTest is not available.
*/
--
++
switch (synth_type)
{
case Accessibility_KEY_PRESS:
spi_dec_plat_synth_keycode_release (controller, keycode);
break;
case Accessibility_KEY_SYM:
--#ifdef SPI_XKB_DEBUG
++#ifdef SPI_XKB_DEBUG
fprintf (stderr, "KeySym synthesis\n");
#endif
-- /*
++ /*
* note: we are using long for 'keycode'
* in our arg list; it can contain either
* a keycode or a keysym.
controller, (int) event.id);
#endif
ret = spi_controller_notify_keylisteners (controller,
-- (Accessibility_DeviceEvent *)
++ (Accessibility_DeviceEvent *)
&event, FALSE) ?
-- TRUE : FALSE;
++ TRUE : FALSE;
reply = dbus_message_new_method_return (message);
if (reply)
{
controller, (int) event.id);
#endif
spi_controller_notify_keylisteners (controller, (Accessibility_DeviceEvent *)
-- &event, FALSE);
++ &event, FALSE);
reply = dbus_message_new_method_return (message);
return reply;
}