]> Pileus Git - ~andy/gtk/blob - gtk/a11y/gtklabelaccessible.c
fd291d787d4253006f84a4de6f6c562ab67493f9
[~andy/gtk] / gtk / a11y / gtklabelaccessible.c
1 /* GAIL - The GNOME Accessibility Enabling Library
2  * Copyright 2001, 2002, 2003 Sun Microsystems Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "config.h"
21
22 #include <gtk/gtk.h>
23 #include <gtk/gtkpango.h>
24 #include "gtklabelaccessible.h"
25
26
27 static void atk_text_interface_init (AtkTextIface *iface);
28
29 G_DEFINE_TYPE_WITH_CODE (GtkLabelAccessible, _gtk_label_accessible, GTK_TYPE_WIDGET_ACCESSIBLE,
30                          G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, atk_text_interface_init))
31
32 static void
33 _gtk_label_accessible_init (GtkLabelAccessible *label)
34 {
35 }
36
37 static void
38 gtk_label_accessible_initialize (AtkObject *obj,
39                                  gpointer   data)
40 {
41   GtkWidget  *widget;
42   GtkLabelAccessible *accessible;
43
44   ATK_OBJECT_CLASS (_gtk_label_accessible_parent_class)->initialize (obj, data);
45
46   accessible = GTK_LABEL_ACCESSIBLE (obj);
47
48   widget = GTK_WIDGET (data);
49
50   accessible->text = g_strdup (gtk_label_get_text (GTK_LABEL (widget)));
51
52   /*
53    * Check whether ancestor of GtkLabel is a GtkButton and if so
54    * set accessible parent for GtkLabelAccessible
55    */
56   while (widget != NULL)
57     {
58       widget = gtk_widget_get_parent (widget);
59       if (GTK_IS_BUTTON (widget))
60         {
61           atk_object_set_parent (obj, gtk_widget_get_accessible (widget));
62           break;
63         }
64     }
65
66   obj->role = ATK_ROLE_LABEL;
67 }
68
69 static gboolean
70 check_for_selection_change (GtkLabelAccessible *accessible,
71                             GtkLabel           *label)
72 {
73   gboolean ret_val = FALSE;
74   gint start, end;
75
76   if (gtk_label_get_selection_bounds (label, &start, &end))
77     {
78       if (end != accessible->cursor_position ||
79           start != accessible->selection_bound)
80         ret_val = TRUE;
81     }
82   else
83     {
84       ret_val = (accessible->cursor_position != accessible->selection_bound);
85     }
86
87   accessible->cursor_position = end;
88   accessible->selection_bound = start;
89
90   return ret_val;
91 }
92
93
94 static void
95 gtk_label_accessible_notify_gtk (GObject    *obj,
96                                  GParamSpec *pspec)
97 {
98   GtkWidget *widget = GTK_WIDGET (obj);
99   AtkObject* atk_obj = gtk_widget_get_accessible (widget);
100   GtkLabelAccessible *accessible;
101   gint length;
102
103   accessible = GTK_LABEL_ACCESSIBLE (atk_obj);
104
105   if (g_strcmp0 (pspec->name, "label") == 0)
106     {
107       const gchar *text;
108
109       text = gtk_label_get_text (GTK_LABEL (widget));
110       if (g_strcmp0 (accessible->text, text) == 0)
111         return;
112
113       /* Create a delete text and an insert text signal */
114       length = g_utf8_strlen (accessible->text, -1);
115       if (length > 0)
116         g_signal_emit_by_name (atk_obj, "text-changed::delete", 0, length);
117
118       g_free (accessible->text);
119       accessible->text = g_strdup (text);
120
121       length = g_utf8_strlen (accessible->text, -1);
122       if (length > 0)
123         g_signal_emit_by_name (atk_obj, "text-changed::insert", 0, length);
124
125       if (atk_obj->name == NULL)
126         /* The label has changed so notify a change in accessible-name */
127         g_object_notify (G_OBJECT (atk_obj), "accessible-name");
128
129       g_signal_emit_by_name (atk_obj, "visible-data-changed");
130     }
131   else if (g_strcmp0 (pspec->name, "cursor-position") == 0)
132     {
133       g_signal_emit_by_name (atk_obj, "text-caret-moved",
134                              _gtk_label_get_cursor_position (GTK_LABEL (widget)));
135       if (check_for_selection_change (accessible, GTK_LABEL (widget)))
136         g_signal_emit_by_name (atk_obj, "text-selection-changed");
137     }
138   else if (g_strcmp0 (pspec->name, "selection-bound") == 0)
139     {
140       if (check_for_selection_change (accessible, GTK_LABEL (widget)))
141         g_signal_emit_by_name (atk_obj, "text-selection-changed");
142     }
143   else
144     GTK_WIDGET_ACCESSIBLE_CLASS (_gtk_label_accessible_parent_class)->notify_gtk (obj, pspec);
145 }
146
147 static void
148 gtk_label_accessible_finalize (GObject *object)
149 {
150   GtkLabelAccessible *accessible = GTK_LABEL_ACCESSIBLE (object);
151
152   g_free (accessible->text);
153
154   G_OBJECT_CLASS (_gtk_label_accessible_parent_class)->finalize (object);
155 }
156
157
158 /* atkobject.h */
159
160 static AtkStateSet *
161 gtk_label_accessible_ref_state_set (AtkObject *accessible)
162 {
163   AtkStateSet *state_set;
164   GtkWidget *widget;
165
166   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
167   if (widget == NULL)
168     return NULL;
169
170   state_set = ATK_OBJECT_CLASS (_gtk_label_accessible_parent_class)->ref_state_set (accessible);
171   atk_state_set_add_state (state_set, ATK_STATE_MULTI_LINE);
172
173   return state_set;
174 }
175
176 static AtkRelationSet *
177 gtk_label_accessible_ref_relation_set (AtkObject *obj)
178 {
179   GtkWidget *widget;
180   AtkRelationSet *relation_set;
181
182   g_return_val_if_fail (GTK_IS_LABEL_ACCESSIBLE (obj), NULL);
183
184   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
185   if (widget == NULL)
186     return NULL;
187
188   relation_set = ATK_OBJECT_CLASS (_gtk_label_accessible_parent_class)->ref_relation_set (obj);
189
190   if (!atk_relation_set_contains (relation_set, ATK_RELATION_LABEL_FOR))
191     {
192       /* Get the mnemonic widget.
193        * The relation set is not updated if the mnemonic widget is changed
194        */
195       GtkWidget *mnemonic_widget;
196
197       mnemonic_widget = gtk_label_get_mnemonic_widget (GTK_LABEL (widget));
198
199       if (mnemonic_widget)
200         {
201           AtkObject *accessible_array[1];
202           AtkRelation* relation;
203
204           if (!gtk_widget_get_can_focus (mnemonic_widget))
205             {
206             /*
207              * Handle the case where a GtkFileChooserButton is specified
208              * as the mnemonic widget. use the combobox which is a child of the
209              * GtkFileChooserButton as the mnemonic widget. See bug #359843.
210              */
211              if (GTK_IS_BOX (mnemonic_widget))
212                {
213                   GList *list, *tmpl;
214
215                   list = gtk_container_get_children (GTK_CONTAINER (mnemonic_widget));
216                   if (g_list_length (list) == 2)
217                     {
218                       tmpl = g_list_last (list);
219                       if (GTK_IS_COMBO_BOX(tmpl->data))
220                         {
221                           mnemonic_widget = GTK_WIDGET(tmpl->data);
222                         }
223                     }
224                   g_list_free (list);
225                 }
226             }
227           accessible_array[0] = gtk_widget_get_accessible (mnemonic_widget);
228           relation = atk_relation_new (accessible_array, 1,
229                                        ATK_RELATION_LABEL_FOR);
230           atk_relation_set_add (relation_set, relation);
231           /*
232            * Unref the relation so that it is not leaked.
233            */
234           g_object_unref (relation);
235         }
236     }
237   return relation_set;
238 }
239
240 static const gchar*
241 gtk_label_accessible_get_name (AtkObject *accessible)
242 {
243   const gchar *name;
244
245   g_return_val_if_fail (GTK_IS_LABEL_ACCESSIBLE (accessible), NULL);
246
247   name = ATK_OBJECT_CLASS (_gtk_label_accessible_parent_class)->get_name (accessible);
248   if (name != NULL)
249     return name;
250   else
251     {
252       /*
253        * Get the text on the label
254        */
255       GtkWidget *widget;
256
257       widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
258       if (widget == NULL)
259         return NULL;
260
261       g_return_val_if_fail (GTK_IS_LABEL (widget), NULL);
262
263       return gtk_label_get_text (GTK_LABEL (widget));
264     }
265 }
266
267 static void
268 _gtk_label_accessible_class_init (GtkLabelAccessibleClass *klass)
269 {
270   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
271   AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
272   GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
273
274   gobject_class->finalize = gtk_label_accessible_finalize;
275
276   widget_class->notify_gtk = gtk_label_accessible_notify_gtk;
277
278   class->get_name = gtk_label_accessible_get_name;
279   class->ref_state_set = gtk_label_accessible_ref_state_set;
280   class->ref_relation_set = gtk_label_accessible_ref_relation_set;
281   class->initialize = gtk_label_accessible_initialize;
282 }
283
284 /* atktext.h */
285
286 static gchar*
287 gtk_label_accessible_get_text (AtkText *atk_text,
288                                gint     start_pos,
289                                gint     end_pos)
290 {
291   GtkWidget *widget;
292   const gchar *text;
293
294   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
295   if (widget == NULL)
296     return NULL;
297
298   text = gtk_label_get_text (GTK_LABEL (widget));
299
300   if (text)
301     return g_utf8_substring (text, start_pos, end_pos > -1 ? end_pos : g_utf8_strlen (text, -1));
302
303   return NULL;
304 }
305
306 static gchar *
307 gtk_label_accessible_get_text_before_offset (AtkText         *text,
308                                              gint             offset,
309                                              AtkTextBoundary  boundary_type,
310                                              gint            *start_offset,
311                                              gint            *end_offset)
312 {
313   GtkWidget *widget;
314
315   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
316   if (widget == NULL)
317     return NULL;
318
319   return _gtk_pango_get_text_before (gtk_label_get_layout (GTK_LABEL (widget)),
320                                      boundary_type, offset,
321                                      start_offset, end_offset);
322 }
323
324 static gchar*
325 gtk_label_accessible_get_text_at_offset (AtkText         *text,
326                                          gint             offset,
327                                          AtkTextBoundary  boundary_type,
328                                          gint            *start_offset,
329                                          gint            *end_offset)
330 {
331   GtkWidget *widget;
332
333   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
334   if (widget == NULL)
335     return NULL;
336
337   return _gtk_pango_get_text_at (gtk_label_get_layout (GTK_LABEL (widget)),
338                                  boundary_type, offset,
339                                  start_offset, end_offset);
340 }
341
342 static gchar*
343 gtk_label_accessible_get_text_after_offset (AtkText         *text,
344                                             gint             offset,
345                                             AtkTextBoundary  boundary_type,
346                                             gint            *start_offset,
347                                             gint            *end_offset)
348 {
349   GtkWidget *widget;
350
351   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
352   if (widget == NULL)
353     return NULL;
354
355   return _gtk_pango_get_text_after (gtk_label_get_layout (GTK_LABEL (widget)),
356                                     boundary_type, offset,
357                                     start_offset, end_offset);
358 }
359
360 static gint
361 gtk_label_accessible_get_character_count (AtkText *atk_text)
362 {
363   GtkWidget *widget;
364   const gchar *text;
365
366   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
367   if (widget == NULL)
368     return 0;
369
370   text = gtk_label_get_text (GTK_LABEL (widget));
371
372   if (text)
373     return g_utf8_strlen (text, -1);
374
375   return 0;
376 }
377
378 static gint
379 gtk_label_accessible_get_caret_offset (AtkText *text)
380 {
381   GtkWidget *widget;
382
383   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
384   if (widget == NULL)
385     return 0;
386
387   return _gtk_label_get_cursor_position (GTK_LABEL (widget));
388 }
389
390 static gboolean
391 gtk_label_accessible_set_caret_offset (AtkText *text,
392                                        gint     offset)
393 {
394   GtkWidget *widget;
395   GtkLabel *label;
396
397   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
398   if (widget == NULL)
399     return FALSE;
400
401   label = GTK_LABEL (widget);
402
403   if (!gtk_label_get_selectable (label))
404     return FALSE;
405
406   gtk_label_select_region (label, offset, offset);
407
408   return TRUE;
409 }
410
411 static gint
412 gtk_label_accessible_get_n_selections (AtkText *text)
413 {
414   GtkWidget *widget;
415
416   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
417   if (widget == NULL)
418     return 0;
419
420   if (gtk_label_get_selection_bounds (GTK_LABEL (widget), NULL, NULL))
421     return 1;
422
423   return 0;
424 }
425
426 static gchar *
427 gtk_label_accessible_get_selection (AtkText *atk_text,
428                                     gint     selection_num,
429                                     gint    *start_pos,
430                                     gint    *end_pos)
431 {
432   GtkWidget *widget;
433   GtkLabel  *label;
434
435   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
436   if (widget == NULL)
437     return NULL;
438
439   if (selection_num != 0)
440     return NULL;
441
442   label = GTK_LABEL (widget);
443
444   if (gtk_label_get_selection_bounds (label, start_pos, end_pos))
445     {
446       const gchar *text;
447
448       text = gtk_label_get_text (label);
449
450       if (text)
451         return g_utf8_substring (text, *start_pos, *end_pos);
452     }
453
454   return NULL;
455 }
456
457 static gboolean
458 gtk_label_accessible_add_selection (AtkText *text,
459                                     gint     start_pos,
460                                     gint     end_pos)
461 {
462   GtkWidget *widget;
463   GtkLabel  *label;
464   gint start, end;
465
466   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
467   if (widget == NULL)
468     return FALSE;
469
470   label = GTK_LABEL (widget);
471
472   if (!gtk_label_get_selectable (label))
473     return FALSE;
474
475   if (!gtk_label_get_selection_bounds (label, &start, &end))
476     {
477       gtk_label_select_region (label, start_pos, end_pos);
478       return TRUE;
479     }
480   else
481     return FALSE;
482 }
483
484 static gboolean
485 gtk_label_accessible_remove_selection (AtkText *text,
486                                        gint     selection_num)
487 {
488   GtkWidget *widget;
489   GtkLabel  *label;
490   gint start, end;
491
492   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
493   if (widget == NULL)
494     return FALSE;
495
496   if (selection_num != 0)
497      return FALSE;
498
499   label = GTK_LABEL (widget);
500
501   if (!gtk_label_get_selectable (label))
502      return FALSE;
503
504   if (gtk_label_get_selection_bounds (label, &start, &end))
505     {
506       gtk_label_select_region (label, end, end);
507       return TRUE;
508     }
509   else
510     return FALSE;
511 }
512
513 static gboolean
514 gtk_label_accessible_set_selection (AtkText *text,
515                                     gint     selection_num,
516                                     gint     start_pos,
517                                     gint     end_pos)
518 {
519   GtkWidget *widget;
520   GtkLabel  *label;
521   gint start, end;
522
523   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
524   if (widget == NULL)
525     return FALSE;
526
527   if (selection_num != 0)
528     return FALSE;
529
530   label = GTK_LABEL (widget);
531
532   if (!gtk_label_get_selectable (label))
533     return FALSE;
534
535   if (gtk_label_get_selection_bounds (label, &start, &end))
536     {
537       gtk_label_select_region (label, start_pos, end_pos);
538       return TRUE;
539     }
540   else
541     return FALSE;
542 }
543
544 static void
545 gtk_label_accessible_get_character_extents (AtkText      *text,
546                                             gint          offset,
547                                             gint         *x,
548                                             gint         *y,
549                                             gint         *width,
550                                             gint         *height,
551                                             AtkCoordType  coords)
552 {
553   GtkWidget *widget;
554   GtkLabel *label;
555   PangoRectangle char_rect;
556   const gchar *label_text;
557   gint index, x_layout, y_layout;
558   GdkWindow *window;
559   gint x_window, y_window;
560
561   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
562   if (widget == NULL)
563     return;
564
565   label = GTK_LABEL (widget);
566
567   gtk_label_get_layout_offsets (label, &x_layout, &y_layout);
568   label_text = gtk_label_get_text (label);
569   index = g_utf8_offset_to_pointer (label_text, offset) - label_text;
570   pango_layout_index_to_pos (gtk_label_get_layout (label), index, &char_rect);
571   pango_extents_to_pixels (&char_rect, NULL);
572
573   window = gtk_widget_get_window (widget);
574   gdk_window_get_origin (window, &x_window, &y_window);
575
576   *x = x_window + x_layout + char_rect.x;
577   *y = y_window + y_layout + char_rect.y;
578   *width = char_rect.width;
579   *height = char_rect.height;
580
581   if (coords == ATK_XY_WINDOW)
582     {
583       window = gdk_window_get_toplevel (window);
584       gdk_window_get_origin (window, &x_window, &y_window);
585
586       *x -= x_window;
587       *y -= y_window;
588     }
589 }
590
591 static gint
592 gtk_label_accessible_get_offset_at_point (AtkText      *atk_text,
593                                           gint          x,
594                                           gint          y,
595                                           AtkCoordType  coords)
596 {
597   GtkWidget *widget;
598   GtkLabel *label;
599   const gchar *text;
600   gint index, x_layout, y_layout;
601   gint x_window, y_window;
602   gint x_local, y_local;
603   GdkWindow *window;
604
605   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
606   if (widget == NULL)
607     return -1;
608
609   label = GTK_LABEL (widget);
610
611   gtk_label_get_layout_offsets (label, &x_layout, &y_layout);
612
613   window = gtk_widget_get_window (widget);
614   gdk_window_get_origin (window, &x_window, &y_window);
615
616   x_local = x - x_layout - x_window;
617   y_local = y - y_layout - y_window;
618
619   if (coords == ATK_XY_WINDOW)
620     {
621       window = gdk_window_get_toplevel (window);
622       gdk_window_get_origin (window, &x_window, &y_window);
623
624       x_local += x_window;
625       y_local += y_window;
626     }
627
628   if (!pango_layout_xy_to_index (gtk_label_get_layout (label),
629                                  x_local * PANGO_SCALE,
630                                  y_local * PANGO_SCALE,
631                                  &index, NULL))
632     {
633       if (x_local < 0 || y_local < 0)
634         index = 0;
635       else
636         index = -1;
637     }
638
639   if (index != -1)
640     {
641       text = gtk_label_get_text (label);
642       return g_utf8_pointer_to_offset (text, text + index);
643     }
644
645   return -1;
646 }
647
648 static AtkAttributeSet *
649 add_attribute (AtkAttributeSet  *attributes,
650                AtkTextAttribute  attr,
651                const gchar      *value)
652 {
653   AtkAttribute *at;
654
655   at = g_new (AtkAttribute, 1);
656   at->name = g_strdup (atk_text_attribute_get_name (attr));
657   at->value = g_strdup (value);
658
659   return g_slist_prepend (attributes, at);
660 }
661
662 static AtkAttributeSet*
663 gtk_label_accessible_get_run_attributes (AtkText *text,
664                                          gint     offset,
665                                          gint    *start_offset,
666                                          gint    *end_offset)
667 {
668   GtkWidget *widget;
669   AtkAttributeSet *attributes;
670
671   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
672   if (widget == NULL)
673     return NULL;
674
675   attributes = NULL;
676   attributes = add_attribute (attributes, ATK_TEXT_ATTR_DIRECTION,
677                    atk_text_attribute_get_value (ATK_TEXT_ATTR_DIRECTION,
678                                                  gtk_widget_get_direction (widget)));
679   attributes = _gtk_pango_get_run_attributes (attributes,
680                                               gtk_label_get_layout (GTK_LABEL (widget)),
681                                               offset,
682                                               start_offset,
683                                               end_offset);
684
685   return attributes;
686 }
687
688 static AtkAttributeSet *
689 gtk_label_accessible_get_default_attributes (AtkText *text)
690 {
691   GtkWidget *widget;
692   AtkAttributeSet *attributes;
693
694   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
695   if (widget == NULL)
696     return NULL;
697
698   attributes = NULL;
699   attributes = add_attribute (attributes, ATK_TEXT_ATTR_DIRECTION,
700                    atk_text_attribute_get_value (ATK_TEXT_ATTR_DIRECTION,
701                                                  gtk_widget_get_direction (widget)));
702   attributes = _gtk_pango_get_default_attributes (attributes,
703                                                   gtk_label_get_layout (GTK_LABEL (widget)));
704   attributes = _gtk_style_context_get_attributes (attributes,
705                                                   gtk_widget_get_style_context (widget),
706                                                   gtk_widget_get_state_flags (widget));
707
708   return attributes;
709 }
710
711 static gunichar
712 gtk_label_accessible_get_character_at_offset (AtkText *atk_text,
713                                               gint     offset)
714 {
715   GtkWidget *widget;
716   const gchar *text;
717   gchar *index;
718
719   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
720   if (widget == NULL)
721     return '\0';
722
723   text = gtk_label_get_text (GTK_LABEL (widget));
724   if (offset >= g_utf8_strlen (text, -1))
725     return '\0';
726
727   index = g_utf8_offset_to_pointer (text, offset);
728
729   return g_utf8_get_char (index);
730 }
731
732 static void
733 atk_text_interface_init (AtkTextIface *iface)
734 {
735   iface->get_text = gtk_label_accessible_get_text;
736   iface->get_character_at_offset = gtk_label_accessible_get_character_at_offset;
737   iface->get_text_before_offset = gtk_label_accessible_get_text_before_offset;
738   iface->get_text_at_offset = gtk_label_accessible_get_text_at_offset;
739   iface->get_text_after_offset = gtk_label_accessible_get_text_after_offset;
740   iface->get_character_count = gtk_label_accessible_get_character_count;
741   iface->get_caret_offset = gtk_label_accessible_get_caret_offset;
742   iface->set_caret_offset = gtk_label_accessible_set_caret_offset;
743   iface->get_n_selections = gtk_label_accessible_get_n_selections;
744   iface->get_selection = gtk_label_accessible_get_selection;
745   iface->add_selection = gtk_label_accessible_add_selection;
746   iface->remove_selection = gtk_label_accessible_remove_selection;
747   iface->set_selection = gtk_label_accessible_set_selection;
748   iface->get_character_extents = gtk_label_accessible_get_character_extents;
749   iface->get_offset_at_point = gtk_label_accessible_get_offset_at_point;
750   iface->get_run_attributes = gtk_label_accessible_get_run_attributes;
751   iface->get_default_attributes = gtk_label_accessible_get_default_attributes;
752 }
753