diff --git a/g13gui/g13gui/app.py b/g13gui/g13gui/app.py
new file mode 100644
index 0000000..46227f9
--- /dev/null
+++ b/g13gui/g13gui/app.py
@@ -0,0 +1,60 @@
+import signal
+
+from g13gui.model.prefsstore import PreferencesStore
+from g13gui.g13.manager import DeviceManager
+from g13gui.ui.appindicator import AppIndicator
+from g13gui.ui.mainwindow import MainWindow
+
+import gi
+gi.require_version('Gtk', '3.0')
+gi.require_version('Gdk', '3.0')
+gi.require_version('GLib', '2.0')
+gi.require_version('GnomeDesktop', '3.0')
+
+from gi.repository import Gtk, GLib, Gio
+
+
+class Application(Gtk.Application):
+    def __init__(self):
+        Gtk.Application.__init__(
+            self,
+            application_id='com.theonelab.g13.G13Configurator')
+
+        GLib.set_application_name('G13 Configurator')
+
+        self._prefs = None
+        self._indicator = None
+        self._dm = None
+        self._mainwindow = None
+
+    def do_startup(self):
+        Gtk.Application.do_startup(self)
+        signal.signal(signal.SIGINT, signal.SIG_DFL)
+
+        action = Gio.SimpleAction.new('quit')
+        action.connect('activate', lambda *x: self.quit())
+        self.add_action(action)
+        self.add_accelerator('<Primary>q', 'app.quit')
+
+    def do_activate(self):
+        if not self._prefs:
+            self._prefs = PreferencesStore.getPrefs()
+        if not self._indicator:
+            self._indicator = AppIndicator(self, self._prefs)
+        if not self._dm:
+            self._dm = DeviceManager(self._prefs)
+            self._dm.start()
+        if not self._mainwindow:
+            self._mainwindow = MainWindow(self, self._prefs)
+        if self._prefs.showWindowOnStart:
+            self.showMainWindow()
+
+    def showMainWindow(self):
+        self._mainwindow.present()
+
+    def do_shutdown(self):
+        if self._mainwindow:
+            self._mainwindow.destroy()
+        if self._dm:
+            self._dm.shutdown()
+        Gtk.Application.do_shutdown(self)
diff --git a/g13gui/g13gui/main.py b/g13gui/g13gui/main.py
index de0ac7b..8e94181 100644
--- a/g13gui/g13gui/main.py
+++ b/g13gui/g13gui/main.py
@@ -1,22 +1,14 @@
 #!/usr/bin/python
 
-import gi
+import sys
 
-import g13gui.ui as ui
-from g13gui.model.prefsstore import PreferencesStore
-from g13gui.g13.manager import Manager
+from dbus.mainloop.glib import DBusGMainLoop
 
-gi.require_version('Gtk', '3.0')
-from gi.repository import Gtk, Gdk, GObject
+from g13gui.app import Application
 
 
 if __name__ == '__main__':
-    Gdk.threads_init()
+    DBusGMainLoop(set_as_default=True)
 
-    prefs = PreferencesStore.getPrefs()
-    manager = Manager(prefs)
-    manager.start()
-
-    indicator = ui.AppIndicator(prefs)
-
-    Gtk.main()
+    app = Application()
+    app.run(sys.argv)
diff --git a/g13gui/g13gui/ui/appindicator.py b/g13gui/g13gui/ui/appindicator.py
index e0dd10e..7839cc4 100644
--- a/g13gui/g13gui/ui/appindicator.py
+++ b/g13gui/g13gui/ui/appindicator.py
@@ -12,25 +12,24 @@ from gi.repository import AppIndicator3 as indicator
 
 
 class AppIndicator(GtkObserver):
-    def __init__(self, prefs):
+    def __init__(self, app, prefs):
         GtkObserver.__init__(self)
 
+        self._app = app
+        self._prefs = prefs
+
         self._initIndicator()
 
-        self._prefs = prefs
-        self._mainWindow = None
         self._menu = Gtk.Menu()
         self._menuItems = []
         self._indicator.set_menu(self._menu)
+
         self._rebuilding = False
 
         self._prefs.registerObserver(self, {'selectedProfile'})
         self.changeTrigger(self.onSelectedProfileChanged,
                            keys={'selectedProfile'})
 
-        if self._prefs.showWindowOnStart:
-            self.showMainWindow(None)
-
         self._rebuildMenu()
 
     def _initIndicator(self):
@@ -75,20 +74,17 @@ class AppIndicator(GtkObserver):
         self._attachMenuItem(sep)
 
         quitItem = Gtk.MenuItem('Quit')
+        quitItem.connect('activate', self.onQuit)
         self._attachMenuItem(quitItem)
