gnome: add option to restore window in hidden state

--restore-last-window-state, -r
If the primary instance of the client is launched with this option
it will check whether or not the main window was hidden when the
client was last quit and restore the same state.

This patch also adds the "window-state-hidden" GSetting to keep
track of this window state"

Issue: #78993
Change-Id: If87776003652535aa6860f0065f07bfb8cd5b673
diff --git a/data/cx.ring.RingGnome.gschema.xml b/data/cx.ring.RingGnome.gschema.xml
index 68c8e14..80852aa 100644
--- a/data/cx.ring.RingGnome.gschema.xml
+++ b/data/cx.ring.RingGnome.gschema.xml
@@ -16,5 +16,10 @@
         <summary>Bring window to foreground on incoming calls.</summary>
         <description>Bring window to foreground on incoming calls.</description>
     </key>
+    <key name="window-state-hidden" type="b">
+        <default>false</default>
+        <summary>Saves whether or not the main window is currently hidden or not.</summary>
+        <description>This is used when launching the application with the '--restore-last-window-state' option, which will launch the application with the main window in the same state as when it was last quit.</description>
+    </key>
   </schema>
 </schemalist>
diff --git a/src/ring_client.cpp b/src/ring_client.cpp
index eadd910..971c25c 100644
--- a/src/ring_client.cpp
+++ b/src/ring_client.cpp
@@ -91,6 +91,8 @@
     std::unique_ptr<QTranslator> translator;
 
     GCancellable *cancellable;
+
+    gboolean restore_window_state;
 };
 
 /* this union is used to pass ints as pointers and vice versa for GAction parameters*/
@@ -191,17 +193,41 @@
     autostart_symlink(g_settings_get_boolean(settings, "start-on-login"));
 }
 
+static void
+ring_window_show(RingClient *client)
+{
+    g_return_if_fail(IS_RING_CLIENT(client));
+    RingClientPrivate *priv = RING_CLIENT_GET_PRIVATE(client);
+
+    g_return_if_fail(priv->win);
+
+    g_debug("showing main window");
+    gtk_window_present(GTK_WINDOW(priv->win));
+    g_settings_set_boolean(priv->settings, "window-state-hidden", FALSE);
+}
+
+static void
+ring_window_hide(RingClient *client)
+{
+    g_return_if_fail(IS_RING_CLIENT(client));
+    RingClientPrivate *priv = RING_CLIENT_GET_PRIVATE(client);
+
+    g_return_if_fail(priv->win);
+
+    g_debug("hiding main window");
+    gtk_widget_hide(priv->win);
+    g_settings_set_boolean(priv->settings, "window-state-hidden", TRUE);
+}
+
 static gboolean
 on_close_window(GtkWidget *window, G_GNUC_UNUSED GdkEvent *event, RingClient *client)
 {
     g_return_val_if_fail(GTK_IS_WINDOW(window) && IS_RING_CLIENT(client), FALSE);
-
     RingClientPrivate *priv = RING_CLIENT_GET_PRIVATE(client);
 
     if (g_settings_get_boolean(priv->settings, "hide-on-close")) {
         /* we want to simply hide the window and keep the client running */
-        g_debug("hiding main window");
-        gtk_widget_hide(window);
+        ring_window_hide(client);
         return TRUE; /* do not propogate event */
     } else {
         /* we want to quit the application, so just propogate the event */
@@ -215,6 +241,8 @@
     RingClient *client = RING_CLIENT(app);
     RingClientPrivate *priv = RING_CLIENT_GET_PRIVATE(client);
 
+    gboolean show_window = TRUE;
+
     if (priv->win == NULL) {
         priv->win = ring_main_window_new(GTK_APPLICATION(app));
 
@@ -223,10 +251,17 @@
 
         /* check if the window should be destoryed or not on close */
         g_signal_connect(priv->win, "delete-event", G_CALLBACK(on_close_window), client);
+
+        /* the only case in which we don't want to show the main window is we're launching the
+         * primary instance of the application with the '-r' (--restore-last-window-state) option
+         * and the window was hidden when the application last quit
+         */
+        if ( priv->restore_window_state && g_settings_get_boolean(priv->settings, "window-state-hidden") )
+            show_window = FALSE;
     }
 
-    g_debug("show window");
-    gtk_window_present(GTK_WINDOW(priv->win));
+    if (show_window)
+        ring_window_show(client);
 }
 
 static void
@@ -357,7 +392,7 @@
             RingClient *client = RING_CLIENT(app);
             RingClientPrivate *priv = RING_CLIENT_GET_PRIVATE(client);
             if (g_settings_get_boolean(priv->settings, "bring-window-to-front"))
-                ring_client_activate(app);
+                ring_window_show(client);
         }
     );
 
