diff --git a/src/fbd-event.c b/src/fbd-event.c index 4868a00..a257034 100644 --- a/src/fbd-event.c +++ b/src/fbd-event.c @@ -430,6 +430,52 @@ fbd_event_end_feedbacks (FbdEvent *self) g_slist_foreach (self->feedbacks, (GFunc)fbd_feedback_end, NULL); } +/** + * fbd_event_end_feedbacks_by_level: + * @self: The Event + * @level: The profile level + * + * End all feedback strictly above the given profile level. + */ +void +fbd_event_end_feedbacks_by_level (FbdEvent *self, guint level) +{ + g_autoptr (GSList) feedbacks = NULL; + guint num = 0; + + g_return_if_fail (FBD_IS_EVENT (self)); + /* Copy the list as we will remove feedbacks from self->feedbacks */ + feedbacks = g_slist_copy (fbd_event_get_feedbacks (self)); + + for (GSList *l = feedbacks; l; l = l->next) { + FbdFeedbackBase *fb = FBD_FEEDBACK_BASE (l->data); + guint event_level; + + event_level = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (fb), "fbd-level")); + if (event_level > level) + num++; + } + + if (num == 0) + return; + + g_debug ("Will end %d feedbacks of event %s", num, fbd_event_get_event (self)); + /* Set 'explicit' if we end all remaining feedbacks */ + if (num == g_slist_length (self->feedbacks)) + fbd_event_set_end_reason (self, FBD_EVENT_END_REASON_EXPLICIT); + + for (GSList *l = feedbacks; l; l = l->next) { + FbdFeedbackBase *fb = FBD_FEEDBACK_BASE (l->data); + guint event_level; + + event_level = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (fb), "fbd-level")); + if (event_level > level) { + fbd_event_remove_feedback (self, fb); + fbd_feedback_end (fb); + } + } +} + /** * fbd_event_get_feedbacks_ended: * @self: The Event diff --git a/src/fbd-event.h b/src/fbd-event.h index f7844c2..b023217 100644 --- a/src/fbd-event.h +++ b/src/fbd-event.h @@ -47,6 +47,7 @@ int fbd_event_remove_feedback (FbdEvent *self, FbdFeedbackBase *feedback); void fbd_event_run_feedbacks (FbdEvent *self); void fbd_event_end_feedbacks (FbdEvent *self); +void fbd_event_end_feedbacks_by_level (FbdEvent *self, guint level); gboolean fbd_event_get_feedbacks_ended (FbdEvent *self); const char *fbd_event_get_sender (FbdEvent *self); diff --git a/tests/test-fbd-event.c b/tests/test-fbd-event.c index 7bf6a1a..7fbad07 100644 --- a/tests/test-fbd-event.c +++ b/tests/test-fbd-event.c @@ -1,5 +1,7 @@ /* * Copyright (C) 2020 Purism SPC + * 2023-2024 The Phosh Developers + * * SPDX-License-Identifier: GPL-3.0+ * Author: Guido Günther */ @@ -109,6 +111,7 @@ test_fbd_event_feedback_ended (void) event = fbd_event_new (1, TEST_APP_ID, TEST_EVENT, FBD_EVENT_TIMEOUT_ONESHOT, NULL); feedback1 = g_object_new (FBD_TYPE_FEEDBACK_DUMMY, NULL); fbd_event_add_feedback (event, FBD_FEEDBACK_BASE (feedback1)); + feedback2 = g_object_new (FBD_TYPE_FEEDBACK_DUMMY, NULL); fbd_event_add_feedback (event, FBD_FEEDBACK_BASE (feedback2)); @@ -119,6 +122,52 @@ test_fbd_event_feedback_ended (void) g_assert_true (ended); } + +static void +test_fbd_event_feedback_end_by_level (void) +{ + FbdEvent *event; + FbdFeedbackDummy *feedback1, *feedback2; + gboolean ended; + + feedback1 = g_object_new (FBD_TYPE_FEEDBACK_DUMMY, NULL); + g_object_set_data (G_OBJECT (feedback1), "fbd-level", GUINT_TO_POINTER (10)); + + feedback2 = g_object_new (FBD_TYPE_FEEDBACK_DUMMY, NULL); + g_object_set_data (G_OBJECT (feedback2), "fbd-level", GUINT_TO_POINTER (5)); + + event = fbd_event_new (1, TEST_APP_ID, TEST_EVENT, FBD_EVENT_TIMEOUT_ONESHOT, NULL); + g_signal_connect (event, "feedbacks-ended", + (GCallback)on_feedbacks_ended, &ended); + + /* End all feedback at once */ + fbd_event_add_feedback (event, FBD_FEEDBACK_BASE (feedback1)); + fbd_event_add_feedback (event, FBD_FEEDBACK_BASE (feedback2)); + fbd_event_end_feedbacks_by_level (event, 3); + g_assert_cmpint (g_slist_length (fbd_event_get_feedbacks (event)), ==, 0); + g_assert_cmpint (fbd_event_get_end_reason (event), ==, FBD_EVENT_END_REASON_EXPLICIT); + g_assert_true (ended); + + /* End feedback one by one */ + ended = FALSE; + fbd_event_set_end_reason (event, FBD_EVENT_END_REASON_NATURAL); + fbd_event_add_feedback (event, FBD_FEEDBACK_BASE (feedback1)); + fbd_event_add_feedback (event, FBD_FEEDBACK_BASE (feedback2)); + fbd_event_end_feedbacks_by_level (event, 7); + g_assert_cmpint (g_slist_length (fbd_event_get_feedbacks (event)), ==, 1); + g_assert_cmpint (fbd_event_get_end_reason (event), ==, FBD_EVENT_END_REASON_NATURAL); + g_assert_false (ended); + fbd_event_end_feedbacks_by_level (event, 4); + g_assert_cmpint (g_slist_length (fbd_event_get_feedbacks (event)), ==, 0); + g_assert_cmpint (fbd_event_get_end_reason (event), ==, FBD_EVENT_END_REASON_EXPLICIT); + g_assert_true (ended); + + g_assert_finalize_object (event); + g_assert_finalize_object (feedback2); + g_assert_finalize_object (feedback1); +} + + static void test_fbd_event_feedback_loop (void) { @@ -171,6 +220,8 @@ main (gint argc, gchar *argv[]) g_test_add_func ("/feedbackd/fbd/event/new", test_fbd_event); g_test_add_func ("/feedbackd/fbd/event/feedbacks/props", test_fbd_event_feedback); g_test_add_func ("/feedbackd/fbd/event/feedbacks/ended", test_fbd_event_feedback_ended); + g_test_add_func ("/feedbackd/fbd/event/feedbacks/end_by_level", + test_fbd_event_feedback_end_by_level); g_test_add_func ("/feedbackd/fbd/event/feedbacks/loop", test_fbd_event_feedback_loop); g_test_add_func ("/feedbackd/fbd/event/feedbacks/timeout", test_fbd_event_feedback_timeout);