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