1
/*
2
 * AT-SPI - Assistive Technology Service Provider Interface
3
 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4
 *
5
 * Copyright 2008 Novell, Inc.
6
 * Copyright 2001, 2002 Sun Microsystems Inc.,
7
 * Copyright 2001, 2002 Ximian, Inc.
8
 *
9
 * This library is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public
11
 * License as published by the Free Software Foundation; either
12
 * version 2.1 of the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public
20
 * License along with this library; if not, write to the
21
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22
 * Boston, MA 02110-1301, USA.
23
 */
24

            
25
#include <atk/atk.h>
26
#include <droute/droute.h>
27

            
28
#include "accessible-stateset.h"
29
#include "bridge.h"
30
#include "introspection.h"
31
#include "object.h"
32
#include "spi-dbus.h"
33

            
34
static DBusMessage *
35
new_socket_call_message (AtkComponent *component, const char *member)
36
{
37
  char *id = g_object_get_data (G_OBJECT (component), "dbus-plug-parent");
38
  char *bus_parent;
39
  char *path_parent;
40

            
41
  if (!id)
42
    {
43
      g_warning ("new_socket_call_message: no id");
44
      return NULL;
45
    }
46
  bus_parent = g_strdup (id);
47
  if (bus_parent && (path_parent = g_utf8_strchr (bus_parent + 1, -1, ':')))
48
    {
49
      DBusMessage *message;
50
      *(path_parent++) = '\0';
51
      message = dbus_message_new_method_call (bus_parent, path_parent,
52
                                              ATSPI_DBUS_INTERFACE_COMPONENT,
53
                                              member);
54
      g_free (bus_parent);
55
      return message;
56
    }
57
  return NULL;
58
}
59

            
60
static void
61
atspi_plug_component_get_extents (AtkComponent *component, gint *x, gint *y, gint *width, gint *height, AtkCoordType coord_type)
62
{
63
  DBusMessage *message = new_socket_call_message (component, "GetExtents");
64
  DBusMessage *reply;
65
  dbus_uint32_t coord_type_dbus = coord_type;
66
  DBusError error;
67
  const char *signature;
68
  DBusMessageIter iter, iter_struct;
69
  dbus_int32_t tmp;
70

            
71
  dbus_error_init (&error);
72
  dbus_message_append_args (message, DBUS_TYPE_UINT32, &coord_type_dbus, DBUS_TYPE_INVALID);
73
  reply = dbus_connection_send_with_reply_and_block (spi_global_app_data->bus,
74
                                                     message, -1, &error);
75
  dbus_message_unref (message);
76
  if (!reply)
77
    {
78
      *x = -1;
79
      *y = -1;
80
      *width = -1;
81
      *height = -1;
82
      return;
83
    }
84
  signature = dbus_message_get_signature (reply);
85
  if (g_strcmp0 (signature, "(iiii)") != 0)
86
    {
87
      g_warning ("Got unexpected signature %s from GetExtents\n", signature);
88
      dbus_message_unref (reply);
89
      *x = -1;
90
      *y = -1;
91
      *width = -1;
92
      *height = -1;
93
      return;
94
    }
95
  dbus_message_iter_init (reply, &iter);
96
  dbus_message_iter_recurse (&iter, &iter_struct);
97
  dbus_message_iter_get_basic (&iter_struct, &tmp);
98
  *x = tmp;
99
  dbus_message_iter_next (&iter_struct);
100
  dbus_message_iter_get_basic (&iter_struct, &tmp);
101
  *y = tmp;
102
  dbus_message_iter_next (&iter_struct);
103
  dbus_message_iter_get_basic (&iter_struct, &tmp);
104
  *width = tmp;
105
  dbus_message_iter_next (&iter_struct);
106
  dbus_message_iter_get_basic (&iter_struct, &tmp);
107
  *height = tmp;
108
  dbus_message_unref (reply);
109
}
110

            
111
static void
112
atspi_plug_component_get_position (AtkComponent *component, gint *x, gint *y, AtkCoordType coord_type)
113
{
114
  DBusMessage *message = new_socket_call_message (component, "GetPosition");
115
  DBusMessage *reply;
116
  dbus_uint32_t coord_type_dbus = coord_type;
117
  DBusError error;
118
  dbus_int32_t x_dbus, y_dbus;
119

            
120
  dbus_error_init (&error);
121
  dbus_message_append_args (message, DBUS_TYPE_UINT32, &coord_type_dbus, DBUS_TYPE_INVALID);
122
  reply = dbus_connection_send_with_reply_and_block (spi_global_app_data->bus,
123
                                                     message, -1, &error);
124
  dbus_message_unref (message);
125
  if (!reply)
126
    {
127
      *x = -1;
128
      *y = -1;
129
      return;
130
    }
131
  if (!dbus_message_get_args (reply, NULL, DBUS_TYPE_INT32, &x_dbus,
132
                              DBUS_TYPE_INT32, &y_dbus, DBUS_TYPE_INVALID))
133
    {
134
      g_warning ("GetPosition failed: %s", error.message);
135
      dbus_error_free (&error);
136
      *x = -1;
137
      *y = -1;
138
    }
139
  else
140
    {
141
      *x = x_dbus;
142
      *y = y_dbus;
143
    }
144
  dbus_message_unref (reply);
145
}
146

            
147
static void
148
atspi_plug_component_get_size (AtkComponent *component,
149
                               gint *width,
150
                               gint *height)
