Skip to content

wayland client-side decorations #4068

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jul 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,14 @@ jobs:
libxxf86vm-dev \
libdrm-dev \
libgbm-dev\
libpulse-dev
libpulse-dev \
libpango1.0-dev
sudo apt install meson
git clone --depth 1 https://gitlab.gnome.org/jadahl/libdecor.git --branch 0.1.0
cd libdecor
meson build --buildtype release -Ddemo=false -Ddbus=disabled
ninja -C build
sudo meson install -C build
- uses: actions/checkout@v2
- name: Configure CMake
run: cmake -B build ${{ matrix.platform.flags }}
Expand Down
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ set_option(CLOCK_GETTIME "Use clock_gettime() instead of gettimeofday()" O
set_option(VIDEO_X11 "Use X11 video driver" ${UNIX_SYS})
set_option(VIDEO_WAYLAND "Use Wayland video driver" ${UNIX_SYS})
dep_option(WAYLAND_SHARED "Dynamically load Wayland support" ON "VIDEO_WAYLAND" OFF)
dep_option(WAYLAND_LIBDECOR "Use client-side window decorations on Wayland" ON "VIDEO_WAYLAND" ON)
dep_option(VIDEO_WAYLAND_QT_TOUCH "QtWayland server support for Wayland video driver" ON "VIDEO_WAYLAND" OFF)
set_option(VIDEO_RPI "Use Raspberry Pi video driver" ${UNIX_SYS})
dep_option(X11_SHARED "Dynamically load X11 support" ON "VIDEO_X11" OFF)
Expand Down Expand Up @@ -2593,6 +2594,9 @@ if(SDL_SHARED)
set_property(TARGET SDL2 APPEND_STRING PROPERTY COMPILE_FLAGS "-fobjc-arc")
target_compile_definitions(SDL2 PRIVATE IOS_DYLIB=1)
endif()
if(WAYLAND_LIBDECOR)
target_include_directories(SDL2 PRIVATE "${libdecor_INCLUDE_DIRS}")
endif()
endif()

if(ANDROID)
Expand Down Expand Up @@ -2644,6 +2648,10 @@ if(SDL_STATIC)
if(IOS OR TVOS)
set_property(TARGET SDL2-static APPEND_STRING PROPERTY COMPILE_FLAGS "-fobjc-arc")
endif()
if(WAYLAND_LIBDECOR)
target_include_directories(SDL2-static PRIVATE "${libdecor_INCLUDE_DIRS}")
target_link_libraries(SDL2-static "${libdecor_LIBRARIES}")
endif()
endif()

##### Tests #####
Expand Down
9 changes: 9 additions & 0 deletions cmake/sdlchecks.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,15 @@ macro(CheckWayland)
set(EXTRA_LIBS ${WAYLAND_LIBRARIES} ${EXTRA_LIBS})
endif()

if(WAYLAND_LIBDECOR)
pkg_check_modules(libdecor REQUIRED libdecor-0)

FindLibraryAndSONAME(decor-0)
set(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR "\"${DECOR_0_LIB_SONAME}\"")

add_definitions(-DHAVE_LIBDECOR_H)
endif()

set(SDL_VIDEO_DRIVER_WAYLAND 1)
endif()
endif()
Expand Down
38 changes: 38 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2766,6 +2766,43 @@ CheckFcitx()
fi
}

