Merge remote branch 'elliot/events-buttons'
* elliot/events-buttons: cookbook: Add recipe about handling button events cookbook: Example of using button press and release events cookbook: Example of ClutterClickAction cookbook: Example of simple handling of button events
This commit is contained in:
commit
c202156794
@ -1021,4 +1021,392 @@ ClutterStage *stage = clutter_event_get_stage (event);
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
<section id="events-buttons">
|
||||
<title>Making an actor respond to button events</title>
|
||||
|
||||
<section>
|
||||
<title>Problem</title>
|
||||
|
||||
<para>You want an actor to respond to button events. These might
|
||||
be buttons on an input device like a mouse;
|
||||
or input events caused by other means, like touches on a screen.</para>
|
||||
|
||||
<para>Some examples of where this is useful:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>For implementing button widgets which respond to
|
||||
button clicks.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>To make actor selections by mouse click (e.g.
|
||||
as part of a drawing application).</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>To recognise a button press followed by pointer
|
||||
motion and button release (e.g. to implement drag
|
||||
and drop or kinetic animations).</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Solution</title>
|
||||
|
||||
<para>Connect a handler to the <emphasis>button-press-event</emphasis>
|
||||
and/or <emphasis>button-release-event</emphasis> signals of an
|
||||
actor.</para>
|
||||
|
||||
<note>
|
||||
<para>The <emphasis>button-press-event</emphasis> is emitted
|
||||
when a button is pressed (not necessarily released) on a reactive
|
||||
actor; the <emphasis>button-release-event</emphasis> when a
|
||||
button is released on a reactive actor (even if the button was
|
||||
pressed down somewhere else).</para>
|
||||
</note>
|
||||
|
||||
<para>First, ensure the actor is reactive:</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
clutter_actor_set_reactive (actor, TRUE);
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>Next, create a function to handle the signal(s) you are
|
||||
interested in. The function signature is the same for both the
|
||||
press and release signals:</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
gboolean
|
||||
callback_function (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer user_data);
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>You can use a single function as the
|
||||
callback for both signals (or write a different one for each signal).
|
||||
Here's an example function which can be used as a callback
|
||||
for both press and release signals, as it simply pulls data
|
||||
out of the event and displays it:</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
/* <varname>event</varname> is a <type>ClutterButtonEvent</type>
|
||||
* for both the press and the release signal; it contains
|
||||
* data about where the event occurred
|
||||
*/
|
||||
static gboolean
|
||||
button_event_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
gfloat x, y;
|
||||
gchar *event_type;
|
||||
guint button_pressed;
|
||||
ClutterModifierType state;
|
||||
gchar *ctrl_pressed;
|
||||
guint32 click_count;
|
||||
|
||||
/* where the pointer was (relative to the stage)
|
||||
* when the button event occurred; use
|
||||
* <function>clutter_actor_transform_stage_point()</function>
|
||||
* to transform to actor-relative coordinates
|
||||
*/
|
||||
clutter_event_get_coords (event, &x, &y);
|
||||
|
||||
/* check whether it was a press or release event */
|
||||
event_type = "released";
|
||||
if (clutter_event_type (event) == CLUTTER_BUTTON_PRESS)
|
||||
event_type = "pressed";
|
||||
|
||||
/* which button triggered the event */
|
||||
button_pressed = clutter_event_get_button (event);
|
||||
|
||||
/* keys down when the event occurred;
|
||||
* this is a bit mask composed of the bits for each key held down
|
||||
* when the button was pressed or released; see the
|
||||
* <type>ClutterModifierType</type> enum in the Clutter API docs
|
||||
* for a list of the available modifiers
|
||||
*/
|
||||
state = clutter_event_get_state (event);
|
||||
|
||||
ctrl_pressed = "ctrl not pressed";
|
||||
if (state & CLUTTER_CONTROL_MASK)
|
||||
ctrl_pressed = "ctrl pressed";
|
||||
|
||||
/* click count */
|
||||
click_count = clutter_event_get_click_count (event);
|
||||
|
||||
g_debug ("button %d was %s at %.0f,%.0f; %s; click count %d",
|
||||
button_pressed,
|
||||
event_type,
|
||||
x,
|
||||
y,
|
||||
ctrl_pressed,
|
||||
click_count);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>Finally, connect the signals to the function(s):</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
/* connect the press event */
|
||||
g_signal_connect (actor,
|
||||
"button-press-event",
|
||||
G_CALLBACK (button_event_cb),
|
||||
NULL);
|
||||
|
||||
/* connect the release event */
|
||||
g_signal_connect (actor,
|
||||
"button-release-event",
|
||||
G_CALLBACK (button_event_cb),
|
||||
NULL);
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>Pressing or releasing a button on the actor will now
|
||||
trigger a call to the <function>button_event_cb()</function>
|
||||
function. See <link linkend="events-buttons-example-1">the full
|
||||
example</link> for more details.</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Discussion</title>
|
||||
|
||||
<para>Properties of the <type>ClutterButtonEvent</type>
|
||||
emitted by both signals should be examined using the
|
||||
<function>clutter_event_*</function> functions (rather than struct
|
||||
members directly), as in the example above. While most of these
|
||||
functions are self-explanatory, a couple require more explanation:
|
||||
see the sections below.</para>
|
||||
|
||||
<para>Also covered below is an alternative approach to handling a
|
||||
button press followed by a release on a single actor: by adding
|
||||
a <type>ClutterClickAction</type> to an actor. See
|
||||
<link linkend="events-buttons-clutterclickaction">this section</link>
|
||||
for details.</para>
|
||||
|
||||
<para>Finally, a <link linkend="events-buttons-example-3">longer
|
||||
example</link> is included, showing how to make use of button press,
|
||||
button release and pointer events in a simple drawing application.</para>
|
||||
|
||||
<section>
|
||||
<title>Click count</title>
|
||||
|
||||
<para>The click count records the number of times a press/release
|
||||
pair occurred in sequence. You can retrieve it via the
|
||||
<function>clutter_event_get_click_count()</function> function.</para>
|
||||
|
||||
<note>
|
||||
<para>A press/release pair is effectively a click, so this term
|
||||
will be used from now on throughout this section,
|
||||
to make the explanation simpler. However, the click count has
|
||||
nothing to do with <type>ClutterClickActions</type>, described
|
||||
<link linkend="events-buttons-clutterclickaction">later</link>.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<para>For clicks to be considered part of the same sequence (for
|
||||
the purposes of counting), all the clicks after the first one
|
||||
must occur within the global <varname>double_click_distance</varname>
|
||||
(pixels) of the first click; and the time between click
|
||||
<code>n</code> and click <code>n+1</code> must be <code><=</code>
|
||||
the global <varname>double_click_time</varname> (milliseconds).</para>
|
||||
|
||||
<para>The clicks <emphasis>do not</emphasis> have to occur on
|
||||
the same actor: providing they occur within the double click
|
||||
distance and time, they are counted as part of the same click
|
||||
sequence. Also note that the clicks don't even have to happen
|
||||
on a reactive actor: providing they happen somewhere on the
|
||||
stage, they will still increment the click count.</para>
|
||||
|
||||
<para>The default double click time and distance are
|
||||
stored in the <type>ClutterSettings</type> associated
|
||||
with an application. You can get/set their values like this:</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
gint double_click_distance;
|
||||
gint double_click_time;
|
||||
|
||||
ClutterSettings *settings = clutter_settings_get_default ();
|
||||
|
||||
/* get double click settings */
|
||||
g_object_get (settings,
|
||||
"double-click-distance", &double_click_distance,
|
||||
"double-click-time", &double_click_time,
|
||||
NULL);
|
||||
|
||||
/* set */
|
||||
g_object_set (settings,
|
||||
"double-click-distance", 50,
|
||||
"double-click-time", 1000,
|
||||
NULL);
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Button numbering</title>
|
||||
|
||||
<para><function>clutter_event_get_button()</function> returns
|
||||
an integer representing the pressed or released button.</para>
|
||||
|
||||
<para>In the case of a standard scroll mouse, the numbers
|
||||
returned are reliable across different hardware models:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>1 = left mouse button</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>2 = scroll wheel</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>3 = right mouse button</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>For mice with more buttons, or other types of
|
||||
input devices, the mappings may not be so
|
||||
straightforward: you may have to experiment to see
|
||||
which button returns which value.</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section id="events-buttons-clutterclickaction">
|
||||
<title><type>ClutterClickAction</type></title>
|
||||
|
||||
<para><type>ClutterActions</type> add flexible event handling
|
||||
to <type>ClutterActors</type>. They recognise and abstract
|
||||
common sequences of low-level events into a single, more easily
|
||||
managed high-level event. In the case of a
|
||||
<type>ClutterClickAction</type>, the abstraction is over
|
||||
a press followed by a release on a single actor. This is
|
||||
achieved by "synthesising" the press and release signals on
|
||||
the actor: in other words, the action captures those
|
||||
two signals when emitted by a single actor; and, once captured, the
|
||||
action emits a single <emphasis>clicked</emphasis> signal
|
||||
<emphasis>instead</emphasis> of the two signals being
|
||||
emitted by the actor.</para>
|
||||
|
||||
<para>The pointer can move off the actor between the press and
|
||||
release, but the press and release must both occur on the same
|
||||
actor, with no intervening presses or releases on other
|
||||
actors. In addition, there are no maximum distance or time
|
||||
constraints on the press and release.</para>
|
||||
|
||||
<para>If a press occurs and you want to force it to be released
|
||||
(e.g. to break a pointer grab after a certain length of
|
||||
time has elapsed), use
|
||||
<function>clutter_click_action_release()</function>.</para>
|
||||
|
||||
<para>On the down side, the <emphasis>clicked</emphasis> signal
|
||||
doesn't present the same detailed <type>ClutterButtonEvent</type>
|
||||
to the handler. So, for example, you can't get a click count from a
|
||||
<type>ClutterClickAction</type> (though you could count
|
||||
the clicks yourself, of course); and you don't have access
|
||||
to the coordinates where the press or release occurred.</para>
|
||||
|
||||
<para>To add a click action to a <type>ClutterActor</type>:</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
ClutterAction *action = clutter_click_action_new ();
|
||||
clutter_actor_add_action (actor, action);
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<note>
|
||||
<para>An actor must still be set to reactive so that its
|
||||
signals can be routed to a click action.</para>
|
||||
</note>
|
||||
|
||||
<para>Create a handler function (note the function
|
||||
signature is different from the one for the press or
|
||||
releas signal handler):</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
void
|
||||
clicked_cb (ClutterClickAction *action,
|
||||
ClutterActor *actor,
|
||||
gpointer user_data)
|
||||
{
|
||||
/* display the number of the clicked button (equivalent
|
||||
* to the number returned by clutter_event_get_button())
|
||||
*/
|
||||
g_debug ("Button %d clicked", clutter_click_action_get_button (action));
|
||||
}
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>Connect the signal to the handler:</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
g_signal_connect (action,
|
||||
"clicked",
|
||||
G_CALLBACK (clicked_cb),
|
||||
NULL);
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>The <link linkend="events-buttons-example-2">example
|
||||
code</link> gives a bit more detail about how to use click
|
||||
actions.</para>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Full examples</title>
|
||||
|
||||
<example id="events-buttons-example-1">
|
||||
<title>Examining properties of a <type>ClutterButtonEvent</type></title>
|
||||
<programlisting>
|
||||
<xi:include href="examples/events-buttons.c" parse="text">
|
||||
<xi:fallback>a code sample should be here... but isn't</xi:fallback>
|
||||
</xi:include>
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
<example id="events-buttons-example-2">
|
||||
<title>Using <type>ClutterClickAction</type> to capture
|
||||
button events on an actor</title>
|
||||
<programlisting>
|
||||
<xi:include href="examples/events-buttons-click.c" parse="text">
|
||||
<xi:fallback>a code sample should be here... but isn't</xi:fallback>
|
||||
</xi:include>
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
<example id="events-buttons-example-3">
|
||||
<title>Using button and pointer events for drawing</title>
|
||||
<para>This code was inspired by
|
||||
<ulink url="http://git.clutter-project.org/cluttersmith/">ClutterSmith</ulink>
|
||||
</para>
|
||||
<programlisting>
|
||||
<xi:include href="examples/events-buttons-lasso.c" parse="text">
|
||||
<xi:fallback>a code sample should be here... but isn't</xi:fallback>
|
||||
</xi:include>
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
|
@ -28,6 +28,9 @@ noinst_PROGRAMS = \
|
||||
textures-crossfade-slideshow \
|
||||
script-ui \
|
||||
script-signals \
|
||||
events-buttons \
|
||||
events-buttons-click \
|
||||
events-buttons-lasso \
|
||||
$(NULL)
|
||||
|
||||
INCLUDES = \
|
||||
@ -76,5 +79,8 @@ textures_crossfade_cogl_SOURCES = textures-crossfade-cogl.c
|
||||
textures_crossfade_slideshow_SOURCES = textures-crossfade-slideshow.c
|
||||
script_ui_SOURCES = script-ui.c
|
||||
script_signals_SOURCES = script-signals.c
|
||||
events_buttons_SOURCES = events-buttons.c
|
||||
events_buttons_click_SOURCES = events-buttons-click.c
|
||||
events_buttons_lasso_SOURCES = events-buttons-lasso.c
|
||||
|
||||
-include $(top_srcdir)/build/autotools/Makefile.am.gitignore
|
||||
|
66
doc/cookbook/examples/events-buttons-click.c
Normal file
66
doc/cookbook/examples/events-buttons-click.c
Normal file
@ -0,0 +1,66 @@
|
||||
#include <stdlib.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static const ClutterColor stage_color = { 0x33, 0x33, 0x55, 0xff };
|
||||
static const ClutterColor red_color = { 0xff, 0x00, 0x00, 0xff };
|
||||
static const ClutterColor blue_color = { 0x00, 0x00, 0xff, 0xff };
|
||||
|
||||
void
|
||||
clicked_cb (ClutterClickAction *action,
|
||||
ClutterActor *actor,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_debug ("Button %d clicked", clutter_click_action_get_button (action));
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ClutterAction *action1;
|
||||
ClutterAction *action2;
|
||||
ClutterActor *actor1;
|
||||
ClutterActor *actor2;
|
||||
|
||||
clutter_init (&argc, &argv);
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
clutter_actor_set_size (stage, 400, 400);
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
actor1 = clutter_rectangle_new_with_color (&red_color);
|
||||
clutter_actor_set_size (actor1, 100, 100);
|
||||
clutter_actor_set_reactive (actor1, TRUE);
|
||||
clutter_actor_set_position (actor1, 50, 150);
|
||||
|
||||
actor2 = clutter_rectangle_new_with_color (&blue_color);
|
||||
clutter_actor_set_size (actor2, 100, 100);
|
||||
clutter_actor_set_position (actor2, 250, 150);
|
||||
clutter_actor_set_reactive (actor2, TRUE);
|
||||
|
||||
action1 = clutter_click_action_new ();
|
||||
clutter_actor_add_action (actor1, action1);
|
||||
|
||||
action2 = clutter_click_action_new ();
|
||||
clutter_actor_add_action (actor2, action2);
|
||||
|
||||
clutter_container_add (CLUTTER_CONTAINER (stage), actor1, actor2, NULL);
|
||||
|
||||
g_signal_connect (action1,
|
||||
"clicked",
|
||||
G_CALLBACK (clicked_cb),
|
||||
NULL);
|
||||
|
||||
g_signal_connect (action2,
|
||||
"clicked",
|
||||
G_CALLBACK (clicked_cb),
|
||||
NULL);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
154
doc/cookbook/examples/events-buttons-lasso.c
Normal file
154
doc/cookbook/examples/events-buttons-lasso.c
Normal file
@ -0,0 +1,154 @@
|
||||
/* Simple rectangle drawing using button and pointer events;
|
||||
* click, drag and release a mouse button to draw a rectangle
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static const ClutterColor stage_color = { 0x33, 0x33, 0x55, 0xff };
|
||||
static const ClutterColor lasso_color = { 0xaa, 0xaa, 0xaa, 0x33 };
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ClutterActor *actor;
|
||||
gfloat x;
|
||||
gfloat y;
|
||||
} Lasso;
|
||||
|
||||
static guint
|
||||
random_color_component ()
|
||||
{
|
||||
return (guint) (155 + (100.0 * rand () / (RAND_MAX + 1.0)));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
button_pressed_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
Lasso *lasso = (Lasso *) user_data;
|
||||
|
||||
/* start drawing the lasso actor */
|
||||
lasso->actor = clutter_rectangle_new_with_color (&lasso_color);
|
||||
|
||||
/* store lasso's start coordinates */
|
||||
clutter_event_get_coords (event, &(lasso->x), &(lasso->y));
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (actor), lasso->actor);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
button_released_cb (ClutterActor *stage,
|
||||
ClutterEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
Lasso *lasso = (Lasso *) user_data;
|
||||
ClutterActor *rectangle;
|
||||
ClutterColor *random_color;
|
||||
gfloat x;
|
||||
gfloat y;
|
||||
gfloat width;
|
||||
gfloat height;
|
||||
|
||||
if (lasso->actor == NULL)
|
||||
return TRUE;
|
||||
|
||||
/* create a new rectangle */
|
||||
random_color = clutter_color_new (random_color_component (),
|
||||
random_color_component (),
|
||||
random_color_component (),
|
||||
random_color_component ());
|
||||
rectangle = clutter_rectangle_new_with_color (random_color);
|
||||
|
||||
/* set the rectangle to the same size and shape as the lasso */
|
||||
clutter_actor_get_position (lasso->actor, &x, &y);
|
||||
clutter_actor_get_size (lasso->actor, &width, &height);
|
||||
|
||||
clutter_actor_set_position (rectangle, x, y);
|
||||
clutter_actor_set_size (rectangle, width, height);
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), rectangle);
|
||||
|
||||
/* clear up the lasso actor */
|
||||
clutter_actor_destroy (lasso->actor);
|
||||
lasso->actor = NULL;
|
||||
|
||||
clutter_actor_queue_redraw (stage);
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pointer_motion_cb (ClutterActor *stage,
|
||||
ClutterEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
gfloat pointer_x;
|
||||
gfloat pointer_y;
|
||||
gfloat new_x;
|
||||
gfloat new_y;
|
||||
gfloat width;
|
||||
gfloat height;
|
||||
|
||||
Lasso *lasso = (Lasso *) user_data;
|
||||
|
||||
if (lasso->actor == NULL)
|
||||
return TRUE;
|
||||
|
||||
/* redraw the lasso actor */
|
||||
clutter_event_get_coords (event, &pointer_x, &pointer_y);
|
||||
|
||||
new_x = MIN (pointer_x, lasso->x);
|
||||
new_y = MIN (pointer_y, lasso->y);
|
||||
width = MAX (pointer_x, lasso->x) - new_x;
|
||||
height = MAX (pointer_y, lasso->y) - new_y;
|
||||
|
||||
clutter_actor_set_position (lasso->actor, new_x, new_y);
|
||||
clutter_actor_set_size (lasso->actor, width, height);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
/* seed random number generator */
|
||||
srand ((unsigned int) time (NULL));
|
||||
|
||||
Lasso *lasso = g_new0 (Lasso, 1);
|
||||
|
||||
ClutterActor *stage;
|
||||
|
||||
clutter_init (&argc, &argv);
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
clutter_actor_set_size (stage, 320, 240);
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
g_signal_connect (stage,
|
||||
"button-press-event",
|
||||
G_CALLBACK (button_pressed_cb),
|
||||
lasso);
|
||||
|
||||
g_signal_connect (stage,
|
||||
"button-release-event",
|
||||
G_CALLBACK (button_released_cb),
|
||||
lasso);
|
||||
|
||||
g_signal_connect (stage,
|
||||
"motion-event",
|
||||
G_CALLBACK (pointer_motion_cb),
|
||||
lasso);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
g_free (lasso);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
107
doc/cookbook/examples/events-buttons.c
Normal file
107
doc/cookbook/examples/events-buttons.c
Normal file
@ -0,0 +1,107 @@
|
||||
#include <stdlib.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static const ClutterColor stage_color = { 0x33, 0x33, 0x55, 0xff };
|
||||
static const ClutterColor red_color = { 0xff, 0x00, 0x00, 0xff };
|
||||
static const ClutterColor green_color = { 0x00, 0xff, 0x00, 0xff };
|
||||
|
||||
static gboolean
|
||||
button_event_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
gfloat x, y;
|
||||
gchar *event_type;
|
||||
guint button_pressed;
|
||||
ClutterModifierType state;
|
||||
gchar *ctrl_pressed;
|
||||
guint32 click_count;
|
||||
|
||||
/* where the pointer was when the button event occurred */
|
||||
clutter_event_get_coords (event, &x, &y);
|
||||
|
||||
/* check whether it was a press or release event */
|
||||
event_type = "released";
|
||||
if (clutter_event_type (event) == CLUTTER_BUTTON_PRESS)
|
||||
event_type = "pressed";
|
||||
|
||||
/* which button triggered the event */
|
||||
button_pressed = clutter_event_get_button (event);
|
||||
|
||||
/* keys down when the button was pressed */
|
||||
state = clutter_event_get_state (event);
|
||||
|
||||
ctrl_pressed = "ctrl not pressed";
|
||||
if (state & CLUTTER_CONTROL_MASK)
|
||||
ctrl_pressed = "ctrl pressed";
|
||||
|
||||
/* click count */
|
||||
click_count = clutter_event_get_click_count (event);
|
||||
|
||||
g_debug ("button %d %s at %.0f,%.0f; %s; click count %d",
|
||||
button_pressed,
|
||||
event_type,
|
||||
x,
|
||||
y,
|
||||
ctrl_pressed,
|
||||
click_count);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ClutterActor *red;
|
||||
ClutterActor *green;
|
||||
|
||||
clutter_init (&argc, &argv);
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
clutter_actor_set_size (stage, 400, 400);
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
red = clutter_rectangle_new_with_color (&red_color);
|
||||
clutter_actor_set_size (red, 100, 100);
|
||||
clutter_actor_set_position (red, 50, 150);
|
||||
clutter_actor_set_reactive (red, TRUE);
|
||||
|
||||
green = clutter_rectangle_new_with_color (&green_color);
|
||||
clutter_actor_set_size (green, 100, 100);
|
||||
clutter_actor_set_position (green, 250, 150);
|
||||
clutter_actor_set_reactive (green, TRUE);
|
||||
|
||||
g_signal_connect (red,
|
||||
"button-press-event",
|
||||
G_CALLBACK (button_event_cb),
|
||||
NULL);
|
||||
|
||||
g_signal_connect (red,
|
||||
"button-release-event",
|
||||
G_CALLBACK (button_event_cb),
|
||||
NULL);
|
||||
|
||||
g_signal_connect (green,
|
||||
"button-press-event",
|
||||
G_CALLBACK (button_event_cb),
|
||||
NULL);
|
||||
|
||||
g_signal_connect (green,
|
||||
"button-release-event",
|
||||
G_CALLBACK (button_event_cb),
|
||||
NULL);
|
||||
|
||||
clutter_container_add (CLUTTER_CONTAINER (stage),
|
||||
red,
|
||||
green,
|
||||
NULL);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user