[gtk+] Wayland: Implement KDE's SSD protocol
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] Wayland: Implement KDE's SSD protocol
- Date: Thu, 26 Oct 2017 20:07:14 +0000 (UTC)
commit 1b279e3d4ac33ebd9a3925d1a388c28bd96232d5
Author: Drew DeVault <sir cmpwn com>
Date: Fri Apr 28 20:35:51 2017 -0400
Wayland: Implement KDE's SSD protocol
If the compositor prefers server-side decorations and the client doesn't
customize the title bar, we disable client-side decorations and let the
compositor know. Otherwise, we continue to use client-side decorations.
Signed-off-by: Drew DeVault <sir cmpwn com>
https://bugzilla.gnome.org/show_bug.cgi?id=781909
gdk/wayland/gdkdisplay-wayland.c | 39 ++++++++++++
gdk/wayland/gdkdisplay-wayland.h | 4 +
gdk/wayland/gdkwaylanddisplay.h | 2 +
gdk/wayland/gdkwaylandwindow.h | 2 +
gdk/wayland/gdkwindow-wayland.c | 16 +++++
gdk/wayland/meson.build | 3 +-
gdk/wayland/protocol/server-decoration.xml | 94 ++++++++++++++++++++++++++++
gtk/gtkwindow.c | 10 +++-
8 files changed, 168 insertions(+), 2 deletions(-)
---
diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c
index 2154e51..ab1aa72 100644
--- a/gdk/wayland/gdkdisplay-wayland.c
+++ b/gdk/wayland/gdkdisplay-wayland.c
@@ -49,6 +49,7 @@
#include "tablet-unstable-v2-client-protocol.h"
#include <wayland/xdg-shell-unstable-v6-client-protocol.h>
#include <wayland/xdg-foreign-unstable-v1-client-protocol.h>
+#include <wayland/server-decoration-client-protocol.h>
/**
* SECTION:wayland_interaction
@@ -337,6 +338,35 @@ static const struct wl_shm_listener wl_shm_listener = {
};
static void
+server_decoration_manager_default_mode (void *data,
+ struct org_kde_kwin_server_decoration_manager *manager,
+ uint32_t mode)
+{
+ g_assert (mode <= ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER);
+ const char *modes[] = {
+ [ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_NONE] = "none",
+ [ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_CLIENT] = "client",
+ [ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER] = "server",
+ };
+ GdkWaylandDisplay *display_wayland = data;
+ g_debug ("Compositor prefers decoration mode '%s'", modes[mode]);
+ display_wayland->server_decoration_mode = mode;
+}
+
+static const struct org_kde_kwin_server_decoration_manager_listener server_decoration_listener = {
+ .default_mode = server_decoration_manager_default_mode
+};
+
+gboolean
+gdk_wayland_display_prefers_ssd (GdkDisplay *display)
+{
+ GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
+ if (display_wayland->server_decoration_manager)
+ return display_wayland->server_decoration_mode == ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER;
+ return FALSE;
+}
+
+static void
gdk_registry_handle_global (void *data,
struct wl_registry *registry,
uint32_t id,
@@ -459,6 +489,15 @@ gdk_registry_handle_global (void *data,
wl_registry_bind (display_wayland->wl_registry, id,
&zwp_keyboard_shortcuts_inhibit_manager_v1_interface, 1);
}
+ else if (strcmp (interface, "org_kde_kwin_server_decoration_manager") == 0)
+ {
+ display_wayland->server_decoration_manager =
+ wl_registry_bind (display_wayland->wl_registry, id,
+ &org_kde_kwin_server_decoration_manager_interface, 1);
+ org_kde_kwin_server_decoration_manager_add_listener (display_wayland->server_decoration_manager,
+ &server_decoration_listener,
+ display_wayland);
+ }
else
handled = FALSE;
diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h
index 3f53108..37083c7 100644
--- a/gdk/wayland/gdkdisplay-wayland.h
+++ b/gdk/wayland/gdkdisplay-wayland.h
@@ -32,6 +32,7 @@
#include <gdk/wayland/xdg-shell-unstable-v6-client-protocol.h>
#include <gdk/wayland/xdg-foreign-unstable-v1-client-protocol.h>
#include <gdk/wayland/keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h>
+#include <gdk/wayland/server-decoration-client-protocol.h>
#include <glib.h>
#include <gdk/gdkkeys.h>
@@ -79,6 +80,7 @@ struct _GdkWaylandDisplay
struct zxdg_exporter_v1 *xdg_exporter;
struct zxdg_importer_v1 *xdg_importer;
struct zwp_keyboard_shortcuts_inhibit_manager_v1 *keyboard_shortcuts_inhibit;
+ struct org_kde_kwin_server_decoration_manager *server_decoration_manager;
GList *async_roundtrips;
@@ -106,6 +108,8 @@ struct _GdkWaylandDisplay
int data_device_manager_version;
int gtk_shell_version;
+ uint32_t server_decoration_mode;
+
struct xkb_context *xkb_context;
GdkWaylandSelection *selection;
diff --git a/gdk/wayland/gdkwaylanddisplay.h b/gdk/wayland/gdkwaylanddisplay.h
index f4b51c8..c77da4f 100644
--- a/gdk/wayland/gdkwaylanddisplay.h
+++ b/gdk/wayland/gdkwaylanddisplay.h
@@ -57,6 +57,8 @@ GDK_AVAILABLE_IN_3_22
void gdk_wayland_display_set_startup_notification_id (GdkDisplay *display,
const char *startup_id);
+gboolean gdk_wayland_display_prefers_ssd (GdkDisplay *display);
+
G_END_DECLS
#endif /* __GDK_WAYLAND_DISPLAY_H__ */
diff --git a/gdk/wayland/gdkwaylandwindow.h b/gdk/wayland/gdkwaylandwindow.h
index 628204f..61c52da 100644
--- a/gdk/wayland/gdkwaylandwindow.h
+++ b/gdk/wayland/gdkwaylandwindow.h
@@ -81,6 +81,8 @@ GDK_AVAILABLE_IN_3_22
gboolean gdk_wayland_window_set_transient_for_exported (GdkWindow *window,
char *parent_handle_str);
+void gdk_wayland_window_announce_csd (GdkWindow *window);
+
G_END_DECLS
#endif /* __GDK_WAYLAND_WINDOW_H__ */
diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c
index 157d41d..298435e 100644
--- a/gdk/wayland/gdkwindow-wayland.c
+++ b/gdk/wayland/gdkwindow-wayland.c
@@ -117,6 +117,7 @@ struct _GdkWindowImplWayland
struct wl_egl_window *egl_window;
struct wl_egl_window *dummy_egl_window;
struct zxdg_exported_v1 *xdg_exported;
+ struct org_kde_kwin_server_decoration *server_decoration;
} display_server;
EGLSurface egl_surface;
@@ -1663,6 +1664,21 @@ window_anchor_to_gravity (GdkGravity rect_anchor)
ZXDG_POSITIONER_V6_GRAVITY_RIGHT);
}
+void
+gdk_wayland_window_announce_csd (GdkWindow *window)
+{
+ GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
+ GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
+ if (!display_wayland->server_decoration_manager)
+ return;
+ impl->display_server.server_decoration =
+ org_kde_kwin_server_decoration_manager_create (display_wayland->server_decoration_manager,
+ impl->display_server.wl_surface);
+ if (impl->display_server.server_decoration)
+ org_kde_kwin_server_decoration_request_mode (impl->display_server.server_decoration,
+ ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_CLIENT);
+}
+
static GdkWindow *
get_real_parent_and_translate (GdkWindow *window,
gint *x,
diff --git a/gdk/wayland/meson.build b/gdk/wayland/meson.build
index bab68ac..8456674 100644
--- a/gdk/wayland/meson.build
+++ b/gdk/wayland/meson.build
@@ -54,7 +54,8 @@ proto_sources = [
['xdg-shell', 'unstable', 'v6', ],
['xdg-foreign', 'unstable', 'v1', ],
['tablet', 'unstable', 'v2', ],
- [ 'keyboard-shortcuts-inhibit', 'unstable', 'v1', ],
+ ['keyboard-shortcuts-inhibit', 'unstable', 'v1', ],
+ ['server-decoration', 'stable' ],
]
gdk_wayland_gen_headers = []
diff --git a/gdk/wayland/protocol/server-decoration.xml b/gdk/wayland/protocol/server-decoration.xml
new file mode 100644
index 0000000..8bc106c
--- /dev/null
+++ b/gdk/wayland/protocol/server-decoration.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="server_decoration">
+ <copyright><![CDATA[
+ Copyright (C) 2015 Martin Gräßlin
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ ]]></copyright>
+ <interface name="org_kde_kwin_server_decoration_manager" version="1">
+ <description summary="Server side window decoration manager">
+ This interface allows to coordinate whether the server should create
+ a server-side window decoration around a wl_surface representing a
+ shell surface (wl_shell_surface or similar). By announcing support
+ for this interface the server indicates that it supports server
+ side decorations.
+ </description>
+ <request name="create">
+ <description summary="Create a server-side decoration object for a given surface">
+ When a client creates a server-side decoration object it indicates
+ that it supports the protocol. The client is supposed to tell the
+ server whether it wants server-side decorations or will provide
+ client-side decorations.
+
+ If the client does not create a server-side decoration object for
+ a surface the server interprets this as lack of support for this
+ protocol and considers it as client-side decorated. Nevertheless a
+ client-side decorated surface should use this protocol to indicate
+ to the server that it does not want a server-side deco.
+ </description>
+ <arg name="id" type="new_id" interface="org_kde_kwin_server_decoration"/>
+ <arg name="surface" type="object" interface="wl_surface"/>
+ </request>
+ <enum name="mode">
+ <description summary="Possible values to use in request_mode and the event mode."/>
+ <entry name="None" value="0" summary="Undecorated: The surface is not decorated at all, neither
server nor client-side. An example is a popup surface which should not be decorated."/>
+ <entry name="Client" value="1" summary="Client-side decoration: The decoration is part of the
surface and the client."/>
+ <entry name="Server" value="2" summary="Server-side decoration: The server embeds the surface
into a decoration frame."/>
+ </enum>
+ <event name="default_mode">
+ <description summary="The default mode used on the server">
+ This event is emitted directly after binding the interface. It contains
+ the default mode for the decoration. When a new server decoration object
+ is created this new object will be in the default mode until the first
+ request_mode is requested.
+
+ The server may change the default mode at any time.
+ </description>
+ <arg name="mode" type="uint" summary="The default decoration mode applied to newly created server
decorations."/>
+ </event>
+ </interface>
+ <interface name="org_kde_kwin_server_decoration" version="1">
+ <request name="release" type="destructor">
+ <description summary="release the server decoration object"/>
+ </request>
+ <enum name="mode">
+ <description summary="Possible values to use in request_mode and the event mode."/>
+ <entry name="None" value="0" summary="Undecorated: The surface is not decorated at all, neither
server nor client-side. An example is a popup surface which should not be decorated."/>
+ <entry name="Client" value="1" summary="Client-side decoration: The decoration is part of the
surface and the client."/>
+ <entry name="Server" value="2" summary="Server-side decoration: The server embeds the surface
into a decoration frame."/>
+ </enum>
+ <request name="request_mode">
+ <description summary="The decoration mode the surface wants to use."/>
+ <arg name="mode" type="uint" summary="The mode this surface wants to use."/>
+ </request>
+ <event name="mode">
+ <description summary="The new decoration mode applied by the server">
+ This event is emitted directly after the decoration is created and
+ represents the base decoration policy by the server. E.g. a server
+ which wants all surfaces to be client-side decorated will send Client,
+ a server which wants server-side decoration will send Server.
+
+ The client can request a different mode through the decoration request.
+ The server will acknowledge this by another event with the same mode. So
+ even if a server prefers server-side decoration it's possible to force a
+ client-side decoration.
+
+ The server may emit this event at any time. In this case the client can
+ again request a different mode. It's the responsibility of the server to
+ prevent a feedback loop.
+ </description>
+ <arg name="mode" type="uint" summary="The decoration mode applied to the surface by the server."/>
+ </event>
+ </interface>
+</protocol>
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 1e87600..68de62e 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -6047,7 +6047,10 @@ gtk_window_should_use_csd (GtkWindow *window)
#ifdef GDK_WINDOWING_WAYLAND
if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (GTK_WIDGET (window))))
- return TRUE;
+ {
+ GdkDisplay *gdk_display = gtk_widget_get_display (GTK_WIDGET (window));
+ return !gdk_wayland_display_prefers_ssd (gdk_display);
+ }
#endif
#ifdef GDK_WINDOWING_MIR
@@ -6894,6 +6897,11 @@ gtk_window_realize (GtkWidget *widget)
if (!priv->decorated || priv->client_decorated)
gdk_window_set_decorations (gdk_window, 0);
+#ifdef GDK_WINDOWING_WAYLAND
+ if (priv->client_decorated && GDK_IS_WAYLAND_WINDOW (gdk_window))
+ gdk_wayland_window_announce_csd (gdk_window);
+#endif
+
if (!priv->deletable)
gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]