[gnome-boxes/wip/run-in-bg: 7/13] app: Keep GApplication alive when running in background




commit 181d3035f4ddfe252b2030aa28f3c9e9464de19e
Author: Felipe Borges <felipeborges gnome org>
Date:   Fri Dec 4 12:54:52 2020 +0100

    app: Keep GApplication alive when running in background
    
    A long standing UX issue we have in Boxes are the "run in background"
    virtual machines. In a typical bare metal session, Boxes wouldn't
    suspend these VMs and instead keep them running thanks to libvirtd.
    But for the Flatpaked apps, the lifetime of the libvirt daemon is
    tied to the lifetime of Boxes itself, therefore we need to manage
    it.
    
    This solution identifies whether the "run in bg" VMs are running, and
    if so, it will just hide the Boxes window and keep the GApplication
    running in the background. This allows for jumping back to Boxes
    if the user wants.
    
    We also throw a notification indicating that a virtual machine is
    running in the background, so the user has an UI to access the VM.
    
    Fixes #379

 src/app.vala             | 65 +++++++++++++++++++++++++++++++++++++++++++++---
 src/libvirt-machine.vala |  1 +
 2 files changed, 62 insertions(+), 4 deletions(-)
---
diff --git a/src/app.vala b/src/app.vala
index 557f2942..4e69ee79 100644
--- a/src/app.vala
+++ b/src/app.vala
@@ -37,6 +37,10 @@ public virtual async void add_source (CollectionSource source) throws GLib.Error
     private bool is_ready;
     public signal void ready ();
 
+    public bool run_in_bg {
+        get; private set;
+    }
+
     // A callback to notify that deletion of machines was undone by user.
     public delegate void UndoNotifyCallback ();
 
@@ -92,6 +96,10 @@ public App () {
         action.activate.connect ((param) => { open_name (param.get_string ()); });
         add_action (action);
 
+        action = new GLib.SimpleAction ("launch-run-in-bg-box", GLib.VariantType.STRING);
+        action.activate.connect ((param) => { open_run_in_bg_vm (param.get_string ()); });
+        add_action (action);
+
         action = new GLib.SimpleAction ("install", GLib.VariantType.STRING);
         action.activate.connect ((param) => { install (param.get_string ()); });
         add_action (action);
@@ -280,6 +288,10 @@ public bool quit_app () {
         var display = Gdk.Display.get_default ();
         display.flush ();
 
+        keep_on_running_on_background ();
+        if (run_in_bg)
+            return true;
+
         Idle.add (() => {
             quit ();
 
@@ -290,17 +302,32 @@ public bool quit_app () {
     }
 
     public override void shutdown () {
-        base.shutdown ();
+        if (!run_in_bg) {
+            base.shutdown ();
+
+            // Withdraw all the existing notifications
+            foreach (var notification in system_notifications)
+                withdraw_notification (notification);
+        } else {
+            this.hold ();
+        }
 
         foreach (var window in windows) {
             window.notificationbar.dismiss_all ();
         }
         async_launcher.await_all ();
         suspend_machines ();
+    }
+
+    private void open_run_in_bg_vm (string name) {
+        activate ();
+
+        var app = this;
+        main_window.present ();
+        call_when_ready (() => {
+            open_name (name);
+        });
 
-        // Withdraw all the existing notifications
-        foreach (var notification in system_notifications)
-            withdraw_notification (notification);
     }
 
     public void open_name (string name) {
@@ -500,6 +527,36 @@ yield foreach_filename_from_dir (dir, (filename) => {
         }
     }
 
+    private void keep_vm_running_in_background (LibvirtMachine machine) {
+        if (!machine.run_in_bg && !machine.is_running)
+            return;
+
+        var msg = _("ā€œ%sā€œ is running in the background").printf (machine.name);
+        var notification = new GLib.Notification (msg);
+        notification.set_default_action ("app.launch-run-in-bg-box::" + machine.name);
+
+        send_notification ("gnome-boxes-run-in-bg-%s" + machine.name, notification);
+    }
+
+    private void keep_on_running_on_background () {
+        if (collection == null)
+            return;
+
+        run_in_bg = false;
+        collection.foreach_item((item) => {
+            var machine = item as LibvirtMachine;
+
+            var keep_vm_running = (machine.run_in_bg && machine.is_running);
+            if (keep_vm_running) {
+                run_in_bg = true;
+
+                keep_vm_running_in_background (machine);
+                debug ("Keep running %s in the background", machine.name);
+
+            }
+        });
+    }
+
     private void suspend_machines () {
         // if we are not the main Boxes instance, 'collection' won't
         // be set as it's created in GtkApplication::startup()
diff --git a/src/libvirt-machine.vala b/src/libvirt-machine.vala
index fad51144..474be0db 100644
--- a/src/libvirt-machine.vala
+++ b/src/libvirt-machine.vala
@@ -47,6 +47,7 @@
         }
     }
 
+    public bool is_running { get { return state == MachineState.RUNNING; } }
     public bool run_in_bg { get; set; } // If true, machine will never be paused automatically by Boxes.
 
     private bool _acceleration_3d;


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