diff --git a/doc/cookbook/Makefile.am b/doc/cookbook/Makefile.am index 2104d2bd2..3ca02255e 100644 --- a/doc/cookbook/Makefile.am +++ b/doc/cookbook/Makefile.am @@ -38,6 +38,7 @@ IMAGE_FILES = \ images/text-shadow.png \ images/textures-sub-texture.png \ images/layouts-stacking-diff-actor-sizes.png \ + images/events-pointer-motion-stacking.png \ $(NULL) VIDEO_FILES = \ videos/animations-fading-out.ogv \ diff --git a/doc/cookbook/events.xml b/doc/cookbook/events.xml index a15c57625..39df6ce7e 100644 --- a/doc/cookbook/events.xml +++ b/doc/cookbook/events.xml @@ -698,4 +698,327 @@ g_signal_connect (viewport, + +
+ Detecting pointer movements on an actor + +
+ Problem + + You want to be able to tell when the pointer (e.g. associated + with a mouse or touches on a screen) enters, leaves, or moves over + an actor. + + Example use cases include: + + + + Adding a tooltip or hover effect to an actor when + a pointer moves onto it. + + + Tracing the path of the pointer over an actor (e.g. + in a drawing application). + + + +
+ +
+ Solution + + Connect to the pointer motion signals emitted by the actor. + +
+ Responding to crossing events + + To detect the pointer crossing the boundary of an actor + (entering or leaving), connect to the enter-event + and/or leave-event signals. For example: + + + +ClutterActor *actor = clutter_texture_new (); + +/* ...set size, color, image etc., depending on the actor... */ + +/* make the actor reactive: see Discussion for more details */ +clutter_actor_set_reactive (actor, TRUE); + +/* connect to the signals */ +g_signal_connect (actor, + "enter-event", + G_CALLBACK (_pointer_enter_cb), + NULL); + +g_signal_connect (actor, + "leave-event", + G_CALLBACK (_pointer_leave_cb), + NULL); + + + + The signature for callbacks connected to each of these + signals is: + + + +gboolean +_on_crossing (ClutterActor *actor, + ClutterEvent *event, + gpointer user_data) + + + + In the callback, you can examine the event to get the + coordinates where the pointer entered or left the actor. For + example, _pointer_enter_cb() could + follow this template: + + + + + + + + See the + code example in the appendix for an example of how + you can implement a hover effect on a "button" (rectangle + with text overlay) using this approach. + +
+ +
+ Responding to motion events + + Motion events occur when a pointer moves over an actor; + the actor emits a motion-event signal when this + happens. To respond to motion events, connect to this signal: + + + +/* set up the actor, make reactive etc., as above */ + +/* connect to motion-event signal */ +g_signal_connect (actor, + "motion-event", + G_CALLBACK (_pointer_motion_cb), + transitions); + + + + The signature of the callback is the same as for + the enter-event/leave-event signals, so you can use + code + similar to the above to handle it. However, the + type of the event is a ClutterMotionEvent + (rather than a ClutterCrossingEvent). + +
+ +
+ +
+ Discussion + + A few more useful things to know about pointer motion + events: + + + + + Each crossing event is accompanied by a motion event at + the same coordinates. + + + + Before an actor will emit signals for pointer events, + it needs to be made reactive with: + + + +clutter_actor_set_reactive (actor, TRUE); + + + + + + A pointer event structure includes other data. Some + examples: + + + +/* keys and mouse buttons pressed down when the pointer moved */ +ClutterModifierType modifiers = clutter_event_get_state (event); + +/* time (since the epoch) when the event occurred */ +guint32 event_time = clutter_event_get_time (event); + +/* actor where the event originated */ +ClutterActor *actor = clutter_event_get_actor (event); + +/* stage where the event originated */ +ClutterStage *stage = clutter_event_get_stage (event); + + + + There's no need to cast the event to use these + functions: they will work on any ClutterEvent. + + + + The coordinates of an event (as returned by + clutter_event_get_coords()) are relative + to the stage where they originated, rather than the actor. Unless + the actor is the same size as the stage, you'll typically want + the actor-relative coordinates instead. To get those, use + clutter_actor_transform_stage_point(). + + + + + The simple + scribble application gives a more + thorough example of how to integrate pointer events into a + Clutter application (in this case, for drawing on a + ClutterTexture). + + The effect of actor depth on pointer motion events is + worth slightly deeper discussion, and is covered next. + +
+ Pointer events on actors at different depths + + If you have actors stacked on top of each other, the + reactive actor nearest the "top" is the one + which emits the signal (when the pointer crosses into or moves + over it). "Top" here means either at the top of + the depth ordering (if all actors are at the same depth) + or the closest to the view point (if actors have different + depths in the z axis). + + Here's an example of three rectangles overlapping each + other: + + + + + + + + Pointer events in actors with different depth ordering + + + + + The rectangles are all at the same point on the + z axis but stacked (different positions in the depth + order). They have the following properties: + + + + The red rectangle is lowest down + the depth ordering and reactive. Pointer motion signals are + emitted by this actor when the pointer crosses or moves on the + area of the rectangle not overlapped by the + green rectangle. + + + The green rectangle is in the + middle of the depth ordering and reactive. This actor emits + events over its whole surface, even though it is overlapped + by the blue rectangle (as the blue rectangle is not + reactive). + Even if the blue rectangle were fully opaque, a pointer + crossing into or moving on the green rectangle's area (even if + obscured by the blue rectangle) would still cause a signal + to be emitted. + + + The blue rectangle is at the top + of the depth ordering and not reactive. + This actor doesn't emit any pointer motion signals and doesn't + block events from occurring on any other actor. + + + + See the + sample code in the appendix for more details. + +
+ +
+ +
+ Full examples + + + Simple button with a hover animation (change in opacity + as the pointer enters and leaves it) + + + a code sample should be here... but isn't + + + + + + Detecting pointer motion on a <type>ClutterRectangle</type> + + + a code sample should be here... but isn't + + + + + + How actors influence pointer events on each other + + + a code sample should be here... but isn't + + + + + + Scribbling on a <type>ClutterTexture</type> in response + to pointer events + + + a code sample should be here... but isn't + + + + +
+ +
diff --git a/doc/cookbook/images/events-pointer-motion-stacking.png b/doc/cookbook/images/events-pointer-motion-stacking.png new file mode 100644 index 000000000..7eb782d7f Binary files /dev/null and b/doc/cookbook/images/events-pointer-motion-stacking.png differ