mirror of
https://github.com/brl/mutter.git
synced 2025-02-16 21:34:09 +00:00
cally: Improving cally doc
* Add documentation for all undocumented symbols * Add an overview section
This commit is contained in:
parent
c931e11e3d
commit
a2f8ce175f
@ -244,7 +244,7 @@ struct _CallyActorPrivate
|
|||||||
*
|
*
|
||||||
* Creates a new #CallyActor for the given @actor
|
* Creates a new #CallyActor for the given @actor
|
||||||
*
|
*
|
||||||
* Return value: the newly created #CallyActor
|
* Return value: the newly created #AtkObject
|
||||||
*
|
*
|
||||||
* Since: 1.4
|
* Since: 1.4
|
||||||
*/
|
*/
|
||||||
|
@ -74,10 +74,10 @@ struct _CallyActor
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* CallyActorClass:
|
* CallyActorClass:
|
||||||
* @notify_clutter: FIXME
|
* @notify_clutter: Signal handler for notify signal on Clutter actor
|
||||||
* @focus_clutter: FIXME
|
* @focus_clutter: Signal handler for key-focus-in and key-focus-out signal on Clutter actor
|
||||||
* @add_actor: FIXME
|
* @add_actor: Signal handler for actor-added signal on ClutterContainer interface
|
||||||
* @remove_actor: FIXME
|
* @remove_actor: Signal handler for actor-added signal on ClutterContainer interface
|
||||||
*
|
*
|
||||||
* The <structname>CallyActorClass</structname> structure contains only
|
* The <structname>CallyActorClass</structname> structure contains only
|
||||||
* private data
|
* private data
|
||||||
|
@ -102,6 +102,17 @@ cally_clone_init (CallyClone *clone)
|
|||||||
/* nothing to do yet */
|
/* nothing to do yet */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cally_clone_new:
|
||||||
|
* @actor: a #ClutterActor
|
||||||
|
*
|
||||||
|
* Creates a new #CallyClone for the given @actor. @actor must be a
|
||||||
|
* #ClutterClone.
|
||||||
|
*
|
||||||
|
* Return value: the newly created #AtkObject
|
||||||
|
*
|
||||||
|
* Since: 1.4
|
||||||
|
*/
|
||||||
AtkObject*
|
AtkObject*
|
||||||
cally_clone_new (ClutterActor *actor)
|
cally_clone_new (ClutterActor *actor)
|
||||||
{
|
{
|
||||||
|
@ -29,6 +29,22 @@
|
|||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
#include <atk/atkobject.h>
|
#include <atk/atkobject.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CALLY_ACCESSIBLE_FACTORY:
|
||||||
|
* @type: GType of the accessible which is created by the factory
|
||||||
|
* @type_as_function: prefix of the accessible object methods
|
||||||
|
* @opt_create_accessible: method to instantiate the accessibility object
|
||||||
|
*
|
||||||
|
* Defines a new #AtkObjectFactory factory to create accessible
|
||||||
|
* objects of a specific GType. It defines the factory GType and also
|
||||||
|
* overrides the proper #AtkObjectFactory methods.
|
||||||
|
*
|
||||||
|
* It assumes that the accessibility object provides a
|
||||||
|
* @opt_create_accessible method in order to create the accessibility
|
||||||
|
* object. It returns a @type GType object.
|
||||||
|
*
|
||||||
|
* Since: 1.4
|
||||||
|
*/
|
||||||
#define CALLY_ACCESSIBLE_FACTORY(type, type_as_function, opt_create_accessible) \
|
#define CALLY_ACCESSIBLE_FACTORY(type, type_as_function, opt_create_accessible) \
|
||||||
\
|
\
|
||||||
static GType \
|
static GType \
|
||||||
@ -83,6 +99,16 @@ type_as_function ## _factory_get_type (void) \
|
|||||||
return t; \
|
return t; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CALLY_ACTOR_SET_FACTORY:
|
||||||
|
* @widget_type: GType of the clutter actor
|
||||||
|
* @type_as_function: prefix of the accessible object methods
|
||||||
|
*
|
||||||
|
* Sets the #AtkObjectFactory to be used in order to instantiate
|
||||||
|
* accessibility objects for the actor which GType is @widget_type.
|
||||||
|
*
|
||||||
|
* Since: 1.4
|
||||||
|
*/
|
||||||
#define CALLY_ACTOR_SET_FACTORY(widget_type, type_as_function) \
|
#define CALLY_ACTOR_SET_FACTORY(widget_type, type_as_function) \
|
||||||
atk_registry_set_factory_type (atk_get_default_registry (), \
|
atk_registry_set_factory_type (atk_get_default_registry (), \
|
||||||
widget_type, \
|
widget_type, \
|
||||||
|
@ -62,6 +62,17 @@ cally_rectangle_init (CallyRectangle *rectangle)
|
|||||||
/* nothing to do yet */
|
/* nothing to do yet */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cally_rectangle_new:
|
||||||
|
* @actor: a #ClutterActor
|
||||||
|
*
|
||||||
|
* Creates a new #CallyRectangle for the given @actor. @actor must be
|
||||||
|
* a #ClutterRectangle.
|
||||||
|
*
|
||||||
|
* Return value: the newly created #AtkObject
|
||||||
|
*
|
||||||
|
* Since: 1.4
|
||||||
|
*/
|
||||||
AtkObject*
|
AtkObject*
|
||||||
cally_rectangle_new (ClutterActor *actor)
|
cally_rectangle_new (ClutterActor *actor)
|
||||||
{
|
{
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION:cally-root
|
* SECTION:cally-root
|
||||||
* @short_description: Root object for the CALLY toolkit
|
* @short_description: Root object for the Cally toolkit
|
||||||
* @see_also: #ClutterStage
|
* @see_also: #ClutterStage
|
||||||
*
|
*
|
||||||
* #CallyRoot is the root object of the accessibility tree-like
|
* #CallyRoot is the root object of the accessibility tree-like
|
||||||
@ -105,6 +105,15 @@ cally_root_init (CallyRoot *root)
|
|||||||
root->priv->stage_removed_id = 0;
|
root->priv->stage_removed_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cally_root_new:
|
||||||
|
*
|
||||||
|
* Creates a new #CallyRoot object.
|
||||||
|
*
|
||||||
|
* Return value: the newly created #AtkObject
|
||||||
|
*
|
||||||
|
* Since: 1.4
|
||||||
|
*/
|
||||||
AtkObject*
|
AtkObject*
|
||||||
cally_root_new (void)
|
cally_root_new (void)
|
||||||
{
|
{
|
||||||
|
@ -28,6 +28,11 @@
|
|||||||
*
|
*
|
||||||
* #CallyStage implements the required ATK interfaces for #ClutterStage
|
* #CallyStage implements the required ATK interfaces for #ClutterStage
|
||||||
*
|
*
|
||||||
|
* Some implementation details: at this moment #CallyStage is used as
|
||||||
|
* the most similar Window object in this toolkit (ie: emitting window
|
||||||
|
* related signals), although the real purpose of #ClutterStage is
|
||||||
|
* being a canvas. Anyway, this is required for applications using
|
||||||
|
* just clutter, or directly #ClutterStage
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cally-stage.h"
|
#include "cally-stage.h"
|
||||||
@ -88,6 +93,18 @@ cally_stage_class_init (CallyStageClass *klass)
|
|||||||
|
|
||||||
g_type_class_add_private (gobject_class, sizeof (CallyStagePrivate));
|
g_type_class_add_private (gobject_class, sizeof (CallyStagePrivate));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CallyStage::activate:
|
||||||
|
* @cally_actor: the object which received the signal
|
||||||
|
*
|
||||||
|
* The ::activate signal is emitted when the stage receives the key
|
||||||
|
* focus from the underlying window system.
|
||||||
|
*
|
||||||
|
* Toolkit implementation note: it is used when anyone adds a global
|
||||||
|
* event listener to "window:activate"
|
||||||
|
*
|
||||||
|
* Since: 1.4
|
||||||
|
*/
|
||||||
cally_stage_signals [ACTIVATE] =
|
cally_stage_signals [ACTIVATE] =
|
||||||
g_signal_new ("activate",
|
g_signal_new ("activate",
|
||||||
G_TYPE_FROM_CLASS (klass),
|
G_TYPE_FROM_CLASS (klass),
|
||||||
@ -96,6 +113,18 @@ cally_stage_class_init (CallyStageClass *klass)
|
|||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
g_cclosure_marshal_VOID__VOID,
|
g_cclosure_marshal_VOID__VOID,
|
||||||
G_TYPE_NONE, 0);
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CallyStage::create:
|
||||||
|
* @cally_actor: the object which received the signal
|
||||||
|
*
|
||||||
|
* The ::create signal is emitted when the stage is created.
|
||||||
|
*
|
||||||
|
* Toolkit implementation note: it is used when anyone adds a global
|
||||||
|
* event listener to "window:create"
|
||||||
|
*
|
||||||
|
* Since: 1.4
|
||||||
|
*/
|
||||||
cally_stage_signals [CREATE] =
|
cally_stage_signals [CREATE] =
|
||||||
g_signal_new ("create",
|
g_signal_new ("create",
|
||||||
G_TYPE_FROM_CLASS (klass),
|
G_TYPE_FROM_CLASS (klass),
|
||||||
@ -104,6 +133,19 @@ cally_stage_class_init (CallyStageClass *klass)
|
|||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
g_cclosure_marshal_VOID__VOID,
|
g_cclosure_marshal_VOID__VOID,
|
||||||
G_TYPE_NONE, 0);
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CallyStage::deactivate:
|
||||||
|
* @cally_actor: the object which received the signal
|
||||||
|
*
|
||||||
|
* The ::deactivate signal is emitted when the stage loses key focus
|
||||||
|
* from the underlying window system.
|
||||||
|
*
|
||||||
|
* Toolkit implementation note: it is used when anyone adds a global
|
||||||
|
* event listener to "window:deactivate"
|
||||||
|
*
|
||||||
|
* Since: 1.4
|
||||||
|
*/
|
||||||
cally_stage_signals [DEACTIVATE] =
|
cally_stage_signals [DEACTIVATE] =
|
||||||
g_signal_new ("deactivate",
|
g_signal_new ("deactivate",
|
||||||
G_TYPE_FROM_CLASS (klass),
|
G_TYPE_FROM_CLASS (klass),
|
||||||
@ -112,6 +154,18 @@ cally_stage_class_init (CallyStageClass *klass)
|
|||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
g_cclosure_marshal_VOID__VOID,
|
g_cclosure_marshal_VOID__VOID,
|
||||||
G_TYPE_NONE, 0);
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CallyStage::destroy:
|
||||||
|
* @cally_actor: the object which received the signal
|
||||||
|
*
|
||||||
|
* The ::destroy signal is emitted when the stage is destroyed.
|
||||||
|
*
|
||||||
|
* Toolkit implementation note: it is used when anyone adds a global
|
||||||
|
* event listener to "window:destroy"
|
||||||
|
*
|
||||||
|
* Since: 1.4
|
||||||
|
*/
|
||||||
cally_stage_signals [DESTROY] =
|
cally_stage_signals [DESTROY] =
|
||||||
g_signal_new ("destroy",
|
g_signal_new ("destroy",
|
||||||
G_TYPE_FROM_CLASS (klass),
|
G_TYPE_FROM_CLASS (klass),
|
||||||
@ -132,6 +186,17 @@ cally_stage_init (CallyStage *cally_stage)
|
|||||||
priv->active = FALSE;
|
priv->active = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cally_stage_new:
|
||||||
|
* @actor: a #ClutterActor
|
||||||
|
*
|
||||||
|
* Creates a new #CallyStage for the given @actor. @actor should be a
|
||||||
|
* #ClutterStage.
|
||||||
|
*
|
||||||
|
* Return value: the newly created #AtkObject
|
||||||
|
*
|
||||||
|
* Since: 1.4
|
||||||
|
*/
|
||||||
AtkObject*
|
AtkObject*
|
||||||
cally_stage_new (ClutterActor *actor)
|
cally_stage_new (ClutterActor *actor)
|
||||||
{
|
{
|
||||||
|
@ -269,6 +269,17 @@ cally_text_finalize (GObject *obj)
|
|||||||
G_OBJECT_CLASS (cally_text_parent_class)->finalize (obj);
|
G_OBJECT_CLASS (cally_text_parent_class)->finalize (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cally_text_new:
|
||||||
|
* @actor: a #ClutterActor
|
||||||
|
*
|
||||||
|
* Creates a new #CallyText for the given @actor. @actor must be a
|
||||||
|
* #ClutterText.
|
||||||
|
*
|
||||||
|
* Return value: the newly created #AtkObject
|
||||||
|
*
|
||||||
|
* Since: 1.4
|
||||||
|
*/
|
||||||
AtkObject*
|
AtkObject*
|
||||||
cally_text_new (ClutterActor *actor)
|
cally_text_new (ClutterActor *actor)
|
||||||
{
|
{
|
||||||
|
@ -63,6 +63,17 @@ cally_texture_init (CallyTexture *texture)
|
|||||||
/* nothing to do yet */
|
/* nothing to do yet */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cally_texture_new:
|
||||||
|
* @actor: a #ClutterActor
|
||||||
|
*
|
||||||
|
* Creates a new #CallyTexture for the given @actor. @actor must be
|
||||||
|
* a #ClutterTexture.
|
||||||
|
*
|
||||||
|
* Return value: the newly created #AtkObject
|
||||||
|
*
|
||||||
|
* Since: 1.4
|
||||||
|
*/
|
||||||
AtkObject*
|
AtkObject*
|
||||||
cally_texture_new (ClutterActor *actor)
|
cally_texture_new (ClutterActor *actor)
|
||||||
{
|
{
|
||||||
|
@ -20,6 +20,15 @@
|
|||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:cally
|
||||||
|
* @Title: Cally
|
||||||
|
* @short_description: Cally initialization methods.
|
||||||
|
*
|
||||||
|
* Cally initialization methods.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
@ -54,7 +63,7 @@ CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_RECTANGLE, cally_rectangle, cally_rectangle
|
|||||||
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_CLONE, cally_clone, cally_clone_new)
|
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_CLONE, cally_clone, cally_clone_new)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cally_acccessibility_init:
|
* cally_accessibility_init:
|
||||||
*
|
*
|
||||||
* Initializes the accessibility support.
|
* Initializes the accessibility support.
|
||||||
*
|
*
|
||||||
|
@ -63,12 +63,14 @@ HTML_IMAGES=
|
|||||||
|
|
||||||
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
|
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
|
||||||
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
|
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
|
||||||
content_files=
|
content_files= \
|
||||||
|
cally-overview.xml
|
||||||
|
|
||||||
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
|
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
|
||||||
# These files must be listed here *and* in content_files
|
# These files must be listed here *and* in content_files
|
||||||
# e.g. expand_content_files=running.sgml
|
# e.g. expand_content_files=running.sgml
|
||||||
expand_content_files=
|
expand_content_files= \
|
||||||
|
cally-overview.xml
|
||||||
|
|
||||||
# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
|
# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
|
||||||
# Only needed if you are using gtkdoc-scangobj to dynamically query widget
|
# Only needed if you are using gtkdoc-scangobj to dynamically query widget
|
||||||
|
@ -10,8 +10,10 @@
|
|||||||
<releaseinfo>for Clutter &version;</releaseinfo>
|
<releaseinfo>for Clutter &version;</releaseinfo>
|
||||||
|
|
||||||
<copyright>
|
<copyright>
|
||||||
|
<year>2008</year>
|
||||||
|
<year>2009</year>
|
||||||
<year>2010</year>
|
<year>2010</year>
|
||||||
<holder>Intel Corporation</holder>
|
<holder>Igalia S.L.</holder>
|
||||||
</copyright>
|
</copyright>
|
||||||
|
|
||||||
<legalnotice>
|
<legalnotice>
|
||||||
@ -37,6 +39,8 @@
|
|||||||
</legalnotice>
|
</legalnotice>
|
||||||
</bookinfo>
|
</bookinfo>
|
||||||
|
|
||||||
|
<xi:include href="xml/cally-overview.xml"/>
|
||||||
|
|
||||||
<part id="callybase">
|
<part id="callybase">
|
||||||
<title>Cally Reference</title>
|
<title>Cally Reference</title>
|
||||||
|
|
||||||
@ -44,6 +48,7 @@
|
|||||||
<title>Base Classes</title>
|
<title>Base Classes</title>
|
||||||
|
|
||||||
<xi:include href="xml/cally-actor.xml"/>
|
<xi:include href="xml/cally-actor.xml"/>
|
||||||
|
<xi:include href="xml/cally-group.xml"/>
|
||||||
<xi:include href="xml/cally-stage.xml"/>
|
<xi:include href="xml/cally-stage.xml"/>
|
||||||
<xi:include href="xml/cally-texture.xml"/>
|
<xi:include href="xml/cally-texture.xml"/>
|
||||||
<xi:include href="xml/cally-rectangle.xml"/>
|
<xi:include href="xml/cally-rectangle.xml"/>
|
||||||
|
74
doc/reference/cally/cally-overview.xml
Normal file
74
doc/reference/cally/cally-overview.xml
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<part id="clutter-overview">
|
||||||
|
<partinfo>
|
||||||
|
<author>
|
||||||
|
<firstname>Alejandro</firstname>
|
||||||
|
<surname>Piñeiro Iglesias</surname>
|
||||||
|
<affiliation>
|
||||||
|
<address>
|
||||||
|
<email>apinheiro@igalia.com</email>
|
||||||
|
</address>
|
||||||
|
</affiliation>
|
||||||
|
</author>
|
||||||
|
</partinfo>
|
||||||
|
|
||||||
|
<title>Overview</title>
|
||||||
|
|
||||||
|
<partintro>
|
||||||
|
|
||||||
|
<para>Cally (Clutter Accessibility Implementation Library) is the
|
||||||
|
Clutter implementation of the ATK interfaces. You can see as the
|
||||||
|
Clutter equivalent of GAIL, which provides accessibility support
|
||||||
|
for GTK+ and other GNOME related libraries.</para>
|
||||||
|
|
||||||
|
<para>This implementation expose Clutter actors to accessibility
|
||||||
|
tools like Orca. This allows not only writing accessible user
|
||||||
|
interfaces, but also allows testing and verification frameworks
|
||||||
|
based on accessibility technologies to inspect and test a Clutter
|
||||||
|
scene graph.</para>
|
||||||
|
|
||||||
|
<para>This reference manual defines the different APIs defined in
|
||||||
|
Cally. Anyway take into account that the most common use of case
|
||||||
|
Cally is transparent to the user, as the different accessibility
|
||||||
|
tools are intended to use the abstract ATK interfaces, and *not
|
||||||
|
directly* Cally, so this tools can communicate with applications
|
||||||
|
using different toolkits, like GTK+, Java, Clutter, etc. </para>
|
||||||
|
|
||||||
|
<para>The purpose of this reference is allow to extend Cally
|
||||||
|
functionality in any Clutter-based widget toolkit. Clutter is more
|
||||||
|
low-level that other toolkits like GTK+, and some toolkits have
|
||||||
|
started to appear based on Clutter: MX, Shell Toolkit, Candies,
|
||||||
|
Glitter, etc. This means that it is really likely that these
|
||||||
|
libraries will require extra accessibility support.</para>
|
||||||
|
|
||||||
|
<para>GAIL used a different approach, being a almost-pure-opaque
|
||||||
|
implementation of the ATK interfaces. So you can't extend it
|
||||||
|
directly. You need to use GObject and ATK mechanisms, like
|
||||||
|
run-time anonymous inheritance, to extend it. Although valid to
|
||||||
|
some custom cases, it showed to be really problematic and hacky in
|
||||||
|
wider approaches, like HAIL(Hildon Accessibility Implementation
|
||||||
|
Library). As explained, Clutter is more likely to be extended, so
|
||||||
|
these issues would arise sooner.</para>
|
||||||
|
|
||||||
|
<para>Part of the accessibility support is implemented on Clutter,
|
||||||
|
like the initialization code, and the method to obtain the
|
||||||
|
accessibility object for each Clutter object. In the same way, to
|
||||||
|
make it easier, and to allow access to Clutter object private
|
||||||
|
data, it would be really likely that the accessibility support
|
||||||
|
would be implemented directly on some Clutter objects</para>
|
||||||
|
|
||||||
|
<para>Check the next clutter methods for more information:</para>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term>clutter_actor_get_accessible()</term>
|
||||||
|
<listitem>Virtual method to obtain the accessibility object of a
|
||||||
|
clutter actor</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>clutter_get_accessibility_enabled()</term>
|
||||||
|
<listitem>Method to check if accessibility is enabled.</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
</partintro>
|
||||||
|
|
||||||
|
</part>
|
@ -137,6 +137,10 @@
|
|||||||
<listitem><para>Unsets FLAGS from the COGL debugging
|
<listitem><para>Unsets FLAGS from the COGL debugging
|
||||||
flags.</para></listitem>
|
flags.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>--clutter-enable-accessibility</term>
|
||||||
|
<listitem><para>Enables accessibility support.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
|
|
||||||
<para>The X11 backends also have the following command line
|
<para>The X11 backends also have the following command line
|
||||||
|
Loading…
x
Reference in New Issue
Block a user