mirror of
https://gitlab.gnome.org/GNOME/calls.git
synced 2025-01-08 04:45:31 +00:00
manager: Delay UI Call removal and adjust to changes
This was handled explicitly in the Call window. By changing the logic to delay the emission of "ui-call-removed" we make sure that the Call UI and the exported DBus object is consistent. We also need to change the test cases to use run a GMainLoop because we now have to wait until signal comes in.
This commit is contained in:
parent
cde517096b
commit
3fe976505c
4 changed files with 141 additions and 98 deletions
|
@ -39,7 +39,6 @@
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
#include <handy.h>
|
#include <handy.h>
|
||||||
|
|
||||||
#define CALLS_WINDOW_HIDE_DELAY 3
|
|
||||||
|
|
||||||
struct _CallsCallWindow
|
struct _CallsCallWindow
|
||||||
{
|
{
|
||||||
|
@ -56,8 +55,6 @@ struct _CallsCallWindow
|
||||||
GtkFlowBox *call_selector;
|
GtkFlowBox *call_selector;
|
||||||
|
|
||||||
guint inhibit_cookie;
|
guint inhibit_cookie;
|
||||||
guint hideout_id;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (CallsCallWindow, calls_call_window, GTK_TYPE_APPLICATION_WINDOW);
|
G_DEFINE_TYPE (CallsCallWindow, calls_call_window, GTK_TYPE_APPLICATION_WINDOW);
|
||||||
|
@ -86,41 +83,19 @@ session_inhibit (CallsCallWindow *self, gboolean inhibit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
on_delayed_window_hide (gpointer user_data)
|
|
||||||
{
|
|
||||||
CallsCallWindow *self = user_data;
|
|
||||||
g_assert (CALLS_IS_CALL_WINDOW (self));
|
|
||||||
|
|
||||||
gtk_widget_set_visible (GTK_WIDGET (self), FALSE);
|
|
||||||
|
|
||||||
gtk_stack_set_visible_child_name (self->main_stack, "calls");
|
|
||||||
|
|
||||||
self->hideout_id = 0;
|
|
||||||
|
|
||||||
return G_SOURCE_REMOVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_visibility (CallsCallWindow *self)
|
update_visibility (CallsCallWindow *self)
|
||||||
{
|
{
|
||||||
guint calls = g_list_model_get_n_items (G_LIST_MODEL (self->calls));
|
guint calls = g_list_model_get_n_items (G_LIST_MODEL (self->calls));
|
||||||
|
|
||||||
if (calls == 0) {
|
gtk_widget_set_visible (GTK_WIDGET (self), calls > 0);
|
||||||
self->hideout_id =
|
|
||||||
g_timeout_add_seconds (CALLS_WINDOW_HIDE_DELAY,
|
|
||||||
G_SOURCE_FUNC (on_delayed_window_hide),
|
|
||||||
self);
|
|
||||||
} else {
|
|
||||||
g_clear_handle_id (&self->hideout_id, g_source_remove);
|
|
||||||
|
|
||||||
gtk_widget_set_visible (GTK_WIDGET (self), TRUE);
|
|
||||||
|
|
||||||
if (calls == 1)
|
|
||||||
gtk_stack_set_visible_child_name (self->main_stack, "active-call");
|
|
||||||
}
|
|
||||||
gtk_widget_set_sensitive (GTK_WIDGET (self->show_calls), calls > 1);
|
gtk_widget_set_sensitive (GTK_WIDGET (self->show_calls), calls > 1);
|
||||||
|
|
||||||
|
if (calls == 0)
|
||||||
|
gtk_stack_set_visible_child_name (self->main_stack, "calls");
|
||||||
|
else if (calls == 1)
|
||||||
|
gtk_stack_set_visible_child_name (self->main_stack, "active-call");
|
||||||
|
|
||||||
session_inhibit (self, !!calls);
|
session_inhibit (self, !!calls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,23 +208,6 @@ add_call (CallsCallWindow *self,
|
||||||
self);
|
self);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DisplayData
|
|
||||||
{
|
|
||||||
GtkStack *call_stack;
|
|
||||||
CuiCallDisplay *display;
|
|
||||||
};
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
on_remove_delayed (gpointer user_data)
|
|
||||||
{
|
|
||||||
struct DisplayData *display_data = user_data;
|
|
||||||
|
|
||||||
gtk_container_remove (GTK_CONTAINER (display_data->call_stack),
|
|
||||||
GTK_WIDGET (display_data->display));
|
|
||||||
|
|
||||||
g_free (display_data);
|
|
||||||
return G_SOURCE_REMOVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
remove_call (CallsCallWindow *self,
|
remove_call (CallsCallWindow *self,
|
||||||
|
@ -272,15 +230,9 @@ remove_call (CallsCallWindow *self,
|
||||||
CALLS_UI_CALL_DATA (cui_call_display_get_call (display));
|
CALLS_UI_CALL_DATA (cui_call_display_get_call (display));
|
||||||
|
|
||||||
if (display_call_data == ui_call_data) {
|
if (display_call_data == ui_call_data) {
|
||||||
struct DisplayData *display_data = g_new0 (struct DisplayData, 1);
|
|
||||||
|
|
||||||
g_list_store_remove (self->calls, i);
|
g_list_store_remove (self->calls, i);
|
||||||
display_data->call_stack = self->call_stack;
|
gtk_container_remove (GTK_CONTAINER (self->call_stack),
|
||||||
display_data->display = display;
|
GTK_WIDGET (display));
|
||||||
g_timeout_add_seconds (CALLS_WINDOW_HIDE_DELAY,
|
|
||||||
G_SOURCE_FUNC (on_remove_delayed),
|
|
||||||
display_data);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -399,4 +351,3 @@ calls_call_window_new (GtkApplication *application)
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef CALLS_WINDOW_HIDE_DELAY
|
|
||||||
|
|
|
@ -246,27 +246,62 @@ add_call (CallsManager *self, CallsCall *call, CallsOrigin *origin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct CallsRemoveData
|
||||||
|
{
|
||||||
|
CallsManager *manager;
|
||||||
|
CallsCall *call;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
on_remove_delayed (struct CallsRemoveData *data)
|
||||||
|
{
|
||||||
|
CallsUiCallData *call_data;
|
||||||
|
|
||||||
|
g_assert (CALLS_IS_MANAGER (data->manager));
|
||||||
|
g_assert (CALLS_IS_CALL (data->call));
|
||||||
|
|
||||||
|
call_data = g_hash_table_lookup (data->manager->calls, data->call);
|
||||||
|
if (!call_data) {
|
||||||
|
g_warning ("Could not find call %s in UI call hash table",
|
||||||
|
calls_call_get_id (data->call));
|
||||||
|
} else {
|
||||||
|
g_signal_emit (data->manager, signals[UI_CALL_REMOVED], 0, call_data);
|
||||||
|
g_hash_table_remove (data->manager->calls, data->call);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (data);
|
||||||
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define DELAY_CALL_REMOVE_MS 3000
|
||||||
static void
|
static void
|
||||||
remove_call (CallsManager *self, CallsCall *call, gchar *reason, CallsOrigin *origin)
|
remove_call (CallsManager *self, CallsCall *call, gchar *reason, CallsOrigin *origin)
|
||||||
{
|
{
|
||||||
CallsUiCallData *call_data;
|
struct CallsRemoveData *data;
|
||||||
|
|
||||||
g_return_if_fail (CALLS_IS_MANAGER (self));
|
g_return_if_fail (CALLS_IS_MANAGER (self));
|
||||||
g_return_if_fail (CALLS_IS_ORIGIN (origin));
|
g_return_if_fail (CALLS_IS_ORIGIN (origin));
|
||||||
g_return_if_fail (CALLS_IS_CALL (call));
|
g_return_if_fail (CALLS_IS_CALL (call));
|
||||||
|
|
||||||
call_data = g_hash_table_lookup (self->calls, call);
|
data = g_new (struct CallsRemoveData, 1);
|
||||||
if (!call_data) {
|
data->manager = self;
|
||||||
g_warning ("Could not remove call %s from hash table", calls_call_get_id (call));
|
data->call = call;
|
||||||
} else {
|
|
||||||
g_signal_emit (self, signals[UI_CALL_REMOVED], 0, call_data);
|
/** Having the delay centrally managed makes sure our UI
|
||||||
g_hash_table_remove (self->calls, call);
|
* and the DBus side stays consistent
|
||||||
}
|
*/
|
||||||
|
g_timeout_add (DELAY_CALL_REMOVE_MS,
|
||||||
|
G_SOURCE_FUNC (on_remove_delayed),
|
||||||
|
data);
|
||||||
|
|
||||||
/* TODO get rid of SIGNAL_CALL_REMOVE signal */
|
/* TODO get rid of SIGNAL_CALL_REMOVE signal */
|
||||||
/* We ignore the reason for now, because it doesn't give any usefull information */
|
/* We ignore the reason for now, because it doesn't give any usefull information */
|
||||||
g_signal_emit (self, signals[SIGNAL_CALL_REMOVE], 0, call, origin);
|
g_signal_emit (self, signals[SIGNAL_CALL_REMOVE], 0, call, origin);
|
||||||
}
|
}
|
||||||
|
#undef DELAY_CALL_REMOVE_MS
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -24,6 +24,11 @@ test_link_args = [
|
||||||
'-fPIC',
|
'-fPIC',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
mock_link_args = [ test_link_args,
|
||||||
|
'-Wl,--wrap=calls_contacts_provider_new',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
tests = [
|
tests = [
|
||||||
[ 'provider', [] ],
|
[ 'provider', [] ],
|
||||||
[ 'origin', [ 'provider' ] ],
|
[ 'origin', [ 'provider' ] ],
|
||||||
|
@ -63,7 +68,7 @@ test_sources = [ 'test-manager.c' ]
|
||||||
|
|
||||||
t = executable('manager', test_sources,
|
t = executable('manager', test_sources,
|
||||||
c_args : test_cflags,
|
c_args : test_cflags,
|
||||||
link_args: test_link_args,
|
link_args: mock_link_args,
|
||||||
pie: true,
|
pie: true,
|
||||||
link_with : [calls_vala, libcalls],
|
link_with : [calls_vala, libcalls],
|
||||||
dependencies: calls_deps,
|
dependencies: calls_deps,
|
||||||
|
@ -115,10 +120,6 @@ t = executable('util', test_sources,
|
||||||
)
|
)
|
||||||
test('util', t, env: test_env)
|
test('util', t, env: test_env)
|
||||||
|
|
||||||
mock_link_args = [ test_link_args,
|
|
||||||
'-Wl,--wrap=calls_contacts_provider_new',
|
|
||||||
]
|
|
||||||
|
|
||||||
test_sources = [ 'test-ui-call.c', 'mock-call.c', 'mock-call.h' ]
|
test_sources = [ 'test-ui-call.c', 'mock-call.c', 'mock-call.h' ]
|
||||||
t = executable('ui-call', test_sources,
|
t = executable('ui-call', test_sources,
|
||||||
c_args : test_cflags,
|
c_args : test_cflags,
|
||||||
|
|
|
@ -5,24 +5,76 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "calls-manager.h"
|
#include "calls-manager.h"
|
||||||
|
#include "mock-contacts-provider.h"
|
||||||
|
|
||||||
#include <cui-call.h>
|
#include <cui-call.h>
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include <libpeas/peas.h>
|
#include <libpeas/peas.h>
|
||||||
|
|
||||||
CuiCall *test_call = NULL;
|
CallsContactsProvider *
|
||||||
|
__wrap_calls_contacts_provider_new (CallsSettings *settings)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestData {
|
||||||
|
GMainLoop *loop;
|
||||||
|
CallsManager *manager;
|
||||||
|
GListModel *origins;
|
||||||
|
GListModel *origins_tel;
|
||||||
|
CallsOrigin *origin;
|
||||||
|
CuiCall *call;
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
call_add_cb (CallsManager *manager, CuiCall *call)
|
call_add_cb (CallsManager *manager,
|
||||||
|
CuiCall *call,
|
||||||
|
struct TestData *data)
|
||||||
{
|
{
|
||||||
test_call = call;
|
static guint phase = 0;
|
||||||
|
|
||||||
|
data->call = call;
|
||||||
|
switch (phase++) {
|
||||||
|
case 0:
|
||||||
|
cui_call_hang_up (call);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
/* Unload the provider */
|
||||||
|
calls_manager_remove_provider (data->manager, "dummy");
|
||||||
|
g_assert_false (calls_manager_has_provider (data->manager, "dummy"));
|
||||||
|
g_assert_false (calls_manager_has_any_provider (data->manager));
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
call_remove_cb (CallsManager *manager, CuiCall *call)
|
call_remove_cb (CallsManager *manager,
|
||||||
|
CuiCall *call,
|
||||||
|
struct TestData *data)
|
||||||
{
|
{
|
||||||
g_assert_true (call == test_call);
|
static guint phase = 0;
|
||||||
test_call = NULL;
|
|
||||||
|
g_assert_true (call == data->call);
|
||||||
|
data->call = NULL;
|
||||||
|
switch (phase++) {
|
||||||
|
case 0:
|
||||||
|
/* Add new call do check if we remove it when we unload the provider */
|
||||||
|
calls_origin_dial (data->origin, "+393422342");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
g_main_loop_quit (data->loop);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -55,16 +107,21 @@ test_calls_manager_without_provider (void)
|
||||||
static void
|
static void
|
||||||
test_calls_manager_dummy_provider (void)
|
test_calls_manager_dummy_provider (void)
|
||||||
{
|
{
|
||||||
g_autoptr (CallsManager) manager = calls_manager_new ();
|
CallsManager *manager;
|
||||||
GListModel *origins;
|
GListModel *origins;
|
||||||
GListModel *origins_tel;
|
GListModel *origins_tel;
|
||||||
guint position;
|
guint position;
|
||||||
g_autoptr (CallsOrigin) origin = NULL;
|
struct TestData *test_data;
|
||||||
|
|
||||||
|
test_data = g_new0 (struct TestData, 1);
|
||||||
|
test_data->manager = calls_manager_new ();
|
||||||
|
manager = test_data->manager;
|
||||||
g_assert_true (CALLS_IS_MANAGER (manager));
|
g_assert_true (CALLS_IS_MANAGER (manager));
|
||||||
g_assert_cmpuint (calls_manager_get_state_flags (manager), ==, CALLS_MANAGER_FLAGS_UNKNOWN);
|
g_assert_cmpuint (calls_manager_get_state_flags (manager), ==, CALLS_MANAGER_FLAGS_UNKNOWN);
|
||||||
|
|
||||||
origins = calls_manager_get_origins (manager);
|
|
||||||
|
test_data->origins = calls_manager_get_origins (manager);
|
||||||
|
origins = test_data->origins;
|
||||||
g_assert_true (origins);
|
g_assert_true (origins);
|
||||||
g_assert_cmpuint (g_list_model_get_n_items (origins), ==, 0);
|
g_assert_cmpuint (g_list_model_get_n_items (origins), ==, 0);
|
||||||
|
|
||||||
|
@ -79,36 +136,35 @@ test_calls_manager_dummy_provider (void)
|
||||||
g_assert_cmpuint (g_list_model_get_n_items (origins), >, 0);
|
g_assert_cmpuint (g_list_model_get_n_items (origins), >, 0);
|
||||||
g_assert_null (calls_manager_get_calls (manager));
|
g_assert_null (calls_manager_get_calls (manager));
|
||||||
|
|
||||||
test_call = NULL;
|
test_data->origin = g_list_model_get_item (origins, 0);
|
||||||
g_signal_connect (manager, "ui-call-added", G_CALLBACK (call_add_cb), NULL);
|
g_assert_true (CALLS_IS_ORIGIN (test_data->origin));
|
||||||
g_signal_connect (manager, "ui-call-removed", G_CALLBACK (call_remove_cb), NULL);
|
|
||||||
|
|
||||||
origin = g_list_model_get_item (origins, 0);
|
test_data->origins_tel = calls_manager_get_suitable_origins (manager, "tel:+393422342");
|
||||||
g_assert_true (CALLS_IS_ORIGIN (origin));
|
origins_tel = test_data->origins_tel;
|
||||||
|
|
||||||
origins_tel = calls_manager_get_suitable_origins (manager, "tel:+393422342");
|
|
||||||
g_assert_true (G_IS_LIST_MODEL (origins_tel));
|
g_assert_true (G_IS_LIST_MODEL (origins_tel));
|
||||||
g_assert_true (G_IS_LIST_STORE (origins_tel));
|
g_assert_true (G_IS_LIST_STORE (origins_tel));
|
||||||
g_assert_true (g_list_store_find (G_LIST_STORE (origins_tel), origin, &position));
|
g_assert_true (g_list_store_find (G_LIST_STORE (origins_tel), test_data->origin, &position));
|
||||||
|
|
||||||
calls_origin_dial (origin, "+393422342");
|
g_signal_connect (manager, "ui-call-added", G_CALLBACK (call_add_cb), test_data);
|
||||||
g_assert_true (CUI_IS_CALL (test_call));
|
g_signal_connect (manager, "ui-call-removed", G_CALLBACK (call_remove_cb), test_data);
|
||||||
cui_call_hang_up (test_call);
|
|
||||||
g_assert_null (test_call);
|
|
||||||
|
|
||||||
/* Add new call do check if we remove it when we unload the provider */
|
calls_origin_dial (test_data->origin, "+393422343");
|
||||||
calls_origin_dial (origin, "+393422342");
|
g_assert_true (CUI_IS_CALL (test_data->call));
|
||||||
|
|
||||||
/* Unload the provider */
|
test_data->loop = g_main_loop_new (NULL, FALSE);
|
||||||
calls_manager_remove_provider (manager, "dummy");
|
g_main_loop_run (test_data->loop);
|
||||||
g_assert_false (calls_manager_has_provider (manager, "dummy"));
|
|
||||||
g_assert_false (calls_manager_has_any_provider (manager));
|
g_main_loop_unref (test_data->loop);
|
||||||
|
|
||||||
g_assert_null (test_call);
|
|
||||||
g_assert_cmpuint (g_list_model_get_n_items (origins), ==, 0);
|
g_assert_cmpuint (g_list_model_get_n_items (origins), ==, 0);
|
||||||
g_assert_cmpuint (g_list_model_get_n_items (origins_tel), ==, 0);
|
g_assert_cmpuint (g_list_model_get_n_items (origins_tel), ==, 0);
|
||||||
|
|
||||||
g_assert_cmpuint (calls_manager_get_state_flags (manager), ==, CALLS_MANAGER_FLAGS_UNKNOWN);
|
g_assert_cmpuint (calls_manager_get_state_flags (manager), ==, CALLS_MANAGER_FLAGS_UNKNOWN);
|
||||||
|
|
||||||
|
g_assert_finalize_object (test_data->origin);
|
||||||
|
g_assert_finalize_object (test_data->manager);
|
||||||
|
|
||||||
|
g_free (test_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Reference in a new issue