diff --git a/src/chatview.cpp b/src/chatview.cpp
index a43fb555030e8cd07feec22b157bfd7b1f1305f4..e5f4bf6d1e76071f013bc1242fd33b9a431deda3 100644
--- a/src/chatview.cpp
+++ b/src/chatview.cpp
@@ -79,6 +79,8 @@ G_DEFINE_TYPE_WITH_PRIVATE(ChatView, chat_view, GTK_TYPE_BOX);
 enum {
     NEW_MESSAGES_DISPLAYED,
     HIDE_VIEW_CLICKED,
+    PLACE_CALL_CLICKED,
+    PLACE_AUDIO_CALL_CLICKED,
     LAST_SIGNAL
 };
 
@@ -142,18 +144,15 @@ placecall_clicked(ChatView *self)
 {
     auto priv = CHAT_VIEW_GET_PRIVATE(self);
     if (!priv->conversation_) return;
-    (*priv->accountInfo_)->conversationModel->placeCall(priv->conversation_->uid);
+    g_signal_emit(G_OBJECT(self), chat_view_signals[PLACE_CALL_CLICKED], 0, priv->conversation_->uid.c_str());
 }
 
 static void
 place_audio_call_clicked(ChatView *self)
 {
     auto priv = CHAT_VIEW_GET_PRIVATE(self);
-
-    if (!priv->conversation_)
-        return;
-
-    (*priv->accountInfo_)->conversationModel->placeAudioOnlyCall(priv->conversation_->uid);
+    if (!priv->conversation_) return;
+    g_signal_emit(G_OBJECT(self), chat_view_signals[PLACE_AUDIO_CALL_CLICKED], 0, priv->conversation_->uid.c_str());
 }
 
 static void
@@ -342,6 +341,26 @@ chat_view_class_init(ChatViewClass *klass)
         nullptr,
         g_cclosure_marshal_VOID__VOID,
         G_TYPE_NONE, 0);
+
+    chat_view_signals[PLACE_CALL_CLICKED] = g_signal_new (
+        "place-call-clicked",
+        G_TYPE_FROM_CLASS(klass),
+        (GSignalFlags) (G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED),
+        0,
+        nullptr,
+        nullptr,
+        g_cclosure_marshal_VOID__STRING,
+        G_TYPE_NONE, 1, G_TYPE_STRING);
+
+    chat_view_signals[PLACE_AUDIO_CALL_CLICKED] = g_signal_new (
+        "place-audio-call-clicked",
+        G_TYPE_FROM_CLASS(klass),
+        (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
+        0,
+        nullptr,
+        nullptr,
+        g_cclosure_marshal_VOID__STRING,
+        G_TYPE_NONE, 1, G_TYPE_STRING);
 }
 
 static void
diff --git a/src/ringmainwindow.cpp b/src/ringmainwindow.cpp
index 58cc2af3b73b568ed1e9f89643a587084e06f23d..7cffef15e32db9ee4fd3e0aa60365974a60e58d5 100644
--- a/src/ringmainwindow.cpp
+++ b/src/ringmainwindow.cpp
@@ -367,6 +367,7 @@ public:
     QMetaObject::Connection accountStatusChangedConnection_;
     QMetaObject::Connection profileUpdatedConnection_;
 
+    std::string eventUid_;
 private:
     CppImpl() = delete;
     CppImpl(const CppImpl&) = delete;
@@ -421,6 +422,50 @@ on_hide_view_clicked(RingMainWindow* self)
     priv->cpp->resetToWelcome();
 }
 
+static gboolean
+place_call_event(RingMainWindow* self)
+{
+    g_return_val_if_fail(IS_RING_MAIN_WINDOW(self), G_SOURCE_REMOVE);
+    auto* priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(self));
+
+    if (!priv->cpp->eventUid_.empty())
+        priv->cpp->accountInfo_->conversationModel->placeCall(priv->cpp->eventUid_);
+
+    return G_SOURCE_REMOVE;
+}
+
+static void
+on_place_call_clicked(G_GNUC_UNUSED GtkWidget*, gchar *uid, RingMainWindow* self)
+{
+    g_return_if_fail(IS_RING_MAIN_WINDOW(self) && uid);
+    auto* priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(self));
+
+    priv->cpp->eventUid_ = uid;
+    g_idle_add((GSourceFunc)place_call_event, self);
+}
+
+static gboolean
+place_audio_call_event(RingMainWindow* self)
+{
+    g_return_val_if_fail(IS_RING_MAIN_WINDOW(self), G_SOURCE_REMOVE);
+    auto* priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(self));
+
+    if (!priv->cpp->eventUid_.empty())
+        priv->cpp->accountInfo_->conversationModel->placeAudioOnlyCall(priv->cpp->eventUid_);
+
+    return G_SOURCE_REMOVE;
+}
+
+static void
+on_place_audio_call_clicked(G_GNUC_UNUSED GtkWidget*, gchar *uid, RingMainWindow* self)
+{
+    g_return_if_fail(IS_RING_MAIN_WINDOW(self) && uid);
+    auto* priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(self));
+
+    priv->cpp->eventUid_ = uid;
+    g_idle_add((GSourceFunc)place_audio_call_event, self);
+}
+
 static void
 on_account_creation_completed(RingMainWindow* self)
 {
@@ -1335,6 +1380,8 @@ CppImpl::displayChatView(lrc::api::conversation::Info conversation, bool redraw_
     chatViewConversation_.reset(new lrc::api::conversation::Info(conversation));
     auto* new_view = chat_view_new(webkitChatContainer(redraw_webview), accountInfo_, chatViewConversation_.get());
     g_signal_connect_swapped(new_view, "hide-view-clicked", G_CALLBACK(on_hide_view_clicked), self);
+    g_signal_connect(new_view, "place-call-clicked", G_CALLBACK(on_place_call_clicked), self);
+    g_signal_connect(new_view, "place-audio-call-clicked", G_CALLBACK(on_place_audio_call_clicked), self);
     try {
         auto contactUri = chatViewConversation_->participants.front();
         auto contactInfo = accountInfo_->contactModel->getContact(contactUri);