Skip to content

Commit 07aabf5

Browse files
authored
[Wayland] Add support for xdg-dialog-v1 protocol (#737)
This protocol is decoupled and upstreamed from GNOME's private gtk-shell-v1 protocol It allows to specify hints on surfaces such as dialog modality and already supported by newer GTK and Qt
1 parent 82885a1 commit 07aabf5

File tree

6 files changed

+270
-1
lines changed

6 files changed

+270
-1
lines changed

meson.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ gudev_req = '>= 232'
3838

3939
# wayland version requirements
4040
wayland_server_req = '>= 1.20'
41-
wayland_protocols_req = '>= 1.23'
41+
wayland_protocols_req = '>= 1.36'
4242

4343
# native backend version requirements
4444
libinput_req = '>= 1.19.0'

src/meson.build

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,8 @@ if have_wayland
585585
'wayland/meta-wayland-xdg-foreign-private.h',
586586
'wayland/meta-wayland-xdg-shell.c',
587587
'wayland/meta-wayland-xdg-shell.h',
588+
'wayland/meta-wayland-xdg-dialog.c',
589+
'wayland/meta-wayland-xdg-dialog.h',
588590
'wayland/meta-window-wayland.c',
589591
'wayland/meta-window-wayland.h',
590592
'wayland/meta-window-xwayland.c',
@@ -804,6 +806,7 @@ if have_wayland
804806
['tablet', 'unstable', 'v2', ],
805807
['text-input', 'unstable', 'v3', ],
806808
['viewporter', 'stable', ],
809+
['xdg-dialog', 'staging', 'v1', ],
807810
['xdg-foreign', 'unstable', 'v1', ],
808811
['xdg-foreign', 'unstable', 'v2', ],
809812
['xdg-output', 'unstable', 'v1', ],
@@ -831,6 +834,10 @@ if have_wayland
831834
'@0@/@1@/@[email protected]'.format(protocol_type,
832835
protocol_name,
833836
output_base))
837+
elif protocol_type == 'staging'
838+
protocol_version = p.get(2)
839+
output_base = '@0@-@1@'.format(protocol_name, protocol_version)
840+
input = protocols_dir / protocol_type / protocol_name / '@[email protected]'.format(output_base)
834841
elif protocol_type == 'private'
835842
output_base = protocol_name
836843
input = 'wayland/protocol/@[email protected]'.format(protocol_name)

src/wayland/meta-wayland-versions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#define META_ZWP_XWAYLAND_KEYBOARD_GRAB_V1_VERSION 1
5555
#define META_ZWP_TEXT_INPUT_V3_VERSION 1
5656
#define META_WP_VIEWPORTER_VERSION 1
57+
#define META_XDG_DIALOG_VERSION 1
5758
#define META_ZWP_PRIMARY_SELECTION_V1_VERSION 1
5859

