wayland: Port to xdg-shell stable

Wayland compositors and clients are expected to support the xdg-shell
stable protocol over the deprecated wl_shell protocol.
This commit is contained in:
Scott Moreau 2019-01-16 01:16:58 -07:00
parent cd8b82b3fa
commit 203ea178d0
4 changed files with 97 additions and 24 deletions

View file

@ -49,12 +49,28 @@ IF(USE_D2D_WSI)
MESSAGE("Using direct to display extension...")
add_definitions(-D_DIRECT2DISPLAY)
ELSEIF(USE_WAYLAND_WSI)
find_program(PKG_CONFIG pkg-config)
if (NOT PKG_CONFIG)
message(FATAL_ERROR "pkg-config binary not found")
endif ()
find_package(Wayland REQUIRED)
if (NOT WAYLAND_FOUND)
message(FATAL_ERROR "Wayland development package not found")
endif ()
pkg_check_modules(WAYLAND_PROTOCOLS REQUIRED wayland-protocols)
if (NOT WAYLAND_PROTOCOLS_FOUND)
message(FATAL_ERROR "Wayland protocols package not found")
endif ()
find_program(WAYLAND_SCANNER wayland-scanner)
if (NOT WAYLAND_SCANNER)
message(FATAL_ERROR "wayland-scanner binary not found")
endif ()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_USE_PLATFORM_WAYLAND_KHR")
include_directories(${WAYLAND_INCLUDE_DIR})
execute_process(COMMAND ${PKG_CONFIG} --variable=pkgdatadir wayland-protocols OUTPUT_VARIABLE protocol_dir OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND ${WAYLAND_SCANNER} client-header ${protocol_dir}/stable/xdg-shell/xdg-shell.xml xdg-shell-client-protocol.h
COMMAND ${WAYLAND_SCANNER} private-code ${protocol_dir}/stable/xdg-shell/xdg-shell.xml xdg-shell-protocol.c)
include_directories(${CMAKE_BINARY_DIR})
ELSE(USE_D2D_WSI)
find_package(XCB REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_USE_PLATFORM_XCB_KHR")
@ -78,7 +94,7 @@ endif()
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
add_definitions(-std=c++11)
set(CXXFLAGS -std=c++11)
file(GLOB SOURCE *.cpp )

View file

@ -456,6 +456,8 @@ void VulkanExampleBase::renderLoop()
viewChanged();
}
while (!configured)
wl_display_dispatch(display);
while (wl_display_prepare_read(display) != 0)
wl_display_dispatch_pending(display);
wl_display_flush(display);
@ -487,7 +489,7 @@ void VulkanExampleBase::renderLoop()
if (!settings.overlay)
{
std::string windowTitle = getWindowTitle();
wl_shell_surface_set_title(shell_surface, windowTitle.c_str());
xdg_toplevel_set_title(xdg_toplevel, windowTitle.c_str());
}
lastFPS = (float)frameCounter * (1000.0f / fpsTimer);
fpsTimer = 0.0f;
@ -800,14 +802,15 @@ VulkanExampleBase::~VulkanExampleBase()
#if defined(_DIRECT2DISPLAY)
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
wl_shell_surface_destroy(shell_surface);
xdg_toplevel_destroy(xdg_toplevel);
xdg_surface_destroy(xdg_surface);
wl_surface_destroy(surface);
if (keyboard)
wl_keyboard_destroy(keyboard);
if (pointer)
wl_pointer_destroy(pointer);
wl_seat_destroy(seat);
wl_shell_destroy(shell);
xdg_wm_base_destroy(shell);
wl_compositor_destroy(compositor);
wl_registry_destroy(registry);
wl_display_disconnect(display);
@ -1631,6 +1634,15 @@ void VulkanExampleBase::seatCapabilities(wl_seat *seat, uint32_t caps)
}
}
static void xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
{
xdg_wm_base_pong(shell, serial);
}
static const struct xdg_wm_base_listener xdg_wm_base_listener = {
xdg_wm_base_ping,
};
void VulkanExampleBase::registryGlobal(wl_registry *registry, uint32_t name,
const char *interface, uint32_t version)
{
@ -1639,10 +1651,11 @@ void VulkanExampleBase::registryGlobal(wl_registry *registry, uint32_t name,
compositor = (wl_compositor *) wl_registry_bind(registry, name,
&wl_compositor_interface, 3);
}
else if (strcmp(interface, "wl_shell") == 0)
else if (strcmp(interface, "xdg_wm_base") == 0)
{
shell = (wl_shell *) wl_registry_bind(registry, name,
&wl_shell_interface, 1);
shell = (xdg_wm_base *) wl_registry_bind(registry, name,
&xdg_wm_base_interface, 1);
xdg_wm_base_add_listener(shell, &xdg_wm_base_listener, nullptr);
}
else if (strcmp(interface, "wl_seat") == 0)
{
@ -1691,34 +1704,70 @@ void VulkanExampleBase::initWaylandConnection()
}
}
static void PingCb(void *data, struct wl_shell_surface *shell_surface,
void VulkanExampleBase::setSize(int width, int height)
{
if (width <= 0 || height <= 0)
return;
destWidth = width;
destHeight = height;
windowResize();
}
static void
xdg_surface_handle_configure(void *data, struct xdg_surface *surface,
uint32_t serial)
{
wl_shell_surface_pong(shell_surface, serial);
VulkanExampleBase *base = (VulkanExampleBase *) data;
xdg_surface_ack_configure(surface, serial);
base->configured = true;
}
static void ConfigureCb(void *data, struct wl_shell_surface *shell_surface,
uint32_t edges, int32_t width, int32_t height)
static const struct xdg_surface_listener xdg_surface_listener = {
xdg_surface_handle_configure,
};
static void
xdg_toplevel_handle_configure(void *data, struct xdg_toplevel *toplevel,
int32_t width, int32_t height,
struct wl_array *states)
{
VulkanExampleBase *base = (VulkanExampleBase *) data;
base->setSize(width, height);
}
static void PopupDoneCb(void *data, struct wl_shell_surface *shell_surface)
static void
xdg_toplevel_handle_close(void *data, struct xdg_toplevel *xdg_toplevel)
{
VulkanExampleBase *base = (VulkanExampleBase *) data;
base->quit = true;
}
wl_shell_surface *VulkanExampleBase::setupWindow()
static const struct xdg_toplevel_listener xdg_toplevel_listener = {
xdg_toplevel_handle_configure,
xdg_toplevel_handle_close,
};
struct xdg_surface *VulkanExampleBase::setupWindow()
{
surface = wl_compositor_create_surface(compositor);
shell_surface = wl_shell_get_shell_surface(shell, surface);
xdg_surface = xdg_wm_base_get_xdg_surface(shell, surface);
static const struct wl_shell_surface_listener shell_surface_listener =
{ PingCb, ConfigureCb, PopupDoneCb };
xdg_surface_add_listener(xdg_surface, &xdg_surface_listener, this);
xdg_toplevel = xdg_surface_get_toplevel(xdg_surface);
xdg_toplevel_add_listener(xdg_toplevel, &xdg_toplevel_listener, this);
wl_shell_surface_add_listener(shell_surface, &shell_surface_listener, this);
wl_shell_surface_set_toplevel(shell_surface);
std::string windowTitle = getWindowTitle();
wl_shell_surface_set_title(shell_surface, windowTitle.c_str());
return shell_surface;
xdg_toplevel_set_title(xdg_toplevel, windowTitle.c_str());
wl_surface_commit(surface);
return xdg_surface;
}
#elif defined(VK_USE_PLATFORM_XCB_KHR)

View file

@ -22,6 +22,7 @@
#include "VulkanAndroid.h"
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
#include <wayland-client.h>
#include "xdg-shell-client-protocol.h"
#elif defined(_DIRECT2DISPLAY)
//
#elif defined(VK_USE_PLATFORM_XCB_KHR)
@ -227,13 +228,15 @@ public:
wl_display *display = nullptr;
wl_registry *registry = nullptr;
wl_compositor *compositor = nullptr;
wl_shell *shell = nullptr;
struct xdg_wm_base *shell = nullptr;
wl_seat *seat = nullptr;
wl_pointer *pointer = nullptr;
wl_keyboard *keyboard = nullptr;
wl_surface *surface = nullptr;
wl_shell_surface *shell_surface = nullptr;
struct xdg_surface *xdg_surface;
struct xdg_toplevel *xdg_toplevel;
bool quit = false;
bool configured = false;
#elif defined(_DIRECT2DISPLAY)
bool quit = false;
@ -265,8 +268,9 @@ public:
#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
void* setupWindow(void* view);
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
wl_shell_surface *setupWindow();
struct xdg_surface *setupWindow();
void initWaylandConnection();
void setSize(int width, int height);
static void registryGlobalCb(void *data, struct wl_registry *registry,
uint32_t name, const char *interface, uint32_t version);
void registryGlobal(struct wl_registry *registry, uint32_t name,

View file

@ -13,6 +13,10 @@ function(buildExample EXAMPLE_NAME)
file(GLOB ADD_SOURCE "../external/imgui/*.cpp")
SET(SOURCE ${SOURCE} ${ADD_SOURCE})
ENDIF()
# wayland requires additional source files
IF(USE_WAYLAND_WSI)
SET(SOURCE ${SOURCE} ${CMAKE_BINARY_DIR}/xdg-shell-client-protocol.h ${CMAKE_BINARY_DIR}/xdg-shell-protocol.c)
ENDIF()
# Add shaders
set(SHADER_DIR "../data/shaders/${EXAMPLE_NAME}")
file(GLOB SHADERS "${SHADER_DIR}/*.vert" "${SHADER_DIR}/*.frag" "${SHADER_DIR}/*.comp" "${SHADER_DIR}/*.geom" "${SHADER_DIR}/*.tesc" "${SHADER_DIR}/*.tese")