@@ -498,3 +533,12 @@
 
     return (GtkWindow *)priv->win;
 }
+
+void
+ring_client_set_restore_main_window_state(RingClient *client, gboolean restore)
+{
+    g_return_if_fail(IS_RING_CLIENT(client));
+    RingClientPrivate *priv = RING_CLIENT_GET_PRIVATE(client);
+
+    priv->restore_window_state = restore;
+}
diff --git a/src/ring_client.h b/src/ring_client.h
index d0e4290..4abfed2 100644
--- a/src/ring_client.h
+++ b/src/ring_client.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2015 Savoir-Faire Linux Inc.
+ *  Copyright (C) 2015 Savoir-faire Linux Inc.
  *  Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -15,17 +15,6 @@
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
- *
- *  Additional permission under GNU GPL version 3 section 7:
- *
- *  If you modify this program, or any covered work, by linking or
- *  combining it with the OpenSSL project's OpenSSL library (or a
- *  modified version of that library), containing parts covered by the
- *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
- *  grants you additional permission to convey the resulting work.
- *  Corresponding Source for a non-source form of such a combination
- *  shall include the source code for the parts of OpenSSL used as well
- *  as that of the covered work.
  */
 
 #ifndef RING_CLIENT_H_
@@ -52,6 +41,13 @@
 RingClient *ring_client_new      (int argc, char *argv[]);
 GtkWindow  *ring_client_get_main_window(RingClient *client);
 
+/**
+ * Sets if the client should attempt to restore the main window state (hidden or not) to what it was
+ * when it was last quit (stored by the "window-state-hidden" gsetting). This function must be
+ * called before the main window is created for the first time for it to have an effect.
+ */
+void        ring_client_set_restore_main_window_state(RingClient *client, gboolean restore);
+
 G_END_DECLS
 
 #endif /* RING_CLIENT_H_ */
diff --git a/src/ring_client_options.c b/src/ring_client_options.c
index 6901a03..99e3f92 100644
--- a/src/ring_client_options.c
+++ b/src/ring_client_options.c
@@ -1,6 +1,7 @@
 /*
  *  Copyright (C) 2013-2015 Savoir-Faire Linux Inc.
  *  Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
+ *  Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -15,22 +16,12 @@
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
- *
- *  Additional permission under GNU GPL version 3 section 7:
- *
- *  If you modify this program, or any covered work, by linking or
- *  combining it with the OpenSSL project's OpenSSL library (or a
- *  modified version of that library), containing parts covered by the
- *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
- *  grants you additional permission to convey the resulting work.
- *  Corresponding Source for a non-source form of such a combination
- *  shall include the source code for the parts of OpenSSL used as well
- *  as that of the covered work.
  */
 
 #include "ring_client_options.h"
 
 #include "config.h"
+#include "ring_client.h"
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 #include <stdlib.h>
@@ -57,9 +48,23 @@
     return TRUE;
 }
 
+static gboolean
+option_restore_cb(G_GNUC_UNUSED const gchar *option_name,
+                  G_GNUC_UNUSED const gchar *value,
+                  G_GNUC_UNUSED gpointer data,
+                  G_GNUC_UNUSED GError **error)
+{
+    GApplication *client = g_application_get_default();
+    if (IS_RING_CLIENT(client))
+        ring_client_set_restore_main_window_state(RING_CLIENT(client), TRUE);
+    return TRUE;
+}
+
 static const GOptionEntry all_options[] = {
     {"version", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, option_version_cb, NULL, NULL},
     {"debug", 'd', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, option_debug_cb, "Enable debug", NULL},
+    {"restore-last-window-state", 'r', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, option_restore_cb,
+     "Restores the hidden state of the main window (only applicable to the primary instance)", NULL},
     {NULL} /* list must be NULL-terminated */
 };