Compare commits

..

No commits in common. "main" and "v0.4.0" have entirely different histories.
main ... v0.4.0

7 changed files with 61 additions and 124 deletions

View file

@ -7,35 +7,8 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Install Nix
uses: nixbuild/nix-quick-install-action@v31
with:
nix_conf: |
keep-env-derivations = true
keep-outputs = true
- name: Restore and save Nix store
uses: nix-community/cache-nix-action@v6
with:
# restore and save a cache using this key
primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }}
# if there's no cache hit, restore a cache by this prefix
restore-prefixes-first-match: nix-${{ runner.os }}-
# collect garbage until the Nix store size (in bytes) is at most this number
# before trying to save a new cache
# 1G = 1073741824
gc-max-store-size-linux: 1G
# do purge caches
purge: true
# purge all versions of the cache
purge-prefixes: nix-${{ runner.os }}-
# created more than this number of seconds ago
purge-created: 0
# or, last accessed more than this number of seconds ago
# relative to the start of the `Post Restore and save Nix store` phase
purge-last-accessed: 0
# except any version with the key that is the same as the `primary-key`
purge-primary-key: never
- uses: cachix/install-nix-action@v25
- uses: DeterminateSystems/magic-nix-cache-action@main
# not needed (yet)
# - uses: cachix/cachix-action@v12

View file

@ -1,12 +1,11 @@
cmake_minimum_required(VERSION 3.19)
file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW)
string(STRIP ${VER_RAW} VERSION)
set(VERSION 0.4.0)
project(
hyprwayland-scanner
DESCRIPTION "A hyprland version of wayland-scanner in and for C++"
VERSION ${VERSION})
project(hyprwayland-scanner
DESCRIPTION "A hyprland version of wayland-scanner in and for C++"
VERSION ${VERSION}
)
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
@ -16,17 +15,18 @@ set(PREFIX ${CMAKE_INSTALL_PREFIX})
set(CMAKE_MESSAGE_LOG_LEVEL "STATUS")
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
message(STATUS "Configuring hyprwayland-scanner in Debug with CMake")
add_compile_definitions(HYPRLAND_DEBUG)
message(STATUS "Configuring hyprwayland-scanner in Debug with CMake")
add_compile_definitions(HYPRLAND_DEBUG)
else()
add_compile_options(-O3)
message(STATUS "Configuring hyprwayland-scanner in Release with CMake")
add_compile_options(-O3)
message(STATUS "Configuring hyprwayland-scanner in Release with CMake")
endif()
# configure
set(CMAKE_CXX_STANDARD 23)
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value
-Wno-missing-field-initializers -Wno-narrowing)
-Wno-missing-field-initializers -Wno-narrowing)
add_compile_definitions(SCANNER_VERSION="${VERSION}")
@ -41,29 +41,25 @@ pkg_check_modules(deps REQUIRED IMPORTED_TARGET pugixml)
file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
add_executable(hyprwayland-scanner ${SRCFILES})
find_library(librt rt)
if("${librt}" MATCHES "librt-NOTFOUND")
unset(LIBRT)
else()
set(LIBRT rt)
endif()
target_link_libraries(hyprwayland-scanner PRIVATE ${LIBRT} Threads::Threads
PkgConfig::deps)
target_link_libraries(hyprwayland-scanner PRIVATE rt Threads::Threads PkgConfig::deps)
configure_package_config_file(
hyprwayland-scanner-config.cmake.in hyprwayland-scanner-config.cmake
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/hyprwayland-scanner"
PATH_VARS CMAKE_INSTALL_BINDIR)
hyprwayland-scanner-config.cmake.in
hyprwayland-scanner-config.cmake
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/hyprwayland-scanner"
PATH_VARS CMAKE_INSTALL_BINDIR
)
write_basic_package_version_file(
"hyprwayland-scanner-config-version.cmake"
VERSION "${VERSION}"
ARCH_INDEPENDENT
COMPATIBILITY AnyNewerVersion)
"hyprwayland-scanner-config-version.cmake"
VERSION "${VERSION}"
COMPATIBILITY AnyNewerVersion
)
# Installation
install(TARGETS hyprwayland-scanner)
install(FILES ${CMAKE_BINARY_DIR}/hyprwayland-scanner.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
install(FILES ${CMAKE_BINARY_DIR}/hyprwayland-scanner-config.cmake
${CMAKE_BINARY_DIR}/hyprwayland-scanner-config-version.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/hyprwayland-scanner)
install(FILES ${CMAKE_BINARY_DIR}/hyprwayland-scanner.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
install(FILES
${CMAKE_BINARY_DIR}/hyprwayland-scanner-config.cmake
${CMAKE_BINARY_DIR}/hyprwayland-scanner-config-version.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/hyprwayland-scanner
)

View file

@ -1,20 +1,12 @@
# hyprwayland-scanner
A Hyprland implementation of wayland-scanner, in and for C++.
hw-s automatically generates properly RAII-ready, modern C++ bindings for Wayland protocols, for
either servers or clients.
## Usage
```sh
hyprwayland-scanner '/path/to/proto' '/path/to/output/directory'
```
### Options
- `--client` -> generate client code
- `--wayland-enums` -> use wayland enum naming (snake instead of camel)
## Dependencies
Requires a compiler with C++23 support.

View file

@ -1 +0,0 @@
0.4.5

6
flake.lock generated
View file

@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1748929857,
"narHash": "sha256-lcZQ8RhsmhsK8u7LIFsJhsLh/pzR9yZ8yqpTzyGdj+Q=",
"lastModified": 1717974879,
"narHash": "sha256-GTO3C88+5DX171F/gVS3Qga/hOs/eRMxPFpiHq2t+D8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "c2a03962b8e24e669fb37b7df10e7c79531ff1a4",
"rev": "c7b821ba2e1e635ba5a76d299af62821cbcb09f3",
"type": "github"
},
"original": {

View file

@ -29,15 +29,13 @@
(builtins.substring 4 2 longDate)
(builtins.substring 6 2 longDate)
]);
version = lib.removeSuffix "\n" (builtins.readFile ./VERSION);
in {
overlays = {
default = self.overlays.hyprwayland-scanner;
hyprwayland-scanner = final: prev: {
hyprwayland-scanner = final.callPackage ./nix/default.nix {
stdenv = final.gcc15Stdenv;
version = version + "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty");
stdenv = final.gcc13Stdenv;
version = "0.1.0" + "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty");
};
};
};

