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

            
24
/*
25
 *
26
 * AtspiComponent function implementations
27
 *
28
 */
29

            
30
#include "atspi-accessible-private.h"
31
#include "atspi-private.h"
32

            
33
/**
34
 * AtspiComponent
35
 *
36
 * An interface implemented by objects which have onscreen visual
37
 * representations.
38
 *
39
 * The Component interface is implemented by objects which occupy on-screen
40
 * space, e.g. objects which have onscreen visual representations. The methods
41
 * in Component allow clients to identify where the objects lie in the onscreen
42
 * coordinate system, their relative size, stacking order, and position. It
43
 * also provides a mechanism whereby keyboard focus may be transferred to
44
 * specific user interface elements programmatically.  This is a 2D API.
45
 * Coordinates of 3D objects are projected into the 2-dimensional screen view
46
 * for purposes of this interface.
47
 */
48

            
49
void
50
atspi_rect_free (AtspiRect *rect)
51
{
52
  g_free (rect);
53
}
54

            
55
AtspiRect *
56
6
atspi_rect_copy (AtspiRect *src)
57
{
58
6
  AtspiRect *dst = g_new (AtspiRect, 1);
59
6
  dst->x = src->x;
60
6
  dst->y = src->y;
61
6
  dst->height = src->height;
62
6
  dst->width = src->width;
63
6
  return dst;
64
}
65

            
66
G_DEFINE_BOXED_TYPE (AtspiRect, atspi_rect, atspi_rect_copy, atspi_rect_free)
67

            
68
AtspiPoint *
69
2
atspi_point_copy (AtspiPoint *src)
70
{
71
2
  AtspiPoint *dst = g_new (AtspiPoint, 1);
72
2
  dst->x = src->x;
73
2
  dst->y = src->y;
74
2
  return dst;
75
}
76

            
77
G_DEFINE_BOXED_TYPE (AtspiPoint, atspi_point, atspi_point_copy, g_free)
78

            
79
/**
80
 * atspi_component_contains:
81
 * @obj: a pointer to the #AtspiComponent to query.
82
 * @x: a #gint specifying the x coordinate in question.
83
 * @y: a #gint specifying the y coordinate in question.
84
 * @ctype: the desired coordinate system of the point (@x, @y)
85
 *         (e.g. CSPI_COORD_TYPE_WINDOW, CSPI_COORD_TYPE_SCREEN).
86
 *
87
 * Queries whether a given #AtspiComponent contains a particular point.
88
 *
89
 * Returns: #TRUE if the specified component contains the point (@x, @y),
90
 *          #FALSE otherwise.
91
 **/
92
gboolean
93
1
atspi_component_contains (AtspiComponent *obj,
94
                          gint x,
95
                          gint y,
96
                          AtspiCoordType ctype,
97
                          GError **error)
98
{
99
1
  dbus_bool_t retval = FALSE;
100
1
  dbus_int32_t d_x = x, d_y = y;
101
1
  dbus_uint32_t d_ctype = ctype;
102

            
103
1
  g_return_val_if_fail (obj != NULL, FALSE);
104

            
105
1
  _atspi_dbus_call (obj, atspi_interface_component, "Contains", error, "iiu=>b", d_x, d_y, d_ctype, &retval);
106

            
107
1
  return retval;
108
}
109

            
110
/**
111
 * atspi_component_get_accessible_at_point:
112
 * @obj: a pointer to the #AtspiComponent to query.
113
 * @x: a #gint specifying the x coordinate of the point in question.
114
 * @y: a #gint specifying the y coordinate of the point in question.
115
 * @ctype: the coordinate system of the point (@x, @y)
116
 *         (e.g. ATSPI_COORD_TYPE_WINDOW, ATSPI_COORD_TYPE_SCREEN).
117
 *
118
 * Gets the accessible child at a given coordinate within an #AtspiComponent.
119
 *
120
 * Returns: (nullable) (transfer full): a pointer to an
121
 *          #AtspiAccessible child of the specified component which
122
 *          contains the point (@x, @y), or NULL if no child contains
123
 *          the point.
124
 **/