151
{
152
  DBusMessage *message = new_socket_call_message (component, "GetSize");
153
  DBusMessage *reply;
154
  DBusError error;
155
  dbus_uint32_t width_dbus, height_dbus;
156

            
157
  dbus_error_init (&error);
158
  reply = dbus_connection_send_with_reply_and_block (spi_global_app_data->bus,
159
                                                     message, -1, &error);
160
  dbus_message_unref (message);
161
  if (!reply)
162
    {
163
      *width = -1;
164
      *height = -1;
165
      return;
166
    }
167
  if (!dbus_message_get_args (reply, NULL, DBUS_TYPE_INT32, &width_dbus,
168
                              DBUS_TYPE_INT32, &height_dbus, DBUS_TYPE_INVALID))
169
    {
170
      g_warning ("GetSize failed: %s", error.message);
171
      dbus_error_free (&error);
172
      *width = -1;
173
      *height = -1;
174
    }
175
  else
176
    {
177
      *width = width_dbus;
178
      *height = height_dbus;
179
    }
180
  dbus_message_unref (reply);
181
}
182

            
183
static DBusMessage *
184
impl_Embedded (DBusConnection *bus,
185
               DBusMessage *message,
186
               void *user_data)
187
{
188
  AtkObject *object = (AtkObject *) user_data;
189
  char *path;
190
  gchar *id;
191

            
192
  if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID))
193
    {
194
      return droute_invalid_arguments_error (message);
195
    }
196
  id = g_strconcat (dbus_message_get_sender (message), ":", path, NULL);
197
  g_object_set_data_full (G_OBJECT (object), "dbus-plug-parent", id, (GDestroyNotify) g_free);
198

            
199
  if (ATK_IS_COMPONENT (object))
200
    {
201
      AtkComponent *component = ATK_COMPONENT (object);
202
      AtkComponentIface *iface = ATK_COMPONENT_GET_IFACE (component);
203
      iface->get_extents = atspi_plug_component_get_extents;
204
      iface->get_size = atspi_plug_component_get_size;
205
      iface->get_position = atspi_plug_component_get_position;
206
    }
207

            
208
  /* Retrieve some info about the children, if they exist, when
209
     embedding the plug to ensure the a11y subtree is generated.
210
     https://bugzilla.gnome.org/show_bug.cgi?id=663876 */
211
  atk_object_get_n_accessible_children (object);
212

            
213
  return dbus_message_new_method_return (message);
214
}
215

            
216
static DRouteMethod methods[] = {
217
  { impl_Embedded, "Embedded" },
218
  { NULL, NULL }
219
};
220

            
221
void
222
161
spi_initialize_socket (DRoutePath *path)
223
{
224
161
  droute_path_add_interface (path,
225
                             ATSPI_DBUS_INTERFACE_SOCKET,
226
                             spi_org_a11y_atspi_Socket,
227
                             methods, NULL);
228
161
};