Improve LEAVE events for border actors

If an actor is lying on the border of the Stage it might miss the LEAVE
event when the pointer of a device leaves the Stage window. Since the
backend is unsetting the Stage back pointer on the InputDevice we can
queue the emission of a LEAVE event on the pointer actor as well.

http://bugzilla.moblin.org/show_bug.cgi?id=9677
This commit is contained in:
Emmanuele Bassi 2010-02-17 10:46:16 +00:00
parent 719e314b8e
commit fbcaf1e0b3
2 changed files with 39 additions and 6 deletions

View File

@ -261,15 +261,36 @@ void
_clutter_input_device_set_stage (ClutterInputDevice *device,
ClutterStage *stage)
{
ClutterStage *old_stage;
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
old_stage = device->stage;
device->stage = stage;
/* if we left the stage then we also need to unset the
* cursor actor (and update its :has-pointer property)
*/
if (device->stage == NULL && device->cursor_actor != NULL)
if (device->stage == NULL &&
device->cursor_actor != NULL &&
device->cursor_actor != CLUTTER_ACTOR (old_stage))
{
ClutterEvent cev;
cev.crossing.type = CLUTTER_LEAVE;
cev.crossing.time = device->current_time;
cev.crossing.flags = 0;
cev.crossing.stage = old_stage;
cev.crossing.source = device->cursor_actor;
cev.crossing.x = device->current_x;
cev.crossing.y = device->current_y;
cev.crossing.device = device;
cev.crossing.related = device->stage != NULL
? CLUTTER_ACTOR (device->stage)
: CLUTTER_ACTOR (old_stage);
_clutter_stage_queue_event (old_stage, &cev);
_clutter_actor_set_has_pointer (device->cursor_actor, FALSE);
g_object_weak_unref (G_OBJECT (device->cursor_actor),
cursor_weak_unref,

View File

@ -261,7 +261,8 @@ test_events_main (int argc, char *argv[])
bcol = { 0, 0, 0xff, 0xff },
gcol = { 0, 0xff, 0, 0xff },
ycol = { 0xff, 0xff, 0, 0xff },
ncol = { 0, 0, 0, 0xff };
ncol = { 0, 0, 0, 0xff },
xcol = { 0xff, 0, 0xff, 0xff };
clutter_init (&argc, &argv);
@ -350,6 +351,17 @@ test_events_main (int argc, char *argv[])
clutter_actor_set_position (group, 100, 350);
clutter_actor_show_all (group);
/* border actor */
actor = clutter_rectangle_new_with_color (&xcol);
clutter_actor_set_name (actor, "Border Box");
clutter_actor_set_size (actor, 100, 100);
clutter_actor_set_position (actor,
(clutter_actor_get_width (stage) - 100) / 2,
clutter_actor_get_height (stage) - 100);
clutter_actor_set_reactive (actor, TRUE);
clutter_container_add_actor (CLUTTER_CONTAINER (stage), actor);
g_signal_connect (actor, "event", G_CALLBACK (input_cb), NULL);
clutter_actor_show_all (CLUTTER_ACTOR (stage));
clutter_main();