Skip to content

Commit

Permalink
wayland: client-side decoration
Browse files Browse the repository at this point in the history
  • Loading branch information
christianrauch authored and slouken committed Jul 25, 2021
1 parent f4f9c6b commit 9e6fcbe
Show file tree
Hide file tree
Showing 13 changed files with 499 additions and 7 deletions.
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 @@ -2777,6 +2777,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 @@ -3572,6 +3609,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
44 changes: 44 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,35 @@ 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_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
53 changes: 53 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,53 @@ 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(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

0 comments on commit 9e6fcbe

Please sign in to comment.