5960
#endif
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
/*
2+
* Wayland Support
3+
*
4+
* Copyright (C) 2024 Red Hat, Inc.
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU General Public License as
8+
* published by the Free Software Foundation; either version 2 of the
9+
* License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful, but
12+
* WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program; if not, see <http://www.gnu.org/licenses/>.
18+
*
19+
* Author: Carlos Garnacho <[email protected]>
20+
*/
21+
22+
#include "config.h"
23+
24+
#include "wayland/meta-wayland-xdg-dialog.h"
25+
26+
#include "core/window-private.h"
27+
#include "wayland/meta-wayland-private.h"
28+
#include "wayland/meta-wayland-xdg-shell.h"
29+
#include "wayland/meta-wayland-versions.h"
30+
31+
#include "xdg-dialog-v1-server-protocol.h"
32+
33+
static GQuark quark_xdg_dialog_data = 0;
34+
35+
typedef struct _MetaWaylandXdgDialog
36+
{
37+
struct wl_resource *resource;
38+
MetaWaylandXdgSurface *toplevel;
39+
gboolean is_modal;
40+
} MetaWaylandXdgDialog;
41+
42+
struct _MetaWaylandXdgWmDialog
43+
{
44+
GObject parent;
45+
struct wl_list resources;
46+
};
47+
48+
#define META_TYPE_WAYLAND_XDG_WM_DIALOG (meta_wayland_xdg_wm_dialog_get_type ())
49+
G_DECLARE_FINAL_TYPE (MetaWaylandXdgWmDialog, meta_wayland_xdg_wm_dialog,
50+
META, WAYLAND_XDG_WM_DIALOG, GObject)
51+
52+
G_DEFINE_TYPE (MetaWaylandXdgWmDialog, meta_wayland_xdg_wm_dialog, G_TYPE_OBJECT)
53+
54+
static void
55+
xdg_dialog_destructor (struct wl_resource *resource)
56+
{
57+
MetaWaylandXdgDialog *xdg_dialog = wl_resource_get_user_data (resource);
58+
59+
if (xdg_dialog->toplevel)
60+
{
61+
g_object_steal_qdata (G_OBJECT (xdg_dialog->toplevel),
62+
quark_xdg_dialog_data);
63+
}
64+
65+
g_free (xdg_dialog);
66+
}
67+
68+
static void
69+
xdg_dialog_set_modal (struct wl_client *client,
70+
struct wl_resource *resource)
71+
{
72+
MetaWaylandXdgDialog *xdg_dialog = wl_resource_get_user_data (resource);
73+
MetaWaylandXdgSurface *xdg_surface;
74+
75+
xdg_surface = xdg_dialog->toplevel;
76+
77+
if (xdg_surface && !xdg_dialog->is_modal)
78+
{
79+
MetaWaylandSurfaceRole *surface_role =
80+
META_WAYLAND_SURFACE_ROLE (xdg_surface);
81+
MetaWaylandSurface *surface =
82+
meta_wayland_surface_role_get_surface (surface_role);
83+
MetaWindow *window = meta_wayland_surface_get_window (surface);
84+
85+
xdg_dialog->is_modal = TRUE;
86+
meta_window_set_type (window, META_WINDOW_MODAL_DIALOG);
87+
}
88+
}
89+
90+
static void
91+
xdg_dialog_unset_modal (struct wl_client *client,
92+
struct wl_resource *resource)
93+
{
94+
MetaWaylandXdgDialog *xdg_dialog = wl_resource_get_user_data (resource);
95+
MetaWaylandXdgSurface *xdg_surface;
96+
97+
xdg_surface = xdg_dialog->toplevel;
98+
99+
if (xdg_surface && xdg_dialog->is_modal)
100+
{
101+
MetaWaylandSurfaceRole *surface_role =
102+
META_WAYLAND_SURFACE_ROLE (xdg_surface);
103+
MetaWaylandSurface *surface =
104+
meta_wayland_surface_role_get_surface (surface_role);
105+
MetaWindow *window = meta_wayland_surface_get_window (surface);
106+
107+
xdg_dialog->is_modal = FALSE;
108+
meta_window_set_type (window, META_WINDOW_NORMAL);
109+
}
110+
}
111+
112+
static void
113+
xdg_dialog_destroy (struct wl_client *client,
114+
struct wl_resource *resource)
115+
{
116+
wl_resource_destroy (resource);
117+
}
118+
119+
static const struct xdg_dialog_v1_interface meta_wayland_xdg_dialog_interface = {
120+
xdg_dialog_destroy,
121+
xdg_dialog_set_modal,
122+
xdg_dialog_unset_modal,
123+
};
124+
125+
static void
126+
xdg_dialog_toplevel_destroyed (MetaWaylandXdgDialog *xdg_dialog)
127+
{
128+
xdg_dialog->toplevel = NULL;
129+
}
130+
131+
static void
132+
xdg_wm_dialog_destroy (struct wl_client *client,
133+
struct wl_resource *resource)
134+
{
135+
wl_resource_destroy (resource);
136+
}
137+
138+
static void
139+
xdg_wm_dialog_get_xdg_dialog (struct wl_client *client,
140+
struct wl_resource *resource,
141+
uint32_t id,
142+
struct wl_resource *toplevel_resource)
143+
{
144+
MetaWaylandXdgSurface *xdg_surface = wl_resource_get_user_data (toplevel_resource);
145+
MetaWaylandXdgDialog *xdg_dialog;
146+
147+
xdg_dialog = g_object_get_qdata (G_OBJECT (xdg_surface), quark_xdg_dialog_data);
148+
if (xdg_dialog)
149+
{
150+
wl_resource_post_error (toplevel_resource,
151+
XDG_WM_DIALOG_V1_ERROR_ALREADY_USED,
152+
"xdg_wm_dialog_v1::get_xdg_dialog already requested");
153+
return;
154+
}
155+
156+
xdg_dialog = g_new0 (MetaWaylandXdgDialog, 1);
157+
xdg_dialog->toplevel = xdg_surface;
158+
xdg_dialog->resource = wl_resource_create (client,
159+
&xdg_dialog_v1_interface,
160+
wl_resource_get_version (resource),
161+
id);
162+
wl_resource_set_implementation (xdg_dialog->resource,
163+
&meta_wayland_xdg_dialog_interface,
164+
xdg_dialog, xdg_dialog_destructor);
165+
166+
g_object_set_qdata_full (G_OBJECT (xdg_surface),
167+
quark_xdg_dialog_data,
168+
xdg_dialog,
169+
(GDestroyNotify) xdg_dialog_toplevel_destroyed);
170+
}
171+
172+
static const struct xdg_wm_dialog_v1_interface meta_wayland_xdg_wm_dialog_interface = {
173+
xdg_wm_dialog_destroy,
174+
xdg_wm_dialog_get_xdg_dialog,
175+
};
176+
177+
static void
178+
unbind_resource (struct wl_resource *resource)
179+
{
180+
wl_list_remove (wl_resource_get_link (resource));
181+
}
182+
183+
static void
184+
bind_xdg_wm_dialog (struct wl_client *client,
185+
void *data,
186+
uint32_t version,
187+
uint32_t id)
188+
{
189+
MetaWaylandXdgWmDialog *xdg_wm_dialog = data;
190+
struct wl_resource *resource;
191+
192+
resource = wl_resource_create (client, &xdg_wm_dialog_v1_interface, version, id);
193+
wl_resource_set_implementation (resource, &meta_wayland_xdg_wm_dialog_interface,
194+
data, unbind_resource);
195+
196+
197+
198+
199+
wl_list_insert (&xdg_wm_dialog->resources, wl_resource_get_link (resource));
200+
}
201+
202+
static void
203+
meta_wayland_xdg_wm_dialog_init (MetaWaylandXdgWmDialog *xdg_wm_dialog)
204+
{
205+
wl_list_init (&xdg_wm_dialog->resources);
206+
}
207+
208+
static void
209+
meta_wayland_xdg_wm_dialog_class_init (MetaWaylandXdgWmDialogClass *klass)
210+
{
211+
quark_xdg_dialog_data =
212+
g_quark_from_static_string ("-meta-wayland-xdg-wm-dialog-surface-data");
213+
}
214+
215+
static MetaWaylandXdgWmDialog *
216+
meta_wayland_xdg_wm_dialog_new (MetaWaylandCompositor *compositor)
217+
{
218+
MetaWaylandXdgWmDialog *xdg_wm_dialog;
219+
220+
xdg_wm_dialog = g_object_new (META_TYPE_WAYLAND_XDG_WM_DIALOG, NULL);
221+
222+
if (wl_global_create (compositor->wayland_display,
223+
&xdg_wm_dialog_v1_interface,
224+
META_XDG_DIALOG_VERSION,
225+
xdg_wm_dialog, bind_xdg_wm_dialog) == NULL)
226+
g_error ("Failed to register a global xdg-dialog object");
227+
228+
return xdg_wm_dialog;
229+
}
230+
231+
void
232+
meta_wayland_init_xdg_wm_dialog (MetaWaylandCompositor *compositor)
233+
{
234+
g_object_set_data_full (G_OBJECT (compositor), "-meta-wayland-xdg-wm-dialog",
235+
meta_wayland_xdg_wm_dialog_new (compositor),
236+
g_object_unref);
237+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright (C) 2016 Red Hat, Inc.
3+
*
4+
* This program is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU General Public License as
6+
* published by the Free Software Foundation; either version 2 of the
7+
* License, or (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful, but
10+
* WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
* General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program; if not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
#pragma once
19+
20+
#include "wayland/meta-wayland.h"
21+
22+
void meta_wayland_init_xdg_wm_dialog (MetaWaylandCompositor *compositor);

src/wayland/meta-wayland.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "wayland/meta-wayland-seat.h"
4444
#include "wayland/meta-wayland-subsurface.h"
4545
#include "wayland/meta-wayland-tablet-manager.h"
46+
#include "wayland/meta-wayland-xdg-dialog.h"
4647
#include "wayland/meta-wayland-xdg-foreign.h"
4748
#include "wayland/meta-xwayland-grab-keyboard.h"
4849
#include "wayland/meta-xwayland-private.h"
@@ -438,6 +439,7 @@ meta_wayland_compositor_setup (MetaWaylandCompositor *wayland_compositor)
438439
meta_wayland_keyboard_shortcuts_inhibit_init (compositor);
439440
meta_wayland_surface_inhibit_shortcuts_dialog_init ();
440441
meta_wayland_text_input_init (compositor);
442+
meta_wayland_init_xdg_wm_dialog (compositor);
441443

442444
/* Xwayland specific protocol, needs to be filtered out for all other clients */
443445
if (meta_xwayland_grab_keyboard_init (compositor))

0 commit comments

Comments
 (0)