Skip to content

Commit

Permalink
Wayland: Add support for xdg-decoration
Browse files Browse the repository at this point in the history
This allows compositors which prefer to draw the decorations around
clients to do so, rather than letting GLFW draw its own decorations.
The appearance is thus entirely subject to the compositor used, but
should generally be better than the current solid colour decorations we
have, which we continue to use when the compositor doesn’t support this
protocol or tells us to draw the decorations ourselves.

This new protocol has been tested against wlroots’s rootston compositor.

Fixes glfw#1257.
  • Loading branch information
linkmauve committed Oct 1, 2018
1 parent 3e884ae commit dcd2a19
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ script:
sudo dpkg -i extra-cmake-modules_5.38.0a-0ubuntu1_amd64.deb;
git clone git://anongit.freedesktop.org/wayland/wayland-protocols;
pushd wayland-protocols;
git checkout 1.12 && ./autogen.sh --prefix=/usr && make && sudo make install;
git checkout 1.15 && ./autogen.sh --prefix=/usr && make && sudo make install;
popd;
fi
- cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} -DGLFW_USE_WAYLAND=${USE_WAYLAND} ..
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ if (_GLFW_WAYLAND)

find_package(Wayland REQUIRED Client Cursor Egl)
find_package(WaylandScanner REQUIRED)
find_package(WaylandProtocols 1.12 REQUIRED)
find_package(WaylandProtocols 1.15 REQUIRED)

list(APPEND glfw_PKG_DEPS "wayland-egl")

Expand Down
4 changes: 4 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ elseif (_GLFW_WAYLAND)
PROTOCOL
"${WAYLAND_PROTOCOLS_PKGDATADIR}/stable/xdg-shell/xdg-shell.xml"
BASENAME xdg-shell)
ecm_add_wayland_client_protocol(glfw_SOURCES
PROTOCOL
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
BASENAME xdg-decoration)
ecm_add_wayland_client_protocol(glfw_SOURCES
PROTOCOL
"${WAYLAND_PROTOCOLS_PKGDATADIR}/stable/viewporter/viewporter.xml"
Expand Down
9 changes: 9 additions & 0 deletions src/wl_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,13 @@ static void registryHandleGlobal(void* data,
wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
xdg_wm_base_add_listener(_glfw.wl.wmBase, &wmBaseListener, NULL);
}
else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0)
{
_glfw.wl.decorationManager =
wl_registry_bind(registry, name,
&zxdg_decoration_manager_v1_interface,
1);
}
else if (strcmp(interface, "wp_viewporter") == 0)
{
_glfw.wl.viewporter =
Expand Down Expand Up @@ -1138,6 +1145,8 @@ void _glfwPlatformTerminate(void)
wl_shell_destroy(_glfw.wl.shell);
if (_glfw.wl.viewporter)
wp_viewporter_destroy(_glfw.wl.viewporter);
if (_glfw.wl.decorationManager)
zxdg_decoration_manager_v1_destroy(_glfw.wl.decorationManager);
if (_glfw.wl.wmBase)
xdg_wm_base_destroy(_glfw.wl.wmBase);
if (_glfw.wl.pointer)
Expand Down
4 changes: 4 additions & 0 deletions src/wl_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
#include "osmesa_context.h"

#include "wayland-xdg-shell-client-protocol.h"
#include "wayland-xdg-decoration-client-protocol.h"
#include "wayland-viewporter-client-protocol.h"
#include "wayland-relative-pointer-unstable-v1-client-protocol.h"
#include "wayland-pointer-constraints-unstable-v1-client-protocol.h"
Expand Down Expand Up @@ -185,6 +186,7 @@ typedef struct _GLFWwindowWayland
struct {
struct xdg_surface* surface;
struct xdg_toplevel* toplevel;
struct zxdg_toplevel_decoration_v1* decoration;
} xdg;

_GLFWcursor* currentCursor;
Expand All @@ -210,6 +212,7 @@ typedef struct _GLFWwindowWayland
GLFWbool justCreated;

struct {
GLFWbool serverSide;
struct wl_buffer* buffer;
_GLFWdecorationWayland top, left, right, bottom;
int focus;
Expand All @@ -231,6 +234,7 @@ typedef struct _GLFWlibraryWayland
struct wl_pointer* pointer;
struct wl_keyboard* keyboard;
struct xdg_wm_base* wmBase;
struct zxdg_decoration_manager_v1* decorationManager;
struct wp_viewporter* viewporter;
struct zwp_relative_pointer_manager_v1* relativePointerManager;
struct zwp_pointer_constraints_v1* pointerConstraints;
Expand Down
56 changes: 49 additions & 7 deletions src/wl_window.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ static void createDecorations(_GLFWwindow* window)
const GLFWimage image = { 1, 1, data };
GLFWbool opaque = (data[3] == 255);

if (!_glfw.wl.viewporter)
if (!_glfw.wl.viewporter || !window->decorated || window->wl.decorations.serverSide)
return;

if (!window->wl.decorations.buffer)
Expand Down Expand Up @@ -321,6 +321,22 @@ static void destroyDecorations(_GLFWwindow* window)
destroyDecoration(&window->wl.decorations.bottom);
}

static void xdgDecorationHandleConfigure(void* data,
struct zxdg_toplevel_decoration_v1* decoration,
uint32_t mode)
{
_GLFWwindow* window = data;

window->wl.decorations.serverSide = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);

if (!window->wl.decorations.serverSide)
createDecorations(window);
}

