diff options
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | docs/reference/ChangeLog | 5 | ||||
-rw-r--r-- | docs/reference/gtk/tmpl/gtkwidget.sgml | 25 | ||||
-rwxr-xr-x | gtk/gtk-builder-convert | 82 | ||||
-rw-r--r-- | gtk/gtktestutils.c | 1 | ||||
-rw-r--r-- | gtk/gtkwidget.c | 316 | ||||
-rw-r--r-- | tests/buildertest.c | 94 |
7 files changed, 465 insertions, 75 deletions
@@ -1,3 +1,20 @@ +2008-01-25 Johan Dahlin <johan@gnome.org> + + * gtk/gtkwidget.c: (gtk_widget_buildable_interface_init), + (gtk_widget_buildable_get_internal_child), (free_action), + (free_relation), (gtk_widget_buildable_parser_finished), + (accessibility_start_element), + (gtk_widget_buildable_custom_tag_start), + (gtk_widget_buildable_custom_finished): + Implement accessible support, fixes #454653. + + * gtk/gtk-builder-convert: + Add support for migrating old glade files + + * tests/buildertest.c: (test_widget), (test_file): + Add accessible tests and imprve the test_file function to display + toplevels and run dialogs. + 2008-01-25 Richard Hult <richard@imendio.com> * gdk/quartz/GdkQuartzView.c: Don't recreate a tracking rect if it diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog index f84a3e6d81..b30db862a9 100644 --- a/docs/reference/ChangeLog +++ b/docs/reference/ChangeLog @@ -1,3 +1,8 @@ +2008-01-24 Johan Dahlin <johan@gnome.org> + + * gtk/tmpl/gtkwidget.sgml: + Add documentation for <accessible> buildable tag. + 2008-01-14 Matthias Clasen <mclasen@redhat.com> * gtk/gtk-docs.sgml: diff --git a/docs/reference/gtk/tmpl/gtkwidget.sgml b/docs/reference/gtk/tmpl/gtkwidget.sgml index 11f7d4ccfc..b03ee0b9f5 100644 --- a/docs/reference/gtk/tmpl/gtkwidget.sgml +++ b/docs/reference/gtk/tmpl/gtkwidget.sgml @@ -37,6 +37,31 @@ modifiers and signal and allows to specify accelerators. </object> ]]></programlisting> </example> +In addition to accelerators, <structname>GtkWidget</structname> also support a +custom <accessible> element, which supports actions and relations. +Properties on the accessible implementation of an object can be set by accessing the +internal child "accessible" of a <structname>GtkWidget</structname>. +<example> +<title>A UI definition fragment specifying an accessible</title> +<programlisting><![CDATA[ +<object class="GtkButton" id="label1"/> + <property name="label">I am a Label for a Button</property> +</object> +<object class="GtkButton" id="button1"> + <accessibility> + <action action_name="click" description="Click the button."/> + <relation target="label1" type="labelled-by"/> + </accessibility> + <child internal-child="accessible"> + <object class="AtkObject" id="a11y-button1"> + <property name="AtkObject::name">Clickable Button</property> + </object> + </child> +</object> +]]></programlisting> +</example> + + </refsect2> <!-- ##### SECTION See_Also ##### --> diff --git a/gtk/gtk-builder-convert b/gtk/gtk-builder-convert index 3544e221ac..9840ad957a 100755 --- a/gtk/gtk-builder-convert +++ b/gtk/gtk-builder-convert @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (C) 2006-2007 Async Open Source +# Copyright (C) 2006-2008 Async Open Source # Henrique Romano <henrique@async.com.br> # Johan Dahlin <jdahlin@async.com.br> # @@ -124,7 +124,7 @@ def get_accelerator_nodes(node): return accelerators def get_object_node(child_node): - assert child_node.tagName == 'child' + assert child_node.tagName == 'child', child_node nodes = [] for node in child_node.childNodes: if node.nodeType == Node.TEXT_NODE: @@ -178,7 +178,7 @@ class GtkBuilderConverter(object): return [w for w in self._dom.getElementsByTagName("object") if w.getAttribute(attribute) == value] - def _create_object(self, obj_class, obj_id, template=None, **properties): + def _create_object(self, obj_class, obj_id, template=None, properties=None): """ Creates a new <object> tag. Optionally a name template can be provided which will be used @@ -207,22 +207,23 @@ class GtkBuilderConverter(object): obj = self._dom.createElement('object') obj.setAttribute('class', obj_class) obj.setAttribute('id', obj_id) - for name, value in properties.items(): - if isinstance(value, Node): - # Reuse the node, so translatable and context still will be - # set when converting nodes. See also #509153 - prop = value - else: - prop = self._dom.createElement('property') - prop.appendChild(self._dom.createTextNode(value)) - - prop.setAttribute('name', name) - obj.appendChild(prop) + if properties: + for name, value in properties.items(): + if isinstance(value, Node): + # Reuse the node, so translatable and context still will be + # set when converting nodes. See also #509153 + prop = value + else: + prop = self._dom.createElement('property') + prop.appendChild(self._dom.createTextNode(value)) + + prop.setAttribute('name', str(name)) + obj.appendChild(prop) self.objects[obj_id] = obj return obj - def _create_root_object(self, obj_class, template, **properties): - obj = self._create_object(obj_class, None, template, **properties) + def _create_root_object(self, obj_class, template, properties=None): + obj = self._create_object(obj_class, None, template, properties) self.root_objects.append(obj) return obj @@ -261,6 +262,10 @@ class GtkBuilderConverter(object): for node in self._dom.getElementsByTagName("ui"): self._convert_ui(node) + # Convert accessibility tag + for node in self._dom.getElementsByTagName("accessibility"): + self._convert_accessibility(node) + # Output the newly created root objects and sort them # by attribute id for obj in sorted(self.root_objects, @@ -421,7 +426,7 @@ class GtkBuilderConverter(object): properties['name'] = object_id action = self._create_object(name, object_id, - **properties) + properties=properties) for signal in get_signal_nodes(node): signal_name = signal.getAttribute('name') @@ -514,12 +519,12 @@ class GtkBuilderConverter(object): value, lower, upper, step, page, page_size = data.split(' ') adj = self._create_root_object("GtkAdjustment", template='adjustment', - value=value, - lower=lower, - upper=upper, - step_increment=step, - page_increment=page, - page_size=page_size) + properties=dict(value=value, + lower=lower, + upper=upper, + step_increment=step, + page_increment=page, + page_size=page_size)) prop.childNodes[0].data = adj.getAttribute('id') def _convert_combobox_items(self, node, prop): @@ -581,7 +586,7 @@ class GtkBuilderConverter(object): prop.removeAttribute('translatable') tbuffer = self._create_root_object("GtkTextBuffer", template='textbuffer', - text=data) + properties=dict(text=data)) prop.childNodes[0].data = tbuffer.getAttribute('id') def _packing_prop_to_child_attr(self, node, prop_name, prop_val, @@ -623,6 +628,35 @@ class GtkBuilderConverter(object): widget.getAttributeNode("constructor").value = parent_id node.removeAttribute("id") + def _convert_accessibility(self, node): + objectNode = node.parentNode + parent_id = objectNode.getAttribute("id") + + properties = {} + for node in node.childNodes: + if node.nodeName == 'atkproperty': + node.tagName = 'property' + properties[node.getAttribute('name')] = node + node.parentNode.removeChild(node) + elif node.nodeName == 'atkrelation': + node.tagName = 'relation' + relation_type = node.getAttribute('type') + relation_type = relation_type.replace('_', '-') + node.setAttribute('type', relation_type) + elif node.nodeName == 'atkaction': + node.tagName = 'action' + + if properties: + child = self._dom.createElement('child') + child.setAttribute("internal-child", "accessible") + + atkobject = self._create_object( + "AtkObject", None, + template='a11y-%s' % (parent_id,), + properties=properties) + child.appendChild(atkobject) + objectNode.appendChild(child) + def _strip_root(self, root_name): for widget in self._dom.getElementsByTagName("widget"): if widget.getAttribute('id') == root_name: diff --git a/gtk/gtktestutils.c b/gtk/gtktestutils.c index dfafa7bfbe..cd9d6abf67 100644 --- a/gtk/gtktestutils.c +++ b/gtk/gtktestutils.c @@ -60,7 +60,6 @@ gtk_test_init (int *argcp, * FUTURE TODO: * - this function could install a mock object around GtkSettings */ - g_setenv ("GTK_MODULES", "", TRUE); g_setenv ("GTK2_RC_FILES", "/dev/null", TRUE); gtk_disable_setlocale(); setlocale (LC_ALL, "C"); diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index e3d824e823..fec929f6e5 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -251,6 +251,9 @@ static void gtk_widget_buildable_interface_init (GtkBuildableIfa static void gtk_widget_buildable_set_name (GtkBuildable *buildable, const gchar *name); static const gchar * gtk_widget_buildable_get_name (GtkBuildable *buildable); +static GObject * gtk_widget_buildable_get_internal_child (GtkBuildable *buildable, + GtkBuilder *builder, + const gchar *childname); static void gtk_widget_buildable_set_buildable_property (GtkBuildable *buildable, GtkBuilder *builder, const gchar *name, @@ -8786,17 +8789,20 @@ gtk_widget_ref_accessible (AtkImplementor *implementor) /* * GtkBuildable implementation */ -static GQuark quark_builder_has_default = 0; -static GQuark quark_builder_has_focus = 0; +static GQuark quark_builder_has_default = 0; +static GQuark quark_builder_has_focus = 0; +static GQuark quark_builder_atk_relations = 0; static void gtk_widget_buildable_interface_init (GtkBuildableIface *iface) { quark_builder_has_default = g_quark_from_static_string ("gtk-builder-has-default"); quark_builder_has_focus = g_quark_from_static_string ("gtk-builder-has-focus"); + quark_builder_atk_relations = g_quark_from_static_string ("gtk-builder-atk-relations"); iface->set_name = gtk_widget_buildable_set_name; iface->get_name = gtk_widget_buildable_get_name; + iface->get_internal_child = gtk_widget_buildable_get_internal_child; iface->set_buildable_property = gtk_widget_buildable_set_buildable_property; iface->parser_finished = gtk_widget_buildable_parser_finished; iface->custom_tag_start = gtk_widget_buildable_custom_tag_start; @@ -8816,6 +8822,17 @@ gtk_widget_buildable_get_name (GtkBuildable *buildable) return gtk_widget_get_name (GTK_WIDGET (buildable)); } +static GObject * +gtk_widget_buildable_get_internal_child (GtkBuildable *buildable, + GtkBuilder *builder, + const gchar *childname) +{ + if (strcmp (childname, "accessible") == 0) + return G_OBJECT (gtk_widget_get_accessible (GTK_WIDGET (buildable))); + + return NULL; +} + static void gtk_widget_buildable_set_buildable_property (GtkBuildable *buildable, GtkBuilder *builder, @@ -8832,17 +8849,224 @@ gtk_widget_buildable_set_buildable_property (GtkBuildable *buildable, g_object_set_property (G_OBJECT (buildable), name, value); } +typedef struct { + gchar *action_name; + gchar *description; +} AtkActionData; + +typedef struct { + gchar *target; + gchar *type; +} AtkRelationData; + +static void +free_action (AtkActionData *data, gpointer user_data) +{ + g_free (data->action_name); + g_free (data->description); + g_slice_free (AtkActionData, data); +} + +static void +free_relation (AtkRelationData *data, gpointer user_data) +{ + g_free (data->target); + g_free (data->type); + g_slice_free (AtkRelationData, data); +} + static void gtk_widget_buildable_parser_finished (GtkBuildable *buildable, GtkBuilder *builder) { + GSList *atk_relations; + if (g_object_get_qdata (G_OBJECT (buildable), quark_builder_has_default)) gtk_widget_grab_default (GTK_WIDGET (buildable)); if (g_object_get_qdata (G_OBJECT (buildable), quark_builder_has_focus)) gtk_widget_grab_focus (GTK_WIDGET (buildable)); + + atk_relations = g_object_get_qdata (G_OBJECT (buildable), + quark_builder_atk_relations); + if (atk_relations) + { + AtkObject *accessible; + AtkRelationSet *relation_set; + GSList *l; + GObject *target; + AtkRelationType relation_type; + AtkObject *target_accessible; + + accessible = gtk_widget_get_accessible (GTK_WIDGET (buildable)); + relation_set = atk_object_ref_relation_set (accessible); + + for (l = atk_relations; l; l = l->next) + { + AtkRelationData *relation = (AtkRelationData*)l->data; + + target = gtk_builder_get_object (builder, relation->target); + if (!target) + { + g_warning ("Target object %s in <relation> does not exist", + relation->target); + continue; + } + target_accessible = gtk_widget_get_accessible (GTK_WIDGET (target)); + g_assert (target_accessible != NULL); + + relation_type = atk_relation_type_for_name (relation->type); + if (relation_type == ATK_RELATION_NULL) + { + g_warning ("<relation> type %s not found", + relation->type); + continue; + } + atk_relation_set_add_relation_by_type (relation_set, relation_type, + target_accessible); + } + g_object_unref (relation_set); + + g_slist_foreach (atk_relations, (GFunc)free_relation, NULL); + g_slist_free (atk_relations); + g_object_set_qdata (G_OBJECT (buildable), quark_builder_atk_relations, + NULL); + } + } typedef struct { + GSList *actions; + GSList *relations; +} AccessibilitySubParserData; + +static void +accessibility_start_element (GMarkupParseContext *context, + const gchar *element_name, + const gchar **names, + const gchar **values, + gpointer user_data, + GError **error) +{ + AccessibilitySubParserData *data = (AccessibilitySubParserData*)user_data; + guint i; + gint line_number, char_number; + + if (strcmp (element_name, "relation") == 0) + { + gchar *target = NULL; + gchar *type = NULL; + AtkRelationData *relation; + + for (i = 0; names[i]; i++) + { + if (strcmp (names[i], "target") == 0) + target = g_strdup (values[i]); + else if (strcmp (names[i], "type") == 0) + type = g_strdup (values[i]); + else + { + g_markup_parse_context_get_position (context, + &line_number, + &char_number); + g_set_error (error, + GTK_BUILDER_ERROR, + GTK_BUILDER_ERROR_INVALID_ATTRIBUTE, + "%s:%d:%d '%s' is not a valid attribute of <%s>", + "<input>", + line_number, char_number, names[i], "relation"); + g_free (target); + g_free (type); + return; + } + } + + if (!target || !type) + { + g_markup_parse_context_get_position (context, + &line_number, + &char_number); + g_set_error (error, + GTK_BUILDER_ERROR, + GTK_BUILDER_ERROR_MISSING_ATTRIBUTE, + "%s:%d:%d <%s> requires attribute \"%s\"", + "<input>", + line_number, char_number, "relation", + type ? "target" : "type"); + g_free (target); + g_free (type); + return; + } + + relation = g_slice_new (AtkRelationData); + relation->target = target; + relation->type = type; + + data->relations = g_slist_prepend (data->relations, relation); + } + else if (strcmp (element_name, "action") == 0) + { + gchar *action_name = NULL; + gchar *description = NULL; + AtkActionData *action; + + for (i = 0; names[i]; i++) + { + if (strcmp (names[i], "action_name") == 0) + action_name = g_strdup (values[i]); + else if (strcmp (names[i], "description") == 0) + description = g_strdup (values[i]); + else + { + g_markup_parse_context_get_position (context, + &line_number, + &char_number); + g_set_error (error, + GTK_BUILDER_ERROR, + GTK_BUILDER_ERROR_INVALID_ATTRIBUTE, + "%s:%d:%d '%s' is not a valid attribute of <%s>", + "<input>", + line_number, char_number, names[i], "action"); + g_free (action_name); + g_free (description); + return; + } + } + + if (!action_name || !description) + { + g_markup_parse_context_get_position (context, + &line_number, + &char_number); + g_set_error (error, + GTK_BUILDER_ERROR, + GTK_BUILDER_ERROR_MISSING_ATTRIBUTE, + "%s:%d:%d <%s> requires attribute \"%s\"", + "<input>", + line_number, char_number, "action", + description ? "action_name" : "description"); + g_free (action_name); + g_free (description); + return; + } + + action = g_slice_new (AtkActionData); + action->action_name = action_name; + action->description = description; + + data->actions = g_slist_prepend (data->actions, action); + } + else if (strcmp (element_name, "accessibility") == 0) + ; + else + g_warning ("Unsupported tag for GtkWidget: %s\n", element_name); +} + +static const GMarkupParser accessibility_parser = + { + accessibility_start_element, + }; + +typedef struct { GObject *object; guint key; guint modifiers; @@ -8894,12 +9118,6 @@ static const GMarkupParser accel_group_parser = accel_group_start_element, }; -static const GMarkupParser accessibility_parser = - { - NULL, - }; - - static gboolean gtk_widget_buildable_custom_tag_start (GtkBuildable *buildable, GtkBuilder *builder, @@ -8908,31 +9126,25 @@ gtk_widget_buildable_custom_tag_start (GtkBuildable *buildable, GMarkupParser *parser, gpointer *data) { - AccelGroupParserData *parser_data; - g_assert (buildable); if (strcmp (tagname, "accelerator") == 0) { + AccelGroupParserData *parser_data; + parser_data = g_slice_new0 (AccelGroupParserData); parser_data->object = g_object_ref (buildable); *parser = accel_group_parser; *data = parser_data; return TRUE; } - else if (strcmp (tagname, "accessibility") == 0) + if (strcmp (tagname, "accessibility") == 0) { - static gboolean warning_showed = FALSE; - - if (!warning_showed) - { - g_warning ("<accessibility> is being ignored,\n" - "see http://bugzilla.gnome.org/show_bug.cgi?id=454653\n"); - warning_showed = TRUE; - } + AccessibilitySubParserData *parser_data; + parser_data = g_slice_new0 (AccessibilitySubParserData); *parser = accessibility_parser; - *data = NULL; + *data = parser_data; return TRUE; } return FALSE; @@ -8945,17 +9157,18 @@ gtk_widget_buildable_custom_finished (GtkBuildable *buildable, const gchar *tagname, gpointer user_data) { - AccelGroupParserData *data; + AccelGroupParserData *accel_data; + AccessibilitySubParserData *a11y_data; GtkWidget *toplevel; GSList *accel_groups; GtkAccelGroup *accel_group; if (strcmp (tagname, "accelerator") == 0) { - data = (AccelGroupParserData*)user_data; - g_assert (data->object); + accel_data = (AccelGroupParserData*)user_data; + g_assert (accel_data->object); - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (data->object)); + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (accel_data->object)); accel_groups = gtk_accel_groups_from_object (G_OBJECT (toplevel)); if (g_slist_length (accel_groups) == 0) { @@ -8967,15 +9180,56 @@ gtk_widget_buildable_custom_finished (GtkBuildable *buildable, g_assert (g_slist_length (accel_groups) == 1); accel_group = g_slist_nth_data (accel_groups, 0); } - gtk_widget_add_accelerator (GTK_WIDGET(data->object), - data->signal, + gtk_widget_add_accelerator (GTK_WIDGET (accel_data->object), + accel_data->signal, accel_group, - data->key, - data->modifiers, + accel_data->key, + accel_data->modifiers, GTK_ACCEL_VISIBLE); - g_object_unref (data->object); - g_free (data->signal); - g_slice_free (AccelGroupParserData, data); + g_object_unref (accel_data->object); + g_free (accel_data->signal); + g_slice_free (AccelGroupParserData, accel_data); + } + else if (strcmp (tagname, "accessibility") == 0) + { + a11y_data = (AccessibilitySubParserData*)user_data; + + if (a11y_data->actions) + { + AtkObject *accessible; + AtkAction *action; + gint i, n_actions; + GSList *l; + + accessible = gtk_widget_get_accessible (GTK_WIDGET (buildable)); + + action = ATK_ACTION (accessible); + n_actions = atk_action_get_n_actions (action); + + for (l = a11y_data->actions; l; l = l->next) + { + AtkActionData *action_data = (AtkActionData*)l->data; + + for (i = 0; i < n_actions; i++) + if (strcmp (atk_action_get_name (action, i), + action_data->action_name) == 0) + break; + + if (i < n_actions) + atk_action_set_description (action, i, + action_data->description); + } + + g_slist_foreach (a11y_data->actions, (GFunc)free_action, NULL); + g_slist_free (a11y_data->actions); + } + + if (a11y_data->relations) + g_object_set_qdata (G_OBJECT (buildable), quark_builder_atk_relations, + a11y_data->relations); + + g_slice_free (AccessibilitySubParserData, a11y_data); + } } diff --git a/tests/buildertest.c b/tests/buildertest.c index 175f273521..98b74b521f 100644 --- a/tests/buildertest.c +++ b/tests/buildertest.c @@ -1468,14 +1468,37 @@ test_widget (void) gchar *buffer3 = "<interface>" " <object class=\"GtkWindow\" id=\"window1\">" - " <accessibility>" - " <atkproperty name=\"AtkObject::accessible_name\" translatable=\"yes\">Contacts</atkproperty>" - " <atkrelation target=\"button1\" type=\"labelled-by\"/>" - " </accessibility>" + " <child>" + " <object class=\"GtkVBox\" id=\"vbox1\">" + " <child>" + " <object class=\"GtkLabel\" id=\"label1\">" + " <child internal-child=\"accessible\">" + " <object class=\"AtkObject\" id=\"a11y-label1\">" + " <property name=\"AtkObject::accessible-name\">A Label</property>" + " </object>" + " </child>" + " <accessibility>" + " <relation target=\"button1\" type=\"label-for\"/>" + " </accessibility>" + " </object>" + " </child>" + " <child>" + " <object class=\"GtkButton\" id=\"button1\">" + " <accessibility>" + " <action action_name=\"click\" description=\"Sliff\"/>" + " </accessibility>" + " </object>" + " </child>" + " </object>" + " </child>" " </object>" - "</interface>"; + "</interface>"; GtkBuilder *builder; - GObject *window1, *button1; + GObject *window1, *button1, *label1; + AtkObject *accessible; + AtkRelationSet *relation_set; + AtkRelation *relation; + char *name; builder = builder_new_from_string (buffer, -1, NULL); button1 = gtk_builder_get_object (builder, "button1"); @@ -1493,20 +1516,28 @@ test_widget (void) g_assert (GTK_WIDGET_RECEIVES_DEFAULT (GTK_WIDGET (button1))); + g_object_unref (builder); + + builder = builder_new_from_string (buffer3, -1, NULL); + window1 = gtk_builder_get_object (builder, "window1"); + label1 = gtk_builder_get_object (builder, "label1"); + + accessible = gtk_widget_get_accessible (GTK_WIDGET (label1)); + relation_set = atk_object_ref_relation_set (accessible); + g_return_if_fail (atk_relation_set_get_n_relations (relation_set) == 1); + relation = atk_relation_set_get_relation (relation_set, 0); + g_return_if_fail (relation != NULL); + g_return_if_fail (ATK_IS_RELATION (relation)); + g_return_if_fail (atk_relation_get_relation_type (relation) != ATK_RELATION_LABELLED_BY); + g_object_unref (relation_set); + + g_object_get (G_OBJECT (accessible), "accessible-name", &name, NULL); + g_return_if_fail (strcmp (name, "A Label") == 0); + g_free (name); + gtk_widget_destroy (GTK_WIDGET (window1)); g_object_unref (builder); - - if (g_test_thorough()) - { - /* this test currently triggers: - * "Gtk-WARNING **: <accessibility> is being ignored, see http://bugzilla.gnome.org/show_bug.cgi?id=454653" - */ - builder = builder_new_from_string (buffer3, -1, NULL); - window1 = gtk_builder_get_object (builder, "window1"); - gtk_widget_destroy (GTK_WIDGET (window1)); - g_object_unref (builder); - } } static void @@ -1746,18 +1777,43 @@ test_file (const gchar *filename) { GtkBuilder *builder; GError *error = NULL; + GSList *l, *objects; builder = gtk_builder_new (); if (!gtk_builder_add_from_file (builder, filename, &error)) { - g_print ("%s\n", error->message); + g_error (error->message); g_error_free (error); + return; + } + + objects = gtk_builder_get_objects (builder); + for (l = objects; l; l = l->next) + { + GObject *obj = (GObject*)l->data; + + if (GTK_IS_DIALOG (obj)) + { + int response; + + g_print ("Running dialog %s.\n", + gtk_widget_get_name (GTK_WIDGET (obj))); + response = gtk_dialog_run (GTK_DIALOG (obj)); + } + else if (GTK_IS_WINDOW (obj)) + { + g_signal_connect (obj, "destroy", G_CALLBACK (gtk_main_quit), NULL); + g_print ("Showing %s.\n", + gtk_widget_get_name (GTK_WIDGET (obj))); + gtk_widget_show_all (GTK_WIDGET (obj)); + } } + gtk_main (); + g_object_unref (builder); builder = NULL; - } int |