[gtk+] GtkWindow: new API to store state in GSettings



commit 730765de9163934d9993b25a87f076f1b36ed271
Author: Ryan Lortie <desrt desrt ca>
Date:   Fri Jan 6 15:37:05 2012 -0500

    GtkWindow: new API to store state in GSettings
    
    https://bugzilla.gnome.org/show_bug.cgi?id=667438

 docs/reference/gtk/gtk3-sections.txt |    1 +
 gtk/Makefile.am                      |    6 +-
 gtk/gtk.symbols                      |    1 +
 gtk/gtkwindow.c                      |  128 ++++++++++++++++++++++++++++++++++
 gtk/gtkwindow.h                      |    4 +
 gtk/org.gtk.WindowState.gschema.xml  |   10 +++
 6 files changed, 148 insertions(+), 2 deletions(-)
---
diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt
index 02e7ce5..0e0499a 100644
--- a/docs/reference/gtk/gtk3-sections.txt
+++ b/docs/reference/gtk/gtk3-sections.txt
@@ -5322,6 +5322,7 @@ gtk_window_fullscreen
 gtk_window_unfullscreen
 gtk_window_set_keep_above
 gtk_window_set_keep_below
+gtk_window_setup_persistent_state
 gtk_window_begin_resize_drag
 gtk_window_begin_move_drag
 gtk_window_set_decorated
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index ab46644..bcac2cf 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -1508,10 +1508,12 @@ EXTRA_DIST +=                   \
 	gtktypebuiltins.h.template \
 	gtkprivatetypebuiltins.c.template \
 	gtkprivatetypebuiltins.h.template \
-	org.gtk.Settings.FileChooser.gschema.xml
+	org.gtk.Settings.FileChooser.gschema.xml \
+	org.gtk.WindowState.gschema.xml
 
 gsettings_SCHEMAS = \
-	org.gtk.Settings.FileChooser.gschema.xml
+	org.gtk.Settings.FileChooser.gschema.xml	\
+	org.gtk.WindowState.gschema.xml
 
 @GSETTINGS_RULES@
 
diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols
index 2006c17..5129f86 100644
--- a/gtk/gtk.symbols
+++ b/gtk/gtk.symbols
@@ -3876,6 +3876,7 @@ gtk_window_set_transient_for
 gtk_window_set_type_hint
 gtk_window_set_urgency_hint
 gtk_window_set_wmclass
+gtk_window_setup_persistent_state
 gtk_window_stick
 gtk_window_type_get_type
 gtk_window_unfullscreen
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 62e75ee..a4b9dd3 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -132,6 +132,9 @@ struct _GtkWindowPrivate
 
   guint16  configure_request_count;
 