static const struct zxdg_toplevel_decoration_v1_listener xdgDecorationListener = {
xdgDecorationHandleConfigure,
};

// Makes the surface considered as XRGB instead of ARGB.
static void setOpaqueRegion(_GLFWwindow* window)
{
Expand Down Expand Up @@ -493,9 +509,6 @@ static GLFWbool createSurface(_GLFWwindow* window,
if (!window->wl.transparent)
setOpaqueRegion(window);

if (window->decorated && !window->monitor)
createDecorations(window);

return GLFW_TRUE;
}

Expand All @@ -517,7 +530,8 @@ static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor,
monitor->wl.output);
}
setIdleInhibitor(window, GLFW_TRUE);
destroyDecorations(window);
if (!window->wl.decorations.serverSide)
destroyDecorations(window);
}

static GLFWbool createShellSurface(_GLFWwindow* window)
Expand Down Expand Up @@ -553,11 +567,13 @@ static GLFWbool createShellSurface(_GLFWwindow* window)
{
wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);
setIdleInhibitor(window, GLFW_FALSE);
createDecorations(window);
}
else
{
wl_shell_surface_set_toplevel(window->wl.shellSurface);
setIdleInhibitor(window, GLFW_FALSE);
createDecorations(window);
}

wl_surface_commit(window->wl.surface);
Expand Down Expand Up @@ -646,6 +662,27 @@ static const struct xdg_surface_listener xdgSurfaceListener = {
xdgSurfaceHandleConfigure
};

static void setXdgDecorations(_GLFWwindow* window)
{
if (_glfw.wl.decorationManager)
{
window->wl.xdg.decoration =
zxdg_decoration_manager_v1_get_toplevel_decoration(
_glfw.wl.decorationManager, window->wl.xdg.toplevel);
zxdg_toplevel_decoration_v1_add_listener(window->wl.xdg.decoration,
&xdgDecorationListener,
window);
zxdg_toplevel_decoration_v1_set_mode(
window->wl.xdg.decoration,
ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
}
else
{
window->wl.decorations.serverSide = GLFW_FALSE;
createDecorations(window);
}
}

static GLFWbool createXdgSurface(_GLFWwindow* window)
{
window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase,
Expand Down Expand Up @@ -693,10 +730,12 @@ static GLFWbool createXdgSurface(_GLFWwindow* window)
{
xdg_toplevel_set_maximized(window->wl.xdg.toplevel);
setIdleInhibitor(window, GLFW_FALSE);
setXdgDecorations(window);
}
else
{
setIdleInhibitor(window, GLFW_FALSE);
setXdgDecorations(window);
}

wl_surface_commit(window->wl.surface);
Expand Down Expand Up @@ -946,6 +985,9 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
window->context.destroy(window);

destroyDecorations(window);
if (window->wl.xdg.decoration)
zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration);

if (window->wl.decorations.buffer)
wl_buffer_destroy(window->wl.decorations.buffer);

Expand Down Expand Up @@ -1061,7 +1103,7 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
int* left, int* top,
int* right, int* bottom)
{
if (window->decorated && !window->monitor)
if (window->decorated && !window->monitor && !window->wl.decorations.serverSide)
{
if (top)
*top = _GLFW_DECORATION_TOP;
Expand Down Expand Up @@ -1190,7 +1232,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
else if (window->wl.shellSurface)
wl_shell_surface_set_toplevel(window->wl.shellSurface);
setIdleInhibitor(window, GLFW_FALSE);
if (window->decorated)
if (!_glfw.wl.decorationManager)
createDecorations(window);
}
_glfwInputWindowMonitor(window, monitor);
Expand Down

0 comments on commit dcd2a19

Please sign in to comment.