diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index b678279b40..749f06f338 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -62,6 +62,7 @@ #include "linux-dmabuf-unstable-v1-client-protocol.h" #include "presentation-time-client-protocol.h" #include "xx-color-management-v4-client-protocol.h" +#include "xx-session-management-v1-client-protocol.h" #include "wm-button-layout-translation.h" @@ -101,6 +102,7 @@ #define NO_XDG_OUTPUT_DONE_SINCE_VERSION 3 #define OUTPUT_VERSION 3 #define XDG_WM_DIALOG_VERSION 1 +#define XX_SESSION_MANAGEMENT_VERSION 1 #ifdef HAVE_TOPLEVEL_STATE_SUSPENDED #define XDG_WM_BASE_VERSION 6 @@ -311,6 +313,46 @@ static const struct org_kde_kwin_server_decoration_manager_listener server_decor .default_mode = server_decoration_manager_default_mode }; +static void +session_listener_created (void *data, + struct xx_session_v1 *xdg_session_v1, + const char *id) +{ + GdkWaylandDisplay *display_wayland = data; + + GDK_DEBUG (MISC, "session created: %s", id); + + if (g_strcmp0 (display_wayland->session_id, id) != 0) + { + g_clear_pointer (&display_wayland->session_id, g_free); + display_wayland->session_id = g_strdup (id); + } +} + +static void +session_listener_restored (void *data, + struct xx_session_v1 *xdg_session_v1) +{ + GdkWaylandDisplay *display_wayland = data; + + GDK_DEBUG (MISC, "session restored: %s", display_wayland->session_id); +} + +static void +session_listener_replaced (void *data, + struct xx_session_v1 *xdg_session_v1) +{ + GdkWaylandDisplay *display_wayland = data; + + GDK_DEBUG (MISC, "session replaced: %s", display_wayland->session_id); +} + +static const struct xx_session_v1_listener xdg_session_listener = { + .created = session_listener_created, + .restored = session_listener_restored, + .replaced = session_listener_replaced, +}; + /* * gdk_wayland_display_prefers_ssd: * @display: (type GdkWaylandDisplay): a `GdkDisplay` @@ -393,6 +435,14 @@ gdk_registry_handle_global (void *data, &xdg_wm_dialog_v1_interface, MIN (version, XDG_WM_DIALOG_VERSION)); } + else if (strcmp (interface, xx_session_manager_v1_interface.name) == 0 && + gdk_has_feature (GDK_FEATURE_SESSION_MANAGEMENT)) + { + display_wayland->xdg_session_manager = + wl_registry_bind (display_wayland->wl_registry, id, + &xx_session_manager_v1_interface, + MIN (version, XX_SESSION_MANAGEMENT_VERSION)); + } else if (strcmp (interface, gtk_shell1_interface.name) == 0) { display_wayland->gtk_shell = @@ -767,6 +817,8 @@ gdk_wayland_display_dispose (GObject *object) g_clear_pointer (&display_wayland->linux_dmabuf, zwp_linux_dmabuf_v1_destroy); g_clear_pointer (&display_wayland->dmabuf_formats_info, dmabuf_formats_info_free); g_clear_pointer (&display_wayland->color, gdk_wayland_color_free); + g_clear_pointer (&display_wayland->xdg_session, xx_session_v1_destroy); + g_clear_pointer (&display_wayland->xdg_session_manager, xx_session_manager_v1_destroy); g_clear_pointer (&display_wayland->shm, wl_shm_destroy); g_clear_pointer (&display_wayland->wl_registry, wl_registry_destroy); @@ -2809,3 +2861,51 @@ gdk_wayland_display_dispatch_queue (GdkDisplay *display, _exit (1); } } + +void +gdk_wayland_display_register_session (GdkDisplay *display, + const char *name) +{ + GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display); + + GDK_DEBUG (MISC, "register session %s", name); + + if (!display_wayland->xdg_session_manager) + return; + + g_clear_pointer (&display_wayland->session_id, g_free); + display_wayland->session_id = g_strdup (name); + + display_wayland->xdg_session = + xx_session_manager_v1_get_session (display_wayland->xdg_session_manager, + XX_SESSION_MANAGER_V1_REASON_LAUNCH, + name); + xx_session_v1_add_listener (display_wayland->xdg_session, + &xdg_session_listener, + display_wayland); + + wl_display_roundtrip (display_wayland->wl_display); +} + +void +gdk_wayland_display_unregister_session (GdkDisplay *display) +{ + GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display); + + if (!display_wayland->xdg_session_manager) + return; + + if (display_wayland->xdg_session) + xx_session_v1_remove (display_wayland->xdg_session); + + g_clear_pointer (&display_wayland->session_id, g_free); + g_clear_pointer (&display_wayland->xdg_session, xx_session_v1_destroy); +} + +const char * +gdk_wayland_display_get_current_session_id (GdkDisplay *display) +{ + GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display); + + return display_wayland->session_id; +} diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h index 9b23f54178..c9741c808c 100644 --- a/gdk/wayland/gdkdisplay-wayland.h +++ b/gdk/wayland/gdkdisplay-wayland.h @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -124,6 +125,8 @@ struct _GdkWaylandDisplay struct wp_viewporter *viewporter; struct wp_presentation *presentation; struct wp_single_pixel_buffer_manager_v1 *single_pixel_buffer; + struct xdg_session_manager_v1 *xdg_session_manager; + struct xdg_session_v1 *xdg_session; GdkWaylandColor *color; GList *async_roundtrips; @@ -153,6 +156,8 @@ struct _GdkWaylandDisplay GListStore *monitors; + char *session_id; + gint64 last_bell_time_ms; }; diff --git a/gdk/wayland/gdkwaylanddisplay.h b/gdk/wayland/gdkwaylanddisplay.h index 396a6f98f2..2637194ac1 100644 --- a/gdk/wayland/gdkwaylanddisplay.h +++ b/gdk/wayland/gdkwaylanddisplay.h @@ -65,5 +65,12 @@ gboolean gdk_wayland_display_query_registry (GdkDisplay *di GDK_AVAILABLE_IN_4_4 gpointer gdk_wayland_display_get_egl_display (GdkDisplay *display); +void gdk_wayland_display_register_session (GdkDisplay *display, + const char *name); + +void gdk_wayland_display_unregister_session (GdkDisplay *display); + +const char * gdk_wayland_display_get_current_session_id (GdkDisplay *display); + G_END_DECLS