1
0
Fork 0

wayland: Implement the XDG dialog protocol

This protocol takes over some of our homegrown GTK Shell
protocol, allowing to specify hints on surfaces such as
dialog modality.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3557>
This commit is contained in:
Carlos Garnacho 2023-09-17 18:57:37 +02:00 committed by Marge Bot
parent 326e4c15de
commit 69e791cda1
6 changed files with 262 additions and 1 deletions

View file

@ -46,7 +46,7 @@ gudev_req = '>= 232'
# wayland version requirements # wayland version requirements
wayland_server_req = '>= 1.22' wayland_server_req = '>= 1.22'
wayland_protocols_req = '>= 1.33' wayland_protocols_req = '>= 1.36'
# native backend version requirements # native backend version requirements
libinput_req = '>= 1.19.0' libinput_req = '>= 1.19.0'

View file

@ -702,6 +702,8 @@ if have_wayland
'wayland/meta-wayland-xdg-foreign-private.h', 'wayland/meta-wayland-xdg-foreign-private.h',
'wayland/meta-wayland-xdg-shell.c', 'wayland/meta-wayland-xdg-shell.c',
'wayland/meta-wayland-xdg-shell.h', '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.c',
'wayland/meta-window-wayland.h', 'wayland/meta-window-wayland.h',
] ]
@ -1077,6 +1079,7 @@ if have_wayland
['text-input', 'unstable', 'v3', ], ['text-input', 'unstable', 'v3', ],
['viewporter', 'stable', ], ['viewporter', 'stable', ],
['xdg-activation', 'staging', 'v1', ], ['xdg-activation', 'staging', 'v1', ],
['xdg-dialog', 'staging', 'v1', ],
['xdg-foreign', 'unstable', 'v1', ], ['xdg-foreign', 'unstable', 'v1', ],
['xdg-foreign', 'unstable', 'v2', ], ['xdg-foreign', 'unstable', 'v2', ],
['xdg-output', 'unstable', 'v1', ], ['xdg-output', 'unstable', 'v1', ],

View file

@ -57,3 +57,4 @@
#define META_WP_SINGLE_PIXEL_BUFFER_V1_VERSION 1 #define META_WP_SINGLE_PIXEL_BUFFER_V1_VERSION 1
#define META_MUTTER_X11_INTEROP_VERSION 1 #define META_MUTTER_X11_INTEROP_VERSION 1
#define META_WP_FRACTIONAL_SCALE_VERSION 1 #define META_WP_FRACTIONAL_SCALE_VERSION 1
#define META_XDG_DIALOG_VERSION 1

View file

@ -0,0 +1,233 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#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);
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "wayland/meta-wayland.h"
void meta_wayland_init_xdg_wm_dialog (MetaWaylandCompositor *compositor);

View file

@ -56,6 +56,7 @@
#include "wayland/meta-wayland-subsurface.h" #include "wayland/meta-wayland-subsurface.h"
#include "wayland/meta-wayland-tablet-manager.h" #include "wayland/meta-wayland-tablet-manager.h"
#include "wayland/meta-wayland-transaction.h" #include "wayland/meta-wayland-transaction.h"
#include "wayland/meta-wayland-xdg-dialog.h"
#include "wayland/meta-wayland-xdg-foreign.h" #include "wayland/meta-wayland-xdg-foreign.h"
#include "wayland/meta-wayland-linux-drm-syncobj.h" #include "wayland/meta-wayland-linux-drm-syncobj.h"
@ -870,6 +871,7 @@ meta_wayland_compositor_new (MetaContext *context)
meta_wayland_transaction_init (compositor); meta_wayland_transaction_init (compositor);
meta_wayland_idle_inhibit_init (compositor); meta_wayland_idle_inhibit_init (compositor);
meta_wayland_drm_syncobj_init (compositor); meta_wayland_drm_syncobj_init (compositor);
meta_wayland_init_xdg_wm_dialog (compositor);
#ifdef HAVE_WAYLAND_EGLSTREAM #ifdef HAVE_WAYLAND_EGLSTREAM
{ {