125
AtspiAccessible *
126
1
atspi_component_get_accessible_at_point (AtspiComponent *obj,
127
                                         gint x,
128
                                         gint y,
129
                                         AtspiCoordType ctype,
130
                                         GError **error)
131
{
132
1
  dbus_int32_t d_x = x, d_y = y;
133
1
  dbus_uint32_t d_ctype = ctype;
134
  DBusMessage *reply;
135

            
136
1
  g_return_val_if_fail (obj != NULL, FALSE);
137

            
138
1
  reply = _atspi_dbus_call_partial (obj, atspi_interface_component, "GetAccessibleAtPoint", error, "iiu", d_x, d_y, d_ctype);
139

            
140
1
  return _atspi_dbus_return_accessible_from_message (reply);
141
}
142

            
143
/**
144
 * atspi_component_get_extents:
145
 * @obj: a pointer to the #AtspiComponent to query.
146
 * @ctype: the desired coordinate system into which to return the results,
147
 *         (e.g. ATSPI_COORD_TYPE_WINDOW, ATSPI_COORD_TYPE_SCREEN).
148
 *
149
 * Gets the bounding box of the specified #AtspiComponent.
150
 * The returned values are meaningful only if the Component has both
151
 * STATE_VISIBLE and STATE_SHOWING.
152
 *
153
 * Returns: An #AtspiRect giving the accessible's extents.
154
 **/
155
AtspiRect *
156
3
atspi_component_get_extents (AtspiComponent *obj,
157
                             AtspiCoordType ctype,
158
                             GError **error)
159
{
160
3
  dbus_uint32_t d_ctype = ctype;
161
  AtspiRect bbox;
162
  AtspiAccessible *accessible;
163

            
164
3
  bbox.x = bbox.y = bbox.width = bbox.height = -1;
165
3
  g_return_val_if_fail (obj != NULL, atspi_rect_copy (&bbox));
166

            
167
3
  accessible = ATSPI_ACCESSIBLE (obj);
168
3
  if (accessible->priv->cache && ctype == ATSPI_COORD_TYPE_SCREEN)
169
    {
170
      GValue *val = g_hash_table_lookup (accessible->priv->cache, "Component.ScreenExtents");
171
      if (val)
172
        {
173
          return g_value_dup_boxed (val);
174
        }
175
    }
176

            
177
3
  _atspi_dbus_call (obj, atspi_interface_component, "GetExtents", error, "u=>(iiii)", d_ctype, &bbox);
178
3
  return atspi_rect_copy (&bbox);
179
}
180

            
181
/**
182
 * atspi_component_get_position:
183
 * @obj: a pointer to the #AtspiComponent to query.
184
 * @ctype: the desired coordinate system into which to return the results,
185
 *         (e.g. ATSPI_COORD_TYPE_WINDOW, ATSPI_COORD_TYPE_SCREEN).
186
 *
187
 * Gets the minimum x and y coordinates of the specified #AtspiComponent.
188
 * The returned values are meaningful only if the Component has both
189
 * STATE_VISIBLE and STATE_SHOWING.
190
 *
191
 * returns: An #AtspiPoint giving the @obj's position.
192
 **/
193
AtspiPoint *
194
atspi_component_get_position (AtspiComponent *obj,
195
                              AtspiCoordType ctype,
196
                              GError **error)