dnl See if libdecor is available
CheckLibDecor()
{
AC_ARG_ENABLE(libdecor,
[AS_HELP_STRING([--enable-libdecor], [use libdecor for Wayland client-side decorations [default=yes]])],
, enable_libdecor=yes)
if test x$enable_libdecor = xyes; then
AC_MSG_CHECKING(for libdecor support)
AS_IF([$PKG_CONFIG --exists libdecor-0],
[video_libdecor=yes],
[video_libdecor=no])
AC_MSG_RESULT($video_libdecor)
if test x$video_libdecor = xyes; then
EXTRA_CFLAGS="$EXTRA_CFLAGS `$PKG_CONFIG --cflags libdecor-0`"
AC_DEFINE(HAVE_LIBDECOR_H, 1, [ ])

AC_ARG_ENABLE(libdecor-shared,
[AS_HELP_STRING([--enable-libdecor-shared], [dynamically load libdecor [default=yes]])],
, enable_libdecor_shared=yes)

decor_lib=[`find_lib "libdecor-0.so.*" "" | sed 's/.*\/\(.*\)/\1/; q'`]

if test x$have_loadso != xyes && \
test x$enable_libdecor_shared = xyes; then
AC_MSG_WARN([You must have SDL_LoadObject() support for dynamic libdecor loading])
fi
if test x$have_loadso = xyes && \
test x$enable_libdecor_shared = xyes && test x$decor_lib != x; then
echo "-- dynamic libdecor -> $decor_lib"
AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR, "$decor_lib", [ ])
else
EXTRA_LDFLAGS="$EXTRA_LDFLAGS `$PKG_CONFIG --libs libdecor-0`"
fi
fi
fi
}

dnl Check to see if GameController framework support is desired
CheckJoystickMFI()
{
Expand Down Expand Up @@ -3561,6 +3598,7 @@ case "$host" in
CheckInotify
CheckIBus
CheckFcitx
CheckLibDecor
case $ARCH in
linux)
CheckInputKD
Expand Down
1 change: 1 addition & 0 deletions include/SDL_config.h.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@
#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL@
#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR@
#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON@
#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR@

#cmakedefine SDL_VIDEO_DRIVER_X11 @SDL_VIDEO_DRIVER_X11@
#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC @SDL_VIDEO_DRIVER_X11_DYNAMIC@
Expand Down
2 changes: 2 additions & 0 deletions include/SDL_config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@
#undef HAVE_IMMINTRIN_H
#undef HAVE_LIBUDEV_H
#undef HAVE_LIBSAMPLERATE_H
#undef HAVE_LIBDECOR_H

#undef HAVE_DDRAW_H
#undef HAVE_DINPUT_H
Expand Down Expand Up @@ -365,6 +366,7 @@
#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL
#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR
#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON
#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR
#undef SDL_VIDEO_DRIVER_X11
#undef SDL_VIDEO_DRIVER_RPI
#undef SDL_VIDEO_DRIVER_KMSDRM
Expand Down
6 changes: 5 additions & 1 deletion src/video/wayland/SDL_waylanddyn.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,16 @@ typedef struct
#ifndef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON
#define SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON NULL
#endif
#ifndef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR
#define SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR NULL
#endif

static waylanddynlib waylandlibs[] = {
{NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC},
{NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL},
{NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR},
{NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON}
{NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON},
{NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR}
};

static void *
Expand Down
48 changes: 48 additions & 0 deletions src/video/wayland/SDL_waylanddyn.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,19 @@ struct wl_display;
struct wl_surface;
struct wl_shm;

/* We also need some for libdecor */
struct wl_seat;
struct wl_output;
struct libdecor;
struct libdecor_frame;
struct libdecor_state;
struct libdecor_configuration;
struct libdecor_interface;
struct libdecor_frame_interface;
enum libdecor_resize_edge;
enum libdecor_capabilities;
enum libdecor_window_state;

#include <stdint.h>
#include "wayland-cursor.h"
#include "wayland-util.h"
Expand Down Expand Up @@ -82,6 +95,8 @@ void SDL_WAYLAND_UnloadSymbols(void);
#define wl_proxy_add_listener (*WAYLAND_wl_proxy_add_listener)
#define wl_proxy_marshal_constructor (*WAYLAND_wl_proxy_marshal_constructor)
#define wl_proxy_marshal_constructor_versioned (*WAYLAND_wl_proxy_marshal_constructor_versioned)
#define wl_proxy_set_tag (*WAYLAND_wl_proxy_set_tag)
#define wl_proxy_get_tag (*WAYLAND_wl_proxy_get_tag)

