mirror of
https://github.com/hyprwm/hyprwayland-scanner.git
synced 2024-12-23 20:19:48 +01:00
client-code: initial work
This commit is contained in:
parent
1419520d5f
commit
f58b7bb49e
1 changed files with 173 additions and 76 deletions
155
src/main.cpp
155
src/main.cpp
|
@ -9,6 +9,7 @@
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
bool waylandEnums = false;
|
bool waylandEnums = false;
|
||||||
|
bool clientCode = false;
|
||||||
|
|
||||||
struct SRequestArgument {
|
struct SRequestArgument {
|
||||||
std::string wlType;
|
std::string wlType;
|
||||||
|
@ -18,21 +19,17 @@ struct SRequestArgument {
|
||||||
bool allowNull = false;
|
bool allowNull = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SRequest {
|
struct SWaylandFunction {
|
||||||
std::vector<SRequestArgument> args;
|
|
||||||
std::string name;
|
|
||||||
std::string since;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SEvent {
|
|
||||||
std::vector<SRequestArgument> args;
|
std::vector<SRequestArgument> args;
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string since;
|
std::string since;
|
||||||
|
std::string newIdType = ""; // client only
|
||||||
|
bool destructor = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SInterface {
|
struct SInterface {
|
||||||
std::vector<SRequest> requests;
|
std::vector<SWaylandFunction> requests;
|
||||||
std::vector<SEvent> events;
|
std::vector<SWaylandFunction> events;
|
||||||
std::string name;
|
std::string name;
|
||||||
int version = 1;
|
int version = 1;
|
||||||
};
|
};
|
||||||
|
@ -187,12 +184,18 @@ void parseXML(pugi::xml_document& doc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& rq : iface.children("request")) {
|
for (auto& rq : iface.children("request")) {
|
||||||
SRequest srq;
|
SWaylandFunction srq;
|
||||||
srq.name = rq.attribute("name").as_string();
|
srq.name = rq.attribute("name").as_string();
|
||||||
srq.since = rq.attribute("since").as_string();
|
srq.since = rq.attribute("since").as_string();
|
||||||
|
srq.destructor = rq.attribute("type").as_string() == std::string{"destructor"};
|
||||||
|
|
||||||
for (auto& arg : rq.children("arg")) {
|
for (auto& arg : rq.children("arg")) {
|
||||||
SRequestArgument sargm;
|
SRequestArgument sargm;
|
||||||
|
if (arg.attribute("type").as_string() == std::string{"new_id"} && clientCode) {
|
||||||
|
srq.newIdType = arg.attribute("interface").as_string();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
sargm.name = sanitize(arg.attribute("name").as_string());
|
sargm.name = sanitize(arg.attribute("name").as_string());
|
||||||
sargm.wlType = arg.attribute("type").as_string();
|
sargm.wlType = arg.attribute("type").as_string();
|
||||||
sargm.interface = arg.attribute("interface").as_string();
|
sargm.interface = arg.attribute("interface").as_string();
|
||||||
|
@ -206,9 +209,10 @@ void parseXML(pugi::xml_document& doc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& ev : iface.children("event")) {
|
for (auto& ev : iface.children("event")) {
|
||||||
SEvent sev;
|
SWaylandFunction sev;
|
||||||
sev.name = ev.attribute("name").as_string();
|
sev.name = ev.attribute("name").as_string();
|
||||||
sev.since = ev.attribute("since").as_string();
|
sev.since = ev.attribute("since").as_string();
|
||||||
|
sev.destructor = ev.attribute("type").as_string() == std::string{"destructor"};
|
||||||
|
|
||||||
for (auto& arg : ev.children("arg")) {
|
for (auto& arg : ev.children("arg")) {
|
||||||
SRequestArgument sargm;
|
SRequestArgument sargm;
|
||||||
|
@ -231,19 +235,20 @@ void parseXML(pugi::xml_document& doc) {
|
||||||
void parseHeader() {
|
void parseHeader() {
|
||||||
|
|
||||||
// add some boilerplate
|
// add some boilerplate
|
||||||
HEADER += R"#(#pragma once
|
HEADER += std::format(R"#(#pragma once
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <wayland-server.h>
|
{}
|
||||||
|
|
||||||
#define F std::function
|
#define F std::function
|
||||||
|
|
||||||
struct wl_client;
|
{}
|
||||||
struct 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
|
// parse all enums
|
||||||
if (!waylandEnums) {
|
if (!waylandEnums) {
|
||||||
|
@ -294,12 +299,18 @@ struct wl_resource;
|
||||||
const auto IFACE_CLASS_NAME_CAMEL = camelize("C_" + iface.name);
|
const auto IFACE_CLASS_NAME_CAMEL = camelize("C_" + iface.name);
|
||||||
|
|
||||||
// begin the class
|
// begin the class
|
||||||
HEADER += std::format(R"#(
|
HEADER +=
|
||||||
|
std::format(R"#(
|
||||||
class {} {{
|
class {} {{
|
||||||
public:
|
public:
|
||||||
{}(wl_client* client, uint32_t version, uint32_t id);
|
{}({});
|
||||||
~{}();
|
~{}();
|
||||||
|
|
||||||
|
)#",
|
||||||
|
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"#(
|
||||||
// set a listener for when this resource is _being_ destroyed
|
// set a listener for when this resource is _being_ destroyed
|
||||||
void setOnDestroy(F<void({}*)> handler) {{
|
void setOnDestroy(F<void({}*)> handler) {{
|
||||||
onDestroy = handler;
|
onDestroy = handler;
|
||||||
|
@ -339,14 +350,36 @@ class {} {{
|
||||||
int version() {{
|
int version() {{
|
||||||
return wl_resource_get_version(pResource);
|
return wl_resource_get_version(pResource);
|
||||||
}}
|
}}
|
||||||
|
|
||||||
)#",
|
)#",
|
||||||
IFACE_CLASS_NAME_CAMEL, IFACE_CLASS_NAME_CAMEL, IFACE_CLASS_NAME_CAMEL, IFACE_CLASS_NAME_CAMEL);
|
IFACE_CLASS_NAME_CAMEL);
|
||||||
|
} else {
|
||||||
|
HEADER += R"#(
|
||||||
|
// set the data for this resource
|
||||||
|
void setData(void* data) {{
|
||||||
|
pData = data;
|
||||||
|
}}
|
||||||
|
|
||||||
|
// get the data for this resource
|
||||||
|
void* data() {{
|
||||||
|
return pData;
|
||||||
|
}}
|
||||||
|
|
||||||
|
// get the raw wl_resource (wl_proxy) ptr
|
||||||
|
wl_resource* resource() {{
|
||||||
|
return pResource;
|
||||||
|
}}
|
||||||
|
|
||||||
|
// get the resource version
|
||||||
|
int version() {{
|
||||||
|
return wl_proxy_get_version(pResource);
|
||||||
|
}}
|
||||||
|
)#";
|
||||||
|
}
|
||||||
|
|
||||||
// add all setters for requests
|
// add all setters for requests
|
||||||
HEADER += "\n // --------------- Requests --------------- //\n\n";
|
HEADER += "\n // --------------- Requests --------------- //\n\n";
|
||||||
|
|
||||||
for (auto& rq : iface.requests) {
|
for (auto& rq : (clientCode ? iface.events : iface.requests)) {
|
||||||
|
|
||||||
std::string args = ", ";
|
std::string args = ", ";
|
||||||
for (auto& arg : rq.args) {
|
for (auto& arg : rq.args) {
|
||||||
|
@ -363,7 +396,7 @@ class {} {{
|
||||||
|
|
||||||
HEADER += "\n // --------------- Events --------------- //\n\n";
|
HEADER += "\n // --------------- Events --------------- //\n\n";
|
||||||
|
|
||||||
for (auto& ev : iface.events) {
|
for (auto& ev : (!clientCode ? iface.events : iface.requests)) {
|
||||||
std::string args = "";
|
std::string args = "";
|
||||||
for (auto& arg : ev.args) {
|
for (auto& arg : ev.args) {
|
||||||
args += WPTypeToCType(arg, true) + ", ";
|
args += WPTypeToCType(arg, true) + ", ";
|
||||||
|
@ -374,11 +407,12 @@ class {} {{
|
||||||
args.pop_back();
|
args.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
HEADER += std::format(" void {}({});\n", camelize("send_" + ev.name), args);
|
HEADER += std::format(" {} {}({});\n", ev.newIdType.empty() ? "void" : camelize("C_" + ev.newIdType) + "*", camelize("send_" + ev.name), args);
|
||||||
}
|
}
|
||||||
|
|
||||||
// dangerous ones
|
// dangerous ones
|
||||||
for (auto& ev : iface.events) {
|
if (!clientCode) {
|
||||||
|
for (auto& ev : (!clientCode ? iface.events : iface.requests)) {
|
||||||
std::string args = "";
|
std::string args = "";
|
||||||
for (auto& arg : ev.args) {
|
for (auto& arg : ev.args) {
|
||||||
args += WPTypeToCType(arg, true, true) + ", ";
|
args += WPTypeToCType(arg, true, true) + ", ";
|
||||||
|
@ -391,6 +425,7 @@ class {} {{
|
||||||
|
|
||||||
HEADER += std::format(" void {}({});\n", camelize("send_" + ev.name + "_raw"), args);
|
HEADER += std::format(" void {}({});\n", camelize("send_" + ev.name + "_raw"), args);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// end events
|
// end events
|
||||||
|
|
||||||
|
@ -400,7 +435,7 @@ class {} {{
|
||||||
// start requests storage
|
// start requests storage
|
||||||
HEADER += " struct {\n";
|
HEADER += " struct {\n";
|
||||||
|
|
||||||
for (auto& rq : iface.requests) {
|
for (auto& rq : (clientCode ? iface.events : iface.requests)) {
|
||||||
|
|
||||||
std::string args = ", ";
|
std::string args = ", ";
|
||||||
for (auto& arg : rq.args) {
|
for (auto& arg : rq.args) {
|
||||||
|
@ -419,6 +454,7 @@ class {} {{
|
||||||
HEADER += " } requests;\n";
|
HEADER += " } requests;\n";
|
||||||
|
|
||||||
// constant resource stuff
|
// constant resource stuff
|
||||||
|
if (!clientCode) {
|
||||||
HEADER += std::format(R"#(
|
HEADER += std::format(R"#(
|
||||||
void onDestroyCalled();
|
void onDestroyCalled();
|
||||||
|
|
||||||
|
@ -430,6 +466,12 @@ class {} {{
|
||||||
|
|
||||||
void* pData = nullptr;)#",
|
void* pData = nullptr;)#",
|
||||||
IFACE_CLASS_NAME_CAMEL);
|
IFACE_CLASS_NAME_CAMEL);
|
||||||
|
} else {
|
||||||
|
HEADER += R"#(
|
||||||
|
wl_resource* pResource = nullptr;
|
||||||
|
|
||||||
|
void* pData = nullptr;)#";
|
||||||
|
}
|
||||||
|
|
||||||
HEADER += "\n};\n\n";
|
HEADER += "\n};\n\n";
|
||||||
}
|
}
|
||||||
|
@ -513,7 +555,7 @@ static const wl_interface* dummyTypes[] = { nullptr };
|
||||||
const auto IFACE_CLASS_NAME_CAMEL = camelize("C_" + iface.name);
|
const auto IFACE_CLASS_NAME_CAMEL = camelize("C_" + iface.name);
|
||||||
|
|
||||||
// create handlers
|
// create handlers
|
||||||
for (auto& rq : iface.requests) {
|
for (auto& rq : (clientCode ? iface.events : iface.requests)) {
|
||||||
const auto REQUEST_NAME = camelize(std::string{"_"} + "C_" + IFACE_NAME + "_" + rq.name);
|
const auto REQUEST_NAME = camelize(std::string{"_"} + "C_" + IFACE_NAME + "_" + rq.name);
|
||||||
|
|
||||||
std::string argsC = ", ";
|
std::string argsC = ", ";
|
||||||
|
@ -534,6 +576,7 @@ static const wl_interface* dummyTypes[] = { nullptr };
|
||||||
argsN.pop_back();
|
argsN.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!clientCode) {
|
||||||
SOURCE += std::format(R"#(
|
SOURCE += std::format(R"#(
|
||||||
static void {}(wl_client* client, wl_resource* resource{}) {{
|
static void {}(wl_client* client, wl_resource* resource{}) {{
|
||||||
const auto PO = ({}*)wl_resource_get_user_data(resource);
|
const auto PO = ({}*)wl_resource_get_user_data(resource);
|
||||||
|
@ -542,9 +585,20 @@ static void {}(wl_client* client, wl_resource* resource{}) {{
|
||||||
}}
|
}}
|
||||||
)#",
|
)#",
|
||||||
REQUEST_NAME, argsC, IFACE_CLASS_NAME_CAMEL, camelize(rq.name), camelize(rq.name), argsN);
|
REQUEST_NAME, argsC, IFACE_CLASS_NAME_CAMEL, camelize(rq.name), camelize(rq.name), argsN);
|
||||||
|
} else {
|
||||||
|
SOURCE += std::format(R"#(
|
||||||
|
static void {}(void* data, void* resource{}) {{
|
||||||
|
const auto PO = ({}*)data;
|
||||||
|
if (PO && PO->requests.{})
|
||||||
|
PO->requests.{}(PO{});
|
||||||
|
}}
|
||||||
|
)#",
|
||||||
|
REQUEST_NAME, argsC, IFACE_CLASS_NAME_CAMEL, camelize(rq.name), camelize(rq.name), argsN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// destroy handler
|
// destroy handler
|
||||||
|
if (!clientCode) {
|
||||||
SOURCE += std::format(R"#(
|
SOURCE += std::format(R"#(
|
||||||
static void _{}__DestroyListener(wl_listener* l, void* d) {{
|
static void _{}__DestroyListener(wl_listener* l, void* d) {{
|
||||||
{}* pResource = wl_container_of(l, pResource, resourceDestroyListener);
|
{}* pResource = wl_container_of(l, pResource, resourceDestroyListener);
|
||||||
|
@ -552,6 +606,7 @@ static void _{}__DestroyListener(wl_listener* l, void* d) {{
|
||||||
}}
|
}}
|
||||||
)#",
|
)#",
|
||||||
IFACE_CLASS_NAME_CAMEL, IFACE_CLASS_NAME_CAMEL);
|
IFACE_CLASS_NAME_CAMEL, IFACE_CLASS_NAME_CAMEL);
|
||||||
|
}
|
||||||
|
|
||||||
// create vtable
|
// create vtable
|
||||||
|
|
||||||
|
@ -562,7 +617,7 @@ static const void* {}[] = {{
|
||||||
)#",
|
)#",
|
||||||
IFACE_VTABLE_NAME);
|
IFACE_VTABLE_NAME);
|
||||||
|
|
||||||
for (auto& rq : iface.requests) {
|
for (auto& rq : (clientCode ? iface.events : iface.requests)) {
|
||||||
const auto REQUEST_NAME = camelize(std::string{"_"} + "C_" + IFACE_NAME + "_" + rq.name);
|
const auto REQUEST_NAME = camelize(std::string{"_"} + "C_" + IFACE_NAME + "_" + rq.name);
|
||||||
SOURCE += std::format(" (void*){},\n", REQUEST_NAME);
|
SOURCE += std::format(" (void*){},\n", REQUEST_NAME);
|
||||||
}
|
}
|
||||||
|
@ -572,7 +627,7 @@ static const void* {}[] = {{
|
||||||
// create events
|
// create events
|
||||||
|
|
||||||
int evid = 0;
|
int evid = 0;
|
||||||
for (auto& ev : iface.events) {
|
for (auto& ev : (!clientCode ? iface.events : iface.requests)) {
|
||||||
const auto EVENT_NAME = camelize("send_" + ev.name);
|
const auto EVENT_NAME = camelize("send_" + ev.name);
|
||||||
|
|
||||||
std::string argsC = "";
|
std::string argsC = "";
|
||||||
|
@ -596,6 +651,7 @@ static const void* {}[] = {{
|
||||||
argsN.pop_back();
|
argsN.pop_back();
|
||||||
argsN.pop_back();
|
argsN.pop_back();
|
||||||
|
|
||||||
|
if (!clientCode) {
|
||||||
SOURCE += std::format(R"#(
|
SOURCE += std::format(R"#(
|
||||||
void {}::{}({}) {{
|
void {}::{}({}) {{
|
||||||
if (!pResource)
|
if (!pResource)
|
||||||
|
@ -604,11 +660,27 @@ void {}::{}({}) {{
|
||||||
}}
|
}}
|
||||||
)#",
|
)#",
|
||||||
IFACE_CLASS_NAME_CAMEL, EVENT_NAME, argsC, evid, argsN);
|
IFACE_CLASS_NAME_CAMEL, EVENT_NAME, argsC, evid, argsN);
|
||||||
|
} else {
|
||||||
|
std::string ptrRetType = ev.newIdType.empty() ? "void" : camelize("C_" + ev.newIdType) + "*";
|
||||||
|
std::string flags = ev.destructor ? "1" : "0";
|
||||||
|
SOURCE += std::format(R"#(
|
||||||
|
{} {}::{}({}) {{
|
||||||
|
if (!pResource)
|
||||||
|
return{};
|
||||||
|
|
||||||
|
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"), evid,
|
||||||
|
(ev.newIdType.empty() ? "nullptr" : "&" + ev.newIdType + "_interface"), flags, (!ev.newIdType.empty() ? ", nullptr" : ""), argsN,
|
||||||
|
(ev.newIdType.empty() ? "" : "\n\n return (" + ptrRetType + ")wl_proxy_get_user_data(proxy);"));
|
||||||
|
}
|
||||||
|
|
||||||
evid++;
|
evid++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// dangerous
|
// dangerous
|
||||||
|
if (!clientCode) {
|
||||||
evid = 0;
|
evid = 0;
|
||||||
for (auto& ev : iface.events) {
|
for (auto& ev : iface.events) {
|
||||||
const auto EVENT_NAME = camelize("send_" + ev.name + "_raw");
|
const auto EVENT_NAME = camelize("send_" + ev.name + "_raw");
|
||||||
|
@ -642,6 +714,7 @@ void {}::{}({}) {{
|
||||||
|
|
||||||
evid++;
|
evid++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// wayland interfaces and stuff
|
// wayland interfaces and stuff
|
||||||
|
|
||||||
|
@ -729,6 +802,7 @@ const wl_interface {} = {{
|
||||||
(iface.events.size() > 0 ? MESSAGE_NAME_EVENTS : "nullptr"));
|
(iface.events.size() > 0 ? MESSAGE_NAME_EVENTS : "nullptr"));
|
||||||
|
|
||||||
// protocol body
|
// protocol body
|
||||||
|
if (!clientCode) {
|
||||||
SOURCE += std::format(R"#(
|
SOURCE += std::format(R"#(
|
||||||
{}::{}(wl_client* client, uint32_t version, uint32_t id) {{
|
{}::{}(wl_client* client, uint32_t version, uint32_t id) {{
|
||||||
pResource = wl_resource_create(client, &{}, version, id);
|
pResource = wl_resource_create(client, &{}, version, id);
|
||||||
|
@ -772,8 +846,26 @@ void {}::onDestroyCalled() {{
|
||||||
)#",
|
)#",
|
||||||
IFACE_CLASS_NAME_CAMEL, IFACE_CLASS_NAME_CAMEL, IFACE_NAME + "_interface", IFACE_CLASS_NAME_CAMEL, IFACE_VTABLE_NAME, IFACE_CLASS_NAME_CAMEL,
|
IFACE_CLASS_NAME_CAMEL, IFACE_CLASS_NAME_CAMEL, IFACE_NAME + "_interface", IFACE_CLASS_NAME_CAMEL, IFACE_VTABLE_NAME, IFACE_CLASS_NAME_CAMEL,
|
||||||
IFACE_CLASS_NAME_CAMEL, IFACE_CLASS_NAME_CAMEL);
|
IFACE_CLASS_NAME_CAMEL, IFACE_CLASS_NAME_CAMEL);
|
||||||
|
} else {
|
||||||
|
SOURCE += std::format(R"#(
|
||||||
|
{}::{}(wl_resource* resource) {{
|
||||||
|
pResource = resource;
|
||||||
|
|
||||||
for (auto& rq : iface.requests) {
|
if (!pResource)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wl_proxy_set_user_data(pResource, this);
|
||||||
|
wl_proxy_add_listener(pResource, (void (**)(void))&{}, this);
|
||||||
|
}}
|
||||||
|
|
||||||
|
{}::~{}() {{
|
||||||
|
;
|
||||||
|
}}
|
||||||
|
)#",
|
||||||
|
IFACE_CLASS_NAME_CAMEL, IFACE_CLASS_NAME_CAMEL, IFACE_VTABLE_NAME, IFACE_CLASS_NAME_CAMEL, IFACE_CLASS_NAME_CAMEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& rq : (clientCode ? iface.events : iface.requests)) {
|
||||||
std::string args = ", ";
|
std::string args = ", ";
|
||||||
for (auto& arg : rq.args) {
|
for (auto& arg : rq.args) {
|
||||||
args += WPTypeToCType(arg, false) + ", ";
|
args += WPTypeToCType(arg, false) + ", ";
|
||||||
|
@ -808,6 +900,11 @@ int main(int argc, char** argv, char** envp) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (curarg == "-c" || curarg == "--client") {
|
||||||
|
clientCode = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (curarg == "--wayland-enums") {
|
if (curarg == "--wayland-enums") {
|
||||||
waylandEnums = true;
|
waylandEnums = true;
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Reference in a new issue