forked from AuroraMiddleware/gtk
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
This commit is contained in:
parent
028e39d6ee
commit
1b279e3d4a
@ -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
|
||||
@ -336,6 +337,35 @@ static const struct wl_shm_listener wl_shm_listener = {
|
||||
wl_shm_format
|
||||
};
|
||||
|
||||
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,
|
||||
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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__ */
|
||||
|
@ -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__ */
|
||||
|
@ -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,
|
||||
|
@ -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 = []
|
||||
|
94
gdk/wayland/protocol/server-decoration.xml
Normal file
94
gdk/wayland/protocol/server-decoration.xml
Normal file
@ -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>
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user