2010-06-14 11:38:25 +00:00
|
|
|
/* CALLY - The Clutter Accessibility Implementation Library
|
|
|
|
*
|
|
|
|
* Copyright (C) 2008 Igalia, S.L.
|
|
|
|
*
|
|
|
|
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
|
|
|
*
|
2010-07-05 13:43:18 +00:00
|
|
|
* Some parts are based on GailWidget from GAIL
|
2010-06-14 11:38:25 +00:00
|
|
|
* GAIL - The GNOME Accessibility Implementation Library
|
|
|
|
* Copyright 2001, 2002, 2003 Sun Microsystems Inc.
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2010-07-05 13:43:18 +00:00
|
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
2010-06-14 11:38:25 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* SECTION:cally-actor
|
2010-07-05 13:43:18 +00:00
|
|
|
* @Title: CallyActor
|
2010-06-14 11:38:25 +00:00
|
|
|
* @short_description: Implementation of the ATK interfaces for #ClutterActor
|
|
|
|
* @see_also: #ClutterActor
|
|
|
|
*
|
|
|
|
* #CallyActor implements the required ATK interfaces of #ClutterActor
|
2010-07-05 14:10:42 +00:00
|
|
|
* exposing the common elements on each actor (position, extents, etc).
|
2010-06-14 11:38:25 +00:00
|
|
|
*/
|
|
|
|
|
2010-07-05 13:43:18 +00:00
|
|
|
/*
|
2010-06-14 11:38:25 +00:00
|
|
|
*
|
|
|
|
* IMPLEMENTATION NOTES:
|
|
|
|
*
|
|
|
|
* ####
|
|
|
|
*
|
|
|
|
* Focus: clutter hasn't got the focus concept in the same way that GTK, but it
|
|
|
|
* has a key focus managed by the stage. Basically any actor can be focused using
|
|
|
|
* clutter_stage_set_key_focus. So, we will use this approach: all actors are
|
|
|
|
* focusable, and we get the currently focused using clutter_stage_get_key_focus
|
|
|
|
* This affects focus related stateset and some atk_componenet focus methods (like
|
2012-02-08 17:46:11 +00:00
|
|
|
* grab focus).
|
|
|
|
*
|
|
|
|
* In the same way, we will manage the focus state change management
|
|
|
|
* on the cally-stage object. The reason is avoid missing a focus
|
|
|
|
* state change event if the object is focused just before the
|
|
|
|
* accessibility object being created.
|
2010-06-14 11:38:25 +00:00
|
|
|
*
|
2011-05-19 10:58:36 +00:00
|
|
|
* #AtkAction implementation: on previous releases ClutterActor added
|
|
|
|
* the actions "press", "release" and "click", as at that time some
|
|
|
|
* general-purpose actors like textures were directly used as buttons.
|
2010-06-14 11:38:25 +00:00
|
|
|
*
|
2011-05-19 10:58:36 +00:00
|
|
|
* But now, new toolkits appeared, providing high-level widgets, like
|
|
|
|
* buttons. So in this environment, it doesn't make sense to keep
|
|
|
|
* adding them as default.
|
2010-06-14 11:38:25 +00:00
|
|
|
*
|
2011-05-19 10:58:36 +00:00
|
|
|
* Anyway, current implementation of AtkAction is done at CallyActor
|
|
|
|
* providing methods to add and remove actions. This is based on the
|
|
|
|
* one used at gailcell, and proposed as a change on #AtkAction
|
|
|
|
* interface:
|
2010-06-14 11:38:25 +00:00
|
|
|
*
|
2011-05-19 10:58:36 +00:00
|
|
|
* https://bugzilla.gnome.org/show_bug.cgi?id=649804
|
2010-06-14 11:38:25 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2010-07-05 13:43:18 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
2010-06-14 11:38:25 +00:00
|
|
|
#include "config.h"
|
2010-07-05 13:43:18 +00:00
|
|
|
#endif
|
2010-06-14 11:38:25 +00:00
|
|
|
|
2010-09-29 13:10:38 +00:00
|
|
|
#include <glib.h>
|
2010-06-14 11:38:25 +00:00
|
|
|
#include <clutter/clutter.h>
|
|
|
|
|
2010-07-06 11:36:48 +00:00
|
|
|
#ifdef HAVE_CLUTTER_GLX
|
2010-06-14 11:38:25 +00:00
|
|
|
#include <clutter/x11/clutter-x11.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
#include "cally-actor.h"
|
|
|
|
#include "cally-actor-private.h"
|
|
|
|
|
|
|
|
typedef struct _CallyActorActionInfo CallyActorActionInfo;
|
|
|
|
|
2010-07-05 14:10:42 +00:00
|
|
|
/*< private >
|
2010-06-14 11:38:25 +00:00
|
|
|
* CallyActorActionInfo:
|
|
|
|
* @name: name of the action
|
|
|
|
* @description: description of the action
|
|
|
|
* @keybinding: keybinding related to the action
|
|
|
|
* @do_action_func: callback
|
2010-12-10 17:46:58 +00:00
|
|
|
* @user_data: data to be passed to @do_action_func
|
|
|
|
* @notify: function to be called when removing the action
|
2010-06-14 11:38:25 +00:00
|
|
|
*
|
|
|
|
* Utility structure to maintain the different actions added to the
|
|
|
|
* #CallyActor
|
|
|
|
*/
|
|
|
|
struct _CallyActorActionInfo
|
|
|
|
{
|
2010-12-10 17:46:58 +00:00
|
|
|
gchar *name;
|
|
|
|
gchar *description;
|
|
|
|
gchar *keybinding;
|
|
|
|
|
|
|
|
CallyActionCallback do_action_func;
|
|
|
|
gpointer user_data;
|
|
|
|
GDestroyNotify notify;
|
2010-06-14 11:38:25 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static void cally_actor_initialize (AtkObject *obj,
|
|
|
|
gpointer data);
|
|
|
|
static void cally_actor_finalize (GObject *obj);
|
|
|
|
|
|
|
|
/* AtkObject.h */
|
|
|
|
static AtkObject* cally_actor_get_parent (AtkObject *obj);
|
|
|
|
static gint cally_actor_get_index_in_parent (AtkObject *obj);
|
|
|
|
static AtkStateSet* cally_actor_ref_state_set (AtkObject *obj);
|
|
|
|
static gint cally_actor_get_n_children (AtkObject *obj);
|
|
|
|
static AtkObject* cally_actor_ref_child (AtkObject *obj,
|
|
|
|
gint i);
|
2011-07-06 12:25:02 +00:00
|
|
|
static AtkAttributeSet * cally_actor_get_attributes (AtkObject *obj);
|
|
|
|
|
2010-06-14 11:38:25 +00:00
|
|
|
/* ClutterContainer */
|
|
|
|
static gint cally_actor_add_actor (ClutterActor *container,
|
|
|
|
ClutterActor *actor,
|
|
|
|
gpointer data);
|
|
|
|
static gint cally_actor_remove_actor (ClutterActor *container,
|
|
|
|
ClutterActor *actor,
|
|
|
|
gpointer data);
|
|
|
|
static gint cally_actor_real_add_actor (ClutterActor *container,
|
|
|
|
ClutterActor *actor,
|
|
|
|
gpointer data);
|
|
|
|
static gint cally_actor_real_remove_actor (ClutterActor *container,
|
|
|
|
ClutterActor *actor,
|
|
|
|
gpointer data);
|
|
|
|
|
|
|
|
/* AtkComponent.h */
|
|
|
|
static void cally_actor_component_interface_init (AtkComponentIface *iface);
|
|
|
|
static void cally_actor_get_extents (AtkComponent *component,
|
|
|
|
gint *x,
|
|
|
|
gint *y,
|
|
|
|
gint *width,
|
|
|
|
gint *height,
|
|
|
|
AtkCoordType coord_type);
|
|
|
|
static gint cally_actor_get_mdi_zorder (AtkComponent *component);
|
|
|
|
static gboolean cally_actor_grab_focus (AtkComponent *component);
|
|
|
|
|
|
|
|
/* AtkAction.h */
|
|
|
|
static void cally_actor_action_interface_init (AtkActionIface *iface);
|
|
|
|
static gboolean cally_actor_action_do_action (AtkAction *action,
|
|
|
|
gint i);
|
|
|
|
static gboolean idle_do_action (gpointer data);
|
|
|
|
static gint cally_actor_action_get_n_actions (AtkAction *action);
|
Eliminate G_CONST_RETURN
The G_CONST_RETURN define in GLib is, and has always been, a bit fuzzy.
We always used it to conform to the platform, at least for public-facing
API.
At first I assumed it has something to do with brain-damaged compilers
or with weird platforms where const was not really supported; sadly,
it's something much, much worse: it's a define that can be toggled at
compile-time to remove const from the signature of public API. This is a
truly terrifying feature that I assume was added in the past century,
and whose inception clearly had something to do with massive doses of
absynthe and opium — because any other explanation would make the
existence of such a feature even worse than assuming drugs had anything
to do with it.
Anyway, and pleasing the gods, this dubious feature is being
removed/deprecated in GLib; see bug:
https://bugzilla.gnome.org/show_bug.cgi?id=644611
Before deprecation, though, we should just remove its usage from the
whole API. We should especially remove its usage from Cally's internals,
since there it never made sense in the first place.
2011-06-07 14:49:20 +00:00
|
|
|
static const gchar* cally_actor_action_get_description (AtkAction *action,
|
2010-06-14 11:38:25 +00:00
|
|
|
gint i);
|
Eliminate G_CONST_RETURN
The G_CONST_RETURN define in GLib is, and has always been, a bit fuzzy.
We always used it to conform to the platform, at least for public-facing
API.
At first I assumed it has something to do with brain-damaged compilers
or with weird platforms where const was not really supported; sadly,
it's something much, much worse: it's a define that can be toggled at
compile-time to remove const from the signature of public API. This is a
truly terrifying feature that I assume was added in the past century,
and whose inception clearly had something to do with massive doses of
absynthe and opium — because any other explanation would make the
existence of such a feature even worse than assuming drugs had anything
to do with it.
Anyway, and pleasing the gods, this dubious feature is being
removed/deprecated in GLib; see bug:
https://bugzilla.gnome.org/show_bug.cgi?id=644611
Before deprecation, though, we should just remove its usage from the
whole API. We should especially remove its usage from Cally's internals,
since there it never made sense in the first place.
2011-06-07 14:49:20 +00:00
|
|
|
static const gchar* cally_actor_action_get_keybinding (AtkAction *action,
|
2010-06-14 11:38:25 +00:00
|
|
|
gint i);
|
Eliminate G_CONST_RETURN
The G_CONST_RETURN define in GLib is, and has always been, a bit fuzzy.
We always used it to conform to the platform, at least for public-facing
API.
At first I assumed it has something to do with brain-damaged compilers
or with weird platforms where const was not really supported; sadly,
it's something much, much worse: it's a define that can be toggled at
compile-time to remove const from the signature of public API. This is a
truly terrifying feature that I assume was added in the past century,
and whose inception clearly had something to do with massive doses of
absynthe and opium — because any other explanation would make the
existence of such a feature even worse than assuming drugs had anything
to do with it.
Anyway, and pleasing the gods, this dubious feature is being
removed/deprecated in GLib; see bug:
https://bugzilla.gnome.org/show_bug.cgi?id=644611
Before deprecation, though, we should just remove its usage from the
whole API. We should especially remove its usage from Cally's internals,
since there it never made sense in the first place.
2011-06-07 14:49:20 +00:00
|
|
|
static const gchar* cally_actor_action_get_name (AtkAction *action,
|
2010-06-14 11:38:25 +00:00
|
|
|
gint i);
|
|
|
|
static gboolean cally_actor_action_set_description (AtkAction *action,
|
|
|
|
gint i,
|
|
|
|
const gchar *desc);
|
|
|
|
static void _cally_actor_destroy_action_info (gpointer action_info,
|
|
|
|
gpointer user_data);
|
|
|
|
static void _cally_actor_clean_action_list (CallyActor *cally_actor);
|
|
|
|
|
|
|
|
static CallyActorActionInfo* _cally_actor_get_action_info (CallyActor *cally_actor,
|
|
|
|
gint index);
|
|
|
|
/* Misc functions */
|
|
|
|
static void cally_actor_notify_clutter (GObject *obj,
|
|
|
|
GParamSpec *pspec);
|
|
|
|
static void cally_actor_real_notify_clutter (GObject *obj,
|
|
|
|
GParamSpec *pspec);
|
|
|
|
|
|
|
|
struct _CallyActorPrivate
|
|
|
|
{
|
|
|
|
GQueue *action_queue;
|
|
|
|
guint action_idle_handler;
|
|
|
|
GList *action_list;
|
|
|
|
|
|
|
|
GList *children;
|
|
|
|
};
|
|
|
|
|
2013-07-03 13:02:09 +00:00
|
|
|
G_DEFINE_TYPE_WITH_CODE (CallyActor,
|
|
|
|
cally_actor,
|
|
|
|
ATK_TYPE_GOBJECT_ACCESSIBLE,
|
|
|
|
G_ADD_PRIVATE (CallyActor)
|
|
|
|
G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT,
|
|
|
|
cally_actor_component_interface_init)
|
|
|
|
G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION,
|
|
|
|
cally_actor_action_interface_init));
|
|
|
|
|
2010-07-05 14:10:42 +00:00
|
|
|
/**
|
|
|
|
* cally_actor_new:
|
|
|
|
* @actor: a #ClutterActor
|
|
|
|
*
|
|
|
|
* Creates a new #CallyActor for the given @actor
|
|
|
|
*
|
2010-07-06 14:51:24 +00:00
|
|
|
* Return value: the newly created #AtkObject
|
2010-07-05 14:10:42 +00:00
|
|
|
*
|
|
|
|
* Since: 1.4
|
|
|
|
*/
|
|
|
|
AtkObject *
|
2010-06-14 11:38:25 +00:00
|
|
|
cally_actor_new (ClutterActor *actor)
|
|
|
|
{
|
|
|
|
gpointer object;
|
|
|
|
AtkObject *atk_object;
|
|
|
|
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), NULL);
|
|
|
|
|
|
|
|
object = g_object_new (CALLY_TYPE_ACTOR, NULL);
|
|
|
|
|
|
|
|
atk_object = ATK_OBJECT (object);
|
|
|
|
atk_object_initialize (atk_object, actor);
|
|
|
|
|
|
|
|
return atk_object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cally_actor_initialize (AtkObject *obj,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
CallyActor *self = NULL;
|
|
|
|
CallyActorPrivate *priv = NULL;
|
|
|
|
ClutterActor *actor = NULL;
|
|
|
|
guint handler_id;
|
|
|
|
|
|
|
|
ATK_OBJECT_CLASS (cally_actor_parent_class)->initialize (obj, data);
|
|
|
|
|
|
|
|
self = CALLY_ACTOR(obj);
|
|
|
|
priv = self->priv;
|
|
|
|
actor = CLUTTER_ACTOR (data);
|
|
|
|
|
|
|
|
g_signal_connect (actor,
|
|
|
|
"notify",
|
|
|
|
G_CALLBACK (cally_actor_notify_clutter),
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
g_object_set_data (G_OBJECT (obj), "atk-component-layer",
|
|
|
|
GINT_TO_POINTER (ATK_LAYER_MDI));
|
|
|
|
|
2011-12-20 14:56:54 +00:00
|
|
|
priv->children = clutter_actor_get_children (actor);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We store the handler ids for these signals in case some objects
|
|
|
|
* need to remove these handlers.
|
|
|
|
*/
|
|
|
|
handler_id = g_signal_connect (actor,
|
|
|
|
"actor-added",
|
|
|
|
G_CALLBACK (cally_actor_add_actor),
|
|
|
|
obj);
|
|
|
|
g_object_set_data (G_OBJECT (obj), "cally-add-handler-id",
|
|
|
|
GUINT_TO_POINTER (handler_id));
|
|
|
|
handler_id = g_signal_connect (actor,
|
|
|
|
"actor-removed",
|
|
|
|
G_CALLBACK (cally_actor_remove_actor),
|
|
|
|
obj);
|
|
|
|
g_object_set_data (G_OBJECT (obj), "cally-remove-handler-id",
|
|
|
|
GUINT_TO_POINTER (handler_id));
|
|
|
|
|
|
|
|
obj->role = ATK_ROLE_PANEL; /* typically objects implementing ClutterContainer
|
|
|
|
interface would be a panel */
|
2010-06-14 11:38:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cally_actor_class_init (CallyActorClass *klass)
|
|
|
|
{
|
|
|
|
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
|
|
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
klass->notify_clutter = cally_actor_real_notify_clutter;
|
|
|
|
klass->add_actor = cally_actor_real_add_actor;
|
|
|
|
klass->remove_actor = cally_actor_real_remove_actor;
|
|
|
|
|
|
|
|
/* GObject */
|
|
|
|
gobject_class->finalize = cally_actor_finalize;
|
|
|
|
|
|
|
|
/* AtkObject */
|
|
|
|
class->get_parent = cally_actor_get_parent;
|
|
|
|
class->get_index_in_parent = cally_actor_get_index_in_parent;
|
|
|
|
class->ref_state_set = cally_actor_ref_state_set;
|
|
|
|
class->initialize = cally_actor_initialize;
|
|
|
|
class->get_n_children = cally_actor_get_n_children;
|
|
|
|
class->ref_child = cally_actor_ref_child;
|
2011-07-06 12:25:02 +00:00
|
|
|
class->get_attributes = cally_actor_get_attributes;
|
2010-06-14 11:38:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cally_actor_init (CallyActor *cally_actor)
|
|
|
|
{
|
2013-07-03 13:02:09 +00:00
|
|
|
CallyActorPrivate *priv = cally_actor_get_instance_private (cally_actor);
|
2010-06-14 11:38:25 +00:00
|
|
|
|
|
|
|
cally_actor->priv = priv;
|
|
|
|
|
2013-07-03 13:02:09 +00:00
|
|
|
priv->action_queue = NULL;
|
2010-06-14 11:38:25 +00:00
|
|
|
priv->action_idle_handler = 0;
|
|
|
|
|
|
|
|
priv->action_list = NULL;
|
|
|
|
|
|
|
|
priv->children = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cally_actor_finalize (GObject *obj)
|
|
|
|
{
|
|
|
|
CallyActor *cally_actor = NULL;
|
|
|
|
CallyActorPrivate *priv = NULL;
|
|
|
|
|
|
|
|
cally_actor = CALLY_ACTOR (obj);
|
|
|
|
priv = cally_actor->priv;
|
|
|
|
|
|
|
|
_cally_actor_clean_action_list (cally_actor);
|
|
|
|
|
|
|
|
if (priv->action_idle_handler)
|
|
|
|
{
|
|
|
|
g_source_remove (priv->action_idle_handler);
|
|
|
|
priv->action_idle_handler = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (priv->action_queue)
|
|
|
|
{
|
|
|
|
g_queue_free (priv->action_queue);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (priv->children)
|
|
|
|
{
|
|
|
|
g_list_free (priv->children);
|
|
|
|
priv->children = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (cally_actor_parent_class)->finalize (obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* AtkObject */
|
|
|
|
|
|
|
|
static AtkObject *
|
|
|
|
cally_actor_get_parent (AtkObject *obj)
|
|
|
|
{
|
|
|
|
ClutterActor *parent_actor = NULL;
|
|
|
|
AtkObject *parent = NULL;
|
|
|
|
ClutterActor *actor = NULL;
|
|
|
|
CallyActor *cally_actor = NULL;
|
|
|
|
|
|
|
|
g_return_val_if_fail (CALLY_IS_ACTOR (obj), NULL);
|
|
|
|
|
|
|
|
/* Check if we have and assigned parent */
|
|
|
|
if (obj->accessible_parent)
|
|
|
|
return obj->accessible_parent;
|
|
|
|
|
|
|
|
/* Try to get it from the clutter parent */
|
|
|
|
cally_actor = CALLY_ACTOR (obj);
|
|
|
|
actor = CALLY_GET_CLUTTER_ACTOR (cally_actor);
|
|
|
|
if (actor == NULL) /* Object is defunct */
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
parent_actor = clutter_actor_get_parent (actor);
|
|
|
|
if (parent_actor == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
parent = clutter_actor_get_accessible (parent_actor);
|
|
|
|
|
|
|
|
/* FIXME: I need to review the clutter-embed, to check if in this case I
|
|
|
|
* should get the widget accessible
|
|
|
|
*/
|
|
|
|
|
|
|
|
return parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
|
|
|
cally_actor_get_index_in_parent (AtkObject *obj)
|
|
|
|
{
|
2011-12-18 22:33:24 +00:00
|
|
|
CallyActor *cally_actor = NULL;
|
|
|
|
ClutterActor *actor = NULL;
|
2010-06-14 11:38:25 +00:00
|
|
|
ClutterActor *parent_actor = NULL;
|
2011-12-18 22:33:24 +00:00
|
|
|
ClutterActor *iter;
|
|
|
|
gint index = -1;
|
2010-06-14 11:38:25 +00:00
|
|
|
|
|
|
|
g_return_val_if_fail (CALLY_IS_ACTOR (obj), -1);
|
|
|
|
|
|
|
|
if (obj->accessible_parent)
|
|
|
|
{
|
|
|
|
gint n_children, i;
|
|
|
|
gboolean found = FALSE;
|
|
|
|
|
|
|
|
n_children = atk_object_get_n_accessible_children (obj->accessible_parent);
|
|
|
|
for (i = 0; i < n_children; i++)
|
|
|
|
{
|
|
|
|
AtkObject *child;
|
|
|
|
|
|
|
|
child = atk_object_ref_accessible_child (obj->accessible_parent, i);
|
|
|
|
if (child == obj)
|
|
|
|
found = TRUE;
|
|
|
|
|
|
|
|
g_object_unref (child);
|
|
|
|
if (found)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
cally_actor = CALLY_ACTOR (obj);
|
|
|
|
actor = CALLY_GET_CLUTTER_ACTOR (cally_actor);
|
|
|
|
if (actor == NULL) /* Object is defunct */
|
|
|
|
return -1;
|
|
|
|
|
2011-12-18 22:33:24 +00:00
|
|
|
index = 0;
|
|
|
|
parent_actor = clutter_actor_get_parent (actor);
|
|
|
|
if (parent_actor == NULL)
|
2010-06-14 11:38:25 +00:00
|
|
|
return -1;
|
|
|
|
|
2011-12-18 22:33:24 +00:00
|
|
|
for (iter = clutter_actor_get_first_child (parent_actor);
|
|
|
|
iter != NULL && iter != actor;
|
|
|
|
iter = clutter_actor_get_next_sibling (iter))
|
|
|
|
{
|
|
|
|
index += 1;
|
|
|
|
}
|
2010-06-14 11:38:25 +00:00
|
|
|
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
|
|
|
static AtkStateSet*
|
|
|
|
cally_actor_ref_state_set (AtkObject *obj)
|
|
|
|
{
|
|
|
|
ClutterActor *actor = NULL;
|
|
|
|
AtkStateSet *state_set = NULL;
|
|
|
|
ClutterStage *stage = NULL;
|
|
|
|
ClutterActor *focus_actor = NULL;
|
|
|
|
CallyActor *cally_actor = NULL;
|
|
|
|
|
|
|
|
g_return_val_if_fail (CALLY_IS_ACTOR (obj), NULL);
|
|
|
|
cally_actor = CALLY_ACTOR (obj);
|
|
|
|
|
|
|
|
state_set = ATK_OBJECT_CLASS (cally_actor_parent_class)->ref_state_set (obj);
|
|
|
|
|
|
|
|
actor = CALLY_GET_CLUTTER_ACTOR (cally_actor);
|
|
|
|
|
|
|
|
if (actor == NULL) /* Object is defunct */
|
|
|
|
{
|
|
|
|
atk_state_set_add_state (state_set, ATK_STATE_DEFUNCT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (CLUTTER_ACTOR_IS_REACTIVE (actor))
|
|
|
|
{
|
|
|
|
atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE);
|
|
|
|
atk_state_set_add_state (state_set, ATK_STATE_ENABLED);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CLUTTER_ACTOR_IS_VISIBLE (actor))
|
|
|
|
{
|
|
|
|
atk_state_set_add_state (state_set, ATK_STATE_VISIBLE);
|
|
|
|
|
2011-07-26 13:56:18 +00:00
|
|
|
/* It would be good to also check if the actor is on screen,
|
|
|
|
like the old and removed clutter_actor_is_on_stage*/
|
|
|
|
if (clutter_actor_get_paint_visibility (actor))
|
2010-06-14 11:38:25 +00:00
|
|
|
atk_state_set_add_state (state_set, ATK_STATE_SHOWING);
|
2011-07-26 13:56:18 +00:00
|
|
|
|
2010-06-14 11:38:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* See focus section on implementation notes */
|
|
|
|
atk_state_set_add_state (state_set, ATK_STATE_FOCUSABLE);
|
|
|
|
|
|
|
|
stage = CLUTTER_STAGE (clutter_actor_get_stage (actor));
|
2011-11-09 17:03:30 +00:00
|
|
|
if (stage != NULL)
|
|
|
|
{
|
|
|
|
focus_actor = clutter_stage_get_key_focus (stage);
|
|
|
|
if (focus_actor == actor)
|
|
|
|
atk_state_set_add_state (state_set, ATK_STATE_FOCUSED);
|
|
|
|
}
|
2010-06-14 11:38:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return state_set;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
|
|
|
cally_actor_get_n_children (AtkObject *obj)
|
|
|
|
{
|
2011-12-18 22:33:24 +00:00
|
|
|
ClutterActor *actor = NULL;
|
2010-06-14 11:38:25 +00:00
|
|
|
|
|
|
|
g_return_val_if_fail (CALLY_IS_ACTOR (obj), 0);
|
|
|
|
|
|
|
|
actor = CALLY_GET_CLUTTER_ACTOR (obj);
|
|
|
|
|
|
|
|
if (actor == NULL) /* State is defunct */
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), 0);
|
|
|
|
|
2011-12-18 22:33:24 +00:00
|
|
|
return clutter_actor_get_n_children (actor);
|
2010-06-14 11:38:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static AtkObject*
|
|
|
|
cally_actor_ref_child (AtkObject *obj,
|
2011-12-18 22:33:24 +00:00
|
|
|
gint i)
|
2010-06-14 11:38:25 +00:00
|
|
|
{
|
2011-12-18 22:33:24 +00:00
|
|
|
ClutterActor *actor = NULL;
|
|
|
|
ClutterActor *child = NULL;
|
2010-06-14 11:38:25 +00:00
|
|
|
|
|
|
|
g_return_val_if_fail (CALLY_IS_ACTOR (obj), NULL);
|
|
|
|
|
|
|
|
actor = CALLY_GET_CLUTTER_ACTOR (obj);
|
|
|
|
if (actor == NULL) /* State is defunct */
|
2011-12-18 22:33:24 +00:00
|
|
|
return NULL;
|
2010-06-14 11:38:25 +00:00
|
|
|
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), NULL);
|
|
|
|
|
2011-12-18 22:33:24 +00:00
|
|
|
if (i >= clutter_actor_get_n_children (actor))
|
|
|
|
return NULL;
|
2010-06-14 11:38:25 +00:00
|
|
|
|
2011-12-18 22:33:24 +00:00
|
|
|
child = clutter_actor_get_child_at_index (actor, i);
|
|
|
|
if (child == NULL)
|
|
|
|
return NULL;
|
2010-06-14 11:38:25 +00:00
|
|
|
|
2011-12-18 22:33:24 +00:00
|
|
|
return g_object_ref (clutter_actor_get_accessible (child));
|
2010-06-14 11:38:25 +00:00
|
|
|
}
|
|
|
|
|
2011-07-06 12:25:02 +00:00
|
|
|
static AtkAttributeSet *
|
|
|
|
cally_actor_get_attributes (AtkObject *obj)
|
|
|
|
{
|
|
|
|
AtkAttributeSet *attributes;
|
|
|
|
AtkAttribute *toolkit;
|
|
|
|
|
|
|
|
toolkit = g_new (AtkAttribute, 1);
|
|
|
|
toolkit->name = g_strdup ("toolkit");
|
|
|
|
toolkit->value = g_strdup ("clutter");
|
|
|
|
|
|
|
|
attributes = g_slist_append (NULL, toolkit);
|
|
|
|
|
|
|
|
return attributes;
|
|
|
|
}
|
|
|
|
|
2010-06-14 11:38:25 +00:00
|
|
|
/* ClutterContainer */
|
|
|
|
static gint
|
|
|
|
cally_actor_add_actor (ClutterActor *container,
|
|
|
|
ClutterActor *actor,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
CallyActor *cally_actor = CALLY_ACTOR (data);
|
|
|
|
CallyActorClass *klass = NULL;
|
|
|
|
|
|
|
|
klass = CALLY_ACTOR_GET_CLASS (cally_actor);
|
|
|
|
|
|
|
|
if (klass->add_actor)
|
|
|
|
return klass->add_actor (container, actor, data);
|
|
|
|
else
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
|
|
|
cally_actor_remove_actor (ClutterActor *container,
|
|
|
|
ClutterActor *actor,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
CallyActor *cally_actor = CALLY_ACTOR (data);
|
|
|
|
CallyActorClass *klass = NULL;
|
|
|
|
|
|
|
|
klass = CALLY_ACTOR_GET_CLASS (cally_actor);
|
|
|
|
|
|
|
|
if (klass->remove_actor)
|
|
|
|
return klass->remove_actor (container, actor, data);
|
|
|
|
else
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static gint
|
|
|
|
cally_actor_real_add_actor (ClutterActor *container,
|
2011-12-20 14:56:54 +00:00
|
|
|
ClutterActor *actor,
|
|
|
|
gpointer data)
|
2010-06-14 11:38:25 +00:00
|
|
|
{
|
|
|
|
AtkObject *atk_parent = ATK_OBJECT (data);
|
|
|
|
AtkObject *atk_child = clutter_actor_get_accessible (actor);
|
|
|
|
CallyActor *cally_actor = CALLY_ACTOR (atk_parent);
|
|
|
|
CallyActorPrivate *priv = cally_actor->priv;
|
|
|
|
gint index;
|
|
|
|
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_CONTAINER (container), 0);
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), 0);
|
|
|
|
|
|
|
|
g_object_notify (G_OBJECT (atk_child), "accessible_parent");
|
|
|
|
|
|
|
|
g_list_free (priv->children);
|
|
|
|
|
2011-12-20 14:56:54 +00:00
|
|
|
priv->children = clutter_actor_get_children (CLUTTER_ACTOR (container));
|
2010-06-14 11:38:25 +00:00
|
|
|
|
|
|
|
index = g_list_index (priv->children, actor);
|
|
|
|
g_signal_emit_by_name (atk_parent, "children_changed::add",
|
|
|
|
index, atk_child, NULL);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
|
|
|
cally_actor_real_remove_actor (ClutterActor *container,
|
2011-12-20 14:56:54 +00:00
|
|
|
ClutterActor *actor,
|
|
|
|
gpointer data)
|
2010-06-14 11:38:25 +00:00
|
|
|
{
|
|
|
|
AtkPropertyValues values = { NULL };
|
|
|
|
AtkObject* atk_parent = NULL;
|
|
|
|
AtkObject *atk_child = NULL;
|
|
|
|
CallyActorPrivate *priv = NULL;
|
|
|
|
gint index;
|
|
|
|
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_CONTAINER (container), 0);
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), 0);
|
|
|
|
|
|
|
|
atk_parent = ATK_OBJECT (data);
|
|
|
|
atk_child = clutter_actor_get_accessible (actor);
|
|
|
|
|
|
|
|
if (atk_child)
|
|
|
|
{
|
|
|
|
g_value_init (&values.old_value, G_TYPE_POINTER);
|
|
|
|
g_value_set_pointer (&values.old_value, atk_parent);
|
|
|
|
|
|
|
|
values.property_name = "accessible-parent";
|
|
|
|
|
|
|
|
g_object_ref (atk_child);
|
|
|
|
g_signal_emit_by_name (atk_child,
|
|
|
|
"property_change::accessible-parent", &values, NULL);
|
|
|
|
g_object_unref (atk_child);
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = CALLY_ACTOR (atk_parent)->priv;
|
|
|
|
index = g_list_index (priv->children, actor);
|
|
|
|
g_list_free (priv->children);
|
2011-12-20 14:56:54 +00:00
|
|
|
|
|
|
|
priv->children = clutter_actor_get_children (CLUTTER_ACTOR (container));
|
2010-06-14 11:38:25 +00:00
|
|
|
|
|
|
|
if (index >= 0 && index <= g_list_length (priv->children))
|
|
|
|
g_signal_emit_by_name (atk_parent, "children_changed::remove",
|
|
|
|
index, atk_child, NULL);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* AtkComponent implementation */
|
|
|
|
static void
|
|
|
|
cally_actor_component_interface_init (AtkComponentIface *iface)
|
|
|
|
{
|
|
|
|
g_return_if_fail (iface != NULL);
|
|
|
|
|
|
|
|
iface->get_extents = cally_actor_get_extents;
|
|
|
|
iface->get_mdi_zorder = cally_actor_get_mdi_zorder;
|
|
|
|
|
|
|
|
/* focus management */
|
|
|
|
iface->grab_focus = cally_actor_grab_focus;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cally_actor_get_extents (AtkComponent *component,
|
|
|
|
gint *x,
|
|
|
|
gint *y,
|
|
|
|
gint *width,
|
|
|
|
gint *height,
|
|
|
|
AtkCoordType coord_type)
|
|
|
|
{
|
|
|
|
CallyActor *cally_actor = NULL;
|
|
|
|
ClutterActor *actor = NULL;
|
|
|
|
gint top_level_x, top_level_y;
|
|
|
|
gfloat f_width, f_height;
|
|
|
|
ClutterVertex verts[4];
|
2012-02-29 14:49:23 +00:00
|
|
|
ClutterActor *stage = NULL;
|
2010-06-14 11:38:25 +00:00
|
|
|
|
|
|
|
g_return_if_fail (CALLY_IS_ACTOR (component));
|
|
|
|
|
|
|
|
cally_actor = CALLY_ACTOR (component);
|
|
|
|
actor = CALLY_GET_CLUTTER_ACTOR (cally_actor);
|
|
|
|
|
|
|
|
if (actor == NULL) /* actor is defunct */
|
|
|
|
return;
|
|
|
|
|
2012-02-29 14:49:23 +00:00
|
|
|
/* If the actor is not placed in any stage, we can't compute the
|
|
|
|
* extents */
|
|
|
|
stage = clutter_actor_get_stage (actor);
|
|
|
|
if (stage == NULL)
|
|
|
|
return;
|
|
|
|
|
2010-06-14 11:38:25 +00:00
|
|
|
clutter_actor_get_abs_allocation_vertices (actor, verts);
|
|
|
|
clutter_actor_get_transformed_size (actor, &f_width, &f_height);
|
|
|
|
|
|
|
|
*x = verts[0].x;
|
|
|
|
*y = verts[0].y;
|
|
|
|
*width = ceilf (f_width);
|
|
|
|
*height = ceilf (f_height);
|
|
|
|
|
|
|
|
/* In the ATK_XY_WINDOW case, we consider the stage as the
|
|
|
|
* "top-level-window"
|
|
|
|
*
|
|
|
|
* http://library.gnome.org/devel/atk/stable/AtkUtil.html#AtkCoordType
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (coord_type == ATK_XY_SCREEN)
|
|
|
|
{
|
2011-02-02 14:02:45 +00:00
|
|
|
_cally_actor_get_top_level_origin (actor, &top_level_x, &top_level_y);
|
2010-06-14 11:38:25 +00:00
|
|
|
|
|
|
|
*x += top_level_x;
|
|
|
|
*y += top_level_y;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
|
|
|
cally_actor_get_mdi_zorder (AtkComponent *component)
|
|
|
|
{
|
|
|
|
CallyActor *cally_actor = NULL;
|
|
|
|
ClutterActor *actor = NULL;
|
|
|
|
|
|
|
|
g_return_val_if_fail (CALLY_IS_ACTOR (component), G_MININT);
|
|
|
|
|
|
|
|
cally_actor = CALLY_ACTOR(component);
|
|
|
|
actor = CALLY_GET_CLUTTER_ACTOR (cally_actor);
|
|
|
|
|
2012-07-05 17:57:38 +00:00
|
|
|
return clutter_actor_get_z_position (actor);
|
2010-06-14 11:38:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
cally_actor_grab_focus (AtkComponent *component)
|
|
|
|
{
|
|
|
|
ClutterActor *actor = NULL;
|
|
|
|
ClutterActor *stage = NULL;
|
|
|
|
CallyActor *cally_actor = NULL;
|
|
|
|
|
|
|
|
g_return_val_if_fail (CALLY_IS_ACTOR (component), FALSE);
|
|
|
|
|
|
|
|
/* See focus section on implementation notes */
|
|
|
|
cally_actor = CALLY_ACTOR(component);
|
|
|
|
actor = CALLY_GET_CLUTTER_ACTOR (cally_actor);
|
|
|
|
stage = clutter_actor_get_stage (actor);
|
|
|
|
|
|
|
|
clutter_stage_set_key_focus (CLUTTER_STAGE (stage),
|
|
|
|
actor);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-07-05 14:10:42 +00:00
|
|
|
/*
|
2010-06-14 11:38:25 +00:00
|
|
|
*
|
|
|
|
* This gets the top level origin, it is, the position of the stage in
|
|
|
|
* the global screen. You can see it as the absolute display position
|
|
|
|
* of the stage.
|
|
|
|
*
|
|
|
|
* FIXME: only the case with x11 is implemented, other backends are
|
|
|
|
* required
|
|
|
|
*
|
2010-07-05 14:10:42 +00:00
|
|
|
*/
|
2011-02-02 14:02:45 +00:00
|
|
|
void
|
|
|
|
_cally_actor_get_top_level_origin (ClutterActor *actor,
|
|
|
|
gint *xp,
|
|
|
|
gint *yp)
|
2010-06-14 11:38:25 +00:00
|
|
|
{
|
|
|
|
/* default values */
|
2011-02-02 14:02:45 +00:00
|
|
|
gint x = 0;
|
|
|
|
gint y = 0;
|
2010-06-14 11:38:25 +00:00
|
|
|
|
2010-07-06 11:36:48 +00:00
|
|
|
#ifdef HAVE_CLUTTER_GLX
|
2010-10-25 12:08:52 +00:00
|
|
|
{
|
|
|
|
ClutterActor *stage = NULL;
|
|
|
|
Display *display = NULL;
|
|
|
|
Window root_window;
|
|
|
|
Window stage_window;
|
|
|
|
Window child;
|
|
|
|
gint return_val = 0;
|
|
|
|
|
|
|
|
stage = clutter_actor_get_stage (actor);
|
|
|
|
|
|
|
|
/* FIXME: what happens if you use another display with
|
|
|
|
clutter_backend_x11_set_display ?*/
|
|
|
|
display = clutter_x11_get_default_display ();
|
|
|
|
root_window = clutter_x11_get_root_window ();
|
|
|
|
stage_window = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
|
|
|
|
|
|
|
|
return_val = XTranslateCoordinates (display, stage_window, root_window,
|
2011-02-02 14:02:45 +00:00
|
|
|
0, 0, &x, &y,
|
2010-10-25 12:08:52 +00:00
|
|
|
&child);
|
|
|
|
|
|
|
|
if (!return_val)
|
|
|
|
g_warning ("[x11] We were not able to get proper absolute "
|
|
|
|
"position of the stage");
|
|
|
|
}
|
2010-06-14 11:38:25 +00:00
|
|
|
#else
|
2010-10-25 12:08:52 +00:00
|
|
|
{
|
|
|
|
static gboolean yet_warned = FALSE;
|
|
|
|
|
|
|
|
if (!yet_warned)
|
|
|
|
{
|
|
|
|
yet_warned = TRUE;
|
|
|
|
|
|
|
|
g_warning ("Using a clutter backend not supported. "
|
|
|
|
"atk_component_get_extents using ATK_XY_SCREEN "
|
|
|
|
"could return a wrong screen position");
|
|
|
|
}
|
|
|
|
}
|
2010-06-14 11:38:25 +00:00
|
|
|
#endif
|
2011-02-02 14:02:45 +00:00
|
|
|
|
|
|
|
if (xp)
|
|
|
|
*xp = x;
|
|
|
|
|
|
|
|
if (yp)
|
|
|
|
*yp = y;
|
2010-06-14 11:38:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* AtkAction implementation */
|
|
|
|
static void
|
|
|
|
cally_actor_action_interface_init (AtkActionIface *iface)
|
|
|
|
{
|
|
|
|
g_return_if_fail (iface != NULL);
|
|
|
|
|
|
|
|
iface->do_action = cally_actor_action_do_action;
|
|
|
|
iface->get_n_actions = cally_actor_action_get_n_actions;
|
|
|
|
iface->get_description = cally_actor_action_get_description;
|
|
|
|
iface->get_keybinding = cally_actor_action_get_keybinding;
|
|
|
|
iface->get_name = cally_actor_action_get_name;
|
|
|
|
iface->set_description = cally_actor_action_set_description;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
cally_actor_action_do_action (AtkAction *action,
|
|
|
|
gint index)
|
|
|
|
{
|
|
|
|
CallyActor *cally_actor = NULL;
|
2011-02-19 16:45:35 +00:00
|
|
|
AtkStateSet *set = NULL;
|
|
|
|
CallyActorPrivate *priv = NULL;
|
|
|
|
CallyActorActionInfo *info = NULL;
|
2010-06-14 11:38:25 +00:00
|
|
|
|
|
|
|
cally_actor = CALLY_ACTOR (action);
|
|
|
|
priv = cally_actor->priv;
|
|
|
|
|
|
|
|
set = atk_object_ref_state_set (ATK_OBJECT (cally_actor));
|
|
|
|
|
|
|
|
if (atk_state_set_contains_state (set, ATK_STATE_DEFUNCT))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!atk_state_set_contains_state (set, ATK_STATE_SENSITIVE) ||
|
|
|
|
!atk_state_set_contains_state (set, ATK_STATE_SHOWING))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
g_object_unref (set);
|
|
|
|
|
|
|
|
info = _cally_actor_get_action_info (cally_actor, index);
|
|
|
|
|
|
|
|
if (info == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (info->do_action_func == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!priv->action_queue)
|
|
|
|
priv->action_queue = g_queue_new ();
|
|
|
|
|
|
|
|
g_queue_push_head (priv->action_queue, info);
|
|
|
|
|
|
|
|
if (!priv->action_idle_handler)
|
|
|
|
priv->action_idle_handler = g_idle_add (idle_do_action, cally_actor);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
idle_do_action (gpointer data)
|
|
|
|
{
|
|
|
|
CallyActor *cally_actor = NULL;
|
|
|
|
CallyActorPrivate *priv = NULL;
|
|
|
|
ClutterActor *actor = NULL;
|
|
|
|
|
|
|
|
cally_actor = CALLY_ACTOR (data);
|
|
|
|
priv = cally_actor->priv;
|
|
|
|
actor = CALLY_GET_CLUTTER_ACTOR (cally_actor);
|
|
|
|
priv->action_idle_handler = 0;
|
|
|
|
|
|
|
|
if (actor == NULL) /* state is defunct*/
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
while (!g_queue_is_empty (priv->action_queue))
|
|
|
|
{
|
|
|
|
CallyActorActionInfo *info = NULL;
|
|
|
|
|
|
|
|
info = (CallyActorActionInfo *) g_queue_pop_head (priv->action_queue);
|
|
|
|
|
2010-12-10 17:46:58 +00:00
|
|
|
info->do_action_func (cally_actor, info->user_data);
|
2010-06-14 11:38:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
|
|
|
cally_actor_action_get_n_actions (AtkAction *action)
|
|
|
|
{
|
|
|
|
CallyActor *cally_actor = NULL;
|
|
|
|
CallyActorPrivate *priv = NULL;
|
|
|
|
|
|
|
|
g_return_val_if_fail (CALLY_IS_ACTOR (action), 0);
|
|
|
|
|
|
|
|
cally_actor = CALLY_ACTOR (action);
|
|
|
|
priv = cally_actor->priv;
|
|
|
|
|
|
|
|
return g_list_length (priv->action_list);
|
|
|
|
}
|
|
|
|
|
Eliminate G_CONST_RETURN
The G_CONST_RETURN define in GLib is, and has always been, a bit fuzzy.
We always used it to conform to the platform, at least for public-facing
API.
At first I assumed it has something to do with brain-damaged compilers
or with weird platforms where const was not really supported; sadly,
it's something much, much worse: it's a define that can be toggled at
compile-time to remove const from the signature of public API. This is a
truly terrifying feature that I assume was added in the past century,
and whose inception clearly had something to do with massive doses of
absynthe and opium — because any other explanation would make the
existence of such a feature even worse than assuming drugs had anything
to do with it.
Anyway, and pleasing the gods, this dubious feature is being
removed/deprecated in GLib; see bug:
https://bugzilla.gnome.org/show_bug.cgi?id=644611
Before deprecation, though, we should just remove its usage from the
whole API. We should especially remove its usage from Cally's internals,
since there it never made sense in the first place.
2011-06-07 14:49:20 +00:00
|
|
|
static const gchar*
|
2010-06-14 11:38:25 +00:00
|
|
|
cally_actor_action_get_name (AtkAction *action,
|
|
|
|
gint i)
|
|
|
|
{
|
|
|
|
CallyActor *cally_actor = NULL;
|
|
|
|
CallyActorActionInfo *info = NULL;
|
|
|
|
|
|
|
|
g_return_val_if_fail (CALLY_IS_ACTOR (action), NULL);
|
|
|
|
cally_actor = CALLY_ACTOR (action);
|
|
|
|
info = _cally_actor_get_action_info (cally_actor, i);
|
|
|
|
|
|
|
|
if (info == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return info->name;
|
|
|
|
}
|
|
|
|
|
Eliminate G_CONST_RETURN
The G_CONST_RETURN define in GLib is, and has always been, a bit fuzzy.
We always used it to conform to the platform, at least for public-facing
API.
At first I assumed it has something to do with brain-damaged compilers
or with weird platforms where const was not really supported; sadly,
it's something much, much worse: it's a define that can be toggled at
compile-time to remove const from the signature of public API. This is a
truly terrifying feature that I assume was added in the past century,
and whose inception clearly had something to do with massive doses of
absynthe and opium — because any other explanation would make the
existence of such a feature even worse than assuming drugs had anything
to do with it.
Anyway, and pleasing the gods, this dubious feature is being
removed/deprecated in GLib; see bug:
https://bugzilla.gnome.org/show_bug.cgi?id=644611
Before deprecation, though, we should just remove its usage from the
whole API. We should especially remove its usage from Cally's internals,
since there it never made sense in the first place.
2011-06-07 14:49:20 +00:00
|
|
|
static const gchar*
|
2010-06-14 11:38:25 +00:00
|
|
|
cally_actor_action_get_description (AtkAction *action,
|
|
|
|
gint i)
|
|
|
|
{
|
|
|
|
CallyActor *cally_actor = NULL;
|
|
|
|
CallyActorActionInfo *info = NULL;
|
|
|
|
|
|
|
|
g_return_val_if_fail (CALLY_IS_ACTOR (action), NULL);
|
|
|
|
cally_actor = CALLY_ACTOR (action);
|
|
|
|
info = _cally_actor_get_action_info (cally_actor, i);
|
|
|
|
|
|
|
|
if (info == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return info->description;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
cally_actor_action_set_description (AtkAction *action,
|
|
|
|
gint i,
|
|
|
|
const gchar *desc)
|
|
|
|
{
|
|
|
|
CallyActor *cally_actor = NULL;
|
|
|
|
CallyActorActionInfo *info = NULL;
|
|
|
|
|
|
|
|
g_return_val_if_fail (CALLY_IS_ACTOR (action), FALSE);
|
|
|
|
cally_actor = CALLY_ACTOR (action);
|
|
|
|
info = _cally_actor_get_action_info (cally_actor, i);
|
|
|
|
|
|
|
|
if (info == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
g_free (info->description);
|
|
|
|
info->description = g_strdup (desc);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
Eliminate G_CONST_RETURN
The G_CONST_RETURN define in GLib is, and has always been, a bit fuzzy.
We always used it to conform to the platform, at least for public-facing
API.
At first I assumed it has something to do with brain-damaged compilers
or with weird platforms where const was not really supported; sadly,
it's something much, much worse: it's a define that can be toggled at
compile-time to remove const from the signature of public API. This is a
truly terrifying feature that I assume was added in the past century,
and whose inception clearly had something to do with massive doses of
absynthe and opium — because any other explanation would make the
existence of such a feature even worse than assuming drugs had anything
to do with it.
Anyway, and pleasing the gods, this dubious feature is being
removed/deprecated in GLib; see bug:
https://bugzilla.gnome.org/show_bug.cgi?id=644611
Before deprecation, though, we should just remove its usage from the
whole API. We should especially remove its usage from Cally's internals,
since there it never made sense in the first place.
2011-06-07 14:49:20 +00:00
|
|
|
static const gchar*
|
2010-06-14 11:38:25 +00:00
|
|
|
cally_actor_action_get_keybinding (AtkAction *action,
|
|
|
|
gint i)
|
|
|
|
{
|
|
|
|
CallyActor *cally_actor = NULL;
|
|
|
|
CallyActorActionInfo *info = NULL;
|
|
|
|
|
|
|
|
g_return_val_if_fail (CALLY_IS_ACTOR (action), NULL);
|
|
|
|
cally_actor = CALLY_ACTOR (action);
|
|
|
|
info = _cally_actor_get_action_info (cally_actor, i);
|
|
|
|
|
|
|
|
if (info == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return info->keybinding;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Misc functions */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function is a signal handler for notify signal which gets emitted
|
|
|
|
* when a property changes value on the ClutterActor associated with the object.
|
|
|
|
*
|
|
|
|
* It calls a function for the CallyActor type
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
cally_actor_notify_clutter (GObject *obj,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
CallyActor *cally_actor = NULL;
|
|
|
|
CallyActorClass *klass = NULL;
|
|
|
|
|
|
|
|
cally_actor = CALLY_ACTOR (clutter_actor_get_accessible (CLUTTER_ACTOR (obj)));
|
|
|
|
klass = CALLY_ACTOR_GET_CLASS (cally_actor);
|
|
|
|
|
|
|
|
if (klass->notify_clutter)
|
|
|
|
klass->notify_clutter (obj, pspec);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function is a signal handler for notify signal which gets emitted
|
|
|
|
* when a property changes value on the ClutterActor associated with a CallyActor
|
|
|
|
*
|
|
|
|
* It constructs an AtkPropertyValues structure and emits a "property_changed"
|
|
|
|
* signal which causes the user specified AtkPropertyChangeHandler
|
|
|
|
* to be called.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
cally_actor_real_notify_clutter (GObject *obj,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
ClutterActor* actor = CLUTTER_ACTOR (obj);
|
|
|
|
AtkObject* atk_obj = clutter_actor_get_accessible (CLUTTER_ACTOR(obj));
|
|
|
|
AtkState state;
|
|
|
|
gboolean value;
|
|
|
|
|
2010-06-15 11:45:19 +00:00
|
|
|
if (g_strcmp0 (pspec->name, "visible") == 0)
|
2010-06-14 11:38:25 +00:00
|
|
|
{
|
|
|
|
state = ATK_STATE_VISIBLE;
|
|
|
|
value = CLUTTER_ACTOR_IS_VISIBLE (actor);
|
|
|
|
}
|
2011-08-04 10:02:52 +00:00
|
|
|
else if (g_strcmp0 (pspec->name, "mapped") == 0)
|
|
|
|
{
|
|
|
|
state = ATK_STATE_SHOWING;
|
|
|
|
value = CLUTTER_ACTOR_IS_MAPPED (actor);
|
|
|
|
}
|
2010-06-15 11:45:19 +00:00
|
|
|
else if (g_strcmp0 (pspec->name, "reactive") == 0)
|
2010-06-14 11:38:25 +00:00
|
|
|
{
|
|
|
|
state = ATK_STATE_SENSITIVE;
|
|
|
|
value = CLUTTER_ACTOR_IS_REACTIVE (actor);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
|
|
|
|
atk_object_notify_state_change (atk_obj, state, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cally_actor_clean_action_list (CallyActor *cally_actor)
|
|
|
|
{
|
|
|
|
CallyActorPrivate *priv = NULL;
|
|
|
|
|
|
|
|
priv = cally_actor->priv;
|
|
|
|
|
|
|
|
if (priv->action_list)
|
|
|
|
{
|
|
|
|
g_list_foreach (priv->action_list,
|
|
|
|
(GFunc) _cally_actor_destroy_action_info,
|
|
|
|
NULL);
|
|
|
|
g_list_free (priv->action_list);
|
|
|
|
priv->action_list = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static CallyActorActionInfo *
|
|
|
|
_cally_actor_get_action_info (CallyActor *cally_actor,
|
|
|
|
gint index)
|
|
|
|
{
|
|
|
|
CallyActorPrivate *priv = NULL;
|
|
|
|
GList *node = NULL;
|
|
|
|
|
|
|
|
g_return_val_if_fail (CALLY_IS_ACTOR (cally_actor), NULL);
|
|
|
|
|
|
|
|
priv = cally_actor->priv;
|
|
|
|
|
|
|
|
if (priv->action_list == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
node = g_list_nth (priv->action_list, index);
|
|
|
|
|
|
|
|
if (node == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return (CallyActorActionInfo *)(node->data);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2010-12-10 17:46:58 +00:00
|
|
|
* cally_actor_add_action: (skip)
|
2010-07-05 14:10:42 +00:00
|
|
|
* @cally_actor: a #CallyActor
|
2010-06-14 11:38:25 +00:00
|
|
|
* @action_name: the action name
|
|
|
|
* @action_description: the action description
|
|
|
|
* @action_keybinding: the action keybinding
|
|
|
|
* @action_func: the callback of the action, to be executed with do_action
|
|
|
|
*
|
2010-07-05 14:10:42 +00:00
|
|
|
* Adds a new action to be accessed with the #AtkAction interface.
|
2010-06-14 11:38:25 +00:00
|
|
|
*
|
2010-12-10 17:46:58 +00:00
|
|
|
* Return value: added action id, or -1 if failure
|
2010-06-14 11:38:25 +00:00
|
|
|
*
|
2010-07-05 14:10:42 +00:00
|
|
|
* Since: 1.4
|
2010-06-14 11:38:25 +00:00
|
|
|
*/
|
|
|
|
guint
|
2010-07-05 14:10:42 +00:00
|
|
|
cally_actor_add_action (CallyActor *cally_actor,
|
|
|
|
const gchar *action_name,
|
|
|
|
const gchar *action_description,
|
|
|
|
const gchar *action_keybinding,
|
|
|
|
CallyActionFunc action_func)
|
2010-12-10 17:46:58 +00:00
|
|
|
{
|
|
|
|
return cally_actor_add_action_full (cally_actor,
|
|
|
|
action_name,
|
|
|
|
action_description,
|
|
|
|
action_keybinding,
|
|
|
|
(CallyActionCallback) action_func,
|
|
|
|
NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* cally_actor_add_action_full:
|
|
|
|
* @cally_actor: a #CallyActor
|
|
|
|
* @action_name: the action name
|
|
|
|
* @action_description: the action description
|
|
|
|
* @action_keybinding: the action keybinding
|
|
|
|
* @callback: (scope notified): the callback of the action
|
|
|
|
* @user_data: (closure): data to be passed to @callback
|
|
|
|
* @notify: function to be called when removing the action
|
|
|
|
*
|
|
|
|
* Adds a new action to be accessed with the #AtkAction interface.
|
|
|
|
*
|
|
|
|
* Return value: added action id, or -1 if failure
|
|
|
|
*
|
|
|
|
* Rename to: cally_actor_add_action
|
2011-02-01 14:32:41 +00:00
|
|
|
*
|
|
|
|
* Since: 1.6
|
2010-12-10 17:46:58 +00:00
|
|
|
*/
|
|
|
|
guint
|
|
|
|
cally_actor_add_action_full (CallyActor *cally_actor,
|
|
|
|
const gchar *action_name,
|
|
|
|
const gchar *action_description,
|
|
|
|
const gchar *action_keybinding,
|
|
|
|
CallyActionCallback callback,
|
|
|
|
gpointer user_data,
|
|
|
|
GDestroyNotify notify)
|
2010-06-14 11:38:25 +00:00
|
|
|
{
|
|
|
|
CallyActorActionInfo *info = NULL;
|
2010-12-10 17:46:58 +00:00
|
|
|
CallyActorPrivate *priv = NULL;
|
2010-06-14 11:38:25 +00:00
|
|
|
|
|
|
|
g_return_val_if_fail (CALLY_IS_ACTOR (cally_actor), -1);
|
2010-12-10 17:46:58 +00:00
|
|
|
g_return_val_if_fail (callback != NULL, -1);
|
2010-06-14 11:38:25 +00:00
|
|
|
|
|
|
|
priv = cally_actor->priv;
|
|
|
|
|
2010-12-10 17:46:58 +00:00
|
|
|
info = g_slice_new (CallyActorActionInfo);
|
|
|
|
info->name = g_strdup (action_name);
|
|
|
|
info->description = g_strdup (action_description);
|
|
|
|
info->keybinding = g_strdup (action_keybinding);
|
|
|
|
info->do_action_func = callback;
|
|
|
|
info->user_data = user_data;
|
|
|
|
info->notify = notify;
|
2010-06-14 11:38:25 +00:00
|
|
|
|
2010-12-10 17:46:58 +00:00
|
|
|
priv->action_list = g_list_append (priv->action_list, info);
|
2010-06-14 11:38:25 +00:00
|
|
|
|
|
|
|
return g_list_length (priv->action_list);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* cally_actor_remove_action:
|
2010-07-05 14:10:42 +00:00
|
|
|
* @cally_actor: a #CallyActor
|
2010-06-14 11:38:25 +00:00
|
|
|
* @action_id: the action id
|
|
|
|
*
|
2010-07-05 14:10:42 +00:00
|
|
|
* Removes a action, using the @action_id returned by cally_actor_add_action()
|
2010-06-14 11:38:25 +00:00
|
|
|
*
|
2010-07-05 14:10:42 +00:00
|
|
|
* Return value: %TRUE if the operation was succesful, %FALSE otherwise
|
2010-06-14 11:38:25 +00:00
|
|
|
*
|
2010-07-05 14:10:42 +00:00
|
|
|
* Since: 1.4
|
2010-06-14 11:38:25 +00:00
|
|
|
*/
|
|
|
|
gboolean
|
|
|
|
cally_actor_remove_action (CallyActor *cally_actor,
|
2010-07-05 14:10:42 +00:00
|
|
|
gint action_id)
|
2010-06-14 11:38:25 +00:00
|
|
|
{
|
|
|
|
GList *list_node = NULL;
|
|
|
|
CallyActorPrivate *priv = NULL;
|
|
|
|
|
|
|
|
g_return_val_if_fail (CALLY_IS_ACTOR (cally_actor), FALSE);
|
|
|
|
priv = cally_actor->priv;
|
|
|
|
|
|
|
|
list_node = g_list_nth (priv->action_list, action_id - 1);
|
|
|
|
|
|
|
|
if (!list_node)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
_cally_actor_destroy_action_info (list_node->data, NULL);
|
|
|
|
|
|
|
|
priv->action_list = g_list_remove_link (priv->action_list, list_node);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2010-07-05 14:10:42 +00:00
|
|
|
* cally_actor_remove_action_by_name:
|
|
|
|
* @cally_actor: a #CallyActor
|
|
|
|
* @action_name: the name of the action to remove
|
2010-06-14 11:38:25 +00:00
|
|
|
*
|
2010-07-05 14:10:42 +00:00
|
|
|
* Removes an action, using the @action_name used when the action was added
|
|
|
|
* with cally_actor_add_action()
|
2010-06-14 11:38:25 +00:00
|
|
|
*
|
2010-07-05 14:10:42 +00:00
|
|
|
* Return value: %TRUE if the operation was succesful, %FALSE otherwise
|
2010-06-14 11:38:25 +00:00
|
|
|
*
|
2010-07-05 14:10:42 +00:00
|
|
|
* Since: 1.4
|
2010-06-14 11:38:25 +00:00
|
|
|
*/
|
|
|
|
gboolean
|
2010-07-05 14:10:42 +00:00
|
|
|
cally_actor_remove_action_by_name (CallyActor *cally_actor,
|
2010-06-14 11:38:25 +00:00
|
|
|
const gchar *action_name)
|
|
|
|
{
|
|
|
|
GList *node = NULL;
|
|
|
|
gboolean action_found = FALSE;
|
|
|
|
CallyActorPrivate *priv = NULL;
|
|
|
|
|
|
|
|
g_return_val_if_fail (CALLY_IS_ACTOR (cally_actor), FALSE);
|
|
|
|
priv = CALLY_ACTOR (cally_actor)->priv;
|
|
|
|
|
|
|
|
for (node = priv->action_list; node && !action_found;
|
|
|
|
node = node->next)
|
|
|
|
{
|
2010-09-29 13:10:38 +00:00
|
|
|
CallyActorActionInfo *ainfo = node->data;
|
|
|
|
|
|
|
|
if (!g_ascii_strcasecmp (ainfo->name, action_name))
|
2010-06-14 11:38:25 +00:00
|
|
|
{
|
|
|
|
action_found = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!action_found)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
_cally_actor_destroy_action_info (node->data, NULL);
|
|
|
|
priv->action_list = g_list_remove_link (priv->action_list, node);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cally_actor_destroy_action_info (gpointer action_info,
|
2010-12-10 17:46:58 +00:00
|
|
|
gpointer user_data)
|
2010-06-14 11:38:25 +00:00
|
|
|
{
|
2010-12-10 17:46:58 +00:00
|
|
|
CallyActorActionInfo *info = action_info;
|
2010-06-14 11:38:25 +00:00
|
|
|
|
|
|
|
g_assert (info != NULL);
|
|
|
|
|
|
|
|
g_free (info->name);
|
|
|
|
g_free (info->description);
|
|
|
|
g_free (info->keybinding);
|
|
|
|
|
2010-12-10 17:46:58 +00:00
|
|
|
if (info->notify)
|
|
|
|
info->notify (info->user_data);
|
|
|
|
|
|
|
|
g_slice_free (CallyActorActionInfo, info);
|
2010-06-14 11:38:25 +00:00
|
|
|
}
|