diff --git a/gajim/gtk/chat_stack.py b/gajim/gtk/chat_stack.py
index 3214c8043972236f4aee9ebdd25f0854b29c31c4..6730277f3061ed57ca39cbea7e8784d050e6fc56 100644
--- a/gajim/gtk/chat_stack.py
+++ b/gajim/gtk/chat_stack.py
@@ -16,9 +16,9 @@
 
 from gi.repository import Gtk
 
-from gajim.chat_control import ChatControl
-from gajim.groupchat_control import GroupchatControl
-from gajim.privatechat_control import PrivateChatControl
+from gajim.gui.controls.chat import ChatControl
+from gajim.gui.controls.groupchat import GroupchatControl
+from gajim.gui.controls.private import PrivateChatControl
 
 
 log = logging.getLogger('gajim.gui.chatstack')
diff --git a/gajim/gtk/controls/__init__.py b/gajim/gtk/controls/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/gajim/chat_control_base.py b/gajim/gtk/controls/base.py
similarity index 99%
rename from gajim/chat_control_base.py
rename to gajim/gtk/controls/base.py
index 724e34ac4106f129752703e74c170a15d867e812..520ecfabd06710065dc42ccff1e67fd55acf36bc 100644
--- a/gajim/chat_control_base.py
+++ b/gajim/gtk/controls/base.py
@@ -91,7 +91,7 @@
 
 
 ################################################################################
-class ChatControlBase(ChatCommandProcessor, CommandTools, EventHelper):
+class BaseControl(ChatCommandProcessor, CommandTools, EventHelper):
     """
     A base class containing a banner, ConversationView, MessageInputTextView
     """
@@ -246,7 +246,7 @@ def __init__(self, widget_name, account, jid):
         self.encryption = self.get_encryption_state()
         self.conversation_view.encryption_enabled = self.encryption is not None
 
-        # PluginSystem: adding GUI extension point for ChatControlBase
+        # PluginSystem: adding GUI extension point for BaseControl
         # instance object (also subclasses, eg. ChatControl or GroupchatControl)
         app.plugin_manager.gui_extension_point('chat_control_base', self)
 
diff --git a/gajim/chat_control.py b/gajim/gtk/controls/chat.py
similarity index 99%
rename from gajim/chat_control.py
rename to gajim/gtk/controls/chat.py
index 9847cba1ec185741fcf830f4dad3877686f7e6f5..7f6eda37653918a87b657f834c36a0757e1b6198 100644
--- a/gajim/chat_control.py
+++ b/gajim/gtk/controls/chat.py
@@ -70,9 +70,9 @@
 
 from gajim.command_system.implementation.hosts import ChatCommands
 from gajim.command_system.framework import CommandHost  # pylint: disable=unused-import
-from gajim.chat_control_base import ChatControlBase
+from gajim.gui.controls.base import BaseControl
 
-log = logging.getLogger('gajim.chat_control')
+log = logging.getLogger('gajim.gui.controls.chat')
 
 
 class JingleObject:
@@ -86,7 +86,7 @@ def __init__(self, state, update):
 
 
 ################################################################################
-class ChatControl(ChatControlBase):
+class ChatControl(BaseControl):
     """
     A control for standard 1-1 chat
     """
@@ -98,7 +98,7 @@ class ChatControl(ChatControlBase):
     COMMAND_HOST = ChatCommands  # type: ClassVar[Type[CommandHost]]
 
     def __init__(self, account, jid):