View file

@ -47,10 +47,6 @@ struct {
std::vector<SEnum> enums;
} XMLDATA;
const char* resourceName() {
return clientCode ? "wl_proxy" : "wl_resource";
}
std::string sanitize(const std::string& in) {
if (in == "namespace")
return "namespace_";
@ -111,16 +107,11 @@ std::string WPTypeToCType(const SRequestArgument& arg, bool event /* events pass
return "uint32_t";
// enum
if (!arg.enumName.empty()) {
if (!arg.enumName.empty())
for (auto& e : XMLDATA.enums) {
if (e.nameOriginal == arg.enumName)
return e.name;
}
return "uint32_t";
}
if (!event && clientCode && arg.wlType == "new_id")
return "wl_proxy*";
// iface
if (!arg.interface.empty() && event) {
@ -128,7 +119,7 @@ std::string WPTypeToCType(const SRequestArgument& arg, bool event /* events pass
if (i.name == arg.interface)
return camelize((clientCode ? "CC_" : "C_") + arg.interface + "*");
}
return std::string{resourceName()} + "*";
return "wl_resource*";
}
return "uint32_t";
@ -140,7 +131,7 @@ std::string WPTypeToCType(const SRequestArgument& arg, bool event /* events pass
return camelize((clientCode ? "CC_" : "C_") + arg.interface + "*");
}
}
return std::string{resourceName()} + "*";
return "wl_resource*";
}
if (arg.wlType == "int" || arg.wlType == "fd")
return "int32_t";
@ -245,8 +236,7 @@ void parseXML(pugi::xml_document& doc) {
void parseHeader() {
// add some boilerplate
HEADER +=
std::format(R"#(#pragma once
HEADER += std::format(R"#(#pragma once
#include <functional>
#include <cstdint>
@ -258,7 +248,8 @@ void parseHeader() {
{}
)#",
(clientCode ? "#include <wayland-client.h>" : "#include <wayland-server.h>"), (clientCode ? "struct wl_proxy;" : "struct wl_client;\nstruct wl_resource;"));
(clientCode ? "#include <wayland-client.h>" : "#include <wayland-server.h>"),
(clientCode ? "struct wl_proxy;\ntypedef wl_proxy wl_resource;" : "struct wl_client;\nstruct wl_resource;"));
// parse all enums
if (!waylandEnums) {
@ -328,7 +319,7 @@ class {} {{
~{}();
)#",
IFACE_CLASS_NAME_CAMEL, IFACE_CLASS_NAME_CAMEL, (clientCode ? "wl_proxy*" : "wl_client* client, uint32_t version, uint32_t id"), IFACE_CLASS_NAME_CAMEL);
IFACE_CLASS_NAME_CAMEL, IFACE_CLASS_NAME_CAMEL, (clientCode ? "wl_resource*" : "wl_client* client, uint32_t version, uint32_t id"), IFACE_CLASS_NAME_CAMEL);
if (!clientCode) {
HEADER += std::format(R"#(
@ -386,12 +377,7 @@ class {} {{
}}
// get the raw wl_resource (wl_proxy) ptr
wl_proxy* resource() {{
return pResource;
}}
// get the raw wl_proxy ptr
wl_proxy* proxy() {{
wl_resource* resource() {{
return pResource;
}}
@ -502,7 +488,7 @@ class {} {{
IFACE_CLASS_NAME_CAMEL, IFACE_CLASS_NAME_CAMEL);
} else {
HEADER += R"#(
wl_proxy* pResource = nullptr;
wl_resource* pResource = nullptr;
bool destroyed = false;
@ -516,8 +502,6 @@ class {} {{
}
void parseSource() {
std::string DUMMY_TYPE_TABLE_NAME = PROTO_DATA.name + "_dummyTypes";
SOURCE += std::format(R"#(#define private public
#define HYPRWAYLAND_SCANNER_NO_INTERFACES
#include "{}.hpp"
@ -529,9 +513,9 @@ void parseSource() {
// reference interfaces
// dummy
SOURCE += std::format(R"#(
static const wl_interface* {}[] = {{ nullptr }};
)#", DUMMY_TYPE_TABLE_NAME);
SOURCE += R"#(
static const wl_interface* dummyTypes[] = { nullptr };
)#";
SOURCE += R"#(
// Reference all other interfaces.
@ -663,10 +647,6 @@ static const void* {}[] = {{
SOURCE += std::format(" (void*){},\n", REQUEST_NAME);
}
if ((clientCode ? iface.events : iface.requests).empty()) {
SOURCE += " nullptr,\n";
}
SOURCE += "};\n";
// create events
@ -690,8 +670,8 @@ static const void* {}[] = {{
std::string argsN = ", ";
for (auto& arg : ev.args) {
if (arg.newType)
argsN += "nullptr, ";
else if (!WPTypeToCType(arg, true).starts_with("C"))
continue;
if (!WPTypeToCType(arg, true).starts_with("C"))
argsN += arg.name + ", ";
else
argsN += (arg.name + " ? " + arg.name + "->pResource : nullptr, ");
@ -718,12 +698,12 @@ void {}::{}({}) {{
if (!pResource)
return{};{}
auto proxy = wl_proxy_marshal_flags(pResource, {}, {}, wl_proxy_get_version(pResource), {}{});{}
auto proxy = wl_proxy_marshal_flags((wl_proxy*)pResource, {}, {}, wl_proxy_get_version((wl_proxy*)pResource), {}{}{});{}
}}
)#",
ptrRetType, IFACE_CLASS_NAME_CAMEL, EVENT_NAME, argsC, (ev.newIdType.empty() ? "" : " nullptr"),
(ev.destructor ? "\n destroyed = true;" : ""), evid, (ev.newIdType.empty() ? "nullptr" : "&" + ev.newIdType + "_interface"), flags, argsN,
(ev.newIdType.empty() ? "\n proxy;" : "\n\n return proxy;"));
(ev.destructor ? "\n destroyed = true;" : ""), evid, (ev.newIdType.empty() ? "nullptr" : "&" + ev.newIdType + "_interface"), flags,
(!ev.newIdType.empty() ? ", nullptr" : ""), argsN, (ev.newIdType.empty() ? "\n proxy;" : "\n\n return proxy;"));
}
evid++;
@ -824,8 +804,7 @@ static const wl_message {}[] = {{
// create type table
const auto TYPE_TABLE_NAME = camelize(std::string{"_"} + "C_" + IFACE_NAME + "_" + rq.name + "_types");
SOURCE += std::format(" {{ .name = \"{}\", .signature = \"{}\", .types = {}}},\n", rq.name, argsToShort(rq.args, rq.since),
rq.args.empty() ? std::format("{} + 0", DUMMY_TYPE_TABLE_NAME) : TYPE_TABLE_NAME + " + 0");
SOURCE += std::format(" {{ \"{}\", \"{}\", {}}},\n", rq.name, argsToShort(rq.args, rq.since), rq.args.empty() ? "dummyTypes + 0" : TYPE_TABLE_NAME + " + 0");
}
SOURCE += "};\n";
@ -840,8 +819,7 @@ static const wl_message {}[] = {{
// create type table
const auto TYPE_TABLE_NAME = camelize(std::string{"_"} + "C_" + IFACE_NAME + "_" + ev.name + "_types");
SOURCE += std::format(" {{ .name = \"{}\", .signature = \"{}\", .types = {}}},\n", ev.name, argsToShort(ev.args, ev.since),
ev.args.empty() ? std::format("{} + 0", DUMMY_TYPE_TABLE_NAME) : TYPE_TABLE_NAME + " + 0");
SOURCE += std::format(" {{ \"{}\", \"{}\", {}}},\n", ev.name, argsToShort(ev.args, ev.since), ev.args.empty() ? "dummyTypes + 0" : TYPE_TABLE_NAME + " + 0");
}
SOURCE += "};\n";
@ -850,9 +828,9 @@ static const wl_message {}[] = {{
// iface
SOURCE += std::format(R"#(
const wl_interface {} = {{
.name = "{}", .version = {},
.method_count = {}, .methods = {},
.event_count = {}, .events = {},
"{}", {},
{}, {},
{}, {},
}};
)#",
IFACE_WL_NAME, iface.name, iface.version, iface.requests.size(), (iface.requests.size() > 0 ? MESSAGE_NAME_REQUESTS : "nullptr"),
@ -862,8 +840,8 @@ const wl_interface {} = {{
// protocol body
if (!clientCode) {
SOURCE += std::format(R"#(
{}::{}(wl_client* client, uint32_t version, uint32_t id) :
pResource(wl_resource_create(client, &{}, version, id)) {{
{}::{}(wl_client* client, uint32_t version, uint32_t id) {{
pResource = wl_resource_create(client, &{}, version, id);
if (!pResource)
return;
@ -920,7 +898,8 @@ void {}::onDestroyCalled() {{
DTOR_FUNC = "wl_proxy_destroy(pResource)";
SOURCE += std::format(R"#(
{}::{}(wl_proxy* resource) : pResource(resource) {{
{}::{}(wl_resource* resource) {{
pResource = resource;
if (!pResource)
return;
@ -1066,4 +1045,4 @@ int main(int argc, char** argv, char** envp) {
}
return 0;
}
}