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))