-        ChatControlBase.__init__(self,
+        BaseControl.__init__(self,
                                  'chat_control',
                                  account,
                                  jid)
@@ -852,7 +852,7 @@ def on_location_eventbox_enter_notify_event(self, _widget, _event):
 
     def update_ui(self):
         # The name banner is drawn here
-        ChatControlBase.update_ui(self)
+        BaseControl.update_ui(self)
         self.update_toolbar()
         self._update_avatar()
         self.update_actions()
@@ -916,7 +916,7 @@ def send_message(self,
         if message in ('', None, '\n'):
             return
 
-        ChatControlBase.send_message(self,
+        BaseControl.send_message(self,
                                      message,
                                      type_='chat',
                                      xhtml=xhtml,
@@ -945,7 +945,7 @@ def add_message(self,
         else:
             name = self.get_our_nick()
 
-        ChatControlBase.add_message(self,
+        BaseControl.add_message(self,
                                     text,
                                     kind,
                                     name,
diff --git a/gajim/groupchat_control.py b/gajim/gtk/controls/groupchat.py
similarity index 99%
rename from gajim/groupchat_control.py
rename to gajim/gtk/controls/groupchat.py
index b09476d53ed44d71196d819a206fc55ad2d66d7c..a66c70caa1d2707c6ab869ba0105622955cda863 100644
--- a/gajim/groupchat_control.py
+++ b/gajim/gtk/controls/groupchat.py
@@ -54,7 +54,7 @@
 from gajim.common.const import MUCJoinedState
 from gajim.common.structs import OutgoingMessage
 
-from gajim.chat_control_base import ChatControlBase
+from gajim.gui.controls.base import BaseControl
 
 from gajim.command_system.implementation.hosts import GroupChatCommands
 
@@ -76,10 +76,10 @@
 from gajim.gui.util import open_window
 from gajim.gui.const import ControlType
 
-log = logging.getLogger('gajim.groupchat_control')
+log = logging.getLogger('gajim.gui.controls.groupchat')
 
 
-class GroupchatControl(ChatControlBase):
+class GroupchatControl(BaseControl):
 
     _type = ControlType.GROUPCHAT
 
@@ -88,7 +88,7 @@ class GroupchatControl(ChatControlBase):
     COMMAND_HOST = GroupChatCommands
 
     def __init__(self, account, jid):
-        ChatControlBase.__init__(self,
+        BaseControl.__init__(self,
                                  'groupchat_control',
                                  account,
                                  jid)
@@ -782,7 +782,7 @@ def add_message(self,
 
             # self.check_focus_out_line()
 
-        ChatControlBase.add_message(self,
+        BaseControl.add_message(self,
                                     text,
                                     kind,
                                     contact,
@@ -1397,7 +1397,7 @@ def _close_control(self, reason=None):
 
     def set_control_active(self, state):
         self.attention_flag = False
-        ChatControlBase.set_control_active(self, state)
+        BaseControl.set_control_active(self, state)
 
     def _on_drag_data_received(self, widget, context, x, y, selection,
                                target_type, timestamp):
@@ -1426,7 +1426,7 @@ def _jid_not_blocked(self, bare_jid: str) -> bool:
         return not helpers.jid_is_blocked(self.account, fjid)
 
     def _on_message_textview_key_press_event(self, widget, event):
-        res = ChatControlBase._on_message_textview_key_press_event(
+        res = BaseControl._on_message_textview_key_press_event(
             self, widget, event)
         if res:
             return True
diff --git a/gajim/privatechat_control.py b/gajim/gtk/controls/private.py
similarity index 99%
rename from gajim/privatechat_control.py
rename to gajim/gtk/controls/private.py
index 6193c8b308da006ade9fdcf94e1a2b59240eedfa..a555e04806d4d95345f2927d064821d2605212d7 100644
--- a/gajim/privatechat_control.py
+++ b/gajim/gtk/controls/private.py
@@ -27,7 +27,7 @@
 from gajim.common import helpers
 from gajim.common.i18n import _
 
-from gajim.chat_control import ChatControl
+from gajim.gui.controls.chat import ChatControl
 from gajim.command_system.implementation.hosts import PrivateChatCommands
 
 from gajim.gui.dialogs import ErrorDialog
diff --git a/gajim/gtk/htmltextview.py b/gajim/gtk/htmltextview.py
index 65cfe2d4f2fb3e29551bed6ca285756650895b27..7dce5da0d1af48838ec75c9df47874f3f0a08f24 100644
--- a/gajim/gtk/htmltextview.py
+++ b/gajim/gtk/htmltextview.py
@@ -727,7 +727,7 @@ def __init__(self, account, standalone=False):
 
     def _on_destroy(self, *args):
         # We restore the TextView’s drag destination to avoid a GTK warning
-        # when closing the control. ChatControlBase.shutdown() calls destroy()
+        # when closing the control. BaseControl.shutdown() calls destroy()
         # on the control’s main box, causing GTK to recursively destroy the
         # child widgets. GTK then tries to set a target list on the TextView,
         # resulting in a warning because the Widget has no drag destination.
diff --git a/gajim/gtk/message_input.py b/gajim/gtk/message_input.py
index a1f2a25957a10871437035d50d8b357b80e9f10c..4988addd59e41a287c2ac4d553cc139034b1b8d5 100644
--- a/gajim/gtk/message_input.py
+++ b/gajim/gtk/message_input.py
@@ -98,7 +98,7 @@ def __init__(self):
 
     def _on_destroy(self, *args):
         # We restore the TextView’s drag destination to avoid a GTK warning
-        # when closing the control. ChatControlBase.shutdown() calls destroy()
+        # when closing the control. BaseControl.shutdown() calls destroy()
         # on the control’s main box, causing GTK to recursively destroy the
         # child widgets. GTK then tries to set a target list on the TextView,
         # resulting in a warning because the Widget has no drag destination.
diff --git a/gajim/gtk/preferences.py b/gajim/gtk/preferences.py
index b81a82b59ca1a8aa3af6c96553f04d1a6f79fe91..c5f240bcc02198ee7da47a323f074225c1221055 100644
--- a/gajim/gtk/preferences.py
+++ b/gajim/gtk/preferences.py
@@ -29,7 +29,7 @@
 from gajim.common.multimedia_helpers import AudioOutputManager
 from gajim.common.multimedia_helpers import VideoInputManager
 
-from gajim.chat_control_base import ChatControlBase
+from gajim.gui.controls.base import BaseControl
 
 from .const import Setting
 from .const import SettingKind
@@ -395,7 +395,7 @@ def _on_use_speller(value, *args):
             gspell_lang = Gspell.language_get_default()
         app.settings.set('speller_language', gspell_lang.get_code())
         for ctrl in get_app_window('Preferences').get_all_controls():
-            if isinstance(ctrl, ChatControlBase):
+            if isinstance(ctrl, BaseControl):
                 ctrl.set_speller()
 
 
diff --git a/gajim/gui_interface.py b/gajim/gui_interface.py
index b7b08db309f19d6fd8d2cffc60f50a4793023ae6..3eeda6f9dccb7ec5c2f4217b0bf5c2379f951ba2 100644
--- a/gajim/gui_interface.py
+++ b/gajim/gui_interface.py
@@ -58,8 +58,8 @@
 from gajim import gui_menu_builder
 from gajim.dialog_messages import get_dialog
 
-from gajim.chat_control_base import ChatControlBase
-from gajim.groupchat_control import GroupchatControl
+from gajim.gui.controls.base import BaseControl
+from gajim.gui.controls.groupchat import GroupchatControl
 
 from gajim.common import idle
 from gajim.common.zeroconf import connection_zeroconf
@@ -1255,7 +1255,7 @@ def handle_event(self, account, fjid, type_):
             w.set_active_tab(ctrl)
             w.window.present()
             # Using isinstance here because we want to catch all derived types
-            if isinstance(ctrl, ChatControlBase):
+            if isinstance(ctrl, BaseControl):
                 ctrl.scroll_to_end()
 
     def show_groupchat(self, account, room_jid):