diff options
| author | Drew DeVault <sir@cmpwn.com> | 2017-04-29 00:35:51 (GMT) |
|---|---|---|
| committer | Matthias Clasen <mclasen@redhat.com> | 2017-10-26 20:34:42 (GMT) |
| commit | f2adaba237519642b88ccb42b47a95cf539a2a12 (patch) | |
| tree | c443fdc2af882fb5792b22238043cc56a2a58b9f | |
| parent | 30e72154066842dc68d02a030aeeb562d8d9ee4f (diff) | |
| download | gtk+-f2adaba23.zip gtk+-f2adaba23.tar.xz | |
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
| -rw-r--r-- | gdk/wayland/Makefile.am | 2 | ||||
| -rw-r--r-- | gdk/wayland/gdkdisplay-wayland.c | 39 | ||||
| -rw-r--r-- | gdk/wayland/gdkdisplay-wayland.h | 4 | ||||
| -rw-r--r-- | gdk/wayland/gdkwaylanddisplay.h | 3 | ||||
| -rw-r--r-- | gdk/wayland/gdkwaylandwindow.h | 3 | ||||
| -rw-r--r-- | gdk/wayland/gdkwindow-wayland.c | 16 | ||||
| -rw-r--r-- | gdk/wayland/protocol/server-decoration.xml | 94 | ||||
| -rw-r--r-- | gtk/gtkwindow.c | 10 |
8 files changed, 170 insertions, 1 deletions
diff --git a/gdk/wayland/Makefile.am b/gdk/wayland/Makefile.am index dbaae63..9295b1a 100644 --- a/gdk/wayland/Makefile.am +++ b/gdk/wayland/Makefile.am @@ -33,6 +33,8 @@ BUILT_SOURCES = \ tablet-unstable-v2-protocol.c \ keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h \ keyboard-shortcuts-inhibit-unstable-v1-protocol.c \ + server-decoration-client-protocol.h \ + server-decoration-protocol.c \ gtk-shell-client-protocol.h \ gtk-shell-protocol.c diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index 3814157..8bcd675 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -46,6 +46,7 @@ #include "tablet-unstable-v2-client-protocol.h" #include "xdg-shell-unstable-v6-client-protocol.h" #include "xdg-foreign-unstable-v1-client-protocol.h" +#include "server-decoration-client-protocol.h" /** * SECTION:wayland_interaction @@ -334,6 +335,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, @@ -456,6 +486,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 d24a48e..9b15557 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..d980d6c 100644 --- a/gdk/wayland/gdkwaylanddisplay.h +++ b/gdk/wayland/gdkwaylanddisplay.h @@ -57,6 +57,9 @@ GDK_AVAILABLE_IN_3_22 void gdk_wayland_display_set_startup_notification_id (GdkDisplay *display, const char *startup_id); +GDK_AVAILABLE_IN_3_22 +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 566d405..93b7802 100644 --- a/gdk/wayland/gdkwaylandwindow.h +++ b/gdk/wayland/gdkwaylandwindow.h @@ -77,6 +77,9 @@ GDK_AVAILABLE_IN_3_22 gboolean gdk_wayland_window_set_transient_for_exported (GdkWindow *window, char *parent_handle_str); +GDK_AVAILABLE_IN_3_22 +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 66c19e0..4b3fc93 100644 --- a/gdk/wayland/gdkwindow-wayland.c +++ b/gdk/wayland/gdkwindow-wayland.c @@ -126,6 +126,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; @@ -1681,6 +1682,21 @@ window_anchor_to_gravity (GdkGravity rect_anchor) } } +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/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 a4ba098..33f81d2 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -6100,7 +6100,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 @@ -7477,6 +7480,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); |