Saving and Loading Window State

Use cases

Saving and restoring the window state across sessions is a useful feature for some applications.

Since applications know best what their state and geometry are—and whether, or how, those should be applied once the application is launched—it’s better to have this function near the code that creates the application window itself.

Where should the state be stored

The are two options for storing the window state:

  • a file under $XDG_CACHE_HOME/your.application.id (or simply $XDG_CACHE_HOME when running inside a Flatpak application)

  • GSettings

Both options have their own advantages and trade offs.

The first option requires you to write the serialization and deserialization code, but it’s portable and does not require ancillary files to be present at run time, like a GSettings schema. This means that you need to write more code, but it allows, for instance, to run your application uninstalled.

The second option gives you the serialization and deserialization code, but it requires you to define the setting keys schema and install it in a known location. This means that you will keep your code to a minimum, but it will also require installation.

It is generally preferred, everything being equal, to use GSettings over a custom file. The GSettings API is nicer, more reliable, and faster.

What kind of state should be saved?

There are few window states that should generally be saved:

  • the window size

  • whether the window is maximized, if the window supports it

  • whether the window is full screen, if the window supports it

The position of the window is best left to the window manager. Other states can be saved along with the ones above, using the same technique, so they will be left as an exercise for the reader.

Tip

If your application uses a GtkPaned widget, you may also want to save the position of the handle, by tracking the GtkPaned:position property.

The window geometry should be updated by getting notifications from the GtkWindow:default-width and GtkWindow:default-height properties; window states, like “maximized” and “fullscreen”, are also mapped to GtkWindow properties.

Saving and restoring state into GSettings

First of all, you will need a GSettings schema, to define the keys, the type of the values, and default value for each key:

<schemalist>
  <schema id="com.example.YourApp.State" path="/com/example/YourApp/State/">
    <key name="width" type="i">
      <default>640</default>
    </key>
    <key name="height" type="i">
      <default>480</default>
    </key>
    <key name="is-maximized" type="b">
      <default>false</default>
    </key>
    <key name="is-fullscreen" type="b">
      <default>false</default>
    </key>
  </schema>
</schemalist>

Once you have a schema, you can map window properties to the GSettings keys defined by that schema:

static void
my_application_window_init (MyApplicationWindow *self)
{
  GSettings *settings = g_settings_new ("com.example.YourApp.State");

  // update the settings when the properties change and vice versa
  g_settings_bind (settings, "width",
                   self, "default-width",
                   G_SETTINGS_BIND_DEFAULT);
  g_settings_bind (settings, "height",
                   self, "default-height",
                    G_SETTINGS_BIND_DEFAULT);
  g_settings_bind (settings, "is-maximized",
                   self, "maximized",
                   G_SETTINGS_BIND_DEFAULT);
  g_settings_bind (settings, "is-fullscreen",
                   self, "fullscreened",
                   G_SETTINGS_BIND_DEFAULT);
}

The code above will automatically set the properties to the value in the corresponding GSettings keys, and will update the GSettings keys with the value of the properties whenever they change.