197
{
198
  dbus_int32_t d_x = -1, d_y = -1;
199
  dbus_uint32_t d_ctype = ctype;
200
  AtspiPoint ret;
201

            
202
  ret.x = ret.y = -1;
203

            
204
  if (!obj)
205
    return atspi_point_copy (&ret);
206

            
207
  _atspi_dbus_call (obj, atspi_interface_component, "GetPosition", error, "u=>ii", d_ctype, &d_x, &d_y);
208

            
209
  ret.x = d_x;
210
  ret.y = d_y;
211
  return atspi_point_copy (&ret);
212
}
213

            
214
/**
215
 * atspi_component_get_size:
216
 * @obj: a pointer to the #AtspiComponent to query.
217
 *
218
 * Gets the size of the specified #AtspiComponent.
219
 * The returned values are meaningful only if the Component has both
220
 * STATE_VISIBLE and STATE_SHOWING.
221
 *
222
 * returns: An #AtspiPoint giving the @obj's size.
223
 **/
224
AtspiPoint *
225
atspi_component_get_size (AtspiComponent *obj, GError **error)
226
{
227
  dbus_int32_t d_w = -1, d_h = -1;
228
  AtspiPoint ret;
229

            
230
  ret.x = ret.y = -1;
231
  if (!obj)
232
    return atspi_point_copy (&ret);
233

            
234
  _atspi_dbus_call (obj, atspi_interface_component, "GetSize", error, "=>ii", &d_w, &d_h);
235
  ret.x = d_w;
236
  ret.y = d_h;
237
  return atspi_point_copy (&ret);
238
}
239

            
240
/**
241
 * atspi_component_get_layer:
242
 * @obj: a pointer to the #AtspiComponent to query.
243
 *
244
 * Queries which layer the component is painted into, to help determine its
245
 *      visibility in terms of stacking order.
246
 *
247
 * Returns: the #AtspiComponentLayer into which this component is painted.
248
 **/
249
AtspiComponentLayer
250
1
atspi_component_get_layer (AtspiComponent *obj, GError **error)
251
{
252
1
  dbus_uint32_t zlayer = -1;
253

            
254
1
  _atspi_dbus_call (obj, atspi_interface_component, "GetLayer", error, "=>u", &zlayer);
255

            
256
1
  return zlayer;
257
}
258

            
259
/**
260
 * atspi_component_get_mdi_z_order:
261
 * @obj: a pointer to the #AtspiComponent to query.
262
 *
263
 * Queries the z stacking order of a component which is in the MDI or window
264
 *       layer. (Bigger z-order numbers mean nearer the top)
265
 *
266
 * Returns: a #gshort indicating the stacking order of the component
267
 *       in the MDI layer, or -1 if the component is not in the MDI layer.
268
 **/
269
gshort
270
1
atspi_component_get_mdi_z_order (AtspiComponent *obj, GError **error)
271
{
272
1
  dbus_uint16_t retval = -1;
273

            
274
1
  _atspi_dbus_call (obj, atspi_interface_component, "GetMDIZOrder", error, "=>n", &retval);
275

            
276
1
  return retval;
277
}
278

            
279
/**
280
 * atspi_component_grab_focus:
281
 * @obj: a pointer to the #AtspiComponent on which to operate.
282
 *
283
 * Attempts to set the keyboard input focus to the specified
284
 *         #AtspiComponent.
285
 *
286
 * Returns: #TRUE if successful, #FALSE otherwise.
287
 *
288
 **/
289
gboolean
290
1
atspi_component_grab_focus (AtspiComponent *obj, GError **error)
291
{
292
1
  dbus_bool_t retval = FALSE;
293

            
294
1
  _atspi_dbus_call (obj, atspi_interface_component, "GrabFocus", error, "=>b", &retval);
295

            
296
1
  return retval;
297
}
298

            
299
/**
300
 * atspi_component_get_alpha:
301
 * @obj: The #AtspiComponent to be queried.
302
 *
303
 * Gets the opacity/alpha value of a component, if alpha blending is in use.
304
 *
305
 * Returns: the opacity value of a component, as a #gdouble between 0.0 and 1.0.
306
 **/
