2 * AT-SPI - Assistive Technology Service Provider Interface
3 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
5 * Copyright 2008, 2009, Codethink Ltd.
6 * Copyright 2001, 2002, 2003 Sun Microsystems Inc.,
7 * Copyright 2001, 2002, 2003 Ximian, Inc.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
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 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
28 #include <droute/droute.h>
31 #include "accessible-register.h"
33 #include "spi-common/spi-dbus.h"
35 static GArray *listener_ids = NULL;
37 static gint atk_bridge_key_event_listener_id;
38 static gint atk_bridge_focus_tracker_id;
40 /*---------------------------------------------------------------------------*/
42 #define ITF_EVENT_OBJECT "org.freedesktop.atspi.Event.Object"
43 #define ITF_EVENT_WINDOW "org.freedesktop.atspi.Event.Window"
44 #define ITF_EVENT_DOCUMENT "org.freedekstop.atspi.Event.Document"
45 #define ITF_EVENT_FOCUS "org.freedesktop.atspi.Event.Focus"
47 /*---------------------------------------------------------------------------*/
50 Accessibility_DeviceEventController_notifyListenersSync(const Accessibility_DeviceEvent *key_event)
54 dbus_bool_t consumed = FALSE;
57 dbus_message_new_method_call(SPI_DBUS_NAME_REGISTRY,
59 SPI_DBUS_INTERFACE_DEC,
60 "notifyListenersSync");
62 dbus_error_init(&error);
63 if (spi_dbus_marshal_deviceEvent(message, key_event))
65 DBusMessage *reply = dbus_connection_send_with_reply_and_block(atk_adaptor_app_data->bus, message, 1000, &error);
69 dbus_error_init(&error);
70 dbus_message_get_args(reply, &error, DBUS_TYPE_BOOLEAN, &consumed, DBUS_TYPE_INVALID);
71 dbus_message_unref(reply);
74 dbus_message_unref(message);
79 spi_init_keystroke_from_atk_key_event (Accessibility_DeviceEvent *keystroke,
80 AtkKeyEventStruct *event)
82 keystroke->id = (dbus_int32_t) event->keyval;
83 keystroke->hw_code = (dbus_int16_t) event->keycode;
84 keystroke->timestamp = (dbus_uint32_t) event->timestamp;
85 keystroke->modifiers = (dbus_uint16_t) (event->state & 0xFFFF);
90 keystroke->event_string = g_strdup (event->string);
91 c = g_utf8_get_char_validated (event->string, -1);
92 if (c > 0 && g_unichar_isprint (c))
93 keystroke->is_text = TRUE;
95 keystroke->is_text = FALSE;
99 keystroke->event_string = g_strdup ("");
100 keystroke->is_text = FALSE;
104 case (ATK_KEY_EVENT_PRESS):
105 keystroke->type = Accessibility_KEY_PRESSED_EVENT;
107 case (ATK_KEY_EVENT_RELEASE):
108 keystroke->type = Accessibility_KEY_RELEASED_EVENT;
115 g_print ("key_event type %d; val=%d code=%d modifiers=%x name=%s is_text=%d, time=%lx\n",
116 (int) keystroke->type, (int) keystroke->id, (int) keystroke->hw_code,
117 (int) keystroke->modifiers,
118 keystroke->event_string, (int) keystroke->is_text, (unsigned long) keystroke->timestamp);
124 spi_atk_bridge_key_listener (AtkKeyEventStruct *event, gpointer data)
127 Accessibility_DeviceEvent key_event;
129 spi_init_keystroke_from_atk_key_event (&key_event, event);
131 result = Accessibility_DeviceEventController_notifyListenersSync (&key_event);
133 if (key_event.event_string) g_free (key_event.event_string);
139 /*---------------------------------------------------------------------------*/
142 * Emits an AT-SPI event.
143 * AT-SPI events names are split into three parts:
145 * This is mapped onto D-Bus events as:
146 * D-Bus Interface:Signal Name:Detail argument
148 * Marshals a basic type into the 'any_data' attribute of
153 emit(AtkObject *accessible,
157 dbus_int32_t detail1,
158 dbus_int32_t detail2,
164 path = atk_dbus_object_to_path (accessible);
166 /* Tough decision here
167 * We won't send events from accessible
168 * objects that have not yet been added to the accessible tree.
173 spi_dbus_emit_signal (atk_adaptor_app_data->bus, path, klass, major, minor, detail1, detail2, type, val);
177 /*---------------------------------------------------------------------------*/
180 * Emits an AT-SPI event, marshalling a BoundingBox structure into the
181 * 'any_data' variant of the event.
184 emit_rect(AtkObject *accessible,
191 DBusMessageIter iter, variant, sub;
192 gchar *path, *cname, *t;
193 dbus_int32_t dummy = 0;
195 path = atk_dbus_object_to_path (accessible);
197 /* Tough decision here
198 * We won't send events from accessible
199 * objects that have not yet been added to the accessible tree.
204 if (!klass) klass = "";
205 if (!major) major = "";
206 if (!minor) minor = "";
209 * This is very annoying, but as '-' isn't a legal signal
210 * name in D-Bus (Why not??!?) The names need converting
211 * on this side, and again on the client side.
213 cname = g_strdup(major);
214 while ((t = strchr(cname, '-')) != NULL) *t = '_';
216 sig = dbus_message_new_signal(path, klass, cname);
220 dbus_message_iter_init_append (sig, &iter);
221 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &minor);
222 dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &dummy);
223 dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &dummy);
225 dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "(iiii)", &variant);
226 dbus_message_iter_open_container (&variant, DBUS_TYPE_STRUCT, NULL, &sub);
227 dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->x));
228 dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->y));
229 dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->width));
230 dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->height));
231 dbus_message_iter_close_container (&variant, &sub);
232 dbus_message_iter_close_container (&iter, &variant);
234 dbus_connection_send(atk_adaptor_app_data->bus, sig, NULL);
237 /*---------------------------------------------------------------------------*/
240 * The focus listener handles the ATK 'focus' signal and forwards it
241 * as the AT-SPI event, 'focus:'
244 focus_tracker (AtkObject *accessible)
246 emit(accessible, ITF_EVENT_FOCUS, "focus", "", 0, 0, DBUS_TYPE_INT32_AS_STRING, 0);
249 /*---------------------------------------------------------------------------*/
251 #define PCHANGE "property-change"
254 * This handler handles the following ATK signals and
255 * converts them to AT-SPI events:
257 * Gtk:AtkObject:property-change -> object:property-change:(property-name)
259 * The property-name is part of the ATK property-change signal.
262 property_event_listener (GSignalInvocationHint *signal_hint,
263 guint n_param_values,
264 const GValue *param_values,
267 AtkObject *accessible;
268 AtkPropertyValues *values;
270 const gchar *pname = NULL;
276 accessible = g_value_get_object (¶m_values[0]);
277 values = (AtkPropertyValues*) g_value_get_pointer (¶m_values[1]);
279 pname = values[0].property_name;
281 /* TODO Could improve this control statement by matching
282 * on only the end of the signal names,
284 if (strcmp (pname, "accessible-table-summary") == 0)
286 otemp = atk_table_get_summary(ATK_TABLE (accessible));
287 stemp = atk_dbus_object_to_path (otemp);
289 emit(accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, DBUS_TYPE_OBJECT_PATH_AS_STRING, stemp);
291 else if (strcmp (pname, "accessible-table-column-header") == 0)
293 i = g_value_get_int (&(values->new_value));
294 otemp = atk_table_get_column_header(ATK_TABLE (accessible), i);
295 stemp = atk_dbus_object_to_path (otemp);
297 emit(accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, DBUS_TYPE_OBJECT_PATH_AS_STRING, stemp);
299 else if (strcmp (pname, "accessible-table-row-header") == 0)
301 i = g_value_get_int (&(values->new_value));
302 otemp = atk_table_get_row_header(ATK_TABLE (accessible), i);
303 stemp = atk_dbus_object_to_path (otemp);
305 emit(accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, DBUS_TYPE_OBJECT_PATH_AS_STRING, stemp);
307 else if (strcmp (pname, "accessible-table-row-description") == 0)
309 i = g_value_get_int (&(values->new_value));
310 stemp = atk_table_get_row_description(ATK_TABLE (accessible), i);
311 emit(accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, DBUS_TYPE_STRING_AS_STRING, stemp);
313 else if (strcmp (pname, "accessible-table-column-description") == 0)
315 i = g_value_get_int (&(values->new_value));
316 stemp = atk_table_get_column_description(ATK_TABLE (accessible), i);
317 emit(accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, DBUS_TYPE_STRING_AS_STRING, stemp);
319 else if (strcmp (pname, "accessible-table-caption-object") == 0)
321 otemp = atk_table_get_caption(ATK_TABLE(accessible));
322 stemp = atk_object_get_name(otemp);
323 emit(accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, DBUS_TYPE_STRING_AS_STRING, stemp);
327 emit(accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, DBUS_TYPE_INT32_AS_STRING, 0);
332 /*---------------------------------------------------------------------------*/
334 #define STATE_CHANGED "state-changed"
337 * The state event listener handles 'Gtk:AtkObject:state-change' ATK signals
338 * and forwards them as object:state-changed:(param-name) AT-SPI events. Where
339 * the param-name is part of the ATK state-change signal.
342 state_event_listener (GSignalInvocationHint *signal_hint,
343 guint n_param_values,
344 const GValue *param_values,
347 AtkObject *accessible;
351 accessible = ATK_OBJECT(g_value_get_object (¶m_values[0]));
352 pname = g_strdup (g_value_get_string (¶m_values[1]));
354 /* TODO - Possibly ignore a change to the 'defunct' state.
355 * This is because without reference counting defunct objects should be removed.
357 detail1 = (g_value_get_boolean (¶m_values[2])) ? 1 : 0;
358 emit(accessible, ITF_EVENT_OBJECT, STATE_CHANGED, pname, detail1, 0, DBUS_TYPE_INT32_AS_STRING, 0);
363 /*---------------------------------------------------------------------------*/
366 * The window event listener handles the following ATK signals and forwards
367 * them as AT-SPI events:
369 * window:create -> window:create
370 * window:destroy -> window:destroy
371 * window:minimize -> window:minimize
372 * window:maximize -> window:maximize
373 * window:activate -> window:activate
374 * window:deactivate -> window:deactivate
377 window_event_listener (GSignalInvocationHint *signal_hint,
378 guint n_param_values,
379 const GValue *param_values,
382 AtkObject *accessible;
383 GSignalQuery signal_query;
384 const gchar *name, *s;
386 g_signal_query (signal_hint->signal_id, &signal_query);
387 name = signal_query.signal_name;
389 accessible = ATK_OBJECT(g_value_get_object(¶m_values[0]));
390 s = atk_object_get_name (accessible);
391 emit(accessible, ITF_EVENT_WINDOW, name, "", 0, 0, DBUS_TYPE_STRING_AS_STRING, s);
396 /*---------------------------------------------------------------------------*/
399 * The document event listener handles the following ATK signals
400 * and converts them to AT-SPI events:
402 * Gtk:AtkDocument:load-complete -> document:load-complete
403 * Gtk:AtkDocument:load-stopped -> document:load-stopped
404 * Gtk:AtkDocument:reload -> document:reload
407 document_event_listener (GSignalInvocationHint *signal_hint,
408 guint n_param_values,
409 const GValue *param_values,
412 AtkObject *accessible;
413 GSignalQuery signal_query;
414 const gchar *name, *s;
416 g_signal_query (signal_hint->signal_id, &signal_query);
417 name = signal_query.signal_name;
419 accessible = ATK_OBJECT(g_value_get_object(¶m_values[0]));
420 s = atk_object_get_name (accessible);
421 emit(accessible, ITF_EVENT_DOCUMENT, name, "", 0, 0, DBUS_TYPE_STRING_AS_STRING, s);
426 /*---------------------------------------------------------------------------*/
429 * Signal handler for "Gtk:AtkComponent:bounds-changed". Converts
430 * this to an AT-SPI event - "object:bounds-changed".
433 bounds_event_listener (GSignalInvocationHint *signal_hint,
434 guint n_param_values,
435 const GValue *param_values,
438 AtkObject *accessible;
439 AtkRectangle *atk_rect;
440 GSignalQuery signal_query;
441 const gchar *name, *s;
443 g_signal_query (signal_hint->signal_id, &signal_query);
444 name = signal_query.signal_name;
446 accessible = ATK_OBJECT(g_value_get_object(¶m_values[0]));
448 if (G_VALUE_HOLDS_BOXED (param_values + 1))
449 atk_rect = g_value_get_boxed (param_values + 1);
451 emit_rect(accessible, ITF_EVENT_OBJECT, name, "", atk_rect);
455 /*---------------------------------------------------------------------------*/
458 * Handles the ATK signal 'Gtk:AtkObject:active-descendant-changed' and
459 * converts it to the AT-SPI signal - 'object:active-descendant-changed'.
463 active_descendant_event_listener (GSignalInvocationHint *signal_hint,
464 guint n_param_values,
465 const GValue *param_values,
468 AtkObject *accessible;
470 GSignalQuery signal_query;
471 const gchar *name, *minor;
475 g_signal_query (signal_hint->signal_id, &signal_query);
476 name = signal_query.signal_name;
478 accessible = ATK_OBJECT(g_value_get_object(¶m_values[0]));
479 child = ATK_OBJECT(g_value_get_pointer (¶m_values[1]));
480 g_return_val_if_fail (ATK_IS_OBJECT (child), TRUE);
481 minor = g_quark_to_string (signal_hint->detail);
483 detail1 = atk_object_get_index_in_parent (child);
484 s = atk_dbus_object_to_path (child);
491 emit(accessible, ITF_EVENT_OBJECT, name, "", detail1, 0, DBUS_TYPE_OBJECT_PATH_AS_STRING, s);
496 /*---------------------------------------------------------------------------*/
499 * Handles the ATK signal 'Gtk:AtkHypertext:link-selected' and
500 * converts it to the AT-SPI signal - 'object:link-selected'
504 link_selected_event_listener (GSignalInvocationHint *signal_hint,
505 guint n_param_values,
506 const GValue *param_values,
509 AtkObject *accessible;
510 GSignalQuery signal_query;
511 const gchar *name, *minor;
514 g_signal_query (signal_hint->signal_id, &signal_query);
515 name = signal_query.signal_name;
517 accessible = ATK_OBJECT(g_value_get_object(¶m_values[0]));
518 minor = g_quark_to_string (signal_hint->detail);
520 if (G_VALUE_TYPE (¶m_values[1]) == G_TYPE_INT)
521 detail1 = g_value_get_int (¶m_values[1]);
523 emit(accessible, ITF_EVENT_OBJECT, name, minor, detail1, 0, DBUS_TYPE_INT32_AS_STRING, 0);
527 /*---------------------------------------------------------------------------*/
530 * Handles the ATK signal 'Gtk:AtkText:text-changed' and
531 * converts it to the AT-SPI signal - 'object:text-changed'
535 text_changed_event_listener (GSignalInvocationHint *signal_hint,
536 guint n_param_values,
537 const GValue *param_values,
540 AtkObject *accessible;
541 GSignalQuery signal_query;
542 const gchar *name, *minor;
544 gint detail1, detail2;
546 g_signal_query (signal_hint->signal_id, &signal_query);
547 name = signal_query.signal_name;
549 accessible = ATK_OBJECT(g_value_get_object(¶m_values[0]));
550 minor = g_quark_to_string (signal_hint->detail);
552 if (G_VALUE_TYPE (¶m_values[1]) == G_TYPE_INT)
553 detail1 = g_value_get_int (¶m_values[1]);
555 if (G_VALUE_TYPE (¶m_values[2]) == G_TYPE_INT)
556 detail2 = g_value_get_int (¶m_values[2]);
558 selected = atk_text_get_text (ATK_TEXT (accessible), detail1, detail1+detail2);
560 emit(accessible, ITF_EVENT_OBJECT, name, minor, detail1, detail2, DBUS_TYPE_STRING_AS_STRING, selected);
564 /*---------------------------------------------------------------------------*/
567 * Handles the ATK signal 'Gtk:AtkText:text-selection-changed' and
568 * converts it to the AT-SPI signal - 'object:text-selection-changed'
572 text_selection_changed_event_listener (GSignalInvocationHint *signal_hint,
573 guint n_param_values,
574 const GValue *param_values,
577 AtkObject *accessible;
578 GSignalQuery signal_query;
579 const gchar *name, *minor;
580 gint detail1, detail2;
582 g_signal_query (signal_hint->signal_id, &signal_query);
583 name = signal_query.signal_name;
585 accessible = ATK_OBJECT(g_value_get_object(¶m_values[0]));
586 minor = g_quark_to_string (signal_hint->detail);
588 if (G_VALUE_TYPE (¶m_values[1]) == G_TYPE_INT)
589 detail1 = g_value_get_int (¶m_values[1]);
591 if (G_VALUE_TYPE (¶m_values[2]) == G_TYPE_INT)
592 detail2 = g_value_get_int (¶m_values[2]);
594 emit(accessible, ITF_EVENT_OBJECT, name, minor, detail1, detail2, DBUS_TYPE_STRING_AS_STRING, "");
598 /*---------------------------------------------------------------------------*/
601 * Generic signal converter and forwarder.
603 * Klass (Interface) org.freedesktop.atspi.Event.Object
604 * Major is the signal name.
611 generic_event_listener (GSignalInvocationHint *signal_hint,
612 guint n_param_values,
613 const GValue *param_values,
616 AtkObject *accessible;
617 GSignalQuery signal_query;
620 g_signal_query (signal_hint->signal_id, &signal_query);
621 name = signal_query.signal_name;
623 accessible = ATK_OBJECT(g_value_get_object(¶m_values[0]));
624 emit(accessible, ITF_EVENT_OBJECT, name, "", 0, 0, DBUS_TYPE_INT32_AS_STRING, 0);
628 /*---------------------------------------------------------------------------*/
631 * Registers the provided function as a handler for the given signal name
632 * and stores the signal id returned so that the function may be
633 * de-registered later.
636 add_signal_listener (GSignalEmissionHook listener, const char *signal_name)
640 id = atk_add_global_event_listener (listener, signal_name);
641 g_array_append_val (listener_ids, id);
645 * Initialization for the signal handlers.
647 * Registers all required signal handlers.
650 spi_atk_register_event_listeners (void)
653 * Kludge to make sure the Atk interface types are registered, otherwise
654 * the AtkText signal handlers below won't get registered
656 GObject *ao = g_object_new (ATK_TYPE_OBJECT, NULL);
657 AtkObject *bo = atk_no_op_object_new (ao);
659 g_object_unref (G_OBJECT (bo));
662 /* Register for focus event notifications, and register app with central registry */
663 listener_ids = g_array_sized_new (FALSE, TRUE, sizeof (guint), 16);
665 atk_bridge_focus_tracker_id = atk_add_focus_tracker (focus_tracker);
667 add_signal_listener (property_event_listener, "Gtk:AtkObject:property-change");
668 add_signal_listener (window_event_listener, "window:create");
669 add_signal_listener (window_event_listener, "window:destroy");
670 add_signal_listener (window_event_listener, "window:minimize");
671 add_signal_listener (window_event_listener, "window:maximize");
672 add_signal_listener (window_event_listener, "window:restore");
673 add_signal_listener (window_event_listener, "window:activate");
674 add_signal_listener (window_event_listener, "window:deactivate");
675 add_signal_listener (document_event_listener, "Gtk:AtkDocument:load-complete");
676 add_signal_listener (document_event_listener, "Gtk:AtkDocument:reload");
677 add_signal_listener (document_event_listener, "Gtk:AtkDocument:load-stopped");
678 add_signal_listener (state_event_listener, "Gtk:AtkObject:state-change");
679 add_signal_listener (active_descendant_event_listener, "Gtk:AtkObject:active-descendant-changed");
680 add_signal_listener (bounds_event_listener, "Gtk:AtkComponent:bounds-changed");
681 add_signal_listener (text_selection_changed_event_listener, "Gtk:AtkText:text-selection-changed");
682 add_signal_listener (text_changed_event_listener, "Gtk:AtkText:text-changed");
683 add_signal_listener (link_selected_event_listener, "Gtk:AtkHypertext:link-selected");
684 add_signal_listener (generic_event_listener, "Gtk:AtkObject:visible-data-changed");
685 add_signal_listener (generic_event_listener, "Gtk:AtkSelection:selection-changed");
686 add_signal_listener (generic_event_listener, "Gtk:AtkText:text-caret-moved");
687 add_signal_listener (generic_event_listener, "Gtk:AtkTable:row-inserted");
688 add_signal_listener (generic_event_listener, "Gtk:AtkTable:row-reordered");
689 add_signal_listener (generic_event_listener, "Gtk:AtkTable:row-deleted");
690 add_signal_listener (generic_event_listener, "Gtk:AtkTable:column-inserted");
691 add_signal_listener (generic_event_listener, "Gtk:AtkTable:column-reordered");
692 add_signal_listener (generic_event_listener, "Gtk:AtkTable:column-deleted");
693 add_signal_listener (generic_event_listener, "Gtk:AtkTable:model-changed");
696 * May add the following listeners to implement preemptive key listening for GTK+
698 * atk_add_global_event_listener (spi_atk_bridge_widgetkey_listener, "Gtk:GtkWidget:key-press-event");
699 * atk_add_global_event_listener (spi_atk_bridge_widgetkey_listener, "Gtk:GtkWidget:key-release-event");
701 atk_bridge_key_event_listener_id = atk_add_key_event_listener (spi_atk_bridge_key_listener, NULL);
704 /*---------------------------------------------------------------------------*/
707 * De-registers all ATK signal handlers.
710 spi_atk_deregister_event_listeners (void)
713 GArray *ids = listener_ids;
716 if (atk_bridge_focus_tracker_id)
717 atk_remove_focus_tracker (atk_bridge_focus_tracker_id);
719 for (i = 0; ids && i < ids->len; i++)
721 atk_remove_global_event_listener (g_array_index (ids, guint, i));
724 if (atk_bridge_key_event_listener_id)
725 atk_remove_key_event_listener (atk_bridge_key_event_listener_id);
728 /*---------------------------------------------------------------------------*/
731 * TODO This function seems out of place here.
733 * Emits fake deactivate signals on all top-level windows.
734 * Used when shutting down AT-SPI, ensuring that all
735 * windows have been removed on the client side.
738 spi_atk_tidy_windows (void)
744 root = atk_get_root ();
745 n_children = atk_object_get_n_accessible_children (root);
746 for (i = 0; i < n_children; i++)
749 AtkStateSet *stateset;
752 child = atk_object_ref_accessible_child (root, i);
753 stateset = atk_object_ref_state_set (child);
755 name = atk_object_get_name (child);
756 if (atk_state_set_contains_state (stateset, ATK_STATE_ACTIVE))
758 emit(child, ITF_EVENT_WINDOW, "deactivate", NULL, 0, 0, DBUS_TYPE_STRING_AS_STRING, name);
760 g_object_unref (stateset);
762 emit(child, ITF_EVENT_WINDOW, "destroy", NULL, 0, 0, DBUS_TYPE_STRING_AS_STRING, name);
763 g_object_unref (child);
767 /*END------------------------------------------------------------------------*/