diff --git a/gajim/chat_control.py b/gajim/chat_control.py
index df5ebe85e4f32bdf2cff1f335298113d49e954a1..34b800dc455f3a9adf8a1513a04201f5cc5d4b95 100644
--- a/gajim/chat_control.py
+++ b/gajim/chat_control.py
@@ -114,6 +114,10 @@ def __init__(self, parent_win, jid, acct, session, resource=None):
 
         self.toggle_emoticons()
 
+        if self._type == ControlType.CHAT:
+            self._client.connect_signal('state-changed',
+                                        self._on_client_state_changed)
+
         if not app.settings.get('hide_chat_banner'):
             self.xml.banner_eventbox.set_no_show_all(False)
 
@@ -1183,13 +1187,14 @@ def _on_convert_to_gc_menuitem_activate(self, _widget):
         """
         dialogs.TransformChatToMUC(self.account, [self.contact.jid])
 
-    def got_connected(self):
-        ChatControlBase.got_connected(self)
-        self.draw_banner()
-        self.update_actions()
+    def _on_client_state_changed(self, _client, _signal_name, state):
+        self.msg_textview.set_sensitive(state.is_connected)
+        self.msg_textview.set_editable(state.is_connected)
 
-    def got_disconnected(self):
-        ChatControlBase.got_disconnected(self)
+        print(state)
+        self._update_avatar()
+        self.update_toolbar()
+        self.draw_banner()
         self.update_actions()
 
     def _on_presence_received(self, event):
diff --git a/gajim/chat_control_base.py b/gajim/chat_control_base.py
index 8cf4b64a7e0c3b44cd03a4a33c3de8825e1a1e20..92fd38df20fa091702db5d905431ab933bb78543 100644
--- a/gajim/chat_control_base.py
+++ b/gajim/chat_control_base.py
@@ -251,7 +251,6 @@ def __init__(self, parent_win, widget_name, jid, acct,
 
         # pylint: disable=line-too-long
         self.register_events([
-            ('our-show', ged.GUI1, self._on_our_show),
             ('ping-sent', ged.GUI1, self._nec_ping),
             ('ping-reply', ged.GUI1, self._nec_ping),
             ('ping-error', ged.GUI1, self._nec_ping),
@@ -448,15 +447,6 @@ def remove_session(self, session):
         self.session.control = None
         self.session = None
 
-    def _on_our_show(self, event):
-        if event.show == 'connecting':
-            return
-
-        if event.show == 'offline':
-            self.got_disconnected()
-        else:
-            self.got_connected()
-
     def _nec_ping(self, obj):
         raise NotImplementedError
 
@@ -686,6 +676,8 @@ def shutdown(self):
         app.plugin_manager.remove_gui_extension_point(
             'chat_control_base_update_toolbar', self)
 
+        self._client.disconnect_all_from_obj(self)
+
         for i in list(self.handlers.keys()):
             if self.handlers[i].handler_is_connected(i):
                 self.handlers[i].disconnect(i)
@@ -1522,18 +1514,6 @@ def scroll_messages(self, direction, msg_buf, msg_type):
                 message = '> %s\n' % message.replace('\n', '\n> ')
         msg_buf.set_text(message)
 
-    def got_connected(self):
-        self.msg_textview.set_sensitive(True)
-        self.msg_textview.set_editable(True)
-        self.update_toolbar()
-
-    def got_disconnected(self):
-        self.msg_textview.set_sensitive(False)
-        self.msg_textview.set_editable(False)
-        self.conversation_view.grab_focus()
-
-        self.update_toolbar()
-
 
 class ScrolledWindow(Gtk.ScrolledWindow):
     def __init__(self, *args, **kwargs):
diff --git a/gajim/common/client.py b/gajim/common/client.py
index 87eeb76409838440f5495e60416b76694672a456..18e94c8a8b4e9ff2cc7267e229dde0a7b6b8adb3 100644
--- a/gajim/common/client.py
+++ b/gajim/common/client.py
@@ -282,6 +282,7 @@ def _on_password(password):
             app.nec.push_incoming_event(NetworkEvent(
                 'our-show', account=self._account, show='offline'))
             self._after_disconnect()
+            self.get_module('Contacts').reset_presence()
             self.notify('state-changed', SimpleClientState.DISCONNECTED)
 
     def _after_disconnect(self):
@@ -296,9 +297,6 @@ def _after_disconnect(self):
             self._destroy_client = False
             self._create_client()
 
-        jid = self.get_own_jid()
-        contact = self.get_module('Contacts').get_contact(jid)
-        contact.update_presence(UNKNOWN_PRESENCE)
         app.nec.push_incoming_event(NetworkEvent('account-disconnected',
                                                  account=self._account))
 
diff --git a/gajim/common/const.py b/gajim/common/const.py
index 60904bd87a9406f7beea957611b9a0dd64cbe80b..72cc4a449bdc95651a628b30f1d85c3d93a04499 100644
--- a/gajim/common/const.py
+++ b/gajim/common/const.py
@@ -274,7 +274,7 @@ def is_available(self):
         return self == ClientState.AVAILABLE
 
 
-class SimpleClientState(IntEnum):
+class SimpleClientState(Enum):
     DISCONNECTED = 'disconnected'
     CONNECTED = 'connected'
     RESUME_IN_PREGRESS = 'resume-in-progress'
diff --git a/gajim/common/modules/contacts.py b/gajim/common/modules/contacts.py
index d996e9a05d8011d73fcd8cb89eb85623d0fb6af3..8349d453544f34c1940ced5ea8d3137875f3a4b1 100644
--- a/gajim/common/modules/contacts.py
+++ b/gajim/common/modules/contacts.py
@@ -90,6 +90,12 @@ def get_contacts_with_domain(self, domain):
                 contacts.append(contact)
         return contacts
 
+    def reset_presence(self):
+        for contact in self._contacts.values():
+            if contact.is_groupchat or contact.is_pm_contact:
+                continue
+            contact.update_presence(UNKNOWN_PRESENCE)
+
 
 class CommonContact(Observable):
     def __init__(self, logger, jid, account):
diff --git a/gajim/common/modules/muc.py b/gajim/common/modules/muc.py
index 99b5e0c52913a881afc92ae7c72dedf0a4324bb7..2b427a6f0e2caff0cfd317c3550ca7d7872a0509 100644
--- a/gajim/common/modules/muc.py
+++ b/gajim/common/modules/muc.py
@@ -107,10 +107,8 @@ def __init__(self, con):
                           priority=49)
         ]
 
-        self.register_events([
-            ('account-disconnected', ged.CORE, self._on_account_disconnected),
-            # ('signed-in', ged.GUI1, self._on_signed_in),
-        ])
+        self._con.connect_signal('state-changed',
+                                 self._on_client_state_changed)
 
         self._rejoin_muc = set()
         self._join_timeouts = {}
@@ -461,7 +459,7 @@ def _on_muc_user_presence(self, _con, stanza, properties):
             self._remove_join_timeout(room_jid)
             self._set_muc_state(room_jid, MUCJoinedState.NOT_JOINED)
             room.set_not_joined()
-            room.notify('destroyed', properties)
+            room.notify('room-destroyed', properties)
             return
 
         if properties.is_nickname_changed:
@@ -517,7 +515,7 @@ def _on_muc_user_presence(self, _con, stanza, properties):
         if properties.is_muc_self_presence and properties.is_kicked:
             self._set_muc_state(room_jid, MUCJoinedState.NOT_JOINED)
             room.set_not_joined()
-            room.notify('kicked', properties)
+            room.notify('room-kicked', properties)
             status_codes = properties.muc_status_codes or []
             if StatusCode.REMOVED_SERVICE_SHUTDOWN in status_codes:
                 self._start_rejoin_timeout(room_jid)
@@ -808,13 +806,15 @@ def invite(self, room, jid, reason=None, continue_=False):
         return self._nbxmpp('MUC').invite(room, jid, reason, password,
                                           continue_, type_)
 
-    @event_filter(['account'])
-    def _on_account_disconnected(self, _event):
-        for room_jid in list(self._rejoin_timeouts.keys()):
-            self._remove_rejoin_timeout(room_jid)
+    def _on_client_state_changed(self, _client, _signal_name, state):
+        if state.is_disconnected:
+            for room_jid in list(self._rejoin_timeouts.keys()):
+                self._remove_rejoin_timeout(room_jid)
 
-        for room_jid in list(self._join_timeouts.keys()):
-            self._remove_join_timeout(room_jid)
+            for room_jid in list(self._join_timeouts.keys()):
+                self._remove_join_timeout(room_jid)
+
+            self.reset_state()
 
 
 def get_instance(*args, **kwargs):
diff --git a/gajim/groupchat_control.py b/gajim/groupchat_control.py
index 34ea24319640bd0955bb5ca8a9a4fc01fc74a9c1..91a557f2c21723ab78981c932cd9431b60adc303 100644
--- a/gajim/groupchat_control.py
+++ b/gajim/groupchat_control.py
@@ -49,6 +49,7 @@
 from gajim.common.helpers import event_filter
 from gajim.common.helpers import to_user_string
 from gajim.common.const import AvatarSize
+from gajim.common.const import SimpleClientState
 
 from gajim.common.i18n import _
 from gajim.common.const import MUCJoinedState
@@ -93,6 +94,9 @@ def __init__(self, parent_win, jid, muc_data, acct):
                                  jid,
                                  acct)
 
+        self._client.connect_signal('state-changed',
+                                    self._on_client_state_changed)
+
         self.force_non_minimizable = False
         self.is_anonymous = True
 
@@ -203,9 +207,7 @@ def __init__(self, parent_win, jid, muc_data, acct):
             ('bookmarks-received', ged.GUI1, self._on_bookmarks_received),
         ])
 
-        self.is_connected = False
-        # disable win, we are not connected yet
-        ChatControlBase.got_disconnected(self)
+        self._set_control_inactive()
 
         # Stack
         self.xml.stack.show_all()
@@ -251,31 +253,13 @@ def _connect_contact_signals(self):
     def _on_muc_state_changed(self, _contact, _signal_name):
         state = self.contact.state
         if state == MUCJoinedState.JOINED:
-            self.roster.initial_draw()
-
-            self.is_connected = True
-            ChatControlBase.got_connected(self)
-
-            self.xml.formattings_button.set_sensitive(True)
-
-            self.conversation_view.update_avatars()
-
-            self.update_actions()
+            self._set_control_active()
 
         elif state == MUCJoinedState.NOT_JOINED:
+            self._set_control_inactive()
 
-            self.xml.formattings_button.set_sensitive(False)
-
-            self.roster.enable_sort(False)
-            self.roster.clear()
-
-            self.is_connected = False
-            ChatControlBase.got_disconnected(self)
-
-            self._client.get_module('Chatstate').remove_delay_timeout(
-                self.contact)
-
-            self.update_actions()
+    def _on_client_state_changed(self, _client, _signal_name, state):
+        pass
 
     @property
     def _muc_data(self):
@@ -978,12 +962,6 @@ def _on_room_config_changed(self, _contact, _signal_name, properties):
         for change in changes:
             self.add_info_message(change)
 
-    def _on_our_show(self, event):
-        client = app.get_client(event.account)
-        if (event.show == 'offline' and
-                not client.state.is_reconnect_scheduled):
-            self.got_disconnected()
-
     @event_filter(['account'])
     def _nec_ping(self, event):
         if not event.contact.is_groupchat:
@@ -1010,14 +988,30 @@ def is_connected(self) -> bool:
     def is_connected(self, value: bool) -> None:
         app.gc_connected[self.account][self.room_jid] = value
 
-    def got_disconnected(self):
+    def _set_control_active(self):
+        self.xml.formattings_button.set_sensitive(True)
+        self.msg_textview.set_sensitive(True)
+        self.msg_textview.set_editable(True)
+
+        self.roster.initial_draw()
+
+        self.is_connected = True
+
+        self.xml.formattings_button.set_sensitive(True)
+
+        self.conversation_view.update_avatars()
+
+        self.update_actions()
+
+    def _set_control_inactive(self):
         self.xml.formattings_button.set_sensitive(False)
+        self.msg_textview.set_sensitive(False)
+        self.msg_textview.set_editable(False)
 
         self.roster.enable_sort(False)
         self.roster.clear()
 
         self.is_connected = False
-        ChatControlBase.got_disconnected(self)
 
         self._client.get_module('Chatstate').remove_delay_timeout(self.contact)
 
@@ -1062,7 +1056,6 @@ def _on_user_joined(self, _contact, _signal_name, user_contact, properties):
         self.update_actions()
 
     def _on_room_config_finished(self, _contact, _signal_name):
-        self.got_connected()
         self._show_page('groupchat')
         self.add_info_message(_('A new group chat has been created'))
 
@@ -1228,11 +1221,6 @@ def _on_room_kicked(self, _contact, _signal_name, properties):
             message = message.format(actor=actor, reason=reason)
             self.add_info_message(message)
 
-        self.got_disconnected()
-
-        # Update Actions
-        self.update_actions()
-
     def _on_user_left(self, _contact, _signal_name, user_contact, properties):
         status_codes = properties.muc_status_codes or []
         nick = user_contact.name
@@ -1289,7 +1277,6 @@ def _on_user_left(self, _contact, _signal_name, user_contact, properties):
             self.add_info_message(message)
 
     def _on_room_joined(self, _contact, _signal_name):
-        self.got_connected()
         self._show_page('groupchat')
 
     def _on_room_password_required(self, _contact, _signal_name, _properties):
@@ -1327,8 +1314,6 @@ def _on_room_destroyed(self, _contact, _signal_name, properties):
                              'instead: xmpp:%s?join') % str(alternate)
             self.add_info_message(join_message)
 
-        self.got_disconnected()
-
         self._client.get_module('Bookmarks').remove(self.room_jid)
 
         if self._wait_for_destruction: