gtk: Add GtkApplication property for session IDs

This API has two "phases":
- An initialization call, calling gtk_application_set_session_id() to
  set a session identifier from previous runs.
- A post-initialization call, to retrieve the session identifier in
  use for this session. This may be the same identifier than previously
  specified, if the session could be recovered, or a brand new one if
  the session is created from scratch.

The storage of this session identifier is left up to the applications,
and could be material for later GNOME session integration with
persistent save states.
This commit is contained in:
Carlos Garnacho
2024-06-19 14:00:37 +02:00
committed by Matthias Clasen
parent f79c181c56
commit a4ad19c934
4 changed files with 136 additions and 1 deletions

View File

@@ -127,6 +127,7 @@ enum {
PROP_SCREENSAVER_ACTIVE,
PROP_MENUBAR,
PROP_ACTIVE_WINDOW,
PROP_SESSION_ID,
NUM_PROPERTIES
};
@@ -147,6 +148,7 @@ typedef struct
GtkActionMuxer *muxer;
GtkBuilder *menus_builder;
char *help_overlay_path;
char *session_id;
} GtkApplicationPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (GtkApplication, gtk_application, G_TYPE_APPLICATION)
@@ -450,6 +452,10 @@ gtk_application_get_property (GObject *object,
g_value_set_object (value, gtk_application_get_active_window (application));
break;
case PROP_SESSION_ID:
g_value_set_string (value, gtk_application_get_session_id (application));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -475,6 +481,10 @@ gtk_application_set_property (GObject *object,
gtk_application_set_menubar (application, g_value_get_object (value));
break;
case PROP_SESSION_ID:
gtk_application_set_session_id (application, g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -635,6 +645,18 @@ gtk_application_class_init (GtkApplicationClass *class)
GTK_TYPE_WINDOW,
G_PARAM_READABLE|G_PARAM_STATIC_STRINGS);
/**
* GtkApplication:session-id: (attributes org.gtk.Property.get=gtk_application_get_session_id org.gtk.Property.set=gtk_application_set_session_id)
*
* The identifier of the session used to restore window state.
*
* Since: 4.16
*/
gtk_application_props[PROP_SESSION_ID] =
g_param_spec_string ("session-id", NULL, NULL,
NULL,
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, NUM_PROPERTIES, gtk_application_props);
}
@@ -1223,3 +1245,95 @@ gtk_application_set_screensaver_active (GtkApplication *application,
g_object_notify (G_OBJECT (application), "screensaver-active");
}
}
/**
* gtk_application_set_session_id:
* @application: a `GtkApplication`
* @session_id: (nullable): The identifier used for session management purposes
*
* Sets the identifier used for session management purposes.
*
* This identifier would have been typically retrieved in prior runs
* through [method@Gtk.Application.get_current_session_id].
*
* This session identifier must be set before `GApplication::startup` happens,
* as it will be applied there. In the case %NULL was passed, or the request
* resulted in a new session being created from scratch,
* [method@Gtk.Application.get_current_session_id] may return a different
* identifier than the one passed here.
**/
void
gtk_application_set_session_id (GtkApplication *application,
const char *session_id)
{
GtkApplicationPrivate *priv =
gtk_application_get_instance_private (application);
g_return_if_fail (GTK_IS_APPLICATION (application));
if (g_set_str (&priv->session_id, session_id))
g_object_notify (G_OBJECT (application), "session-id");
}
/**
* gtk_application_get_session_id:
* @application: a `GtkApplication`
*
* Gets the session identifier that this `GtkApplication` will use
* for session management registration.
*
* See [method@Gtk.Application.set_session_id] for more information about
* session management.
*
* Returns: (nullable): The session management ID
**/
const char *
gtk_application_get_session_id (GtkApplication *application)
{
GtkApplicationPrivate *priv =
gtk_application_get_instance_private (application);
return priv->session_id;
}
/**
* gtk_application_get_current_session_id:
* @application: a `GtkApplication`
*
* Retrieves the session management identifier that the application
* is using during execution.
*
* This identifier may be saved for future executions of the application
* to have their window state recovered.
*
* This function may be used during or after [signal@Gio.Application.startup]
* to retrieve a session identifier string in environments where session
* management is supported.
*
* In order to restore window state in future runs of the same application,
* this string should be stored, so it can be passed through
* [method@Gtk.Application.set_session_id] in these future executions.
*
* Note that this identifier may end up being different from the one
* initially specified through [method@Gtk.Application.set_session_id],
* e.g. in the case the specified session ID could not be recovered and a
* new session was created.
*
* If called on an environment/backend that does not support session
* management, or prior to application startup, this method will return `NULL`.
*
* Currently, session management is only supported in the Wayland backend.
*
* Returns: (nullable): The session identifier to preserve for future runs
**/
const char *
gtk_application_get_current_session_id (GtkApplication *application)
{
GtkApplicationPrivate *priv =
gtk_application_get_instance_private (application);
if (!priv->impl)
return NULL;
return gtk_application_impl_get_current_session_id (priv->impl);
}

View File

@@ -134,6 +134,16 @@ GDK_AVAILABLE_IN_ALL
GMenu * gtk_application_get_menu_by_id (GtkApplication *application,
const char *id);
GDK_AVAILABLE_IN_4_16
void gtk_application_set_session_id (GtkApplication *application,
const char *session_id);
GDK_AVAILABLE_IN_4_16
const char * gtk_application_get_session_id (GtkApplication *application);
GDK_AVAILABLE_IN_4_16
const char * gtk_application_get_current_session_id (GtkApplication *application);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkApplication, g_object_unref)
G_END_DECLS

View File

@@ -153,6 +153,15 @@ gtk_application_impl_prefers_app_menu (GtkApplicationImpl *impl)
return GTK_APPLICATION_IMPL_GET_CLASS (impl)->prefers_app_menu (impl);
}
const char *
gtk_application_impl_get_current_session_id (GtkApplicationImpl *impl)
{
if (!GTK_APPLICATION_IMPL_GET_CLASS (impl)->get_current_session_id)
return NULL;
return GTK_APPLICATION_IMPL_GET_CLASS (impl)->get_current_session_id (impl);
}
GtkApplicationImpl *
gtk_application_impl_new (GtkApplication *application,
GdkDisplay *display)

View File

@@ -100,7 +100,7 @@ typedef struct
gboolean (* prefers_app_menu) (GtkApplicationImpl *impl);
const char * (* get_current_session_id) (GtkApplicationImpl *impl);
} GtkApplicationImplClass;
#define GTK_TYPE_APPLICATION_IMPL_DBUS (gtk_application_impl_dbus_get_type ())
@@ -195,5 +195,7 @@ gboolean gtk_application_impl_prefers_app_menu (GtkAppl
void gtk_application_impl_quartz_setup_menu (GMenuModel *model,
GtkActionMuxer *muxer);
const char * gtk_application_impl_get_current_session_id (GtkApplicationImpl *impl);
G_END_DECLS