+  GSettings *state_settings;
+  guint      state_save_id;
+
   /* The following flags are initially TRUE (before a window is mapped).
    * They cause us to compute a configure request that involves
    * default-only parameters. Once mapped, we set them to FALSE.
@@ -4590,6 +4593,40 @@ gtk_window_reshow_with_initial_size (GtkWindow *window)
   gtk_widget_show (widget);
 }
 
+static gboolean
+gtk_window_persistent_state_flush (gpointer user_data)
+{
+  GtkWindow *window = user_data;
+  GtkWidget *widget = user_data;
+  gboolean was_maximized;
+  gboolean is_maximized;
+
+  was_maximized = g_settings_get_boolean (window->priv->state_settings, "is-maximized");
+  is_maximized = gdk_window_get_state (gtk_widget_get_window (widget)) & GDK_WINDOW_STATE_MAXIMIZED;
+
+  if (is_maximized != was_maximized)
+    g_settings_set_boolean (window->priv->state_settings, "is-maximized", is_maximized);
+
+  if (!is_maximized)
+    {
+      gint old_width, old_height;
+      GtkAllocation size;
+
+      G_STATIC_ASSERT (sizeof (size.width) == sizeof (int));
+
+      g_settings_get (window->priv->state_settings, "size", "(ii)", &old_width, &old_height);
+      gtk_widget_get_allocation (widget, &size);
+
+      if (size.width != old_width || size.height != old_height)
+        g_settings_set (window->priv->state_settings, "size", "(ii)", size.width, size.height);
+    }
+
+  g_source_remove (window->priv->state_save_id);
+  window->priv->state_save_id = 0;
+
+  return G_SOURCE_REMOVE;
+}
+
 static void
 gtk_window_destroy (GtkWidget *widget)
 {
@@ -5231,6 +5268,9 @@ gtk_window_unrealize (GtkWidget *widget)
   GtkWindowPrivate *priv = window->priv;
   GtkWindowGeometryInfo *info;
 
+  if (window->priv->state_save_id)
+    gtk_window_persistent_state_flush (window);
+
   /* On unrealize, we reset the size of the window such
    * that we will re-apply the default sizing stuff
    * next time we show the window.
@@ -5426,6 +5466,14 @@ gtk_window_size_allocate (GtkWidget     *widget,
   GtkWidget *child;
   guint border_width;
 
+  if (window->priv->state_settings)
+    {
+      if (window->priv->state_save_id)
+        g_source_remove (window->priv->state_save_id);
+
+      window->priv->state_save_id = g_timeout_add (1000, gtk_window_persistent_state_flush, window);
+    }
+
   gtk_widget_set_allocation (widget, allocation);
 
   if (gtk_widget_get_realized (widget))
@@ -9721,3 +9769,83 @@ ensure_state_flag_window_unfocused (GtkWidget *widget)
 
   gtk_widget_queue_draw (widget);
 }
+
+/**
+ * gtk_window_setup_persistent_state:
+ * @window: a #GtkWindow
+ * @settings: a #GSettings object
+ * @child_name: the name of a child on @settings with schema
+ *              'org.gtk.WindowState'
+ *
+ * Sets up persistent window state using #GSettings.
+ *
+ * The size of the window and its maximized state is saved.
+ *
+ * At the time of the call, the values are read out of GSettings and
+ * applied to the window as the default size and maximized state.  This
+ * must be done before the window is shown.
+ *
+ * When the size or maximized state of the window is changed, the
+ * updated values are stored back into GSettings (with an unspecified
+ * delay to prevent trashing).
+ *
+ * @child_name must be the name of a child of @settings (ie:
+ * g_settings_get_child() must succeed).  The resulting #GSettings
+ * object must have the schema 'org.gtk.WindowState', which is installed
+ * by Gtk.
+ *
+ * Your application's schema should look something like this:
+ *
+ * |[<![CDATA[
+ *   <schema id='org.example.awesome' path='/org/example/awesome/'>
+ *     ... keys ...
+ *
+ *     <child name='main-window-state' schema='org.gtk.WindowState'/>
+ *   </schema>
+ * ]]>]|
+ *
+ * Then you should call this function like this:
+ *
+ * |[
+ *   GSettings *settings;
+ *
+ *   settings = g_settings_new ("org.example.awesome");
+ *   gtk_window_setup_persistent_state (window, settings, "main-window-state");
+ * ]|
+ *
+ * You may only call this function once per window.
+ *
+ * Since: 3.4
+ **/
+void
+gtk_window_setup_persistent_state (GtkWindow   *window,
+                                   GSettings   *settings,
+                                   const gchar *child_name)
+{
+  gint width, height;
+  GSList *node;
+
+  g_return_if_fail (GTK_IS_WINDOW (window));
+  g_return_if_fail (G_IS_SETTINGS (settings));
+  g_return_if_fail (child_name != NULL);
+  g_return_if_fail (window->priv->state_settings == NULL);
+
+  /* Force other windows to flush their state first.  We may be sharing
+   * the same settings as they are and we want to see them up to date...
+   */
+  for (node = toplevel_list; node; node = node->next)
+    {
+      GtkWindow *w = node->data;
+
+      if (w->priv->state_save_id)
+        gtk_window_persistent_state_flush (w);
+      g_assert (w->priv->state_save_id == 0);
+    }
+
+  window->priv->state_settings = g_settings_get_child (settings, child_name);
+  window->priv->maximize_initially = g_settings_get_boolean (window->priv->state_settings, "is-maximized");
+
+  g_settings_get (window->priv->state_settings, "size", "(ii)", &width, &height);
+  if (width > 0 && height > 0)
+    gtk_window_set_default_size (window, width, height);
+}
diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h
index 1720307..01b3eb3 100644
--- a/gtk/gtkwindow.h
+++ b/gtk/gtkwindow.h
@@ -338,6 +338,10 @@ gboolean gtk_window_get_has_resize_grip    (GtkWindow    *window);
 gboolean gtk_window_resize_grip_is_visible (GtkWindow    *window);
 gboolean gtk_window_get_resize_grip_area   (GtkWindow    *window,
                                             GdkRectangle *rect);
+void     gtk_window_setup_persistent_state (GtkWindow   *window,
+                                            GSettings   *settings,
+                                            const gchar *child_name);
+
 
 G_END_DECLS
 
diff --git a/gtk/org.gtk.WindowState.gschema.xml b/gtk/org.gtk.WindowState.gschema.xml
new file mode 100644
index 0000000..966edf6
--- /dev/null
+++ b/gtk/org.gtk.WindowState.gschema.xml
@@ -0,0 +1,10 @@
+<schemalist>
+  <schema id='org.gtk.WindowState'>
+    <key name='size' type='(ii)'>
+      <default>(-1, -1)</default>
+    </key>
+    <key name='is-maximized' type='b'>
+      <default>false</default>
+    </key>
+  </schema>
+</schemalist>



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