#define wl_seat_interface (*WAYLAND_wl_seat_interface)
#define wl_surface_interface (*WAYLAND_wl_surface_interface)
Expand All @@ -101,6 +116,39 @@ void SDL_WAYLAND_UnloadSymbols(void);
#define wl_data_source_interface (*WAYLAND_wl_data_source_interface)
#define wl_data_device_manager_interface (*WAYLAND_wl_data_device_manager_interface)

#ifdef HAVE_LIBDECOR_H
/* Must be included before our defines */
#include <libdecor.h>

#define libdecor_unref (*WAYLAND_libdecor_unref)
#define libdecor_new (*WAYLAND_libdecor_new)
#define libdecor_decorate (*WAYLAND_libdecor_decorate)
#define libdecor_frame_unref (*WAYLAND_libdecor_frame_unref)
#define libdecor_frame_set_title (*WAYLAND_libdecor_frame_set_title)
#define libdecor_frame_set_app_id (*WAYLAND_libdecor_frame_set_app_id)
#define libdecor_frame_set_max_content_size (*WAYLAND_libdecor_frame_set_max_content_size)
#define libdecor_frame_set_min_content_size (*WAYLAND_libdecor_frame_set_min_content_size)
#define libdecor_frame_resize (*WAYLAND_libdecor_frame_resize)
#define libdecor_frame_move (*WAYLAND_libdecor_frame_move)
#define libdecor_frame_commit (*WAYLAND_libdecor_frame_commit)
#define libdecor_frame_set_minimized (*WAYLAND_libdecor_frame_set_minimized)
#define libdecor_frame_set_maximized (*WAYLAND_libdecor_frame_set_maximized)
#define libdecor_frame_unset_maximized (*WAYLAND_libdecor_frame_unset_maximized)
#define libdecor_frame_set_fullscreen (*WAYLAND_libdecor_frame_set_fullscreen)
#define libdecor_frame_unset_fullscreen (*WAYLAND_libdecor_frame_unset_fullscreen)
#define libdecor_frame_set_capabilities (*WAYLAND_libdecor_frame_set_capabilities)
#define libdecor_frame_unset_capabilities (*WAYLAND_libdecor_frame_unset_capabilities)
#define libdecor_frame_has_capability (*WAYLAND_libdecor_frame_has_capability)
#define libdecor_frame_set_visibility (*WAYLAND_libdecor_frame_set_visibility)
#define libdecor_frame_is_visible (*WAYLAND_libdecor_frame_is_visible)
#define libdecor_frame_is_floating (*WAYLAND_libdecor_frame_is_floating)
#define libdecor_frame_map (*WAYLAND_libdecor_frame_map)
#define libdecor_state_new (*WAYLAND_libdecor_state_new)
#define libdecor_state_free (*WAYLAND_libdecor_state_free)
#define libdecor_configuration_get_content_size (*WAYLAND_libdecor_configuration_get_content_size)
#define libdecor_configuration_get_window_state (*WAYLAND_libdecor_configuration_get_window_state)
#endif

#endif /* SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC */

#include "wayland-client-protocol.h"
Expand Down
40 changes: 40 additions & 0 deletions src/video/wayland/SDL_waylandevents.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
#include "xdg-shell-unstable-v6-client-protocol.h"
#include "keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h"

#ifdef HAVE_LIBDECOR_H
#include <libdecor.h>
#endif

#ifdef SDL_INPUT_LINUXEV
#include <linux/input.h>
#else
Expand Down Expand Up @@ -272,6 +276,11 @@ pointer_handle_enter(void *data, struct wl_pointer *pointer,
return;
}

/* check that this surface belongs to one of the SDL windows */
if (!SDL_WAYLAND_own_surface(surface)) {
return;
}

/* This handler will be called twice in Wayland 1.4
* Once for the window surface which has valid user data
* and again for the mouse cursor surface which does not have valid user data
Expand Down Expand Up @@ -301,6 +310,10 @@ pointer_handle_leave(void *data, struct wl_pointer *pointer,
{
struct SDL_WaylandInput *input = data;

if (!surface || !SDL_WAYLAND_own_surface(surface)) {
return;
}

if (input->pointer_focus) {
SDL_SetMouseFocus(NULL);
input->pointer_focus = NULL;
Expand Down Expand Up @@ -328,8 +341,20 @@ ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
WL_SHELL_SURFACE_RESIZE_*), but the values are the same. */
const uint32_t *directions_zxdg = directions_wl;

