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: .. code:: 640 480 false false Once you have a schema, you can map window properties to the GSettings keys defined by that schema: .. tabs:: .. code-tab:: c 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); } .. code-tab:: python class MyApplicationWindow(Gtk.ApplicationWindow): def __init__(self, **kwargs): super().__init__(**kwargs) self.settings = Gio.Settings(schema_id="com.example.YourApp.State") self.settings.bind("width", self, "default-width", Gio.SettingsBindFlags.DEFAULT) self.settings.bind("height", self, "default-height", Gio.SettingsBindFlags.DEFAULT) self.settings.bind("is-maximized", self, "maximized", Gio.SettingsBindFlags.DEFAULT) self.settings.bind("is-fullscreen", self, "fullscreened", Gio.SettingsBindFlags.DEFAULT) .. code-tab:: vala My.ApplicationWindow : Gtk.ApplicationWindow { public void init () { var settings = new Settings ("com.example.YourApp.State"); // update the settings when the properties change and vice versa settings.bind ("width", this, "default-width", SettingsBindFlags.DEFAULT); settings.bind ("height", this, "default-height", SettingsBindFlags.DEFAULT); settings.bind ("is-maximized", this, "maximized", SettingsBindFlags.DEFAULT); settings.bind ("is-fullscreen", this, "fullscreened", SettingsBindFlags.DEFAULT); } } .. code-tab:: js const settings = new Gio.Settings({ schema: "com.example.YourApp.State", }); const window = new Adw.ApplicationWindow({ application }); // update the settings when the properties change and vice versa settings.bind( "width", window, "default-width", Gio.SettingsBindFlags.DEFAULT, ); settings.bind( "height", window, "default-height", Gio.SettingsBindFlags.DEFAULT, ); settings.bind( "is-maximized", window, "maximized", Gio.SettingsBindFlags.DEFAULT, ); settings.bind( "is-fullscreen", window, "fullscreened", Gio.SettingsBindFlags.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.