307
gdouble
308
1
atspi_component_get_alpha (AtspiComponent *obj, GError **error)
309
{
310
1
  double retval = 1;
311

            
312
1
  _atspi_dbus_call (obj, atspi_interface_component, "GetAlpha", error, "=>d", &retval);
313

            
314
1
  return retval;
315
}
316

            
317
/**
318
 * atspi_component_set_extents:
319
 * @obj: a pointer to the #AtspiComponent to move.
320
 * @x: the new horizontal position to which the component should be moved.
321
 * @y: the new vertical position to which the component should be moved.
322
 * @width: the width to which the component should be resized.
323
 * @height: the height to which the component should be resized.
324
 * @ctype: the coordinate system in which the position is specified.
325
 *         (e.g. ATSPI_COORD_TYPE_WINDOW, ATSPI_COORD_TYPE_SCREEN).
326
 *
327
 * Moves and resizes the specified component.
328
 *
329
 * Returns: #TRUE if successful; #FALSE otherwise.
330
 **/
331
gboolean
332
1
atspi_component_set_extents (AtspiComponent *obj,
333
                             gint x,
334
                             gint y,
335
                             gint width,
336
                             gint height,
337
                             AtspiCoordType ctype,
338
                             GError **error)
339
{
340
1
  dbus_int32_t d_x = x, d_y = y, d_width = width, d_height = height;
341
1
  dbus_uint32_t d_ctype = ctype;
342
  DBusMessageIter iter, iter_struct;
343
  DBusMessage *message, *reply;
344
1
  dbus_bool_t retval = FALSE;
345
1
  AtspiAccessible *aobj = ATSPI_ACCESSIBLE (obj);
346

            
347
1
  g_return_val_if_fail (obj != NULL, FALSE);
348

            
349
1
  if (!aobj->parent.app || !aobj->parent.app->bus_name)
350
    {
351
      g_set_error_literal (error, ATSPI_ERROR, ATSPI_ERROR_APPLICATION_GONE,
352
                           _ ("The application no longer exists"));
353
      return FALSE;
354
    }
355

            
356
1
  message = dbus_message_new_method_call (aobj->parent.app->bus_name,
357
1
                                          aobj->parent.path,
358
                                          atspi_interface_component,
359
                                          "SetExtents");
360
1
  if (!message)
361
    return FALSE;
362

            
363
1
  dbus_message_iter_init_append (message, &iter);
364
1
  if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL, &iter_struct))
365
    {
366
      dbus_message_unref (message);
367
      return FALSE;
368
    }
369
1
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_x);
370
1
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_y);
371
1
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_width);
372
1
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_height);
373
1
  dbus_message_iter_close_container (&iter, &iter_struct);
374
1
  dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &d_ctype);
375

            
376
1
  reply = _atspi_dbus_send_with_reply_and_block (message, error);
377
1
  dbus_message_get_args (reply, NULL, DBUS_TYPE_BOOLEAN, &retval,
378
                         DBUS_TYPE_INVALID);
379
1
  dbus_message_unref (reply);
380
1
  return retval;
381
}
382

            
383
/**
384
 * atspi_component_set_position:
385
 * @obj: a pointer to the #AtspiComponent to move.
386
 * @x: the new horizontal position to which the component should be moved.
387
 * @y: the new vertical position to which the component should be moved.
388
 * @ctype: the coordinate system in which the position is specified.
389
 *         (e.g. ATSPI_COORD_TYPE_WINDOW, ATSPI_COORD_TYPE_SCREEN).
390
 *
391
 * Moves the component to the specified position.
392
 *
393
 * Returns: #TRUE if successful; #FALSE otherwise.
394
 **/
395
gboolean
396
atspi_component_set_position (AtspiComponent *obj,
397
                              gint x,
398
                              gint y,
399
                              AtspiCoordType ctype,
400
                              GError **error)
