diff --git a/meson.build b/meson.build
index f9bf3b5d0..58d75d91a 100644
--- a/meson.build
+++ b/meson.build
@@ -38,7 +38,7 @@ gudev_req = '>= 232'
# wayland version requirements
wayland_server_req = '>= 1.20'
-wayland_protocols_req = '>= 1.23'
+wayland_protocols_req = '>= 1.36'
# native backend version requirements
libinput_req = '>= 1.19.0'
diff --git a/src/meson.build b/src/meson.build
index e4be36537..8a11856e5 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -585,6 +585,8 @@ if have_wayland
'wayland/meta-wayland-xdg-foreign-private.h',
'wayland/meta-wayland-xdg-shell.c',
'wayland/meta-wayland-xdg-shell.h',
+ 'wayland/meta-wayland-xdg-dialog.c',
+ 'wayland/meta-wayland-xdg-dialog.h',
'wayland/meta-window-wayland.c',
'wayland/meta-window-wayland.h',
'wayland/meta-window-xwayland.c',
@@ -804,6 +806,7 @@ if have_wayland
['tablet', 'unstable', 'v2', ],
['text-input', 'unstable', 'v3', ],
['viewporter', 'stable', ],
+ ['xdg-dialog', 'staging', 'v1', ],
['xdg-foreign', 'unstable', 'v1', ],
['xdg-foreign', 'unstable', 'v2', ],
['xdg-output', 'unstable', 'v1', ],
@@ -831,6 +834,10 @@ if have_wayland
'@0@/@1@/@2@.xml'.format(protocol_type,
protocol_name,
output_base))
+ elif protocol_type == 'staging'
+ protocol_version = p.get(2)
+ output_base = '@0@-@1@'.format(protocol_name, protocol_version)
+ input = protocols_dir / protocol_type / protocol_name / '@0@.xml'.format(output_base)
elif protocol_type == 'private'
output_base = protocol_name
input = 'wayland/protocol/@0@.xml'.format(protocol_name)
diff --git a/src/wayland/meta-wayland-versions.h b/src/wayland/meta-wayland-versions.h
index d3e3e01b7..e09e721a3 100644
--- a/src/wayland/meta-wayland-versions.h
+++ b/src/wayland/meta-wayland-versions.h
@@ -54,6 +54,7 @@
#define META_ZWP_XWAYLAND_KEYBOARD_GRAB_V1_VERSION 1
#define META_ZWP_TEXT_INPUT_V3_VERSION 1
#define META_WP_VIEWPORTER_VERSION 1
+#define META_XDG_DIALOG_VERSION 1
#define META_ZWP_PRIMARY_SELECTION_V1_VERSION 1
#endif
diff --git a/src/wayland/meta-wayland-xdg-dialog.c b/src/wayland/meta-wayland-xdg-dialog.c
new file mode 100644
index 000000000..89fb77933
--- /dev/null
+++ b/src/wayland/meta-wayland-xdg-dialog.c
@@ -0,0 +1,237 @@
+/*
+ * Wayland Support
+ *
+ * Copyright (C) 2024 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see .
+ *
+ * Author: Carlos Garnacho
+ */
+
+#include "config.h"
+
+#include "wayland/meta-wayland-xdg-dialog.h"
+
+#include "core/window-private.h"
+#include "wayland/meta-wayland-private.h"
+#include "wayland/meta-wayland-xdg-shell.h"
+#include "wayland/meta-wayland-versions.h"
+
+#include "xdg-dialog-v1-server-protocol.h"
+
+static GQuark quark_xdg_dialog_data = 0;
+
+typedef struct _MetaWaylandXdgDialog
+{
+ struct wl_resource *resource;
+ MetaWaylandXdgSurface *toplevel;
+ gboolean is_modal;
+} MetaWaylandXdgDialog;
+
+struct _MetaWaylandXdgWmDialog
+{
+ GObject parent;
+ struct wl_list resources;
+};
+
+#define META_TYPE_WAYLAND_XDG_WM_DIALOG (meta_wayland_xdg_wm_dialog_get_type ())
+G_DECLARE_FINAL_TYPE (MetaWaylandXdgWmDialog, meta_wayland_xdg_wm_dialog,
+ META, WAYLAND_XDG_WM_DIALOG, GObject)
+
+G_DEFINE_TYPE (MetaWaylandXdgWmDialog, meta_wayland_xdg_wm_dialog, G_TYPE_OBJECT)
+
+static void
+xdg_dialog_destructor (struct wl_resource *resource)
+{
+ MetaWaylandXdgDialog *xdg_dialog = wl_resource_get_user_data (resource);
+
+ if (xdg_dialog->toplevel)
+ {
+ g_object_steal_qdata (G_OBJECT (xdg_dialog->toplevel),
+ quark_xdg_dialog_data);
+ }
+
+ g_free (xdg_dialog);
+}
+
+static void
+xdg_dialog_set_modal (struct wl_client *client,
+ struct wl_resource *resource)
+{
+ MetaWaylandXdgDialog *xdg_dialog = wl_resource_get_user_data (resource);
+ MetaWaylandXdgSurface *xdg_surface;
+
+ xdg_surface = xdg_dialog->toplevel;
+
+ if (xdg_surface && !xdg_dialog->is_modal)
+ {
+ MetaWaylandSurfaceRole *surface_role =
+ META_WAYLAND_SURFACE_ROLE (xdg_surface);
+ MetaWaylandSurface *surface =
+ meta_wayland_surface_role_get_surface (surface_role);
+ MetaWindow *window = meta_wayland_surface_get_window (surface);
+
+ xdg_dialog->is_modal = TRUE;
+ meta_window_set_type (window, META_WINDOW_MODAL_DIALOG);
+ }
+}
+
+static void
+xdg_dialog_unset_modal (struct wl_client *client,
+ struct wl_resource *resource)
+{
+ MetaWaylandXdgDialog *xdg_dialog = wl_resource_get_user_data (resource);
+ MetaWaylandXdgSurface *xdg_surface;
+
+ xdg_surface = xdg_dialog->toplevel;
+
+ if (xdg_surface && xdg_dialog->is_modal)
+ {
+ MetaWaylandSurfaceRole *surface_role =
+ META_WAYLAND_SURFACE_ROLE (xdg_surface);
+ MetaWaylandSurface *surface =
+ meta_wayland_surface_role_get_surface (surface_role);
+ MetaWindow *window = meta_wayland_surface_get_window (surface);
+
+ xdg_dialog->is_modal = FALSE;
+ meta_window_set_type (window, META_WINDOW_NORMAL);
+ }
+}
+
+static void
+xdg_dialog_destroy (struct wl_client *client,
+ struct wl_resource *resource)
+{
+ wl_resource_destroy (resource);
+}
+
+static const struct xdg_dialog_v1_interface meta_wayland_xdg_dialog_interface = {
+ xdg_dialog_destroy,
+ xdg_dialog_set_modal,
+ xdg_dialog_unset_modal,
+};
+
+static void
+xdg_dialog_toplevel_destroyed (MetaWaylandXdgDialog *xdg_dialog)
+{
+ xdg_dialog->toplevel = NULL;
+}
+
+static void
+xdg_wm_dialog_destroy (struct wl_client *client,
+ struct wl_resource *resource)
+{
+ wl_resource_destroy (resource);
+}
+
+static void
+xdg_wm_dialog_get_xdg_dialog (struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t id,
+ struct wl_resource *toplevel_resource)
+{
+ MetaWaylandXdgSurface *xdg_surface = wl_resource_get_user_data (toplevel_resource);
+ MetaWaylandXdgDialog *xdg_dialog;
+
+ xdg_dialog = g_object_get_qdata (G_OBJECT (xdg_surface), quark_xdg_dialog_data);
+ if (xdg_dialog)
+ {
+ wl_resource_post_error (toplevel_resource,
+ XDG_WM_DIALOG_V1_ERROR_ALREADY_USED,
+ "xdg_wm_dialog_v1::get_xdg_dialog already requested");
+ return;
+ }
+
+ xdg_dialog = g_new0 (MetaWaylandXdgDialog, 1);
+ xdg_dialog->toplevel = xdg_surface;
+ xdg_dialog->resource = wl_resource_create (client,
+ &xdg_dialog_v1_interface,
+ wl_resource_get_version (resource),
+ id);
+ wl_resource_set_implementation (xdg_dialog->resource,
+ &meta_wayland_xdg_dialog_interface,
+ xdg_dialog, xdg_dialog_destructor);
+
+ g_object_set_qdata_full (G_OBJECT (xdg_surface),
+ quark_xdg_dialog_data,
+ xdg_dialog,
+ (GDestroyNotify) xdg_dialog_toplevel_destroyed);
+}
+
+static const struct xdg_wm_dialog_v1_interface meta_wayland_xdg_wm_dialog_interface = {
+ xdg_wm_dialog_destroy,
+ xdg_wm_dialog_get_xdg_dialog,
+};
+
+static void
+unbind_resource (struct wl_resource *resource)
+{
+ wl_list_remove (wl_resource_get_link (resource));
+}
+
+static void
+bind_xdg_wm_dialog (struct wl_client *client,
+ void *data,
+ uint32_t version,
+ uint32_t id)
+{
+ MetaWaylandXdgWmDialog *xdg_wm_dialog = data;
+ struct wl_resource *resource;
+
+ resource = wl_resource_create (client, &xdg_wm_dialog_v1_interface, version, id);
+ wl_resource_set_implementation (resource, &meta_wayland_xdg_wm_dialog_interface,
+ data, unbind_resource);
+
+
+
+
+ wl_list_insert (&xdg_wm_dialog->resources, wl_resource_get_link (resource));
+}
+
+static void
+meta_wayland_xdg_wm_dialog_init (MetaWaylandXdgWmDialog *xdg_wm_dialog)
+{
+ wl_list_init (&xdg_wm_dialog->resources);
+}
+
+static void
+meta_wayland_xdg_wm_dialog_class_init (MetaWaylandXdgWmDialogClass *klass)
+{
+ quark_xdg_dialog_data =
+ g_quark_from_static_string ("-meta-wayland-xdg-wm-dialog-surface-data");
+}
+
+static MetaWaylandXdgWmDialog *
+meta_wayland_xdg_wm_dialog_new (MetaWaylandCompositor *compositor)
+{
+ MetaWaylandXdgWmDialog *xdg_wm_dialog;
+
+ xdg_wm_dialog = g_object_new (META_TYPE_WAYLAND_XDG_WM_DIALOG, NULL);
+
+ if (wl_global_create (compositor->wayland_display,
+ &xdg_wm_dialog_v1_interface,
+ META_XDG_DIALOG_VERSION,
+ xdg_wm_dialog, bind_xdg_wm_dialog) == NULL)
+ g_error ("Failed to register a global xdg-dialog object");
+
+ return xdg_wm_dialog;
+}
+
+void
+meta_wayland_init_xdg_wm_dialog (MetaWaylandCompositor *compositor)
+{
+ g_object_set_data_full (G_OBJECT (compositor), "-meta-wayland-xdg-wm-dialog",
+ meta_wayland_xdg_wm_dialog_new (compositor),
+ g_object_unref);
+}
diff --git a/src/wayland/meta-wayland-xdg-dialog.h b/src/wayland/meta-wayland-xdg-dialog.h
new file mode 100644
index 000000000..13135eecd
--- /dev/null
+++ b/src/wayland/meta-wayland-xdg-dialog.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see .
+ */
+
+#pragma once
+
+#include "wayland/meta-wayland.h"
+
+void meta_wayland_init_xdg_wm_dialog (MetaWaylandCompositor *compositor);
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 04dcd32b9..524fd02f3 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -43,6 +43,7 @@
#include "wayland/meta-wayland-seat.h"
#include "wayland/meta-wayland-subsurface.h"
#include "wayland/meta-wayland-tablet-manager.h"
+#include "wayland/meta-wayland-xdg-dialog.h"
#include "wayland/meta-wayland-xdg-foreign.h"
#include "wayland/meta-xwayland-grab-keyboard.h"
#include "wayland/meta-xwayland-private.h"
@@ -438,6 +439,7 @@ meta_wayland_compositor_setup (MetaWaylandCompositor *wayland_compositor)
meta_wayland_keyboard_shortcuts_inhibit_init (compositor);
meta_wayland_surface_inhibit_shortcuts_dialog_init ();
meta_wayland_text_input_init (compositor);
+ meta_wayland_init_xdg_wm_dialog (compositor);
/* Xwayland specific protocol, needs to be filtered out for all other clients */
if (meta_xwayland_grab_keyboard_init (compositor))