From 3a79b7b066358a5901705d7eae036e23612ed22f Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Wed, 17 Nov 2021 23:17:14 +0100 Subject: [PATCH] clutter: Add docs and introspection annotations to grabs Since we want these accessed from bindings this must be a boxed type. This has the side effect of making ClutterGrab a refcounted object, since we want to avoid JS from pointing to freed memory and maybe causing crashes if misusing the object after dismiss. Part-of: --- clutter/clutter/clutter-grab.h | 10 ++++++ clutter/clutter/clutter-stage.c | 59 +++++++++++++++++++++++++++++++- src/tests/clutter/conform/grab.c | 14 ++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) diff --git a/clutter/clutter/clutter-grab.h b/clutter/clutter/clutter-grab.h index 5d23d634b..ca3324b68 100644 --- a/clutter/clutter/clutter-grab.h +++ b/clutter/clutter/clutter-grab.h @@ -30,12 +30,22 @@ #include +#define CLUTTER_TYPE_GRAB (clutter_grab_get_type ()) typedef struct _ClutterGrab ClutterGrab; +CLUTTER_EXPORT +GType clutter_grab_get_type (void) G_GNUC_CONST; + CLUTTER_EXPORT void clutter_grab_dismiss (ClutterGrab *grab); CLUTTER_EXPORT ClutterGrabState clutter_grab_get_seat_state (ClutterGrab *grab); +CLUTTER_EXPORT +ClutterGrab * clutter_grab_ref (ClutterGrab *grab); + +CLUTTER_EXPORT +void clutter_grab_unref (ClutterGrab *grab); + #endif /* CLUTTER_GRAB_H */ diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c index 1fe5ab927..67f5f6a65 100644 --- a/clutter/clutter/clutter-stage.c +++ b/clutter/clutter/clutter-stage.c @@ -137,6 +137,7 @@ struct _ClutterStagePrivate struct _ClutterGrab { + grefcount ref_count; ClutterStage *stage; ClutterActor *actor; ClutterGrab *prev; @@ -3750,6 +3751,37 @@ clutter_stage_notify_grab (ClutterStage *stage, clutter_stage_notify_grab_on_key_focus (stage, cur_actor, old_actor); } +ClutterGrab * +clutter_grab_ref (ClutterGrab *grab) +{ + g_ref_count_inc (&grab->ref_count); + return grab; +} + +void +clutter_grab_unref (ClutterGrab *grab) +{ + if (g_ref_count_dec (&grab->ref_count)) + { + clutter_grab_dismiss (grab); + g_free (grab); + } +} + +G_DEFINE_BOXED_TYPE (ClutterGrab, clutter_grab, + clutter_grab_ref, clutter_grab_unref) + +/** + * clutter_stage_grab: + * @stage: The #ClutterStage + * @actor: The actor grabbing input + * + * Grabs input onto a certain actor. Events will be propagated as + * usual inside its hierarchy. + * + * Returns: (transfer none): (nullable): an opaque #ClutterGrab handle, drop + * with clutter_grab_dismiss() + **/ ClutterGrab * clutter_stage_grab (ClutterStage *stage, ClutterActor *actor) @@ -3773,6 +3805,7 @@ clutter_stage_grab (ClutterStage *stage, } grab = g_new0 (ClutterGrab, 1); + g_ref_count_init (&grab->ref_count); grab->stage = stage; grab->actor = actor; grab->prev = NULL; @@ -3833,15 +3866,31 @@ clutter_stage_unlink_grab (ClutterStage *stage, grab->prev = NULL; } +/** + * clutter_grab_dismiss: + * @grab: Grab to undo + * + * Removes a grab. If this grab is effective, crossing events + * will be generated to indicate the change in event redirection. + **/ void clutter_grab_dismiss (ClutterGrab *grab) { g_return_if_fail (grab != NULL); clutter_stage_unlink_grab (grab->stage, grab); - g_free (grab); } +/** + * clutter_grab_get_seat_state: + * @grab: a Grab handle + * + * Returns the windowing-level state of the + * grab, the devices that are guaranteed to be + * grabbed. + * + * Returns: The state of the grab. + **/ ClutterGrabState clutter_grab_get_seat_state (ClutterGrab *grab) { @@ -3850,6 +3899,14 @@ clutter_grab_get_seat_state (ClutterGrab *grab) return grab->stage->priv->grab_state; } +/** + * clutter_stage_get_grab_actor: + * @stage: a #ClutterStage + * + * Gets the actor that currently holds a grab. + * + * Returns: (transfer none): The grabbing actor + **/ ClutterActor * clutter_stage_get_grab_actor (ClutterStage *stage) { diff --git a/src/tests/clutter/conform/grab.c b/src/tests/clutter/conform/grab.c index e2ecb9640..b5ee3f41f 100644 --- a/src/tests/clutter/conform/grab.c +++ b/src/tests/clutter/conform/grab.c @@ -217,6 +217,7 @@ grab_under_pointer (void) event_log_compare ((EventLog *) &grab_log, data.events); clutter_grab_dismiss (grab); + clutter_grab_unref (grab); event_log_compare ((EventLog *) &ungrab_log, data.events); test_data_shutdown (&data); @@ -243,6 +244,7 @@ grab_under_pointers_parent (void) event_log_compare ((EventLog *) &grab_log, data.events); clutter_grab_dismiss (grab); + clutter_grab_unref (grab); event_log_compare ((EventLog *) &ungrab_log, data.events); test_data_shutdown (&data); @@ -273,6 +275,7 @@ grab_outside_pointer (void) event_log_compare ((EventLog *) &grab_log, data.events); clutter_grab_dismiss (grab); + clutter_grab_unref (grab); event_log_compare ((EventLog *) &ungrab_log, data.events); test_data_shutdown (&data); @@ -297,6 +300,7 @@ grab_stage (void) event_log_compare ((EventLog *) &grab_log, data.events); clutter_grab_dismiss (grab); + clutter_grab_unref (grab); event_log_compare ((EventLog *) &ungrab_log, data.events); test_data_shutdown (&data); @@ -340,9 +344,11 @@ grab_stack_1 (void) /* Dismiss orderly */ clutter_grab_dismiss (grab2); + clutter_grab_unref (grab2); event_log_compare ((EventLog *) &ungrab2_log, data.events); clutter_grab_dismiss (grab1); + clutter_grab_unref (grab1); event_log_compare ((EventLog *) &ungrab1_log, data.events); test_data_shutdown (&data); @@ -388,9 +394,11 @@ grab_stack_2 (void) /* Dismiss orderly */ clutter_grab_dismiss (grab2); + clutter_grab_unref (grab2); event_log_compare ((EventLog *) &ungrab2_log, data.events); clutter_grab_dismiss (grab1); + clutter_grab_unref (grab1); event_log_compare ((EventLog *) &ungrab1_log, data.events); test_data_shutdown (&data); @@ -434,9 +442,11 @@ grab_unordered_ungrab_1 (void) /* Dismiss disorderly */ clutter_grab_dismiss (grab1); + clutter_grab_unref (grab1); event_log_compare ((EventLog *) &ungrab1_log, data.events); clutter_grab_dismiss (grab2); + clutter_grab_unref (grab2); event_log_compare ((EventLog *) &ungrab2_log, data.events); test_data_shutdown (&data); @@ -478,9 +488,11 @@ grab_unordered_ungrab_2 (void) /* Dismiss disorderly */ clutter_grab_dismiss (grab1); + clutter_grab_unref (grab1); event_log_compare ((EventLog *) &ungrab1_log, data.events); clutter_grab_dismiss (grab2); + clutter_grab_unref (grab2); event_log_compare ((EventLog *) &ungrab2_log, data.events); test_data_shutdown (&data); @@ -501,6 +513,7 @@ grab_key_focus_in_grab (void) g_assert_true (clutter_actor_has_key_focus (data.b)); clutter_grab_dismiss (grab); + clutter_grab_unref (grab); g_assert_true (clutter_actor_has_key_focus (data.b)); test_data_shutdown (&data); @@ -521,6 +534,7 @@ grab_key_focus_outside_grab (void) g_assert_false (clutter_actor_has_key_focus (data.b)); clutter_grab_dismiss (grab); + clutter_grab_unref (grab); g_assert_true (clutter_actor_has_key_focus (data.b)); test_data_shutdown (&data);