#ifdef HAVE_LIBDECOR_H
/* ditto for libdecor. */
const uint32_t *directions_libdecor = directions_wl;
#endif

switch (rc) {
case SDL_HITTEST_DRAGGABLE:
#ifdef HAVE_LIBDECOR_H
if (input->display->shell.libdecor) {
if (window_data->shell_surface.libdecor.frame) {
libdecor_frame_move(window_data->shell_surface.libdecor.frame, input->seat, serial);
}
} else
#endif
if (input->display->shell.xdg) {
if (window_data->shell_surface.xdg.roleobj.toplevel) {
xdg_toplevel_move(window_data->shell_surface.xdg.roleobj.toplevel,
Expand Down Expand Up @@ -357,6 +382,13 @@ ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
case SDL_HITTEST_RESIZE_BOTTOM:
case SDL_HITTEST_RESIZE_BOTTOMLEFT:
case SDL_HITTEST_RESIZE_LEFT:
#ifdef HAVE_LIBDECOR_H
if (input->display->shell.libdecor) {
if (window_data->shell_surface.libdecor.frame) {
libdecor_frame_resize(window_data->shell_surface.libdecor.frame, input->seat, serial, directions_libdecor[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
}
} else
#endif
if (input->display->shell.xdg) {
if (window_data->shell_surface.xdg.roleobj.toplevel) {
xdg_toplevel_resize(window_data->shell_surface.xdg.roleobj.toplevel,
Expand Down Expand Up @@ -723,6 +755,10 @@ keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
return;
}

if (!SDL_WAYLAND_own_surface(surface)) {
return;
}

window = wl_surface_get_user_data(surface);

if (window) {
Expand All @@ -741,6 +777,10 @@ keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
{
struct SDL_WaylandInput *input = data;

if (!surface || !SDL_WAYLAND_own_surface(surface)) {
return;
}

/* Stop key repeat before clearing keyboard focus */
keyboard_repeat_clear(&input->keyboard_repeat);

Expand Down
58 changes: 58 additions & 0 deletions src/video/wayland/SDL_waylandsym.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
#define SDL_WAYLAND_INTERFACE(iface)
#endif

#include <stdbool.h>

SDL_WAYLAND_MODULE(WAYLAND_CLIENT)
SDL_WAYLAND_SYM(void, wl_proxy_marshal, (struct wl_proxy *, uint32_t, ...))
SDL_WAYLAND_SYM(struct wl_proxy *, wl_proxy_create, (struct wl_proxy *, const struct wl_interface *))
Expand Down Expand Up @@ -71,6 +73,10 @@ SDL_WAYLAND_SYM(struct wl_proxy *, wl_proxy_marshal_constructor, (struct wl_prox
SDL_WAYLAND_MODULE(WAYLAND_CLIENT_1_10)
SDL_WAYLAND_SYM(struct wl_proxy *, wl_proxy_marshal_constructor_versioned, (struct wl_proxy *proxy, uint32_t opcode, const struct wl_interface *interface, uint32_t version, ...))

SDL_WAYLAND_MODULE(WAYLAND_CLIENT_1_18)
SDL_WAYLAND_SYM(void, wl_proxy_set_tag, (struct wl_proxy *, const char * const *))
SDL_WAYLAND_SYM(const char * const *, wl_proxy_get_tag, (struct wl_proxy *))

SDL_WAYLAND_INTERFACE(wl_seat_interface)
SDL_WAYLAND_INTERFACE(wl_surface_interface)
SDL_WAYLAND_INTERFACE(wl_shm_pool_interface)
Expand Down Expand Up @@ -134,6 +140,58 @@ SDL_WAYLAND_SYM(int, xkb_keymap_key_get_syms_by_level, (struct xkb_keymap *,
const xkb_keysym_t **) )
SDL_WAYLAND_SYM(uint32_t, xkb_keysym_to_utf32, (xkb_keysym_t) )

#ifdef HAVE_LIBDECOR_H
SDL_WAYLAND_MODULE(WAYLAND_LIBDECOR)
SDL_WAYLAND_SYM(void, libdecor_unref, (struct libdecor *))
SDL_WAYLAND_SYM(struct libdecor *, libdecor_new, (struct wl_display *, struct libdecor_interface *))
SDL_WAYLAND_SYM(struct libdecor_frame *, libdecor_decorate, (struct libdecor *,\
struct wl_surface *,\
struct libdecor_frame_interface *,\
void *))
SDL_WAYLAND_SYM(void, libdecor_frame_unref, (struct libdecor_frame *))
SDL_WAYLAND_SYM(void, libdecor_frame_set_title, (struct libdecor_frame *, const char *))
SDL_WAYLAND_SYM(void, libdecor_frame_set_app_id, (struct libdecor_frame *, const char *))
SDL_WAYLAND_SYM(void, libdecor_frame_set_max_content_size, (struct libdecor_frame *frame,\
int content_width,\
int content_height))
SDL_WAYLAND_SYM(void, libdecor_frame_set_min_content_size, (struct libdecor_frame *frame,\
int content_width,\
int content_height))
SDL_WAYLAND_SYM(void, libdecor_frame_resize, (struct libdecor_frame *,\
struct wl_seat *,\
uint32_t,\
enum libdecor_resize_edge))
SDL_WAYLAND_SYM(void, libdecor_frame_move, (struct libdecor_frame *,\
struct wl_seat *,\
uint32_t))
SDL_WAYLAND_SYM(void, libdecor_frame_commit, (struct libdecor_frame *,\
struct libdecor_state *,\
struct libdecor_configuration *))
SDL_WAYLAND_SYM(void, libdecor_frame_set_minimized, (struct libdecor_frame *))
SDL_WAYLAND_SYM(void, libdecor_frame_set_maximized, (struct libdecor_frame *))
SDL_WAYLAND_SYM(void, libdecor_frame_unset_maximized, (struct libdecor_frame *))
SDL_WAYLAND_SYM(void, libdecor_frame_set_fullscreen, (struct libdecor_frame *, struct wl_output *))
SDL_WAYLAND_SYM(void, libdecor_frame_unset_fullscreen, (struct libdecor_frame *))
SDL_WAYLAND_SYM(void, libdecor_frame_set_capabilities, (struct libdecor_frame *, \
enum libdecor_capabilities))
SDL_WAYLAND_SYM(void, libdecor_frame_unset_capabilities, (struct libdecor_frame *, \
enum libdecor_capabilities))
SDL_WAYLAND_SYM(bool, libdecor_frame_has_capability, (struct libdecor_frame *, \
enum libdecor_capabilities))
SDL_WAYLAND_SYM(void, libdecor_frame_set_visibility, (struct libdecor_frame *, bool))
SDL_WAYLAND_SYM(bool, libdecor_frame_is_visible, (struct libdecor_frame *))
SDL_WAYLAND_SYM(bool, libdecor_frame_is_floating, (struct libdecor_frame *))
SDL_WAYLAND_SYM(void, libdecor_frame_map, (struct libdecor_frame *))
SDL_WAYLAND_SYM(struct libdecor_state *, libdecor_state_new, (int, int))
SDL_WAYLAND_SYM(void, libdecor_state_free, (struct libdecor_state *))
SDL_WAYLAND_SYM(bool, libdecor_configuration_get_content_size, (struct libdecor_configuration *,\
struct libdecor_frame *,\
int *,\
int *))
SDL_WAYLAND_SYM(bool, libdecor_configuration_get_window_state, (struct libdecor_configuration *,\
enum libdecor_window_state *))
#endif

#undef SDL_WAYLAND_MODULE
#undef SDL_WAYLAND_SYM
#undef SDL_WAYLAND_INTERFACE
Expand Down
Loading