139 lines
4.8 KiB
C
139 lines
4.8 KiB
C
|
// Copyright 2021 The ChromiumOS Authors
|
||
|
// Use of this source code is governed by a BSD-style license that can be
|
||
|
// found in the LICENSE file.
|
||
|
|
||
|
#ifndef VM_TOOLS_SOMMELIER_SOMMELIER_UTIL_H_
|
||
|
#define VM_TOOLS_SOMMELIER_SOMMELIER_UTIL_H_
|
||
|
|
||
|
#include <assert.h>
|
||
|
#include <cerrno>
|
||
|
#include <cstdio>
|
||
|
#include <cstring>
|
||
|
#include <memory>
|
||
|
|
||
|
#include <wayland-server.h>
|
||
|
|
||
|
#define errno_assert(rv) \
|
||
|
{ \
|
||
|
int macro_private_assert_value = (rv); \
|
||
|
if (!macro_private_assert_value) { \
|
||
|
fprintf(stderr, "Unexpected error: %s\n", strerror(errno)); \
|
||
|
assert(false); \
|
||
|
} \
|
||
|
}
|
||
|
|
||
|
#define UNUSED(x) ((void)(x))
|
||
|
|
||
|
// Performs an asprintf operation and checks the result for validity and calls
|
||
|
// abort() if there's a failure. Returns a newly allocated string rather than
|
||
|
// taking a double pointer argument like asprintf.
|
||
|
__attribute__((__format__(__printf__, 1, 0))) char* sl_xasprintf(
|
||
|
const char* fmt, ...);
|
||
|
|
||
|
#define DEFAULT_DELETER_FDECL(TypeName) \
|
||
|
namespace std { \
|
||
|
template <> \
|
||
|
struct default_delete<TypeName> { \
|
||
|
void operator()(TypeName* ptr); \
|
||
|
}; \
|
||
|
}
|
||
|
|
||
|
DEFAULT_DELETER_FDECL(struct wl_event_source);
|
||
|
|
||
|
// Maps wl_ to sl_ types, e.g. WlToSl<wl_seat>::type == sl_host_seat.
|
||
|
template <typename WaylandType>
|
||
|
struct WlToSl;
|
||
|
|
||
|
#define MAP_STRUCTS(WlType, SlType) \
|
||
|
template <> \
|
||
|
struct WlToSl<WlType> { \
|
||
|
using type = SlType; \
|
||
|
};
|
||
|
|
||
|
// Convert a request argument of type InArg to type OutArg. InArg is the type
|
||
|
// sommelier receives as a Wayland host. OutArg is the type used passed to the
|
||
|
// real host compositor. For Wayland resources, these will be wl_resource* and
|
||
|
// wl_..* (e.g. wl_surface*) respectively.
|
||
|
template <typename InArg, typename OutArg>
|
||
|
struct ConvertRequestArg {};
|
||
|
|
||
|
template <>
|
||
|
struct ConvertRequestArg<const char*, const char*> {
|
||
|
inline static const char* Convert(const char* arg) { return arg; }
|
||
|
};
|
||
|
template <>
|
||
|
struct ConvertRequestArg<uint32_t, uint32_t> {
|
||
|
inline static uint32_t Convert(uint32_t arg) { return arg; }
|
||
|
};
|
||
|
template <>
|
||
|
struct ConvertRequestArg<int32_t, int32_t> {
|
||
|
inline static int32_t Convert(int32_t arg) { return arg; }
|
||
|
};
|
||
|
|
||
|
template <typename OutArg>
|
||
|
struct ConvertRequestArg<wl_resource*, OutArg*> {
|
||
|
static OutArg* Convert(wl_resource* resource) {
|
||
|
if (!resource)
|
||
|
return nullptr;
|
||
|
using SlType = typename WlToSl<OutArg>::type;
|
||
|
SlType* host = static_cast<SlType*>(wl_resource_get_user_data(resource));
|
||
|
return host ? host->proxy : nullptr;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template <typename T>
|
||
|
inline bool IsNullWlResource(T arg) {
|
||
|
return false;
|
||
|
}
|
||
|
template <>
|
||
|
inline bool IsNullWlResource(wl_resource* resource) {
|
||
|
return resource == nullptr;
|
||
|
}
|
||
|
|
||
|
enum class AllowNullResource {
|
||
|
kNo = 0,
|
||
|
kYes = 1,
|
||
|
};
|
||
|
|
||
|
// Invoke the given wl_ function with each arg converted. This helper struct is
|
||
|
// so we can extract types from the wl_ function into a parameter pack for the
|
||
|
// fold expression and not require them to be explicitly written out.
|
||
|
template <typename... T>
|
||
|
struct ForwardRequestHelper;
|
||
|
template <typename... OutArgs>
|
||
|
struct ForwardRequestHelper<void (*)(OutArgs...)> {
|
||
|
template <auto wl_function, AllowNullResource allow_null, typename... InArgs>
|
||
|
static void Forward(struct wl_client* client, InArgs... args) {
|
||
|
if (allow_null == AllowNullResource::kNo) {
|
||
|
if ((IsNullWlResource<InArgs>(args) || ...)) {
|
||
|
fprintf(stderr, "error: received unexpected null resource in: %s\n",
|
||
|
__PRETTY_FUNCTION__);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
wl_function(ConvertRequestArg<InArgs, OutArgs>::Convert(args)...);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// Wraps the function which dispatches an request to the host for use as
|
||
|
// implementation for sommelier's implementation as a host. If null Wayland
|
||
|
// resources should be allowed, AllowNullResource::kYes should be set,
|
||
|
// otherwise the request will be considered invalid and dropped.
|
||
|
// Example usage:
|
||
|
// - ForwardRequest<wl_shell_surface_move>,
|
||
|
// - ForwardRequest<wl_shell_surface_set_fullscreen, AllowNullResource::kYes>
|
||
|
//
|
||
|
// The first argument (receiving object) is guaranteed by Wayland to be
|
||
|
// non-null but for code simplicity it is handled the same as the request
|
||
|
// arguments, with null being allowed or disallowed based on |allow_null|.
|
||
|
template <auto wl_function,
|
||
|
AllowNullResource allow_null = AllowNullResource::kNo,
|
||
|
typename... InArgs>
|
||
|
void ForwardRequest(InArgs... args) {
|
||
|
ForwardRequestHelper<decltype(wl_function)>::template Forward<wl_function,
|
||
|
allow_null>(
|
||
|
args...);
|
||
|
}
|
||
|
|
||
|
#endif // VM_TOOLS_SOMMELIER_SOMMELIER_UTIL_H_
|