401
{
402
  dbus_int32_t d_x = x, d_y = y;
403
  dbus_uint32_t d_ctype = ctype;
404
  dbus_bool_t ret = FALSE;
405

            
406
  g_return_val_if_fail (obj != NULL, FALSE);
407

            
408
  _atspi_dbus_call (obj, atspi_interface_component, "SetPosition", error,
409
                    "iiu=>b", d_x, d_y, d_ctype, &ret);
410

            
411
  return ret;
412
}
413

            
414
/**
415
 * atspi_component_set_size:
416
 * @obj: a pointer to the #AtspiComponent to query.
417
 * @width: the width to which the component should be resized.
418
 * @height: the height to which the component should be resized.
419
 *
420
 * Resizes the specified component to the given pixel dimensions.
421
 *
422
 * Returns: #TRUE if successful; #FALSE otherwise.
423
 **/
424
gboolean
425
atspi_component_set_size (AtspiComponent *obj,
426
                          gint width,
427
                          gint height,
428
                          GError **error)
429
{
430
  dbus_int32_t d_width = width, d_height = height;
431
  dbus_bool_t ret = FALSE;
432

            
433
  g_return_val_if_fail (obj != NULL, FALSE);
434

            
435
  _atspi_dbus_call (obj, atspi_interface_component, "SetSize", error, "ii=>b",
436
                    d_width, d_height, &ret);
437

            
438
  return ret;
439
}
440

            
441
/**
442
 * atspi_component_scroll_to:
443
 * @obj: a pointer to the #AtspiComponent object on which to operate.
444
 * @type: a #AtspiScrollType indicating where the object should be placed on the
445
 *        screen.
446
 *
447
 * Scrolls whatever container of the #AtspiComponent object so it becomes
448
 * visible on the screen.
449
 *
450
 * Returns: #TRUE if successful, #FALSE otherwise.
451
 **/
452
gboolean
453
atspi_component_scroll_to (AtspiComponent *obj,
454
                           AtspiScrollType type,
455
                           GError **error)
456
{
457
  dbus_bool_t retval = FALSE;
458

            
459
  g_return_val_if_fail (obj != NULL, FALSE);
460

            
461
  _atspi_dbus_call (obj, atspi_interface_component,
462
                    "ScrollTo", error, "u=>b", type, &retval);
463

            
464
  return retval;
465
}
466

            
467
/**
468
 * atspi_component_scroll_to_point:
469
 * @obj: a pointer to the #AtspiComponent object on which to operate.
470
 * @coords: a #AtspiCoordType indicating whether the coordinates are relative to
471
 *          the screen, to the window, or to the parent object.
472
 * @x: the x coordinate of the point to reach
473
 * @y: the y coordinate of the point to reach
474
 * @error: return location for a #GError
475
 *
476
 * Scrolls whatever container of the #AtspiComponent object so it becomes
477
 * visible on the screen at a given position.
478
 *
479
 * Returns: #TRUE if successful, #FALSE otherwise.
480
 **/
481
gboolean
482
atspi_component_scroll_to_point (AtspiComponent *obj,
483
                                 AtspiCoordType coords,
484
                                 gint x,
485
                                 gint y,
486
                                 GError **error)
487
{
488
  dbus_bool_t retval = FALSE;
489

            
490
  g_return_val_if_fail (obj != NULL, FALSE);
491

            
492
  _atspi_dbus_call (obj, atspi_interface_component,
493
                    "ScrollToPoint", error, "uii=>b", coords, x, y, &retval);
494

            
495
  return retval;
496
}
497

            
498
static void
499
4
atspi_component_base_init (AtspiComponent *klass)
500
{
501
4
}
502

            
503
GType
504
11
atspi_component_get_type (void)
505
{
506
  static GType type = 0;
507

            
508
11
  if (!type)
509
    {
510
      static const GTypeInfo tinfo = {
511
        sizeof (AtspiComponent),
512
        (GBaseInitFunc) atspi_component_base_init,
513
        (GBaseFinalizeFunc) NULL,
514
      };
515

            
516
2
      type = g_type_register_static (G_TYPE_INTERFACE, "AtspiComponent", &tinfo, 0);
517
    }
518
11
  return type;
519
}