[polari/wip/fmuellner/bg-app: 2/3] app: Add option to run in background



commit 00ab02ca5244483d205d69774c7adbb4f620ae49
Author: Florian Müllner <fmuellner gnome org>
Date:   Fri Jun 24 13:15:03 2016 +0200

    app: Add option to run in background
    
    Like other messaging applications, IRC clients don't require constant
    attention from the user, but can sit in the background and notify the
    user when an important message was received. We currently don't have
    any explicit support for this mode, so users need to ignore the window
    the best they can (by moving it to another workspace or keeping it at
    the bottom of the window stack). This is obviously not great, but neither
    are status icons that have traditionally been used by applications to
    offer this mode.
    
    Instead, implement a pattern for background applications that was agreed
    upon with the GNOME design team:
    
    When set up to run in the background, the application:
     - sets itself up to start in the background on login
     - keeps running after the last window has been closed
     - can be stopped via the 'quit' action in the application menu
    
    https://bugzilla.gnome.org/show_bug.cgi?id=770750

 data/Makefile.am                        |    4 ++
 data/org.gnome.Polari.Autostart.desktop |    4 ++
 data/org.gnome.Polari.gschema.xml       |    5 +++
 data/resources/menus.ui                 |    6 ++++
 src/application.js                      |   48 +++++++++++++++++++++++++++++-
 5 files changed, 65 insertions(+), 2 deletions(-)
---
diff --git a/data/Makefile.am b/data/Makefile.am
index 3f9866c..4756d21 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -4,6 +4,9 @@ desktopdir = $(datadir)/applications
 desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
 desktop_in_files = $(APP_ID).desktop.in
 
+autostartdir = $(pkgdatadir)
+autostart_DATA = $(APP_ID).Autostart.desktop
+
 %.desktop: %.desktop.in Makefile
        $(AM_V_GEN) $(MSGFMT) --desktop --template $< -d $(top_srcdir)/po -o $@
 
@@ -25,6 +28,7 @@ clientdir=$(datadir)/telepathy/clients
 dist_client_DATA = Polari.client
 
 EXTRA_DIST = \
+       $(autostart_DATA) \
        $(desktop_in_files) \
        $(service_in_files) \
        $(APP_ID).data.gresource.xml \
diff --git a/data/org.gnome.Polari.Autostart.desktop b/data/org.gnome.Polari.Autostart.desktop
new file mode 100644
index 0000000..d0cc77d
--- /dev/null
+++ b/data/org.gnome.Polari.Autostart.desktop
@@ -0,0 +1,4 @@
+[Desktop Entry]
+Type=Application
+Exec=gapplication action org.gnome.Polari start-client
+NoDisplay=True
diff --git a/data/org.gnome.Polari.gschema.xml b/data/org.gnome.Polari.gschema.xml
index 839983c..d6a16b9 100644
--- a/data/org.gnome.Polari.gschema.xml
+++ b/data/org.gnome.Polari.gschema.xml
@@ -6,6 +6,11 @@
       <summary>Saved channel list</summary>
       <description>List of channels to restore on startup</description>
     </key>
+    <key type="b" name="run-in-background">
+      <default>false</default>
+      <summary>Run in Background</summary>
+      <description>Keep running in background when closed.</description>
+    </key>
     <key type="ai" name="window-size">
       <default>[800,500]</default>
       <summary>Window size</summary>
diff --git a/data/resources/menus.ui b/data/resources/menus.ui
index 22f20e5..eff8d78 100644
--- a/data/resources/menus.ui
+++ b/data/resources/menus.ui
@@ -2,6 +2,12 @@
   <menu id="app-menu">
     <section>
       <item>
+        <attribute name="action">app.run-in-background</attribute>
+        <attribute name="label" translatable="yes">Run in Background</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
         <attribute name="action">win.show-help-overlay</attribute>
         <attribute name="label" translatable="yes">Keyboard Shortcuts</attribute>
       </item>
diff --git a/src/application.js b/src/application.js
index 6e2f40d..7818776 100644
--- a/src/application.js
+++ b/src/application.js
@@ -21,6 +21,9 @@ const MAX_RETRIES = 3;
 
 const IRC_SCHEMA_REGEX = /^(irc?:\/\/)([\da-z\.-]+):?(\d+)?\/(?:%23)?([\w\.\+-]+)/i;
 
+const AUTOSTART_DIR = GLib.get_user_config_dir() + '/autostart';
+const AUTOSTART_FILE = '/org.gnome.Polari.Autostart.desktop';
+
 const Application = new Lang.Class({
     Name: 'Application',
     Extends: Gtk.Application,
@@ -149,6 +152,14 @@ const Application = new Lang.Class({
                 this.add_action(action);
         }));
 
+        this._settings = new Gio.Settings({ schema_id: 'org.gnome.Polari' });
+        let action = this._settings.create_action('run-in-background');
+        this.add_action(action);
+
+        this._settings.connect('changed::run-in-background',
+                               Lang.bind(this, this._onRunInBackgroundChanged));
+        this._onRunInBackgroundChanged();
+
         for (let i = 1; i < 10; i++)
             this.set_accels_for_action('app.nth-room(%d)'.format(i), ['<Alt>' + i]);
 
@@ -184,8 +195,11 @@ const Application = new Lang.Class({
 
         if (!this.active_window) {
             let window = new MainWindow.MainWindow({ application: this });
-            window.connect('destroy',
-                           () => { this.emit('prepare-shutdown'); });
+            window.connect('destroy', () => {
+                if (this._settings.get_boolean('run-in-background'))
+                    return;
+                this.emit('prepare-shutdown');
+            });
             window.connect('notify::active-room',
                            () => { this.emit('room-focus-changed'); });
             window.connect('notify::is-active',
@@ -500,6 +514,35 @@ const Application = new Lang.Class({
         dialog.show();
     },
 
+    _createLink: function(file, target) {
+        try {
+            file.get_parent().make_directory_with_parents(null);
+        } catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.EXISTS)) {
+            // not an error, carry on
+        }
+
+        file.make_symbolic_link(target, null);
+    },
+
+    _onRunInBackgroundChanged: function() {
+        let file = Gio.File.new_for_path(AUTOSTART_DIR + AUTOSTART_FILE);
+
+        if (this._settings.get_boolean('run-in-background'))
+            try {
+                this._createLink(file, pkg.pkgdatadir + AUTOSTART_FILE);
+            } catch(e) {
+                if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.EXISTS))
+                    log('Failed to create autostart link: ' + e.message);
+            }
+        else
+            try {
+                file.delete(null);
+            } catch(e) {
+                if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
+                    log('Failed to remove autostart link: ' + e.message);
+            }
+    },
+
     _onStartClient: function() {
         if (this._telepathyClient)
             return;
@@ -564,5 +607,6 @@ const Application = new Lang.Class({
 
     _onQuit: function() {
         this.get_windows().reverse().forEach(w => { w.destroy(); });
+        this.emit('prepare-shutdown');
     }
 });


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]