gnome-shell-3.6.3.1/src/st/st-button.c

No issues found

  1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
  2 /*
  3  * st-button.c: Plain button actor
  4  *
  5  * Copyright 2007 OpenedHand
  6  * Copyright 2008, 2009 Intel Corporation.
  7  * Copyright 2009, 2010 Red Hat, Inc.
  8  *
  9  * This program is free software; you can redistribute it and/or modify it
 10  * under the terms and conditions of the GNU Lesser General Public License,
 11  * version 2.1, as published by the Free Software Foundation.
 12  *
 13  * This program is distributed in the hope it will be useful, but WITHOUT ANY
 14  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 15  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
 16  * more details.
 17  *
 18  * You should have received a copy of the GNU Lesser General Public License
 19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
 20  */
 21 
 22 /**
 23  * SECTION:st-button
 24  * @short_description: Button widget
 25  *
 26  * A button widget with support for either a text label or icon, toggle mode
 27  * and transitions effects between states.
 28  */
 29 
 30 #ifdef HAVE_CONFIG_H
 31 #include "config.h"
 32 #endif
 33 
 34 #include <stdlib.h>
 35 #include <string.h>
 36 
 37 #include <glib.h>
 38 
 39 #include <clutter/clutter.h>
 40 
 41 #include "st-button.h"
 42 
 43 #include "st-enum-types.h"
 44 #include "st-texture-cache.h"
 45 #include "st-private.h"
 46 
 47 #include <st/st-widget-accessible.h>
 48 
 49 enum
 50 {
 51   PROP_0,
 52 
 53   PROP_LABEL,
 54   PROP_BUTTON_MASK,
 55   PROP_TOGGLE_MODE,
 56   PROP_CHECKED,
 57   PROP_PRESSED
 58 };
 59 
 60 enum
 61 {
 62   CLICKED,
 63 
 64   LAST_SIGNAL
 65 };
 66 
 67 #define ST_BUTTON_GET_PRIVATE(obj)    \
 68   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_BUTTON, StButtonPrivate))
 69 
 70 struct _StButtonPrivate
 71 {
 72   gchar *text;
 73 
 74   guint  button_mask : 3;
 75   guint  is_toggle   : 1;
 76 
 77   guint  pressed     : 3;
 78   guint  grabbed     : 3;
 79   guint  is_checked  : 1;
 80 
 81   gint   spacing;
 82 };
 83 
 84 static guint button_signals[LAST_SIGNAL] = { 0, };
 85 
 86 G_DEFINE_TYPE (StButton, st_button, ST_TYPE_BIN);
 87 
 88 static GType st_button_accessible_get_type (void) G_GNUC_CONST;
 89 
 90 static void
 91 st_button_update_label_style (StButton *button)
 92 {
 93   ClutterActor *label;
 94 
 95   label = st_bin_get_child (ST_BIN (button));
 96 
 97   /* check the child is really a label */
 98   if (!CLUTTER_IS_TEXT (label))
 99     return;
100 
101   _st_set_text_from_style (CLUTTER_TEXT (label), st_widget_get_theme_node (ST_WIDGET (button)));
102 }
103 
104 static void
105 st_button_style_changed (StWidget *widget)
106 {
107   StButton *button = ST_BUTTON (widget);
108   StButtonPrivate *priv = button->priv;
109   StButtonClass *button_class = ST_BUTTON_GET_CLASS (button);
110   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (button));
111   double spacing;
112 
113   ST_WIDGET_CLASS (st_button_parent_class)->style_changed (widget);
114 
115   spacing = 6;
116   st_theme_node_lookup_length (theme_node, "border-spacing", FALSE, &spacing);
117   priv->spacing = (int)(0.5 + spacing);
118 
119   /* update the label styling */
120   st_button_update_label_style (button);
121 
122   /* run a transition if applicable */
123   if (button_class->transition)
124     {
125       button_class->transition (button);
126     }
127 }
128 
129 static void
130 st_button_press (StButton     *button,
131                  StButtonMask  mask)
132 {
133   if (button->priv->pressed == 0)
134     st_widget_add_style_pseudo_class (ST_WIDGET (button), "active");
135 
136   button->priv->pressed |= mask;
137 }
138 
139 static void
140 st_button_release (StButton     *button,
141                    StButtonMask  mask,
142                    int           clicked_button)
143 {
144   button->priv->pressed &= ~mask;
145   if (button->priv->pressed != 0)
146     return;
147 
148   st_widget_remove_style_pseudo_class (ST_WIDGET (button), "active");
149 
150   if (clicked_button)
151     {
152       if (button->priv->is_toggle)
153         st_button_set_checked (button, !button->priv->is_checked);
154 
155       g_signal_emit (button, button_signals[CLICKED], 0, clicked_button);
156     }
157 }
158 
159 static gboolean
160 st_button_button_press (ClutterActor       *actor,
161                         ClutterButtonEvent *event)
162 {
163   StButton *button = ST_BUTTON (actor);
164   StButtonMask mask = ST_BUTTON_MASK_FROM_BUTTON (event->button);
165 
166   if (button->priv->button_mask & mask)
167     {
168       if (button->priv->grabbed == 0)
169         clutter_grab_pointer (actor);
170 
171       button->priv->grabbed |= mask;
172       st_button_press (button, mask);
173 
174       return TRUE;
175     }
176 
177   return FALSE;
178 }
179 
180 static gboolean
181 st_button_button_release (ClutterActor       *actor,
182                           ClutterButtonEvent *event)
183 {
184   StButton *button = ST_BUTTON (actor);
185   StButtonMask mask = ST_BUTTON_MASK_FROM_BUTTON (event->button);
186 
187   if (button->priv->button_mask & mask)
188     {
189       gboolean is_click;
190 
191       is_click = button->priv->grabbed && st_widget_get_hover (ST_WIDGET (button));
192       st_button_release (button, mask, is_click ? event->button : 0);
193 
194       button->priv->grabbed &= ~mask;
195       if (button->priv->grabbed == 0)
196         clutter_ungrab_pointer ();
197 
198       return TRUE;
199     }
200 
201   return FALSE;
202 }
203 
204 static gboolean
205 st_button_key_press (ClutterActor    *actor,
206                      ClutterKeyEvent *event)
207 {
208   StButton *button = ST_BUTTON (actor);
209 
210   if (button->priv->button_mask & ST_BUTTON_ONE)
211     {
212       if (event->keyval == CLUTTER_KEY_space ||
213           event->keyval == CLUTTER_KEY_Return ||
214           event->keyval == CLUTTER_KEY_KP_Enter)
215         {
216           st_button_press (button, ST_BUTTON_ONE);
217           return TRUE;
218         }
219     }
220 
221   return CLUTTER_ACTOR_CLASS (st_button_parent_class)->key_press_event (actor, event);
222 }
223 
224 static gboolean
225 st_button_key_release (ClutterActor    *actor,
226                        ClutterKeyEvent *event)
227 {
228   StButton *button = ST_BUTTON (actor);
229 
230   if (button->priv->button_mask & ST_BUTTON_ONE)
231     {
232       if (event->keyval == CLUTTER_KEY_space ||
233           event->keyval == CLUTTER_KEY_Return ||
234           event->keyval == CLUTTER_KEY_KP_Enter)
235         {
236           gboolean is_click;
237 
238           is_click = (button->priv->pressed & ST_BUTTON_ONE);
239           st_button_release (button, ST_BUTTON_ONE, is_click ? 1 : 0);
240           return TRUE;
241         }
242     }
243 
244   return FALSE;
245 }
246 
247 static void
248 st_button_key_focus_out (ClutterActor *actor)
249 {
250   StButton *button = ST_BUTTON (actor);
251 
252   /* If we lose focus between a key press and release, undo the press */
253   if ((button->priv->pressed & ST_BUTTON_ONE) &&
254       !(button->priv->grabbed & ST_BUTTON_ONE))
255     st_button_release (button, ST_BUTTON_ONE, 0);
256 
257   CLUTTER_ACTOR_CLASS (st_button_parent_class)->key_focus_out (actor);
258 }
259 
260 static gboolean
261 st_button_enter (ClutterActor         *actor,
262                  ClutterCrossingEvent *event)
263 {
264   StButton *button = ST_BUTTON (actor);
265   gboolean ret;
266 
267   ret = CLUTTER_ACTOR_CLASS (st_button_parent_class)->enter_event (actor, event);
268 
269   if (button->priv->grabbed)
270     {
271       if (st_widget_get_hover (ST_WIDGET (button)))
272         st_button_press (button, button->priv->grabbed);
273       else
274         st_button_release (button, button->priv->grabbed, 0);
275     }
276 
277   return ret;
278 }
279 
280 static gboolean
281 st_button_leave (ClutterActor         *actor,
282                  ClutterCrossingEvent *event)
283 {
284   StButton *button = ST_BUTTON (actor);
285   gboolean ret;
286 
287   ret = CLUTTER_ACTOR_CLASS (st_button_parent_class)->leave_event (actor, event);
288 
289   if (button->priv->grabbed)
290     {
291       if (st_widget_get_hover (ST_WIDGET (button)))
292         st_button_press (button, button->priv->grabbed);
293       else
294         st_button_release (button, button->priv->grabbed, 0);
295     }
296 
297   return ret;
298 }
299 
300 static void
301 st_button_set_property (GObject      *gobject,
302                         guint         prop_id,
303                         const GValue *value,
304                         GParamSpec   *pspec)
305 {
306   StButton *button = ST_BUTTON (gobject);
307 
308   switch (prop_id)
309     {
310     case PROP_LABEL:
311       st_button_set_label (button, g_value_get_string (value));
312       break;
313     case PROP_BUTTON_MASK:
314       st_button_set_button_mask (button, g_value_get_flags (value));
315       break;
316     case PROP_TOGGLE_MODE:
317       st_button_set_toggle_mode (button, g_value_get_boolean (value));
318       break;
319     case PROP_CHECKED:
320       st_button_set_checked (button, g_value_get_boolean (value));
321       break;
322 
323 
324     default:
325       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
326       break;
327     }
328 }
329 
330 static void
331 st_button_get_property (GObject    *gobject,
332                         guint       prop_id,
333                         GValue     *value,
334                         GParamSpec *pspec)
335 {
336   StButtonPrivate *priv = ST_BUTTON (gobject)->priv;
337 
338   switch (prop_id)
339     {
340     case PROP_LABEL:
341       g_value_set_string (value, priv->text);
342       break;
343     case PROP_BUTTON_MASK:
344       g_value_set_flags (value, priv->button_mask);
345       break;
346     case PROP_TOGGLE_MODE:
347       g_value_set_boolean (value, priv->is_toggle);
348       break;
349     case PROP_CHECKED:
350       g_value_set_boolean (value, priv->is_checked);
351       break;
352     case PROP_PRESSED:
353       g_value_set_boolean (value, priv->pressed != 0);
354       break;
355 
356 
357     default:
358       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
359       break;
360     }
361 }
362 
363 static void
364 st_button_finalize (GObject *gobject)
365 {
366   StButtonPrivate *priv = ST_BUTTON (gobject)->priv;
367 
368   g_free (priv->text);
369 
370   G_OBJECT_CLASS (st_button_parent_class)->finalize (gobject);
371 }
372 
373 static void
374 st_button_class_init (StButtonClass *klass)
375 {
376   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
377   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
378   StWidgetClass *widget_class = ST_WIDGET_CLASS (klass);
379   GParamSpec *pspec;
380 
381   g_type_class_add_private (klass, sizeof (StButtonPrivate));
382 
383   gobject_class->set_property = st_button_set_property;
384   gobject_class->get_property = st_button_get_property;
385   gobject_class->finalize = st_button_finalize;
386 
387   actor_class->button_press_event = st_button_button_press;
388   actor_class->button_release_event = st_button_button_release;
389   actor_class->key_press_event = st_button_key_press;
390   actor_class->key_release_event = st_button_key_release;
391   actor_class->key_focus_out = st_button_key_focus_out;
392   actor_class->enter_event = st_button_enter;
393   actor_class->leave_event = st_button_leave;
394 
395   widget_class->style_changed = st_button_style_changed;
396   widget_class->get_accessible_type = st_button_accessible_get_type;
397 
398   pspec = g_param_spec_string ("label",
399                                "Label",
400                                "Label of the button",
401                                NULL, G_PARAM_READWRITE);
402   g_object_class_install_property (gobject_class, PROP_LABEL, pspec);
403 
404   pspec = g_param_spec_flags ("button-mask",
405                               "Button mask",
406                               "Which buttons trigger the 'clicked' signal",
407                               ST_TYPE_BUTTON_MASK, ST_BUTTON_ONE,
408                               G_PARAM_READWRITE);
409   g_object_class_install_property (gobject_class, PROP_BUTTON_MASK, pspec);
410 
411   pspec = g_param_spec_boolean ("toggle-mode",
412                                 "Toggle Mode",
413                                 "Enable or disable toggling",
414                                 FALSE, G_PARAM_READWRITE);
415   g_object_class_install_property (gobject_class, PROP_TOGGLE_MODE, pspec);
416 
417   pspec = g_param_spec_boolean ("checked",
418                                 "Checked",
419                                 "Indicates if a toggle button is \"on\""
420                                 " or \"off\"",
421                                 FALSE, G_PARAM_READWRITE);
422   g_object_class_install_property (gobject_class, PROP_CHECKED, pspec);
423 
424   pspec = g_param_spec_boolean ("pressed",
425                                 "Pressed",
426                                 "Indicates if the button is pressed in",
427                                 FALSE, G_PARAM_READABLE);
428   g_object_class_install_property (gobject_class, PROP_PRESSED, pspec);
429 
430 
431   /**
432    * StButton::clicked:
433    * @button: the object that received the signal
434    * @clicked_button: the mouse button that was used
435    *
436    * Emitted when the user activates the button, either with a mouse press and
437    * release or with the keyboard.
438    */
439   button_signals[CLICKED] =
440     g_signal_new ("clicked",
441                   G_TYPE_FROM_CLASS (klass),
442                   G_SIGNAL_RUN_LAST,
443                   G_STRUCT_OFFSET (StButtonClass, clicked),
444                   NULL, NULL, NULL,
445                   G_TYPE_NONE, 1,
446                   G_TYPE_INT);
447 }
448 
449 static void
450 st_button_init (StButton *button)
451 {
452   button->priv = ST_BUTTON_GET_PRIVATE (button);
453   button->priv->spacing = 6;
454   button->priv->button_mask = ST_BUTTON_ONE;
455 
456   clutter_actor_set_reactive (CLUTTER_ACTOR (button), TRUE);
457   st_widget_set_track_hover (ST_WIDGET (button), TRUE);
458 }
459 
460 /**
461  * st_button_new:
462  *
463  * Create a new button
464  *
465  * Returns: a new #StButton
466  */
467 StWidget *
468 st_button_new (void)
469 {
470   return g_object_new (ST_TYPE_BUTTON, NULL);
471 }
472 
473 /**
474  * st_button_new_with_label:
475  * @text: text to set the label to
476  *
477  * Create a new #StButton with the specified label
478  *
479  * Returns: a new #StButton
480  */
481 StWidget *
482 st_button_new_with_label (const gchar *text)
483 {
484   return g_object_new (ST_TYPE_BUTTON, "label", text, NULL);
485 }
486 
487 /**
488  * st_button_get_label:
489  * @button: a #StButton
490  *
491  * Get the text displayed on the button
492  *
493  * Returns: the text for the button. This must not be freed by the application
494  */
495 const gchar *
496 st_button_get_label (StButton *button)
497 {
498   g_return_val_if_fail (ST_IS_BUTTON (button), NULL);
499 
500   return button->priv->text;
501 }
502 
503 /**
504  * st_button_set_label:
505  * @button: a #Stbutton
506  * @text: text to set the label to
507  *
508  * Sets the text displayed on the button
509  */
510 void
511 st_button_set_label (StButton    *button,
512                      const gchar *text)
513 {
514   StButtonPrivate *priv;
515   ClutterActor *label;
516 
517   g_return_if_fail (ST_IS_BUTTON (button));
518 
519   priv = button->priv;
520 
521   g_free (priv->text);
522 
523   if (text)
524     priv->text = g_strdup (text);
525   else
526     priv->text = g_strdup ("");
527 
528   label = st_bin_get_child (ST_BIN (button));
529 
530   if (label && CLUTTER_IS_TEXT (label))
531     {
532       clutter_text_set_text (CLUTTER_TEXT (label), priv->text);
533     }
534   else
535     {
536       label = g_object_new (CLUTTER_TYPE_TEXT,
537                             "text", priv->text,
538                             "line-alignment", PANGO_ALIGN_CENTER,
539                             "ellipsize", PANGO_ELLIPSIZE_END,
540                             "use-markup", TRUE,
541                             NULL);
542       st_bin_set_child (ST_BIN (button), label);
543     }
544 
545   /* Fake a style change so that we reset the style properties on the label */
546   st_widget_style_changed (ST_WIDGET (button));
547 
548   g_object_notify (G_OBJECT (button), "label");
549 }
550 
551 /**
552  * st_button_get_button_mask:
553  * @button: a #StButton
554  *
555  * Gets the mask of mouse buttons that @button emits the
556  * #StButton::clicked signal for.
557  *
558  * Returns: the mask of mouse buttons that @button emits the
559  * #StButton::clicked signal for.
560  */
561 StButtonMask
562 st_button_get_button_mask (StButton *button)
563 {
564   g_return_val_if_fail (ST_IS_BUTTON (button), 0);
565 
566   return button->priv->button_mask;
567 }
568 
569 /**
570  * st_button_set_button_mask:
571  * @button: a #Stbutton
572  * @mask: the mask of mouse buttons that @button responds to
573  *
574  * Sets which mouse buttons @button emits #StButton::clicked for.
575  */
576 void
577 st_button_set_button_mask (StButton     *button,
578                            StButtonMask  mask)
579 {
580   g_return_if_fail (ST_IS_BUTTON (button));
581 
582   button->priv->button_mask = mask;
583 
584   g_object_notify (G_OBJECT (button), "button-mask");
585 }
586 
587 /**
588  * st_button_get_toggle_mode:
589  * @button: a #StButton
590  *
591  * Get the toggle mode status of the button.
592  *
593  * Returns: %TRUE if toggle mode is set, otherwise %FALSE
594  */
595 gboolean
596 st_button_get_toggle_mode (StButton *button)
597 {
598   g_return_val_if_fail (ST_IS_BUTTON (button), FALSE);
599 
600   return button->priv->is_toggle;
601 }
602 
603 /**
604  * st_button_set_toggle_mode:
605  * @button: a #Stbutton
606  * @toggle: %TRUE or %FALSE
607  *
608  * Enables or disables toggle mode for the button. In toggle mode, the active
609  * state will be "toggled" when the user clicks the button.
610  */
611 void
612 st_button_set_toggle_mode (StButton *button,
613                            gboolean  toggle)
614 {
615   g_return_if_fail (ST_IS_BUTTON (button));
616 
617   button->priv->is_toggle = toggle;
618 
619   g_object_notify (G_OBJECT (button), "toggle-mode");
620 }
621 
622 /**
623  * st_button_get_checked:
624  * @button: a #StButton
625  *
626  * Get the state of the button that is in toggle mode.
627  *
628  * Returns: %TRUE if the button is checked, or %FALSE if not
629  */
630 gboolean
631 st_button_get_checked (StButton *button)
632 {
633   g_return_val_if_fail (ST_IS_BUTTON (button), FALSE);
634 
635   return button->priv->is_checked;
636 }
637 
638 /**
639  * st_button_set_checked:
640  * @button: a #Stbutton
641  * @checked: %TRUE or %FALSE
642  *
643  * Sets the pressed state of the button. This is only really useful if the
644  * button has #toggle-mode mode set to %TRUE.
645  */
646 void
647 st_button_set_checked (StButton *button,
648                        gboolean  checked)
649 {
650   g_return_if_fail (ST_IS_BUTTON (button));
651 
652   if (button->priv->is_checked != checked)
653     {
654       button->priv->is_checked = checked;
655 
656       if (checked)
657         st_widget_add_style_pseudo_class (ST_WIDGET (button), "checked");
658       else
659         st_widget_remove_style_pseudo_class (ST_WIDGET (button), "checked");
660     }
661 
662   g_object_notify (G_OBJECT (button), "checked");
663 }
664 
665 /**
666  * st_button_fake_release:
667  * @button: an #StButton
668  *
669  * If this widget is holding a pointer grab, this function will
670  * will ungrab it, and reset the pressed state.  The effect is
671  * similar to if the user had released the mouse button, but without
672  * emitting the clicked signal.
673  *
674  * This function is useful if for example you want to do something
675  * after the user is holding the mouse button for a given period of
676  * time, breaking the grab.
677  */
678 void
679 st_button_fake_release (StButton *button)
680 {
681   if (button->priv->pressed)
682     st_button_release (button, button->priv->pressed, 0);
683 
684   if (button->priv->grabbed)
685     {
686       button->priv->grabbed = 0;
687       clutter_ungrab_pointer ();
688     }
689 }
690 
691 /******************************************************************************/
692 /*************************** ACCESSIBILITY SUPPORT ****************************/
693 /******************************************************************************/
694 
695 #define ST_TYPE_BUTTON_ACCESSIBLE st_button_accessible_get_type ()
696 
697 #define ST_BUTTON_ACCESSIBLE(obj) \
698   (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
699   ST_TYPE_BUTTON_ACCESSIBLE, StButtonAccessible))
700 
701 #define ST_IS_BUTTON_ACCESSIBLE(obj) \
702   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
703   ST_TYPE_BUTTON_ACCESSIBLE))
704 
705 #define ST_BUTTON_ACCESSIBLE_CLASS(klass) \
706   (G_TYPE_CHECK_CLASS_CAST ((klass), \
707   ST_TYPE_BUTTON_ACCESSIBLE, StButtonAccessibleClass))
708 
709 #define ST_IS_BUTTON_ACCESSIBLE_CLASS(klass) \
710   (G_TYPE_CHECK_CLASS_TYPE ((klass), \
711   ST_TYPE_BUTTON_ACCESSIBLE))
712 
713 #define ST_BUTTON_ACCESSIBLE_GET_CLASS(obj) \
714   (G_TYPE_INSTANCE_GET_CLASS ((obj), \
715   ST_TYPE_BUTTON_ACCESSIBLE, StButtonAccessibleClass))
716 
717 typedef struct _StButtonAccessible  StButtonAccessible;
718 typedef struct _StButtonAccessibleClass  StButtonAccessibleClass;
719 
720 struct _StButtonAccessible
721 {
722   StWidgetAccessible parent;
723 };
724 
725 struct _StButtonAccessibleClass
726 {
727   StWidgetAccessibleClass parent_class;
728 };
729 
730 static void st_button_accessible_class_init (StButtonAccessibleClass *klass);
731 static void st_button_accessible_init       (StButtonAccessible *button);
732 
733 /* AtkObject */
734 static void          st_button_accessible_initialize (AtkObject *obj,
735                                                       gpointer   data);
736 
737 G_DEFINE_TYPE (StButtonAccessible, st_button_accessible, ST_TYPE_WIDGET_ACCESSIBLE)
738 
739 static const gchar *
740 st_button_accessible_get_name (AtkObject *obj)
741 {
742   StButton *button = NULL;
743   const gchar *name = NULL;
744 
745   button = ST_BUTTON (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (obj)));
746 
747   if (button == NULL)
748     return NULL;
749 
750   name = ATK_OBJECT_CLASS (st_button_accessible_parent_class)->get_name (obj);
751   if (name != NULL)
752     return name;
753 
754   return button->priv->text;
755 }
756 
757 static void
758 st_button_accessible_class_init (StButtonAccessibleClass *klass)
759 {
760   AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass);
761 
762   atk_class->initialize = st_button_accessible_initialize;
763   atk_class->get_name = st_button_accessible_get_name;
764 }
765 
766 static void
767 st_button_accessible_init (StButtonAccessible *self)
768 {
769   /* initialization done on AtkObject->initialize */
770 }
771 
772 static void
773 st_button_accessible_notify_label_cb (StButton   *button,
774                                       GParamSpec *psec,
775                                       AtkObject  *accessible)
776 {
777   g_object_notify (G_OBJECT (accessible), "accessible-name");
778 }
779 
780 static void
781 st_button_accessible_compute_role (AtkObject *accessible,
782                                    StButton  *button)
783 {
784   atk_object_set_role (accessible, button->priv->is_toggle
785                        ? ATK_ROLE_TOGGLE_BUTTON : ATK_ROLE_PUSH_BUTTON);
786 }
787 
788 static void
789 st_button_accessible_notify_toggle_mode_cb (StButton   *button,
790                                             GParamSpec *psec,
791                                             AtkObject  *accessible)
792 {
793   st_button_accessible_compute_role (accessible, button);
794 }
795 
796 static void
797 st_button_accessible_initialize (AtkObject *obj,
798                                  gpointer   data)
799 {
800   ATK_OBJECT_CLASS (st_button_accessible_parent_class)->initialize (obj, data);
801 
802   st_button_accessible_compute_role (obj, ST_BUTTON (data));
803 
804   g_signal_connect (data, "notify::label",
805                     G_CALLBACK (st_button_accessible_notify_label_cb), obj);
806   g_signal_connect (data, "notify::toggle-mode",
807                     G_CALLBACK (st_button_accessible_notify_toggle_mode_cb), obj);
808 }