-        quitItem.connect('activate', Gtk.main_quit)
 
         self._menu.show_all()
         self._rebuilding = False
 
-    def onMainWindowHidden(self, win):
-        del self._mainWindow
-        self._mainWindow = None
-
     def showMainWindow(self, menuItem):
-        self._mainWindow = MainWindow(self._prefs)
-        self._mainWindow.connect('hide', self.onMainWindowHidden)
-        self._mainWindow.show_all()
+        self._app.showMainWindow()
+
+    def onQuit(self, menuItem):
+        self._app.do_shutdown()
 
     def changeProfile(self, menuItem):
         self._prefs.setSelectedProfile(menuItem.get_label())
diff --git a/g13gui/g13gui/ui/mainwindow.py b/g13gui/g13gui/ui/mainwindow.py
index c18998e..b304b05 100644
--- a/g13gui/g13gui/ui/mainwindow.py
+++ b/g13gui/g13gui/ui/mainwindow.py
@@ -1,29 +1,32 @@
-#!/usr/bin/python
-
-import gi
 import threading
 
-import g13gui.ui as ui
-
+from g13gui.ui.profilecombobox import ProfileComboBox
+from g13gui.ui.profilepopover import ProfilePopover
+from g13gui.ui.profilepopover import ProfilePopoverMode
+from g13gui.ui.g13button import G13Button
 from g13gui.observer.gtkobserver import GtkObserver
 from g13gui.model.prefsstore import PreferencesStore
 
+import gi
 gi.require_version('Gtk', '3.0')
 gi.require_version('Gdk', '3.0')
 from gi.repository import Gtk, Gdk, GObject
 
 
-class MainWindow(Gtk.Window, GtkObserver):
-    def __init__(self, prefs):
-        Gtk.Window.__init__(self)
+class MainWindow(Gtk.ApplicationWindow, GtkObserver):
+    def __init__(self, app, prefs, **kwargs):
+        Gtk.ApplicationWindow.__init__(
+            self,
+            default_width=640,
+            default_height=480,
+            window_position=Gtk.WindowPosition.NONE,
+            name='g13configurator',
+            icon_name='g13configurator',
+            application=app,
+            **kwargs)
         GtkObserver.__init__(self)
 
-        self.set_default_size(640, 480)
-        geometry = Gdk.Geometry()
-        geometry.max_width = 640
-        geometry.max_height = 480
-        self.set_geometry_hints(None, geometry, Gdk.WindowHints.MAX_SIZE)
-
+        self._app = app
         self._prefs = prefs
         self._prefs.registerObserver(self, 'selectedProfile')
         self._prefs.selectedProfile().registerObserver(self)
@@ -46,6 +49,8 @@ class MainWindow(Gtk.Window, GtkObserver):
 
         self.setupG13ButtonGrid()
 
+        self.show_all()
+
     def _updateProfileRegistration(self):
         self._lastProfileName.removeObserver(self)
         self._lastProfileName = self._prefs.selectedProfile()
@@ -66,22 +71,22 @@ class MainWindow(Gtk.Window, GtkObserver):
         self._headerBar.set_title("G13 Configurator")
         self._headerBar.set_show_close_button(True)
 
-        self._profileComboBox = ui.ProfileComboBox(self._prefs)
+        self._profileComboBox = ProfileComboBox(self._prefs)
         self._headerBar.add(self._profileComboBox)
 
         addProfileButton = Gtk.MenuButton.new()
         addProfileButton.add(Gtk.Image.new_from_icon_name(
             "document-new-symbolic", 1))
-        addProfilePopover = ui.ProfilePopover(self._prefs,
-                                              mode=ui.ProfilePopoverMode.ADD)
+        addProfilePopover = ProfilePopover(self._prefs,
+                                           mode=ProfilePopoverMode.ADD)
         addProfileButton.set_popover(addProfilePopover)
         self._headerBar.add(addProfileButton)
 
         editProfileButton = Gtk.MenuButton.new()
         editProfileButton.add(
             Gtk.Image.new_from_icon_name('document-edit-symbolic', 1))
-        editProfilePopover = ui.ProfilePopover(self._prefs,
-                                               mode=ui.ProfilePopoverMode.EDIT)
+        editProfilePopover = ProfilePopover(self._prefs,
+                                            mode=ProfilePopoverMode.EDIT)
         editProfileButton.set_popover(editProfilePopover)
         self._headerBar.add(editProfileButton)
 
@@ -146,6 +151,6 @@ class MainWindow(Gtk.Window, GtkObserver):
         return button
 
     def newG13Button(self, name):
-        button = ui.G13Button(self._prefs, name)
+        button = G13Button(self._prefs, name)
         self._g13Buttons[name] = button
         return button