gdk/wayland: Implement support for xdg-dialog Wayland protocol
This protocol lifts some functionality from the gtk-shell protocol, namely the ability to tag dialogs as modal. Ensure to use this new protocol if available for the task, instead of the gtk-shell protocol.
This commit is contained in:
@@ -97,6 +97,7 @@
|
||||
#define OUTPUT_VERSION_WITH_DONE 2
|
||||
#define NO_XDG_OUTPUT_DONE_SINCE_VERSION 3
|
||||
#define OUTPUT_VERSION 3
|
||||
#define XDG_WM_DIALOG_VERSION 1
|
||||
|
||||
#ifdef HAVE_TOPLEVEL_STATE_SUSPENDED
|
||||
#define XDG_WM_BASE_VERSION 6
|
||||
@@ -468,6 +469,13 @@ gdk_registry_handle_global (void *data,
|
||||
{
|
||||
display_wayland->zxdg_shell_v6_id = id;
|
||||
}
|
||||
else if (strcmp (interface, "xdg_wm_dialog_v1") == 0)
|
||||
{
|
||||
display_wayland->xdg_wm_dialog =
|
||||
wl_registry_bind (display_wayland->wl_registry, id,
|
||||
&xdg_wm_dialog_v1_interface,
|
||||
MIN (version, XDG_WM_DIALOG_VERSION));
|
||||
}
|
||||
else if (strcmp (interface, "gtk_shell1") == 0)
|
||||
{
|
||||
display_wayland->gtk_shell =
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <gdk/wayland/fractional-scale-v1-client-protocol.h>
|
||||
#include <gdk/wayland/viewporter-client-protocol.h>
|
||||
#include <gdk/wayland/presentation-time-client-protocol.h>
|
||||
#include <gdk/wayland/xdg-dialog-v1-client-protocol.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <gdk/gdkkeys.h>
|
||||
@@ -109,6 +110,7 @@ struct _GdkWaylandDisplay
|
||||
LinuxDmabufFormat *linux_dmabuf_formats;
|
||||
struct xdg_wm_base *xdg_wm_base;
|
||||
struct zxdg_shell_v6 *zxdg_shell_v6;
|
||||
struct xdg_wm_dialog_v1 *xdg_wm_dialog;
|
||||
struct gtk_shell1 *gtk_shell;
|
||||
struct wl_data_device_manager *data_device_manager;
|
||||
struct wl_subcompositor *subcompositor;
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <wayland/presentation-time-client-protocol.h>
|
||||
#include <wayland/xdg-shell-unstable-v6-client-protocol.h>
|
||||
#include <wayland/xdg-foreign-unstable-v2-client-protocol.h>
|
||||
#include <wayland/xdg-dialog-v1-client-protocol.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@@ -84,6 +85,7 @@ struct _GdkWaylandToplevel
|
||||
struct gtk_surface1 *gtk_surface;
|
||||
struct xdg_toplevel *xdg_toplevel;
|
||||
struct zxdg_toplevel_v6 *zxdg_toplevel_v6;
|
||||
struct xdg_dialog_v1 *xdg_dialog;
|
||||
} display_server;
|
||||
|
||||
GdkWaylandToplevel *transient_for;
|
||||
@@ -205,6 +207,7 @@ gdk_wayland_toplevel_clear_saved_size (GdkWaylandToplevel *toplevel)
|
||||
|
||||
static void maybe_set_gtk_surface_dbus_properties (GdkWaylandToplevel *wayland_toplevel);
|
||||
static void maybe_set_gtk_surface_modal (GdkWaylandToplevel *wayland_toplevel);
|
||||
static gboolean maybe_set_xdg_dialog_modal (GdkWaylandToplevel *wayland_toplevel);
|
||||
|
||||
static void
|
||||
gdk_wayland_toplevel_hide_surface (GdkWaylandSurface *wayland_surface)
|
||||
@@ -215,6 +218,7 @@ gdk_wayland_toplevel_hide_surface (GdkWaylandSurface *wayland_surface)
|
||||
|
||||
g_clear_pointer (&toplevel->display_server.xdg_toplevel, xdg_toplevel_destroy);
|
||||
g_clear_pointer (&toplevel->display_server.zxdg_toplevel_v6, zxdg_toplevel_v6_destroy);
|
||||
g_clear_pointer (&toplevel->display_server.xdg_dialog, xdg_dialog_v1_destroy);
|
||||
|
||||
if (toplevel->display_server.gtk_surface)
|
||||
{
|
||||
@@ -877,7 +881,8 @@ gdk_wayland_surface_create_xdg_toplevel (GdkWaylandToplevel *wayland_toplevel)
|
||||
gdk_wayland_toplevel_set_application_id (GDK_TOPLEVEL (wayland_toplevel), app_id);
|
||||
|
||||
maybe_set_gtk_surface_dbus_properties (wayland_toplevel);
|
||||
maybe_set_gtk_surface_modal (wayland_toplevel);
|
||||
if (!maybe_set_xdg_dialog_modal (wayland_toplevel))
|
||||
maybe_set_gtk_surface_modal (wayland_toplevel);
|
||||
|
||||
gdk_profiler_add_mark (GDK_PROFILER_CURRENT_TIME, 0, "Wayland surface commit", NULL);
|
||||
wl_surface_commit (wayland_surface->display_server.wl_surface);
|
||||
@@ -1089,12 +1094,40 @@ maybe_set_gtk_surface_modal (GdkWaylandToplevel *wayland_toplevel)
|
||||
|
||||
}
|
||||
|
||||
static gboolean
|
||||
maybe_set_xdg_dialog_modal (GdkWaylandToplevel *wayland_toplevel)
|
||||
{
|
||||
GdkWaylandDisplay *display_wayland =
|
||||
GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SURFACE (wayland_toplevel)));
|
||||
|
||||
if (!display_wayland->xdg_wm_dialog)
|
||||
return FALSE;
|
||||
if (!is_realized_toplevel (GDK_WAYLAND_SURFACE (wayland_toplevel)))
|
||||
return FALSE;
|
||||
|
||||
if (!wayland_toplevel->display_server.xdg_dialog)
|
||||
{
|
||||
wayland_toplevel->display_server.xdg_dialog =
|
||||
xdg_wm_dialog_v1_get_xdg_dialog (display_wayland->xdg_wm_dialog,
|
||||
wayland_toplevel->display_server.xdg_toplevel);
|
||||
}
|
||||
|
||||
if (GDK_SURFACE (wayland_toplevel)->modal_hint)
|
||||
xdg_dialog_v1_set_modal (wayland_toplevel->display_server.xdg_dialog);
|
||||
else
|
||||
xdg_dialog_v1_unset_modal (wayland_toplevel->display_server.xdg_dialog);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_toplevel_set_modal_hint (GdkWaylandToplevel *wayland_toplevel,
|
||||
gboolean modal)
|
||||
{
|
||||
GDK_SURFACE (wayland_toplevel)->modal_hint = modal;
|
||||
maybe_set_gtk_surface_modal (wayland_toplevel);
|
||||
|
||||
if (!maybe_set_xdg_dialog_modal (wayland_toplevel))
|
||||
maybe_set_gtk_surface_modal (wayland_toplevel);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -136,6 +136,18 @@ proto_sources = [
|
||||
'stability': 'stable',
|
||||
'version': 1,
|
||||
},
|
||||
{
|
||||
'name': 'xdg-dialog',
|
||||
'stability': 'staging',
|
||||
'version': 1,
|
||||
'required': '>=1.36',
|
||||
},
|
||||
{
|
||||
'name': 'xdg-dialog',
|
||||
'stability': 'private',
|
||||
'version': 1,
|
||||
'required': '<1.36',
|
||||
},
|
||||
]
|
||||
|
||||
gdk_wayland_gen_headers = []
|
||||
|
||||
110
gdk/wayland/protocol/xdg-dialog-v1.xml
Normal file
110
gdk/wayland/protocol/xdg-dialog-v1.xml
Normal file
@@ -0,0 +1,110 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="xdg_dialog_v1">
|
||||
<copyright>
|
||||
Copyright © 2023 Carlos Garnacho
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<interface name="xdg_wm_dialog_v1" version="1">
|
||||
<description summary="create dialogs related to other toplevels">
|
||||
The xdg_wm_dialog_v1 interface is exposed as a global object allowing
|
||||
to register surfaces with a xdg_toplevel role as "dialogs" relative to
|
||||
another toplevel.
|
||||
|
||||
The compositor may let this relation influence how the surface is
|
||||
placed, displayed or interacted with.
|
||||
|
||||
Warning! The protocol described in this file is currently in the testing
|
||||
phase. Backward compatible changes may be added together with the
|
||||
corresponding interface version bump. Backward incompatible changes can
|
||||
only be done by creating a new major version of the extension.
|
||||
</description>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="already_used" value="0"
|
||||
summary="the xdg_toplevel object has already been used to create a xdg_dialog_v1"/>
|
||||
</enum>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the dialog manager object">
|
||||
Destroys the xdg_wm_dialog_v1 object. This does not affect
|
||||
the xdg_dialog_v1 objects generated through it.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="get_xdg_dialog">
|
||||
<description summary="create a dialog object">
|
||||
Creates a xdg_dialog_v1 object for the given toplevel. See the interface
|
||||
description for more details.
|
||||
|
||||
Compositors must raise an already_used error if clients attempt to
|
||||
create multiple xdg_dialog_v1 objects for the same xdg_toplevel.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="xdg_dialog_v1"/>
|
||||
<arg name="toplevel" type="object" interface="xdg_toplevel"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="xdg_dialog_v1" version="1">
|
||||
<description summary="dialog object">
|
||||
A xdg_dialog_v1 object is an ancillary object tied to a xdg_toplevel. Its
|
||||
purpose is hinting the compositor that the toplevel is a "dialog" (e.g. a
|
||||
temporary window) relative to another toplevel (see
|
||||
xdg_toplevel.set_parent). If the xdg_toplevel is destroyed, the xdg_dialog_v1
|
||||
becomes inert.
|
||||
|
||||
Through this object, the client may provide additional hints about
|
||||
the purpose of the secondary toplevel. This interface has no effect
|
||||
on toplevels that are not attached to a parent toplevel.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the dialog object">
|
||||
Destroys the xdg_dialog_v1 object. If this object is destroyed
|
||||
before the related xdg_toplevel, the compositor should unapply its
|
||||
effects.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="set_modal">
|
||||
<description summary="mark dialog as modal">
|
||||
Hints that the dialog has "modal" behavior. Modal dialogs typically
|
||||
require to be fully addressed by the user (i.e. closed) before resuming
|
||||
interaction with the parent toplevel, and may require a distinct
|
||||
presentation.
|
||||
|
||||
Clients must implement the logic to filter events in the parent
|
||||
toplevel on their own.
|
||||
|
||||
Compositors may choose any policy in event delivery to the parent
|
||||
toplevel, from delivering all events unfiltered to using them for
|
||||
internal consumption.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="unset_modal">
|
||||
<description summary="mark dialog as not modal">
|
||||
Drops the hint that this dialog has "modal" behavior. See
|
||||
xdg_dialog_v1.set_modal for more details.
|
||||
</description>
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
||||
Reference in New Issue
Block a user