diff --git a/src/wayland/tools/CMakeLists.txt b/src/wayland/tools/CMakeLists.txt
index 3b1aa59469..0a8af1737e 100644
--- a/src/wayland/tools/CMakeLists.txt
+++ b/src/wayland/tools/CMakeLists.txt
@@ -5,6 +5,7 @@ find_package(Qt5Concurrent ${QT_MIN_VERSION} CONFIG QUIET)
if (Qt5Concurrent_FOUND)
set(scannerSRCS generator.cpp)
+ add_definitions(-DMAPPING_FILE="${CMAKE_CURRENT_SOURCE_DIR}/mapping.txt")
add_executable(kwaylandScanner ${scannerSRCS})
target_link_libraries(kwaylandScanner Qt5::Core Qt5::Concurrent)
ecm_mark_as_test(kwaylandScanner)
diff --git a/src/wayland/tools/generator.cpp b/src/wayland/tools/generator.cpp
index 8c639801d8..95ab47e560 100644
--- a/src/wayland/tools/generator.cpp
+++ b/src/wayland/tools/generator.cpp
@@ -29,12 +29,99 @@ License along with this library. If not, see .
#include
#include
#include
+#include
+
+#include
namespace KWayland
{
namespace Tools
{
+static QMap s_clientClassNameMapping;
+
+Argument::Argument()
+{
+}
+
+Argument::Argument(const QXmlStreamAttributes &attributes)
+ : m_name(attributes.value(QStringLiteral("name")).toString())
+ , m_type(parseType(attributes.value(QStringLiteral("type"))))
+ , m_allowNull(attributes.hasAttribute(QStringLiteral("allow-null")))
+ , m_inteface(attributes.value(QStringLiteral("interface")).toString())
+{
+}
+
+Argument::~Argument() = default;
+
+Argument::Type Argument::parseType(const QStringRef &type)
+{
+ if (type.compare(QLatin1String("new_id")) == 0) {
+ return Type::NewId;
+ }
+ if (type.compare(QLatin1String("destructor")) == 0) {
+ return Type::Destructor;
+ }
+ if (type.compare(QLatin1String("object")) == 0) {
+ return Type::Object;
+ }
+ if (type.compare(QLatin1String("fd")) == 0) {
+ return Type::FileDescriptor;
+ }
+ if (type.compare(QLatin1String("fixed")) == 0) {
+ return Type::Fixed;
+ }
+ if (type.compare(QLatin1String("uint")) == 0) {
+ return Type::Uint;
+ }
+ if (type.compare(QLatin1String("int")) == 0) {
+ return Type::Int;
+ }
+ if (type.compare(QLatin1String("string")) == 0) {
+ return Type::String;
+ }
+
+ return Type::Unknown;
+}
+
+Request::Request()
+{
+}
+
+Request::Request(const QString &name)
+ : m_name(name)
+{
+}
+
+Request::~Request() = default;
+
+Event::Event()
+{
+}
+
+Event::Event(const QString &name)
+ : m_name(name)
+{
+}
+
+Event::~Event() = default;
+
+Interface::Interface() = default;
+
+Interface::Interface(const QXmlStreamAttributes &attributes)
+ : m_name(attributes.value(QStringLiteral("name")).toString())
+ , m_version(attributes.value(QStringLiteral("version")).toUInt())
+{
+ auto it = s_clientClassNameMapping.constFind(m_name);
+ if (it != s_clientClassNameMapping.constEnd()) {
+ m_clientName = it.value();
+ } else {
+ qWarning() << "Failed to map " << m_name << " to a KWayland name";
+ }
+}
+
+Interface::~Interface() = default;
+
Generator::Generator(QObject *parent)
: QObject(parent)
{
@@ -47,10 +134,134 @@ void Generator::start()
startAuthorNameProcess();
startAuthorEmailProcess();
+ startParseXml();
+
startGenerateHeaderFile();
startGenerateCppFile();
}
+void Generator::startParseXml()
+{
+ if (m_xmlFileName.isEmpty()) {
+ return;
+ }
+ QFile xmlFile(m_xmlFileName);
+ xmlFile.open(QIODevice::ReadOnly);
+ m_xmlReader.setDevice(&xmlFile);
+ while (!m_xmlReader.atEnd()) {
+ if (!m_xmlReader.readNextStartElement()) {
+ continue;
+ }
+ if (m_xmlReader.qualifiedName().compare(QLatin1String("protocol")) == 0) {
+ parseProtocol();
+ }
+ }
+
+ auto findFactory = [this] (const QString interfaceName) -> Interface* {
+ for (auto it = m_interfaces.begin(); it != m_interfaces.end(); ++it) {
+ if ((*it).name().compare(interfaceName) == 0) {
+ continue;
+ }
+ for (auto r: (*it).requests()) {
+ for (auto a: r.arguments()) {
+ if (a.type() == Argument::Type::NewId && a.interface().compare(interfaceName) == 0) {
+ return &(*it);
+ }
+ }
+ }
+ }
+ return nullptr;
+ };
+ for (auto it = m_interfaces.begin(); it != m_interfaces.end(); ++it) {
+ Interface *factory = findFactory((*it).name());
+ if (factory) {
+ qDebug() << (*it).name() << "gets factored by" << factory->kwaylandClientName();
+ (*it).setFactory(factory);
+ } else {
+ qDebug() << (*it).name() << "considered as a global";
+ (*it).markAsGlobal();
+ }
+ }
+}
+
+void Generator::parseProtocol()
+{
+ const auto attributes = m_xmlReader.attributes();
+ const QString protocolName = attributes.value(QStringLiteral("name")).toString();
+
+ if (m_baseFileName.isEmpty()) {
+ m_baseFileName = protocolName.toLower();
+ }
+
+ while (!m_xmlReader.atEnd()) {
+ if (!m_xmlReader.readNextStartElement()) {
+ if (m_xmlReader.qualifiedName().compare(QLatin1String("protocol")) == 0) {
+ return;
+ }
+ continue;
+ }
+ if (m_xmlReader.qualifiedName().compare(QLatin1String("interface")) == 0) {
+ m_interfaces << parseInterface();
+ }
+ }
+}
+
+Interface Generator::parseInterface()
+{
+ Interface interface(m_xmlReader.attributes());
+ while (!m_xmlReader.atEnd()) {
+ if (!m_xmlReader.readNextStartElement()) {
+ if (m_xmlReader.qualifiedName().compare(QLatin1String("interface")) == 0) {
+ break;
+ }
+ continue;
+ }
+ if (m_xmlReader.qualifiedName().compare(QLatin1String("request")) == 0) {
+ interface.addRequest(parseRequest());
+ }
+ if (m_xmlReader.qualifiedName().compare(QLatin1String("event")) == 0) {
+ interface.addEvent(parseEvent());
+ }
+ }
+ return interface;
+}
+
+Request Generator::parseRequest()
+{
+ const auto attributes = m_xmlReader.attributes();
+ Request request(attributes.value(QStringLiteral("name")).toString());
+ while (!m_xmlReader.atEnd()) {
+ if (!m_xmlReader.readNextStartElement()) {
+ if (m_xmlReader.qualifiedName().compare(QLatin1String("request")) == 0) {
+ break;
+ }
+ continue;
+ }
+ if (m_xmlReader.qualifiedName().compare(QLatin1String("arg")) == 0) {
+ request.addArgument(Argument(m_xmlReader.attributes()));
+ }
+ }
+ return request;
+}
+
+Event Generator::parseEvent()
+{
+ const auto attributes = m_xmlReader.attributes();
+ Event event(attributes.value(QStringLiteral("name")).toString());
+ while (!m_xmlReader.atEnd()) {
+ if (!m_xmlReader.readNextStartElement()) {
+ if (m_xmlReader.qualifiedName().compare(QLatin1String("event")) == 0) {
+ break;
+ }
+ continue;
+ }
+ if (m_xmlReader.qualifiedName().compare(QLatin1String("arg")) == 0) {
+ event.addArgument(Argument(m_xmlReader.attributes()));
+ }
+ }
+ return event;
+}
+
void Generator::startGenerateHeaderFile()
{
QFutureWatcher *watcher = new QFutureWatcher(this);
@@ -66,7 +277,9 @@ void Generator::startGenerateHeaderFile()
generateWaylandForwardDeclarations();
generateStartNamespace();
generateNamespaceForwardDeclarations();
- generateClass();
+ for (auto it = m_interfaces.constBegin(); it != m_interfaces.constEnd(); ++it) {
+ generateClass(*it);
+ }
generateEndNamespace();
generateEndIncludeGuard();
@@ -87,8 +300,10 @@ void Generator::startGenerateCppFile()
generateCopyrightHeader();
generateCppIncludes();
generateStartNamespace();
- generatePrivateClass();
- generateClientCpp();
+ for (auto it = m_interfaces.constBegin(); it != m_interfaces.constEnd(); ++it) {
+ generatePrivateClass(*it);
+ generateClientCpp(*it);
+ }
generateEndNamespace();
@@ -188,7 +403,7 @@ void Generator::generateStartIncludeGuard()
"#ifndef KWAYLAND_%1_%2_H\n"
"#define KWAYLAND_%1_%2_H\n\n");
- *m_stream.localData() << templateString.arg(projectToName().toUpper()).arg(m_className.toUpper());
+ *m_stream.localData() << templateString.arg(projectToName().toUpper()).arg(m_baseFileName.toUpper());
}
void Generator::generateStartNamespace()
@@ -223,7 +438,7 @@ void Generator::generateHeaderIncludes()
void Generator::generateCppIncludes()
{
- *m_stream.localData() << QStringLiteral("#include \"%1.h\"\n").arg(m_className.toLower());
+ *m_stream.localData() << QStringLiteral("#include \"%1.h\"\n").arg(m_baseFileName.toLower());
switch (m_project) {
case Project::Client:
*m_stream.localData() << QStringLiteral("#include \"event_queue.h\"\n\n");
@@ -236,14 +451,15 @@ void Generator::generateCppIncludes()
}
}
-void Generator::generateClass()
+void Generator::generateClass(const Interface &interface)
{
switch (m_project) {
case Project::Client:
- generateClientClassStart();
- generateClientClassCasts();
- generateClientClassSignals();
- generateClientClassEnd();
+ if (interface.isGlobal()) {
+ generateClientGlobalClass(interface);
+ } else {
+ generateClientResourceClass(interface);
+ }
break;
case Project::Server:
// TODO: implement
@@ -253,11 +469,35 @@ void Generator::generateClass()
}
}
-void Generator::generatePrivateClass()
+void Generator::generateClientGlobalClass(const Interface &interface)
+{
+ generateClientGlobalClassDoxy(interface);
+ generateClientClassQObjectDerived(interface);
+ generateClientGlobalClassCtor(interface);
+ generateClientClassDtor(interface);
+ generateClientGlobalClassSetup(interface);
+ generateClientClassReleaseDestroy(interface);
+ generateClientClassStart(interface);
+ generateClientClassCasts(interface);
+ generateClientClassSignals(interface);
+ generateClientGlobalClassEnd(interface);
+}
+
+void Generator::generateClientResourceClass(const Interface &interface)
+{
+ generateClientClassQObjectDerived(interface);
+ generateClientClassDtor(interface);
+ generateClientResourceClassSetup(interface);
+ generateClientClassReleaseDestroy(interface);
+ generateClientClassCasts(interface);
+ generateClientResourceClassEnd(interface);
+}
+
+void Generator::generatePrivateClass(const Interface &interface)
{
switch (m_project) {
case Project::Client:
- generateClientPrivateClass();
+ generateClientPrivateClass(interface);
break;
case Project::Server:
// TODO: implement
@@ -267,7 +507,7 @@ void Generator::generatePrivateClass()
}
}
-void Generator::generateClientPrivateClass()
+void Generator::generateClientPrivateClass(const Interface &interface)
{
const QString templateString = QStringLiteral(
"class %1::Private\n"
@@ -275,14 +515,16 @@ void Generator::generateClientPrivateClass()
"public:\n"
" Private() = default;\n"
"\n"
-" WaylandPointer<%2, %2_destroy> %3;\n"
-" EventQueue *queue = nullptr;\n"
-"};\n\n");
+" WaylandPointer<%2, %2_destroy> %3;\n");
- *m_stream.localData() << templateString.arg(m_className).arg(m_waylandGlobal).arg(m_className.toLower());
+ *m_stream.localData() << templateString.arg(interface.kwaylandClientName()).arg(interface.name()).arg(interface.kwaylandClientName().toLower());
+ if (interface.isGlobal()) {
+ *m_stream.localData() << " EventQueue *queue = nullptr;\n";
+ }
+ *m_stream.localData() << "};\n\n";
}
-void Generator::generateClientCpp()
+void Generator::generateClientCpp(const Interface &interface)
{
const QString templateString = QStringLiteral(
"%1::%1(QObject *parent)\n"
@@ -336,10 +578,12 @@ void Generator::generateClientCpp()
" return d->%2.isValid();\n"
"}\n\n");
- *m_stream.localData() << templateString.arg(m_className).arg(m_className.toLower()).arg(m_waylandGlobal);
+ *m_stream.localData() << templateString.arg(interface.kwaylandClientName())
+ .arg(interface.kwaylandClientName().toLower())
+ .arg(interface.name());
}
-void Generator::generateClientClassStart()
+void Generator::generateClientGlobalClassDoxy(const Interface &interface)
{
const QString templateString = QStringLiteral(
"/**\n"
@@ -364,31 +608,46 @@ void Generator::generateClientClassStart()
" * pointer as it provides matching cast operators.\n"
" *\n"
" * @see Registry\n"
-" **/\n"
-"class KWAYLAND%3_EXPORT %1 : public QObject\n"
+" **/\n");
+ *m_stream.localData() << templateString.arg(interface.kwaylandClientName()).arg(interface.name());
+}
+
+void Generator::generateClientClassQObjectDerived(const Interface &interface)
+{
+ const QString templateString = QStringLiteral(
+"class KWAYLANDCLIENT_EXPORT %1 : public QObject\n"
"{\n"
" Q_OBJECT\n"
-"public:\n"
+"public:\n");
+ *m_stream.localData() << templateString.arg(interface.kwaylandClientName());
+}
+
+void Generator::generateClientGlobalClassCtor(const Interface &interface)
+{
+ const QString templateString = QStringLiteral(
" /**\n"
" * Creates a new %1.\n"
" * Note: after constructing the %1 it is not yet valid and one needs\n"
" * to call setup. In order to get a ready to use %1 prefer using\n"
" * Registry::create%1.\n"
" **/\n"
-" explicit %1(QObject *parent = nullptr);\n"
-" virtual ~%1();\n"
-"\n"
+" explicit %1(QObject *parent = nullptr);\n");
+ *m_stream.localData() << templateString.arg(interface.kwaylandClientName());
+}
+
+void Generator::generateClientClassDtor(const Interface &interface)
+{
+ *m_stream.localData() << QStringLiteral(" virtual ~%1();\n\n").arg(interface.kwaylandClientName());
+}
+
+void Generator::generateClientClassReleaseDestroy(const Interface &interface)
+{
+ const QString templateString = QStringLiteral(
" /**\n"
" * @returns @c true if managing a %2.\n"
" **/\n"
" bool isValid() const;\n"
" /**\n"
-" * Setup this %1 to manage the @p %4.\n"
-" * When using Registry::create%1 there is no need to call this\n"
-" * method.\n"
-" **/\n"
-" void setup(%2 *%4);\n"
-" /**\n"
" * Releases the %2 interface.\n"
" * After the interface has been released the %1 instance is no\n"
" * longer valid and can be setup with another %2 interface.\n"
@@ -405,13 +664,47 @@ void Generator::generateClientClassStart()
" *\n"
" * It is suggested to connect this method to ConnectionThread::connectionDied:\n"
" * @code\n"
-" * connect(connection, &ConnectionThread::connectionDied, %4, &%1::destroy);\n"
+" * connect(connection, &ConnectionThread::connectionDied, %3, &%1::destroy);\n"
" * @endcode\n"
" *\n"
" * @see release\n"
" **/\n"
" void destroy();\n"
-"\n"
+"\n");
+ *m_stream.localData() << templateString.arg(interface.kwaylandClientName()).arg(interface.name()).arg(interface.kwaylandClientName().toLower());
+}
+
+void Generator::generateClientGlobalClassSetup(const Interface &interface)
+{
+ const QString templateString = QStringLiteral(
+" /**\n"
+" * Setup this %1 to manage the @p %3.\n"
+" * When using Registry::create%1 there is no need to call this\n"
+" * method.\n"
+" **/\n"
+" void setup(%2 *%3);\n");
+ *m_stream.localData() << templateString.arg(interface.kwaylandClientName()).arg(interface.name()).arg(interface.kwaylandClientName().toLower());
+}
+
+void Generator::generateClientResourceClassSetup(const Interface &interface)
+{
+ const QString templateString = QStringLiteral(
+" /**\n"
+" * Setup this %1 to manage the @p %3.\n"
+" * When using %4::create%1 there is no need to call this\n"
+" * method.\n"
+" **/\n"
+" void setup(%2 *%3);\n");
+ *m_stream.localData() << templateString.arg(interface.kwaylandClientName())
+ .arg(interface.name())
+ .arg(interface.kwaylandClientName().toLower())
+ .arg(interface.factory()->kwaylandClientName());
+
+}
+
+void Generator::generateClientClassStart(const Interface &interface)
+{
+ const QString templateString = QStringLiteral(
" /**\n"
" * Sets the @p queue to use for creating objects with this %1.\n"
" **/\n"
@@ -420,36 +713,90 @@ void Generator::generateClientClassStart()
" * @returns The event queue to use for creating objects with this %1.\n"
" **/\n"
" EventQueue *eventQueue();\n\n");
- *m_stream.localData() << templateString.arg(m_className).arg(m_waylandGlobal).arg(projectToName().toUpper()).arg(m_className.toLower());
+ *m_stream.localData() << templateString.arg(interface.kwaylandClientName());
}
-void Generator::generateClientClassCasts()
+void Generator::generateClientClassCasts(const Interface &interface)
{
const QString templateString = QStringLiteral(
" operator %1*();\n"
" operator %1*() const;\n\n");
- *m_stream.localData() << templateString.arg(m_waylandGlobal);
+ *m_stream.localData() << templateString.arg(interface.name());
}
-void Generator::generateClientClassEnd()
+void Generator::generateClientGlobalClassEnd(const Interface &interface)
+{
+ Q_UNUSED(interface)
+ *m_stream.localData() << QStringLiteral("private:\n");
+ generateClientClassDptr(interface);
+ *m_stream.localData() << QStringLiteral("};\n\n");
+}
+
+void Generator::generateClientClassDptr(const Interface &interface)
+{
+ Q_UNUSED(interface)
+ *m_stream.localData() << QStringLiteral(
+" class Private;\n"
+" QScopedPointer d;\n");
+}
+
+void Generator::generateClientResourceClassEnd(const Interface &interface)
{
*m_stream.localData() << QStringLiteral(
"private:\n"
-" class Private;\n"
-" QScopedPointer d;\n"
-"};\n\n");
+" friend class %2;\n"
+" explicit %1(QObject *parent = nullptr);\n"
+ ).arg(interface.kwaylandClientName()).arg(interface.factory()->kwaylandClientName());
+ generateClientClassDptr(interface);
+ *m_stream.localData() << QStringLiteral("};\n\n");
}
void Generator::generateWaylandForwardDeclarations()
{
- *m_stream.localData() << QStringLiteral("struct %1;\n\n").arg(m_waylandGlobal);
+ for (auto it = m_interfaces.constBegin(); it != m_interfaces.constEnd(); ++it) {
+ *m_stream.localData() << QStringLiteral("struct %1;\n").arg((*it).name());
+ }
+ *m_stream.localData() << "\n";
}
void Generator::generateNamespaceForwardDeclarations()
{
+ QSet referencedObjects;
+ for (auto it = m_interfaces.constBegin(); it != m_interfaces.constEnd(); ++it) {
+ const auto events = (*it).events();
+ const auto requests = (*it).requests();
+ for (const auto &e: events) {
+ const auto args = e.arguments();
+ for (const auto &a: args) {
+ if (a.type() != Argument::Type::Object && a.type() != Argument::Type::NewId) {
+ continue;
+ }
+ referencedObjects << a.interface();
+ }
+ }
+ for (const auto &r: requests) {
+ const auto args = r.arguments();
+ for (const auto &a: args) {
+ if (a.type() != Argument::Type::Object && a.type() != Argument::Type::NewId) {
+ continue;
+ }
+ referencedObjects << a.interface();
+ }
+ }
+ }
+
switch (m_project) {
case Project::Client:
- *m_stream.localData() << QStringLiteral("class EventQueue;\n\n");
+ *m_stream.localData() << QStringLiteral("class EventQueue;\n");
+ for (const auto &o : referencedObjects) {
+ auto it = s_clientClassNameMapping.constFind(o);
+ if (it != s_clientClassNameMapping.constEnd()) {
+ *m_stream.localData() << QStringLiteral("class %1;\n").arg(it.value());
+ } else {
+ qWarning() << "Cannot forward declare KWayland class for interface " << it.key();
+ }
+ }
+ *m_stream.localData() << QStringLiteral("\n");
break;
case Project::Server:
// TODO: implement
@@ -459,7 +806,7 @@ void Generator::generateNamespaceForwardDeclarations()
}
}
-void Generator::generateClientClassSignals()
+void Generator::generateClientClassSignals(const Interface &interface)
{
const QString templateString = QStringLiteral(
"Q_SIGNALS:\n"
@@ -470,7 +817,7 @@ void Generator::generateClientClassSignals()
" * Registry::create%1\n"
" **/\n"
" void removed();\n\n");
- *m_stream.localData() << templateString.arg(m_className);
+ *m_stream.localData() << templateString.arg(interface.kwaylandClientName());
}
QString Generator::projectToName() const
@@ -485,36 +832,53 @@ QString Generator::projectToName() const
}
}
+static void parseMapping()
+{
+ QFile mappingFile(QStringLiteral(MAPPING_FILE));
+ mappingFile.open(QIODevice::ReadOnly);
+ QTextStream stream(&mappingFile);
+ while (!stream.atEnd()) {
+ QString line = stream.readLine();
+ if (line.startsWith(QLatin1String("#")) || line.isEmpty()) {
+ continue;
+ }
+ const QStringList parts = line.split(QStringLiteral(";"));
+ if (parts.count() < 2) {
+ continue;
+ }
+ s_clientClassNameMapping.insert(parts.first(), parts.at(1));
+ }
+}
+
}
}
int main(int argc, char **argv)
{
using namespace KWayland::Tools;
+
+ parseMapping();
+
QCoreApplication app(argc, argv);
QCommandLineParser parser;
- QCommandLineOption className(QStringList{QStringLiteral("c"), QStringLiteral("class")},
- QStringLiteral("The class name to generate. On Server \"Interface\" is added."),
- QStringLiteral("ClassName"));
+ QCommandLineOption xmlFile(QStringList{QStringLiteral("x"), QStringLiteral("xml")},
+ QStringLiteral("The wayland protocol to parse."),
+ QStringLiteral("FileName"));
QCommandLineOption fileName(QStringList{QStringLiteral("f"), QStringLiteral("file")},
- QStringLiteral("The base name of files to be generated. E.g. for \"foo\" the files \"foo.h\" and \"foo.cpp\" are generated"),
+ QStringLiteral("The base name of files to be generated. E.g. for \"foo\" the files \"foo.h\" and \"foo.cpp\" are generated."
+ "If not provided the base name gets derived from the xml protocol name"),
QStringLiteral("FileName"));
- QCommandLineOption globalName(QStringList{QStringLiteral("g"), QStringLiteral("global")},
- QStringLiteral("The name for the Wayland global for which the wrapper is generated. E.g. \"wl_foo\"."),
- QStringLiteral("wl_global"));
parser.addHelpOption();
- parser.addOption(className);
+ parser.addOption(xmlFile);
parser.addOption(fileName);
- parser.addOption(globalName);
parser.process(app);
Generator generator(&app);
- generator.setClassName(parser.value(className));
+ generator.setXmlFileName(parser.value(xmlFile));
generator.setBaseFileName(parser.value(fileName));
- generator.setWaylandGlobal(parser.value(globalName));
generator.setProject(Generator::Project::Client);
generator.start();
diff --git a/src/wayland/tools/generator.h b/src/wayland/tools/generator.h
index ae62f9de3f..2221e9451f 100644
--- a/src/wayland/tools/generator.h
+++ b/src/wayland/tools/generator.h
@@ -21,9 +21,11 @@ License along with this library. If not, see .
#define KWAYLAND_TOOLS_GENERATOR_H
#include
+#include
#include
#include
#include
+#include
class QTextStream;
@@ -32,6 +34,150 @@ namespace KWayland
namespace Tools
{
+class Argument
+{
+public:
+ explicit Argument();
+ explicit Argument(const QXmlStreamAttributes &attributes);
+ ~Argument();
+
+ enum class Type {
+ Unknown,
+ NewId,
+ Destructor,
+ Object,
+ FileDescriptor,
+ Fixed,
+ Uint,
+ Int,
+ String
+ };
+
+ QString name() const {
+ return m_name;
+ }
+ Type type() const {
+ return m_type;
+ }
+ bool isNullAllowed() const {
+ return m_allowNull;
+ }
+ QString interface() const {
+ return m_inteface;
+ }
+
+private:
+ Type parseType(const QStringRef &type);
+ QString m_name;
+ Type m_type = Type::Unknown;
+ bool m_allowNull = false;
+ QString m_inteface;
+};
+
+class Request
+{
+public:
+ explicit Request();
+ explicit Request(const QString &name);
+ ~Request();
+
+ void addArgument(const Argument &arg) {
+ m_arguments << arg;
+ }
+
+ QString name() const {
+ return m_name;
+ }
+
+ QVector arguments() const {
+ return m_arguments;
+ }
+
+private:
+ QString m_name;
+ QVector m_arguments;
+};
+
+class Event
+{
+public:
+ explicit Event();
+ explicit Event(const QString &name);
+ ~Event();
+
+ void addArgument(const Argument &arg) {
+ m_arguments << arg;
+ }
+
+ QString name() const {
+ return m_name;
+ }
+
+ QVector arguments() const {
+ return m_arguments;
+ }
+
+private:
+ QString m_name;
+ QVector m_arguments;
+};
+
+class Interface
+{
+public:
+ explicit Interface();
+ explicit Interface(const QXmlStreamAttributes &attributes);
+ virtual ~Interface();
+
+ void addRequest(const Request &request) {
+ m_requests << request;
+ }
+ void addEvent(const Event &event) {
+ m_events << event;
+ }
+
+ QString name() const {
+ return m_name;
+ }
+ quint32 version() const {
+ return m_version;
+ }
+ QString kwaylandClientName() const {
+ return m_clientName;
+ }
+
+ QVector requests() const {
+ return m_requests;
+ }
+
+ QVector events() const {
+ return m_events;
+ }
+
+ void markAsGlobal() {
+ m_global = true;
+ }
+ bool isGlobal() const {
+ return m_global;
+ }
+ void setFactory(Interface *factory) {
+ m_factory = factory;
+ }
+ Interface *factory() const {
+ return m_factory;
+ }
+
+private:
+ QString m_name;
+ QString m_clientName;
+ quint32 m_version;
+ QVector m_requests;
+ QVector m_events;
+ bool m_global = false;
+ Interface *m_factory;
+};
+
+
class Generator : public QObject
{
Q_OBJECT
@@ -39,15 +185,12 @@ public:
explicit Generator(QObject *parent = nullptr);
virtual ~Generator();
- void setClassName(const QString &name) {
- m_className = name;
+ void setXmlFileName(const QString &name) {
+ m_xmlFileName = name;
}
void setBaseFileName(const QString &name) {
m_baseFileName = name;
}
- void setWaylandGlobal(const QString &name) {
- m_waylandGlobal = name;
- }
enum class Project {
Client,
Server
@@ -65,16 +208,28 @@ private:
void generateEndNamespace();
void generateHeaderIncludes();
void generateCppIncludes();
- void generatePrivateClass();
- void generateClientPrivateClass();
- void generateClientCpp();
- void generateClass();
- void generateClientClassStart();
- void generateClientClassCasts();
- void generateClientClassSignals();
- void generateClientClassEnd();
+ void generatePrivateClass(const Interface &interface);
+ void generateClientPrivateClass(const Interface &interface);
+ void generateClientCpp(const Interface &interface);
+ void generateClass(const Interface &interface);
+ void generateClientGlobalClass(const Interface &interface);
+ void generateClientResourceClass(const Interface &interface);
+ void generateClientClassQObjectDerived(const Interface &interface);
+ void generateClientGlobalClassDoxy(const Interface &interface);
+ void generateClientGlobalClassCtor(const Interface &interface);
+ void generateClientGlobalClassSetup(const Interface &interface);
+ void generateClientResourceClassSetup(const Interface &interface);
+ void generateClientClassDtor(const Interface &interface);
+ void generateClientClassReleaseDestroy(const Interface &interface);
+ void generateClientClassStart(const Interface &interface);
+ void generateClientClassCasts(const Interface &interface);
+ void generateClientClassSignals(const Interface &interface);
+ void generateClientClassDptr(const Interface &interface);
+ void generateClientGlobalClassEnd(const Interface &interface);
+ void generateClientResourceClassEnd(const Interface &interface);
void generateWaylandForwardDeclarations();
void generateNamespaceForwardDeclarations();
+ void startParseXml();
void startAuthorNameProcess();
void startAuthorEmailProcess();
void startGenerateHeaderFile();
@@ -82,11 +237,15 @@ private:
void checkEnd();
+ void parseProtocol();
+ Interface parseInterface();
+ Request parseRequest();
+ Event parseEvent();
+
QString projectToName() const;
QThreadStorage m_stream;
- QString m_className;
- QString m_waylandGlobal;
+ QString m_xmlFileName;
Project m_project;
QString m_authorName;
QString m_authorEmail;
@@ -94,6 +253,8 @@ private:
QMutex m_mutex;
QWaitCondition m_waitCondition;
+ QXmlStreamReader m_xmlReader;
+ QVector m_interfaces;
int m_finishedCounter = 0;
};
diff --git a/src/wayland/tools/mapping.txt b/src/wayland/tools/mapping.txt
new file mode 100644
index 0000000000..4c0e0e040f
--- /dev/null
+++ b/src/wayland/tools/mapping.txt
@@ -0,0 +1,33 @@
+#wl_name;KWayland::ClientName
+wl_buffer;Buffer
+wl_compositor;Compositor
+wl_data_device;DataDevice
+wl_data_device_manager;DataDeviceManager
+wl_data_offer;DataOffer
+wl_data_source;DataSource
+wl_event_queue;EventQueue
+wl_keyboard;Keyboard
+wl_output;Output
+wl_pointer;Pointer
+wl_region;Region
+wl_registry;Registry
+wl_seat;Seat
+wl_shell;Shell
+wl_shell_surface;ShellSurface
+wl_shm;ShmPool
+wl_subcompositor;SubCompositor
+wl_subsurface;SubSurface
+wl_surface;Surface
+wl_touch;Touch
+_wl_fullscreen_shell;FullscreenShell
+org_kde_kwin_blur;Blur
+org_kde_kwin_blur_manager;BlurManager
+org_kde_kwin_fake_input;FakeInput
+org_kde_kwin_idle;Idle
+org_kde_kwin_idle_timeout;IdleTimeout
+org_kde_kwin_shadow;Shadow
+org_kde_kwin_shadow_manager;ShadowManager
+org_kde_plasma_shell;PlasmaShell
+org_kde_plasma_surface;PlasmaShellSurface
+org_kde_plasma_window_management;PlasmaWindowManagement
+org_kde_plasma_window;PlasmaWindow