File indexing completed on 2024-11-10 04:57:24

0001 /****************************************************************************
0002 **
0003 ** Copyright (C) 2016 The Qt Company Ltd.
0004 ** Contact: https://www.qt.io/licensing/
0005 **
0006 ** This file is part of the tools applications of the Qt Toolkit.
0007 **
0008 ** $QT_BEGIN_LICENSE:LGPL$
0009 ** Commercial License Usage
0010 ** Licensees holding valid commercial Qt licenses may use this file in
0011 ** accordance with the commercial license agreement provided with the
0012 ** Software or, alternatively, in accordance with the terms contained in
0013 ** a written agreement between you and The Qt Company. For licensing terms
0014 ** and conditions see https://www.qt.io/terms-conditions. For further
0015 ** information use the contact form at https://www.qt.io/contact-us.
0016 **
0017 ** GNU Lesser General Public License Usage
0018 ** Alternatively, this file may be used under the terms of the GNU Lesser
0019 ** General Public License version 3 as published by the Free Software
0020 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
0021 ** packaging of this file. Please review the following information to
0022 ** ensure the GNU Lesser General Public License version 3 requirements
0023 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
0024 **
0025 ** GNU General Public License Usage
0026 ** Alternatively, this file may be used under the terms of the GNU
0027 ** General Public License version 2.0 or (at your option) the GNU General
0028 ** Public license version 3 or any later version approved by the KDE Free
0029 ** Qt Foundation. The licenses are as published by the Free Software
0030 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
0031 ** included in the packaging of this file. Please review the following
0032 ** information to ensure the GNU General Public License requirements will
0033 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
0034 ** https://www.gnu.org/licenses/gpl-3.0.html.
0035 **
0036 ** $QT_END_LICENSE$
0037 **
0038 ****************************************************************************/
0039 
0040 #include <QCoreApplication>
0041 #include <QFile>
0042 #include <QXmlStreamReader>
0043 
0044 #include <vector>
0045 #include <utility>
0046 
0047 class Scanner
0048 {
0049 public:
0050     explicit Scanner() {}
0051     ~Scanner() { delete m_xml; }
0052 
0053     bool parseArguments(int argc, char **argv);
0054     void printUsage();
0055     bool process();
0056     void printErrors();
0057 
0058 private:
0059     struct WaylandEnumEntry {
0060         QByteArray name;
0061         QByteArray value;
0062         QByteArray summary;
0063     };
0064 
0065     struct WaylandEnum {
0066         QByteArray name;
0067 
0068         std::vector<WaylandEnumEntry> entries;
0069     };
0070 
0071     struct WaylandArgument {
0072         QByteArray name;
0073         QByteArray type;
0074         QByteArray interface;
0075         QByteArray summary;
0076         bool allowNull;
0077     };
0078 
0079     struct WaylandEvent {
0080         bool request;
0081         QByteArray name;
0082         QByteArray type;
0083         std::vector<WaylandArgument> arguments;
0084     };
0085 
0086     struct WaylandInterface {
0087         QByteArray name;
0088         int version;
0089 
0090         std::vector<WaylandEnum> enums;
0091         std::vector<WaylandEvent> events;
0092         std::vector<WaylandEvent> requests;
0093     };
0094 
0095     bool isServerSide();
0096     bool parseOption(const QByteArray &str);
0097 
0098     QByteArray byteArrayValue(const QXmlStreamReader &xml, const char *name);
0099     int intValue(const QXmlStreamReader &xml, const char *name, int defaultValue = 0);
0100     bool boolValue(const QXmlStreamReader &xml, const char *name);
0101     WaylandEvent readEvent(QXmlStreamReader &xml, bool request);
0102     Scanner::WaylandEnum readEnum(QXmlStreamReader &xml);
0103     Scanner::WaylandInterface readInterface(QXmlStreamReader &xml);
0104     QByteArray waylandToCType(const QByteArray &waylandType, const QByteArray &interface);
0105     QByteArray waylandToQtType(const QByteArray &waylandType, const QByteArray &interface, bool cStyleArray);
0106     const Scanner::WaylandArgument *newIdArgument(const std::vector<WaylandArgument> &arguments);
0107 
0108     void printEvent(const WaylandEvent &e, bool omitNames = false, bool withResource = false);
0109     void printEventHandlerSignature(const WaylandEvent &e, const char *interfaceName, bool deepIndent = true);
0110     void printEnums(const std::vector<WaylandEnum> &enums);
0111 
0112     QByteArray stripInterfaceName(const QByteArray &name);
0113     bool ignoreInterface(const QByteArray &name);
0114 
0115     enum Option {
0116         ClientHeader,
0117         ServerHeader,
0118         ClientCode,
0119         ServerCode,
0120     } m_option;
0121 
0122     QByteArray m_protocolName;
0123     QByteArray m_protocolFilePath;
0124     QByteArray m_scannerName;
0125     QByteArray m_headerPath;
0126     QByteArray m_prefix;
0127     QList <QByteArray> m_includes;
0128     QXmlStreamReader *m_xml = nullptr;
0129 };
0130 
0131 bool Scanner::parseArguments(int argc, char **argv)
0132 {
0133     QList<QByteArray> args;
0134     args.reserve(argc);
0135     for (int i = 0; i < argc; ++i)
0136         args << QByteArray(argv[i]);
0137 
0138     m_scannerName = args[0];
0139 
0140     if (argc <= 2 || !parseOption(args[1]))
0141         return false;
0142 
0143     m_protocolFilePath = args[2];
0144 
0145     if (argc > 3 && !args[3].startsWith('-')) {
0146         // legacy positional arguments
0147             m_headerPath = args[3];
0148         if (argc == 5)
0149             m_prefix = args[4];
0150     } else {
0151         // --header-path=<path> (14 characters)
0152         // --prefix=<prefix> (9 characters)
0153         // --add-include=<include> (14 characters)
0154         for (int pos = 3; pos < argc; pos++) {
0155             const QByteArray &option = args[pos];
0156             if (option.startsWith("--header-path=")) {
0157                 m_headerPath = option.mid(14);
0158             } else if (option.startsWith("--prefix=")) {
0159                 m_prefix = option.mid(10);
0160             } else if (option.startsWith("--add-include=")) {
0161                 auto include = option.mid(14);
0162                 if (!include.isEmpty())
0163                     m_includes << include;
0164             } else {
0165                 return false;
0166             }
0167         }
0168     }
0169 
0170     return true;
0171 }
0172 
0173 void Scanner::printUsage()
0174 {
0175     fprintf(stderr, "Usage: %s [client-header|server-header|client-code|server-code] specfile [--header-path=<path>] [--prefix=<prefix>] [--add-include=<include>]\n", m_scannerName.constData());
0176 }
0177 
0178 bool Scanner::isServerSide()
0179 {
0180     return m_option == ServerHeader || m_option == ServerCode;
0181 }
0182 
0183 bool Scanner::parseOption(const QByteArray &str)
0184 {
0185     if (str == "client-header")
0186         m_option = ClientHeader;
0187     else if (str == "server-header")
0188         m_option = ServerHeader;
0189     else if (str == "client-code")
0190         m_option = ClientCode;
0191     else if (str == "server-code")
0192         m_option = ServerCode;
0193     else
0194         return false;
0195 
0196     return true;
0197 }
0198 
0199 QByteArray Scanner::byteArrayValue(const QXmlStreamReader &xml, const char *name)
0200 {
0201     if (xml.attributes().hasAttribute(name))
0202         return xml.attributes().value(name).toUtf8();
0203     return QByteArray();
0204 }
0205 
0206 int Scanner::intValue(const QXmlStreamReader &xml, const char *name, int defaultValue)
0207 {
0208     bool ok;
0209     int result = byteArrayValue(xml, name).toInt(&ok);
0210     return ok ? result : defaultValue;
0211 }
0212 
0213 bool Scanner::boolValue(const QXmlStreamReader &xml, const char *name)
0214 {
0215     return byteArrayValue(xml, name) == "true";
0216 }
0217 
0218 Scanner::WaylandEvent Scanner::readEvent(QXmlStreamReader &xml, bool request)
0219 {
0220     WaylandEvent event = {
0221         .request = request,
0222         .name = byteArrayValue(xml, "name"),
0223         .type = byteArrayValue(xml, "type"),
0224         .arguments = {},
0225     };
0226     while (xml.readNextStartElement()) {
0227         if (xml.name() == QLatin1String("arg")) {
0228             WaylandArgument argument = {
0229                 .name      = byteArrayValue(xml, "name"),
0230                 .type      = byteArrayValue(xml, "type"),
0231                 .interface = byteArrayValue(xml, "interface"),
0232                 .summary   = byteArrayValue(xml, "summary"),
0233                 .allowNull = boolValue(xml, "allowNull"),
0234             };
0235             event.arguments.push_back(std::move(argument));
0236         }
0237 
0238         xml.skipCurrentElement();
0239     }
0240     return event;
0241 }
0242 
0243 Scanner::WaylandEnum Scanner::readEnum(QXmlStreamReader &xml)
0244 {
0245     WaylandEnum result = {
0246         .name = byteArrayValue(xml, "name"),
0247         .entries = {},
0248     };
0249 
0250     while (xml.readNextStartElement()) {
0251         if (xml.name() == QLatin1String("entry")) {
0252             WaylandEnumEntry entry = {
0253                 .name    = byteArrayValue(xml, "name"),
0254                 .value   = byteArrayValue(xml, "value"),
0255                 .summary = byteArrayValue(xml, "summary"),
0256             };
0257             result.entries.push_back(std::move(entry));
0258         }
0259 
0260         xml.skipCurrentElement();
0261     }
0262 
0263     return result;
0264 }
0265 
0266 Scanner::WaylandInterface Scanner::readInterface(QXmlStreamReader &xml)
0267 {
0268     WaylandInterface interface = {
0269         .name = byteArrayValue(xml, "name"),
0270         .version = intValue(xml, "version", 1),
0271         .enums = {},
0272         .events = {},
0273         .requests = {},
0274     };
0275 
0276     while (xml.readNextStartElement()) {
0277         if (xml.name() == QLatin1String("event"))
0278             interface.events.push_back(readEvent(xml, false));
0279         else if (xml.name() == QLatin1String("request"))
0280             interface.requests.push_back(readEvent(xml, true));
0281         else if (xml.name() == QLatin1String("enum"))
0282             interface.enums.push_back(readEnum(xml));
0283         else
0284             xml.skipCurrentElement();
0285     }
0286 
0287     return interface;
0288 }
0289 
0290 QByteArray Scanner::waylandToCType(const QByteArray &waylandType, const QByteArray &interface)
0291 {
0292     if (waylandType == "string")
0293         return "const char *";
0294     else if (waylandType == "int")
0295         return "int32_t";
0296     else if (waylandType == "uint")
0297         return "uint32_t";
0298     else if (waylandType == "fixed")
0299         return "wl_fixed_t";
0300     else if (waylandType == "fd")
0301         return "int32_t";
0302     else if (waylandType == "array")
0303         return "wl_array *";
0304     else if (waylandType == "object" || waylandType == "new_id") {
0305         if (isServerSide())
0306             return "struct ::wl_resource *";
0307         if (interface.isEmpty())
0308             return "struct ::wl_object *";
0309         return "struct ::" + interface + " *";
0310     }
0311     return waylandType;
0312 }
0313 
0314 QByteArray Scanner::waylandToQtType(const QByteArray &waylandType, const QByteArray &interface, bool cStyleArray)
0315 {
0316     if (waylandType == "string")
0317         return "const QString &";
0318     else if (waylandType == "array")
0319         return cStyleArray ? "wl_array *" : "const QByteArray &";
0320     else
0321         return waylandToCType(waylandType, interface);
0322 }
0323 
0324 const Scanner::WaylandArgument *Scanner::newIdArgument(const std::vector<WaylandArgument> &arguments)
0325 {
0326     for (const WaylandArgument &a : arguments) {
0327         if (a.type == "new_id")
0328             return &a;
0329     }
0330     return nullptr;
0331 }
0332 
0333 void Scanner::printEvent(const WaylandEvent &e, bool omitNames, bool withResource)
0334 {
0335     printf("%s(", e.name.constData());
0336     bool needsComma = false;
0337     if (isServerSide()) {
0338         if (e.request) {
0339             printf("Resource *%s", omitNames ? "" : "resource");
0340             needsComma = true;
0341         } else if (withResource) {
0342             printf("struct ::wl_resource *%s", omitNames ? "" : "resource");
0343             needsComma = true;
0344         }
0345     }
0346     for (const WaylandArgument &a : e.arguments) {
0347         bool isNewId = a.type == "new_id";
0348         if (isNewId && !isServerSide() && (a.interface.isEmpty() != e.request))
0349             continue;
0350         if (needsComma)
0351             printf(", ");
0352         needsComma = true;
0353         if (isNewId) {
0354             if (isServerSide()) {
0355                 if (e.request) {
0356                     printf("uint32_t");
0357                     if (!omitNames)
0358                         printf(" %s", a.name.constData());
0359                     continue;
0360                 }
0361             } else {
0362                 if (e.request) {
0363                     printf("const struct ::wl_interface *%s, uint32_t%s", omitNames ? "" : "interface", omitNames ? "" : " version");
0364                     continue;
0365                 }
0366             }
0367         }
0368 
0369         QByteArray qtType = waylandToQtType(a.type, a.interface, e.request == isServerSide());
0370         printf("%s%s%s", qtType.constData(), qtType.endsWith("&") || qtType.endsWith("*") ? "" : " ", omitNames ? "" : a.name.constData());
0371     }
0372     printf(")");
0373 }
0374 
0375 void Scanner::printEventHandlerSignature(const WaylandEvent &e, const char *interfaceName, bool deepIndent)
0376 {
0377     const char *indent = deepIndent ? "    " : "";
0378     printf("handle_%s(\n", e.name.constData());
0379     if (isServerSide()) {
0380         printf("        %s::wl_client *client,\n", indent);
0381         printf("        %sstruct wl_resource *resource", indent);
0382     } else {
0383         printf("        %svoid *data,\n", indent);
0384         printf("        %sstruct ::%s *object", indent, interfaceName);
0385     }
0386     for (const WaylandArgument &a : e.arguments) {
0387         printf(",\n");
0388         bool isNewId = a.type == "new_id";
0389         if (isServerSide() && isNewId) {
0390             printf("        %suint32_t %s", indent, a.name.constData());
0391         } else {
0392             QByteArray cType = waylandToCType(a.type, a.interface);
0393             printf("        %s%s%s%s", indent, cType.constData(), cType.endsWith("*") ? "" : " ", a.name.constData());
0394         }
0395     }
0396     printf(")");
0397 }
0398 
0399 void Scanner::printEnums(const std::vector<WaylandEnum> &enums)
0400 {
0401     for (const WaylandEnum &e : enums) {
0402         printf("\n");
0403         printf("        enum %s {\n", e.name.constData());
0404         for (const WaylandEnumEntry &entry : e.entries) {
0405             printf("            %s_%s = %s,", e.name.constData(), entry.name.constData(), entry.value.constData());
0406             if (!entry.summary.isNull())
0407                 printf(" // %s", entry.summary.constData());
0408             printf("\n");
0409         }
0410         printf("        };\n");
0411     }
0412 }
0413 
0414 QByteArray Scanner::stripInterfaceName(const QByteArray &name)
0415 {
0416     if (!m_prefix.isEmpty() && name.startsWith(m_prefix))
0417         return name.mid(m_prefix.size());
0418     if (name.startsWith("qt_") || name.startsWith("wl_"))
0419         return name.mid(3);
0420 
0421     return name;
0422 }
0423 
0424 bool Scanner::ignoreInterface(const QByteArray &name)
0425 {
0426     return name == "wl_display"
0427            || (isServerSide() && name == "wl_registry");
0428 }
0429 
0430 bool Scanner::process()
0431 {
0432     QFile file(m_protocolFilePath);
0433     if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
0434         fprintf(stderr, "Unable to open file %s\n", m_protocolFilePath.constData());
0435         return false;
0436     }
0437 
0438     m_xml = new QXmlStreamReader(&file);
0439     if (!m_xml->readNextStartElement())
0440         return false;
0441 
0442     if (m_xml->name() != QLatin1String("protocol")) {
0443         m_xml->raiseError(QStringLiteral("The file is not a wayland protocol file."));
0444         return false;
0445     }
0446 
0447     m_protocolName = byteArrayValue(*m_xml, "name");
0448 
0449     if (m_protocolName.isEmpty()) {
0450         m_xml->raiseError(QStringLiteral("Missing protocol name."));
0451         return false;
0452     }
0453 
0454     //We should convert - to _ so that the preprocessor wont generate code which will lead to unexpected behavior
0455     //However, the wayland-scanner doesn't do so we will do the same for now
0456     //QByteArray preProcessorProtocolName = QByteArray(m_protocolName).replace('-', '_').toUpper();
0457     QByteArray preProcessorProtocolName = QByteArray(m_protocolName).toUpper();
0458 
0459     std::vector<WaylandInterface> interfaces;
0460 
0461     while (m_xml->readNextStartElement()) {
0462         if (m_xml->name() == QLatin1String("interface"))
0463             interfaces.push_back(readInterface(*m_xml));
0464         else
0465             m_xml->skipCurrentElement();
0466     }
0467 
0468     if (m_xml->hasError())
0469         return false;
0470 
0471     printf("// This file was generated by qtwaylandscanner\n");
0472     printf("// source file is %s\n\n", qPrintable(m_protocolFilePath));
0473 
0474     for (auto b : std::as_const(m_includes))
0475         printf("#include %s\n", b.constData());
0476 
0477     if (m_option == ServerHeader) {
0478         QByteArray inclusionGuard = QByteArray("QT_WAYLAND_SERVER_") + preProcessorProtocolName.constData();
0479         printf("#ifndef %s\n", inclusionGuard.constData());
0480         printf("#define %s\n", inclusionGuard.constData());
0481         printf("\n");
0482         printf("#include \"wayland-server-core.h\"\n");
0483         if (m_headerPath.isEmpty())
0484             printf("#include \"wayland-%s-server-protocol.h\"\n", QByteArray(m_protocolName).replace('_', '-').constData());
0485         else
0486             printf("#include <%s/wayland-%s-server-protocol.h>\n", m_headerPath.constData(), QByteArray(m_protocolName).replace('_', '-').constData());
0487         printf("#include <QByteArray>\n");
0488         printf("#include <QMultiMap>\n");
0489         printf("#include <QString>\n");
0490 
0491         printf("\n");
0492         printf("#include <unistd.h>\n");
0493 
0494         printf("\n");
0495         printf("#ifndef WAYLAND_VERSION_CHECK\n");
0496         printf("#define WAYLAND_VERSION_CHECK(major, minor, micro) \\\n");
0497         printf("    ((WAYLAND_VERSION_MAJOR > (major)) || \\\n");
0498         printf("    (WAYLAND_VERSION_MAJOR == (major) && WAYLAND_VERSION_MINOR > (minor)) || \\\n");
0499         printf("    (WAYLAND_VERSION_MAJOR == (major) && WAYLAND_VERSION_MINOR == (minor) && WAYLAND_VERSION_MICRO >= (micro)))\n");
0500         printf("#endif\n");
0501 
0502         printf("\n");
0503         printf("QT_BEGIN_NAMESPACE\n");
0504         printf("QT_WARNING_PUSH\n");
0505         printf("QT_WARNING_DISABLE_GCC(\"-Wmissing-field-initializers\")\n");
0506         printf("QT_WARNING_DISABLE_CLANG(\"-Wmissing-field-initializers\")\n");
0507         QByteArray serverExport;
0508         if (m_headerPath.size()) {
0509             serverExport = QByteArray("Q_WAYLAND_SERVER_") + preProcessorProtocolName + "_EXPORT";
0510             printf("\n");
0511             printf("#if !defined(%s)\n", serverExport.constData());
0512             printf("#  if defined(QT_SHARED)\n");
0513             printf("#    define %s Q_DECL_EXPORT\n", serverExport.constData());
0514             printf("#  else\n");
0515             printf("#    define %s\n", serverExport.constData());
0516             printf("#  endif\n");
0517             printf("#endif\n");
0518         }
0519         printf("\n");
0520         printf("namespace QtWaylandServer {\n");
0521 
0522         bool needsNewLine = false;
0523         for (const WaylandInterface &interface : interfaces) {
0524 
0525             if (ignoreInterface(interface.name))
0526                 continue;
0527 
0528             if (needsNewLine)
0529                 printf("\n");
0530             needsNewLine = true;
0531 
0532             const char *interfaceName = interface.name.constData();
0533 
0534             QByteArray stripped = stripInterfaceName(interface.name);
0535             const char *interfaceNameStripped = stripped.constData();
0536 
0537             printf("    class %s %s\n    {\n", serverExport.constData(), interfaceName);
0538             printf("    public:\n");
0539             printf("        %s(struct ::wl_client *client, int id, int version);\n", interfaceName);
0540             printf("        %s(struct ::wl_display *display, int version);\n", interfaceName);
0541             printf("        %s(struct ::wl_resource *resource);\n", interfaceName);
0542             printf("        %s();\n", interfaceName);
0543             printf("\n");
0544             printf("        virtual ~%s();\n", interfaceName);
0545             printf("\n");
0546             printf("        class Resource\n");
0547             printf("        {\n");
0548             printf("        public:\n");
0549             printf("            Resource() : %s_object(nullptr), handle(nullptr) {}\n", interfaceNameStripped);
0550             printf("            virtual ~Resource() {}\n");
0551             printf("\n");
0552             printf("            %s *%s_object;\n", interfaceName, interfaceNameStripped);
0553             printf("            %s *object() { return %s_object; } \n", interfaceName, interfaceNameStripped);
0554             printf("            struct ::wl_resource *handle;\n");
0555             printf("\n");
0556             printf("            struct ::wl_client *client() const { return wl_resource_get_client(handle); }\n");
0557             printf("            int version() const { return wl_resource_get_version(handle); }\n");
0558             printf("\n");
0559             printf("            static Resource *fromResource(struct ::wl_resource *resource);\n");
0560             printf("        };\n");
0561             printf("\n");
0562             printf("        void init(struct ::wl_client *client, int id, int version);\n");
0563             printf("        void init(struct ::wl_display *display, int version);\n");
0564             printf("        void init(struct ::wl_resource *resource);\n");
0565             printf("\n");
0566             printf("        Resource *add(struct ::wl_client *client, int version);\n");
0567             printf("        Resource *add(struct ::wl_client *client, int id, int version);\n");
0568             printf("        Resource *add(struct wl_list *resource_list, struct ::wl_client *client, int id, int version);\n");
0569             printf("\n");
0570             printf("        Resource *resource() { return m_resource; }\n");
0571             printf("        const Resource *resource() const { return m_resource; }\n");
0572             printf("\n");
0573             printf("        QMultiMap<struct ::wl_client*, Resource*> resourceMap() { return m_resource_map; }\n");
0574             printf("        const QMultiMap<struct ::wl_client*, Resource*> resourceMap() const { return m_resource_map; }\n");
0575             printf("\n");
0576             printf("        bool isGlobalRemoved() const { return m_globalRemovedEvent; }\n");
0577             printf("        void globalRemove();\n");
0578             printf("\n");
0579             printf("        bool isGlobal() const { return m_global != nullptr; }\n");
0580             printf("        bool isResource() const { return m_resource != nullptr; }\n");
0581             printf("\n");
0582             printf("        static const struct ::wl_interface *interface();\n");
0583             printf("        static QByteArray interfaceName() { return interface()->name; }\n");
0584             printf("        static int interfaceVersion() { return interface()->version; }\n");
0585             printf("\n");
0586 
0587             printEnums(interface.enums);
0588 
0589             bool hasEvents = !interface.events.empty();
0590 
0591             if (hasEvents) {
0592                 printf("\n");
0593                 for (const WaylandEvent &e : interface.events) {
0594                     printf("        void send_");
0595                     printEvent(e);
0596                     printf(";\n");
0597                     printf("        void send_");
0598                     printEvent(e, false, true);
0599                     printf(";\n");
0600                 }
0601             }
0602 
0603             printf("\n");
0604             printf("    protected:\n");
0605             printf("        virtual Resource *%s_allocate();\n", interfaceNameStripped);
0606             printf("\n");
0607             printf("        virtual void %s_destroy_global();\n", interfaceNameStripped);
0608             printf("\n");
0609             printf("        virtual void %s_bind_resource(Resource *resource);\n", interfaceNameStripped);
0610             printf("        virtual void %s_destroy_resource(Resource *resource);\n", interfaceNameStripped);
0611 
0612             bool hasRequests = !interface.requests.empty();
0613 
0614             if (hasRequests) {
0615                 printf("\n");
0616                 for (const WaylandEvent &e : interface.requests) {
0617                     printf("        virtual void %s_", interfaceNameStripped);
0618                     printEvent(e);
0619                     printf(";\n");
0620                 }
0621             }
0622 
0623             printf("\n");
0624             printf("    private:\n");
0625             printf("        static void bind_func(struct ::wl_client *client, void *data, uint32_t version, uint32_t id);\n");
0626             printf("        static void destroy_func(struct ::wl_resource *client_resource);\n");
0627             printf("        static void display_destroy_func(struct ::wl_listener *listener, void *data);\n");
0628             printf("        static int deferred_destroy_global_func(void *data);\n");
0629             printf("\n");
0630             printf("        Resource *bind(struct ::wl_client *client, uint32_t id, int version);\n");
0631             printf("        Resource *bind(struct ::wl_resource *handle);\n");
0632 
0633             if (hasRequests) {
0634                 printf("\n");
0635                 printf("        static const struct ::%s_interface m_%s_interface;\n", interfaceName, interfaceName);
0636 
0637                 printf("\n");
0638                 for (const WaylandEvent &e : interface.requests) {
0639                     printf("        static void ");
0640 
0641                     printEventHandlerSignature(e, interfaceName);
0642                     printf(";\n");
0643                 }
0644             }
0645 
0646             printf("\n");
0647             printf("        QMultiMap<struct ::wl_client*, Resource*> m_resource_map;\n");
0648             printf("        Resource *m_resource;\n");
0649             printf("        struct ::wl_global *m_global;\n");
0650             printf("        struct ::wl_display *m_display;\n");
0651             printf("        struct wl_event_source *m_globalRemovedEvent;\n");
0652             printf("        struct DisplayDestroyedListener : ::wl_listener {\n");
0653             printf("            %s *parent;\n", interfaceName);
0654             printf("        };\n");
0655             printf("        DisplayDestroyedListener m_displayDestroyedListener;\n");
0656             printf("    };\n");
0657         }
0658 
0659         printf("}\n");
0660         printf("\n");
0661         printf("QT_WARNING_POP\n");
0662         printf("QT_END_NAMESPACE\n");
0663         printf("\n");
0664         printf("#endif\n");
0665     }
0666 
0667     if (m_option == ServerCode) {
0668         if (m_headerPath.isEmpty())
0669             printf("#include \"qwayland-server-%s.h\"\n", QByteArray(m_protocolName).replace('_', '-').constData());
0670         else
0671             printf("#include <%s/qwayland-server-%s.h>\n", m_headerPath.constData(), QByteArray(m_protocolName).replace('_', '-').constData());
0672         printf("\n");
0673         printf("QT_BEGIN_NAMESPACE\n");
0674         printf("QT_WARNING_PUSH\n");
0675         printf("QT_WARNING_DISABLE_GCC(\"-Wmissing-field-initializers\")\n");
0676         printf("\n");
0677         printf("namespace QtWaylandServer {\n");
0678 
0679         bool needsNewLine = false;
0680 
0681         for (const WaylandInterface &interface : interfaces) {
0682 
0683             if (ignoreInterface(interface.name))
0684                 continue;
0685 
0686             if (needsNewLine)
0687                 printf("\n");
0688 
0689             needsNewLine = true;
0690 
0691             const char *interfaceName = interface.name.constData();
0692 
0693             QByteArray stripped = stripInterfaceName(interface.name);
0694             const char *interfaceNameStripped = stripped.constData();
0695 
0696             printf("\n");
0697             printf("    int %s::deferred_destroy_global_func(void *data) {\n", interfaceName);
0698             printf("        auto object = static_cast<%s *>(data);\n", interfaceName);
0699             printf("        wl_global_destroy(object->m_global);\n");
0700             printf("        object->m_global = nullptr;\n");
0701             printf("        wl_event_source_remove(object->m_globalRemovedEvent);\n");
0702             printf("        object->m_globalRemovedEvent = nullptr;\n");
0703             printf("        wl_list_remove(&object->m_displayDestroyedListener.link);\n");
0704             printf("        object->%s_destroy_global();\n", interfaceNameStripped);
0705             printf("        return 0;\n");
0706             printf("    }\n");
0707             printf("\n");
0708 
0709             printf("    %s::%s(struct ::wl_client *client, int id, int version)\n", interfaceName, interfaceName);
0710             printf("        : m_resource_map()\n");
0711             printf("        , m_resource(nullptr)\n");
0712             printf("        , m_global(nullptr)\n");
0713             printf("        , m_display(nullptr)\n");
0714             printf("        , m_globalRemovedEvent(nullptr)\n");
0715             printf("    {\n");
0716             printf("        init(client, id, version);\n");
0717             printf("    }\n");
0718             printf("\n");
0719 
0720             printf("    %s::%s(struct ::wl_display *display, int version)\n", interfaceName, interfaceName);
0721             printf("        : m_resource_map()\n");
0722             printf("        , m_resource(nullptr)\n");
0723             printf("        , m_global(nullptr)\n");
0724             printf("        , m_display(nullptr)\n");
0725             printf("        , m_globalRemovedEvent(nullptr)\n");
0726             printf("    {\n");
0727             printf("        init(display, version);\n");
0728             printf("    }\n");
0729             printf("\n");
0730 
0731             printf("    %s::%s(struct ::wl_resource *resource)\n", interfaceName, interfaceName);
0732             printf("        : m_resource_map()\n");
0733             printf("        , m_resource(nullptr)\n");
0734             printf("        , m_global(nullptr)\n");
0735             printf("        , m_display(nullptr)\n");
0736             printf("        , m_globalRemovedEvent(nullptr)\n");
0737             printf("    {\n");
0738             printf("        init(resource);\n");
0739             printf("    }\n");
0740             printf("\n");
0741 
0742             printf("    %s::%s()\n", interfaceName, interfaceName);
0743             printf("        : m_resource_map()\n");
0744             printf("        , m_resource(nullptr)\n");
0745             printf("        , m_global(nullptr)\n");
0746             printf("        , m_display(nullptr)\n");
0747             printf("        , m_globalRemovedEvent(nullptr)\n");
0748             printf("    {\n");
0749             printf("    }\n");
0750             printf("\n");
0751 
0752             printf("    %s::~%s()\n", interfaceName, interfaceName);
0753             printf("    {\n");
0754             printf("        for (auto resource : std::as_const(m_resource_map))\n");
0755             printf("            resource->%s_object = nullptr;\n", interfaceNameStripped);
0756             printf("\n");
0757             printf("        if (m_resource)\n");
0758             printf("            m_resource->%s_object = nullptr;\n", interfaceNameStripped);
0759             printf("\n");
0760             printf("        if (m_global) {\n");
0761             printf("            if (m_globalRemovedEvent)\n");
0762             printf("                wl_event_source_remove(m_globalRemovedEvent);\n");
0763             printf("            wl_global_destroy(m_global);\n");
0764             printf("            wl_list_remove(&m_displayDestroyedListener.link);\n");
0765             printf("        }\n");
0766             printf("    }\n");
0767             printf("\n");
0768 
0769             printf("    void %s::init(struct ::wl_client *client, int id, int version)\n", interfaceName);
0770             printf("    {\n");
0771             printf("        m_resource = bind(client, id, version);\n");
0772             printf("    }\n");
0773             printf("\n");
0774 
0775             printf("    void %s::init(struct ::wl_resource *resource)\n", interfaceName);
0776             printf("    {\n");
0777             printf("        m_resource = bind(resource);\n");
0778             printf("    }\n");
0779             printf("\n");
0780 
0781             printf("    %s::Resource *%s::add(struct ::wl_client *client, int version)\n", interfaceName, interfaceName);
0782             printf("    {\n");
0783             printf("        Resource *resource = bind(client, 0, version);\n");
0784             printf("        m_resource_map.insert(client, resource);\n");
0785             printf("        return resource;\n");
0786             printf("    }\n");
0787             printf("\n");
0788 
0789             printf("    %s::Resource *%s::add(struct ::wl_client *client, int id, int version)\n", interfaceName, interfaceName);
0790             printf("    {\n");
0791             printf("        Resource *resource = bind(client, id, version);\n");
0792             printf("        m_resource_map.insert(client, resource);\n");
0793             printf("        return resource;\n");
0794             printf("    }\n");
0795             printf("\n");
0796 
0797             printf("    void %s::init(struct ::wl_display *display, int version)\n", interfaceName);
0798             printf("    {\n");
0799             printf("        m_display = display;\n");
0800             printf("        m_global = wl_global_create(display, &::%s_interface, version, this, bind_func);\n", interfaceName);
0801             printf("        m_displayDestroyedListener.notify = %s::display_destroy_func;\n", interfaceName);
0802             printf("        m_displayDestroyedListener.parent = this;\n");
0803             printf("        wl_display_add_destroy_listener(display, &m_displayDestroyedListener);\n");
0804             printf("    }\n");
0805             printf("\n");
0806 
0807             printf("    const struct wl_interface *%s::interface()\n", interfaceName);
0808             printf("    {\n");
0809             printf("        return &::%s_interface;\n", interfaceName);
0810             printf("    }\n");
0811             printf("\n");
0812 
0813             printf("    %s::Resource *%s::%s_allocate()\n", interfaceName, interfaceName, interfaceNameStripped);
0814             printf("    {\n");
0815             printf("        return new Resource;\n");
0816             printf("    }\n");
0817             printf("\n");
0818 
0819             printf("    void %s::%s_destroy_global()\n", interfaceName, interfaceNameStripped);
0820             printf("    {\n");
0821             printf("    }\n");
0822             printf("\n");
0823 
0824             printf("    void %s::%s_bind_resource(Resource *)\n", interfaceName, interfaceNameStripped);
0825             printf("    {\n");
0826             printf("    }\n");
0827             printf("\n");
0828 
0829             printf("    void %s::%s_destroy_resource(Resource *)\n", interfaceName, interfaceNameStripped);
0830             printf("    {\n");
0831             printf("    }\n");
0832             printf("\n");
0833 
0834             printf("    void %s::bind_func(struct ::wl_client *client, void *data, uint32_t version, uint32_t id)\n", interfaceName);
0835             printf("    {\n");
0836             printf("        %s *that = static_cast<%s *>(data);\n", interfaceName, interfaceName);
0837             printf("        that->add(client, id, version);\n");
0838             printf("    }\n");
0839             printf("\n");
0840 
0841             printf("    void %s::display_destroy_func(struct ::wl_listener *listener, void *data)\n", interfaceName);
0842             printf("    {\n");
0843             printf("        Q_UNUSED(data);\n");
0844             printf("        %s *that = static_cast<%s::DisplayDestroyedListener *>(listener)->parent;\n", interfaceName, interfaceName);
0845             printf("        that->m_global = nullptr;\n");
0846             printf("        that->m_globalRemovedEvent = nullptr;\n");
0847             printf("    }\n");
0848             printf("\n");
0849 
0850             printf("    void %s::destroy_func(struct ::wl_resource *client_resource)\n", interfaceName);
0851             printf("    {\n");
0852             printf("        Resource *resource = Resource::fromResource(client_resource);\n");
0853             printf("        Q_ASSERT(resource);\n");
0854             printf("        %s *that = resource->%s_object;\n", interfaceName, interfaceNameStripped);
0855             printf("        if (Q_LIKELY(that)) {\n");
0856             printf("            that->m_resource_map.remove(resource->client(), resource);\n");
0857             printf("            that->%s_destroy_resource(resource);\n", interfaceNameStripped);
0858             printf("\n");
0859             printf("            that = resource->%s_object;\n", interfaceNameStripped);
0860             printf("            if (that && that->m_resource == resource)\n");
0861             printf("                that->m_resource = nullptr;\n");
0862             printf("        }\n");
0863             printf("        delete resource;\n");
0864             printf("    }\n");
0865             printf("\n");
0866 
0867             // Removing a global is racey. Announce removal, and then only perform internal cleanup after a delay
0868             // See https://gitlab.freedesktop.org/wayland/wayland/issues/10
0869             printf("\n");
0870             printf("    void %s::globalRemove()\n", interfaceName);
0871             printf("    {\n");
0872             printf("        if (!m_global || m_globalRemovedEvent)\n");
0873             printf("            return;\n");
0874             printf("\n");
0875             printf("        wl_global_remove(m_global);\n");
0876             printf("\n");
0877             printf("        struct wl_event_loop *event_loop = wl_display_get_event_loop(m_display);\n");
0878             printf("        m_globalRemovedEvent = wl_event_loop_add_timer(event_loop, deferred_destroy_global_func, this);\n");
0879             printf("        wl_event_source_timer_update(m_globalRemovedEvent, 5000);\n");
0880             printf("    }\n");
0881             printf("\n");
0882 
0883             bool hasRequests = !interface.requests.empty();
0884 
0885             QByteArray interfaceMember = hasRequests ? "&m_" + interface.name + "_interface" : QByteArray("nullptr");
0886 
0887             //We should consider changing bind so that it doesn't special case id == 0
0888             //and use function overloading instead. Jan do you have a lot of code dependent on this behavior?
0889             printf("    %s::Resource *%s::bind(struct ::wl_client *client, uint32_t id, int version)\n", interfaceName, interfaceName);
0890             printf("    {\n");
0891             printf("        Q_ASSERT_X(!wl_client_get_object(client, id), \"QWaylandObject bind\", QStringLiteral(\"binding to object %%1 more than once\").arg(id).toLocal8Bit().constData());\n");
0892             printf("        struct ::wl_resource *handle = wl_resource_create(client, &::%s_interface, version, id);\n", interfaceName);
0893             printf("        return bind(handle);\n");
0894             printf("    }\n");
0895             printf("\n");
0896 
0897             printf("    %s::Resource *%s::bind(struct ::wl_resource *handle)\n", interfaceName, interfaceName);
0898             printf("    {\n");
0899             printf("        Resource *resource = %s_allocate();\n", interfaceNameStripped);
0900             printf("        resource->%s_object = this;\n", interfaceNameStripped);
0901             printf("\n");
0902             printf("        wl_resource_set_implementation(handle, %s, resource, destroy_func);", interfaceMember.constData());
0903             printf("\n");
0904             printf("        resource->handle = handle;\n");
0905             printf("        %s_bind_resource(resource);\n", interfaceNameStripped);
0906             printf("        return resource;\n");
0907             printf("    }\n");
0908 
0909             printf("    %s::Resource *%s::Resource::fromResource(struct ::wl_resource *resource)\n", interfaceName, interfaceName);
0910             printf("    {\n");
0911             printf("        if (Q_UNLIKELY(!resource))\n");
0912             printf("            return nullptr;\n");
0913             printf("        if (wl_resource_instance_of(resource, &::%s_interface, %s))\n",  interfaceName, interfaceMember.constData());
0914             printf("            return static_cast<Resource *>(wl_resource_get_user_data(resource));\n");
0915             printf("        return nullptr;\n");
0916             printf("    }\n");
0917 
0918             if (hasRequests) {
0919                 printf("\n");
0920                 printf("    const struct ::%s_interface %s::m_%s_interface = {", interfaceName, interfaceName, interfaceName);
0921                 bool needsComma = false;
0922                 for (const WaylandEvent &e : interface.requests) {
0923                     if (needsComma)
0924                         printf(",");
0925                     needsComma = true;
0926                     printf("\n");
0927                     printf("        %s::handle_%s", interfaceName, e.name.constData());
0928                 }
0929                 printf("\n");
0930                 printf("    };\n");
0931 
0932                 for (const WaylandEvent &e : interface.requests) {
0933                     printf("\n");
0934                     printf("    void %s::%s_", interfaceName, interfaceNameStripped);
0935                     printEvent(e, true);
0936                     printf("\n");
0937                     printf("    {\n");
0938                     printf("    }\n");
0939                 }
0940                 printf("\n");
0941 
0942                 for (const WaylandEvent &e : interface.requests) {
0943                     printf("\n");
0944                     printf("    void %s::", interfaceName);
0945 
0946                     printEventHandlerSignature(e, interfaceName, false);
0947 
0948                     printf("\n");
0949                     printf("    {\n");
0950                     printf("        Q_UNUSED(client);\n");
0951                     printf("        Resource *r = Resource::fromResource(resource);\n");
0952                     printf("        if (Q_UNLIKELY(!r->%s_object)) {\n", interfaceNameStripped);
0953                     for (const WaylandArgument &a : e.arguments) {
0954                         if (a.type == QByteArrayLiteral("fd"))
0955                             printf("        close(%s);\n", a.name.constData());
0956                     }
0957                     if (e.type == "destructor")
0958                         printf("            wl_resource_destroy(resource);\n");
0959                     printf("            return;\n");
0960                     printf("        }\n");
0961                     printf("        static_cast<%s *>(r->%s_object)->%s_%s(\n", interfaceName, interfaceNameStripped, interfaceNameStripped, e.name.constData());
0962                     printf("            r");
0963                     for (const WaylandArgument &a : e.arguments) {
0964                         printf(",\n");
0965                         QByteArray cType = waylandToCType(a.type, a.interface);
0966                         QByteArray qtType = waylandToQtType(a.type, a.interface, e.request);
0967                         const char *argumentName = a.name.constData();
0968                         if (cType == qtType)
0969                             printf("            %s", argumentName);
0970                         else if (a.type == "string")
0971                             printf("            QString::fromUtf8(%s)", argumentName);
0972                     }
0973                     printf(");\n");
0974                     printf("    }\n");
0975                 }
0976             }
0977 
0978             for (const WaylandEvent &e : interface.events) {
0979                 printf("\n");
0980                 printf("    void %s::send_", interfaceName);
0981                 printEvent(e);
0982                 printf("\n");
0983                 printf("    {\n");
0984                 printf("        Q_ASSERT_X(m_resource, \"%s::%s\", \"Uninitialised resource\");\n", interfaceName, e.name.constData());
0985                 printf("        if (Q_UNLIKELY(!m_resource)) {\n");
0986                 printf("            qWarning(\"could not call %s::%s as it's not initialised\");\n", interfaceName, e.name.constData());
0987                 printf("            return;\n");
0988                 printf("        }\n");
0989                 printf("        send_%s(\n", e.name.constData());
0990                 printf("            m_resource->handle");
0991                 for (const WaylandArgument &a : e.arguments) {
0992                     printf(",\n");
0993                     printf("            %s", a.name.constData());
0994                 }
0995                 printf(");\n");
0996                 printf("    }\n");
0997                 printf("\n");
0998 
0999                 printf("    void %s::send_", interfaceName);
1000                 printEvent(e, false, true);
1001                 printf("\n");
1002                 printf("    {\n");
1003 
1004                 for (const WaylandArgument &a : e.arguments) {
1005                     if (a.type != "array")
1006                         continue;
1007                     QByteArray array = a.name + "_data";
1008                     const char *arrayName = array.constData();
1009                     const char *variableName = a.name.constData();
1010                     printf("        struct wl_array %s;\n", arrayName);
1011                     printf("        %s.size = %s.size();\n", arrayName, variableName);
1012                     printf("        %s.data = static_cast<void *>(const_cast<char *>(%s.constData()));\n", arrayName, variableName);
1013                     printf("        %s.alloc = 0;\n", arrayName);
1014                     printf("\n");
1015                 }
1016 
1017                 printf("        %s_send_%s(\n", interfaceName, e.name.constData());
1018                 printf("            resource");
1019 
1020                 for (const WaylandArgument &a : e.arguments) {
1021                     printf(",\n");
1022                     QByteArray cType = waylandToCType(a.type, a.interface);
1023                     QByteArray qtType = waylandToQtType(a.type, a.interface, e.request);
1024                     if (a.type == "string")
1025                         printf("            %s.toUtf8().constData()", a.name.constData());
1026                     else if (a.type == "array")
1027                         printf("            &%s_data", a.name.constData());
1028                     else if (cType == qtType)
1029                         printf("            %s", a.name.constData());
1030                 }
1031 
1032                 printf(");\n");
1033                 printf("    }\n");
1034                 printf("\n");
1035             }
1036         }
1037         printf("}\n");
1038         printf("\n");
1039         printf("QT_WARNING_POP\n");
1040         printf("QT_END_NAMESPACE\n");
1041     }
1042 
1043     if (m_option == ClientHeader) {
1044         QByteArray inclusionGuard = QByteArray("QT_WAYLAND_") + preProcessorProtocolName.constData();
1045         printf("#ifndef %s\n", inclusionGuard.constData());
1046         printf("#define %s\n", inclusionGuard.constData());
1047         printf("\n");
1048         if (m_headerPath.isEmpty())
1049             printf("#include \"wayland-%s-client-protocol.h\"\n", QByteArray(m_protocolName).replace('_', '-').constData());
1050         else
1051             printf("#include <%s/wayland-%s-client-protocol.h>\n", m_headerPath.constData(), QByteArray(m_protocolName).replace('_', '-').constData());
1052         printf("#include <QByteArray>\n");
1053         printf("#include <QString>\n");
1054         printf("\n");
1055         printf("struct wl_registry;\n");
1056         printf("\n");
1057         printf("QT_BEGIN_NAMESPACE\n");
1058         printf("QT_WARNING_PUSH\n");
1059         printf("QT_WARNING_DISABLE_GCC(\"-Wmissing-field-initializers\")\n");
1060 
1061         QByteArray clientExport;
1062 
1063         if (m_headerPath.size()) {
1064             clientExport = QByteArray("Q_WAYLAND_CLIENT_") + preProcessorProtocolName + "_EXPORT";
1065             printf("\n");
1066             printf("#if !defined(%s)\n", clientExport.constData());
1067             printf("#  if defined(QT_SHARED)\n");
1068             printf("#    define %s Q_DECL_EXPORT\n", clientExport.constData());
1069             printf("#  else\n");
1070             printf("#    define %s\n", clientExport.constData());
1071             printf("#  endif\n");
1072             printf("#endif\n");
1073         }
1074         printf("\n");
1075         printf("namespace QtWayland {\n");
1076 
1077         bool needsNewLine = false;
1078         for (const WaylandInterface &interface : interfaces) {
1079 
1080             if (ignoreInterface(interface.name))
1081                 continue;
1082 
1083             if (needsNewLine)
1084                 printf("\n");
1085             needsNewLine = true;
1086 
1087             const char *interfaceName = interface.name.constData();
1088 
1089             QByteArray stripped = stripInterfaceName(interface.name);
1090             const char *interfaceNameStripped = stripped.constData();
1091 
1092             printf("    class %s %s\n    {\n", clientExport.constData(), interfaceName);
1093             printf("    public:\n");
1094             printf("        %s(struct ::wl_registry *registry, int id, int version);\n", interfaceName);
1095             printf("        %s(struct ::%s *object);\n", interfaceName, interfaceName);
1096             printf("        %s();\n", interfaceName);
1097             printf("\n");
1098             printf("        virtual ~%s();\n", interfaceName);
1099             printf("\n");
1100             printf("        void init(struct ::wl_registry *registry, int id, int version);\n");
1101             printf("        void init(struct ::%s *object);\n", interfaceName);
1102             printf("\n");
1103             printf("        struct ::%s *object() { return m_%s; }\n", interfaceName, interfaceName);
1104             printf("        const struct ::%s *object() const { return m_%s; }\n", interfaceName, interfaceName);
1105             printf("        static %s *fromObject(struct ::%s *object);\n", interfaceName, interfaceName);
1106             printf("\n");
1107             printf("        bool isInitialized() const;\n");
1108             printf("\n");
1109             printf("        static const struct ::wl_interface *interface();\n");
1110 
1111             printEnums(interface.enums);
1112 
1113             if (!interface.requests.empty()) {
1114                 printf("\n");
1115                 for (const WaylandEvent &e : interface.requests) {
1116                     const WaylandArgument *new_id = newIdArgument(e.arguments);
1117                     QByteArray new_id_str = "void ";
1118                     if (new_id) {
1119                         if (new_id->interface.isEmpty())
1120                             new_id_str = "void *";
1121                         else
1122                             new_id_str = "struct ::" + new_id->interface + " *";
1123                     }
1124                     printf("        %s", new_id_str.constData());
1125                     printEvent(e);
1126                     printf(";\n");
1127                 }
1128             }
1129 
1130             bool hasEvents = !interface.events.empty();
1131 
1132             if (hasEvents) {
1133                 printf("\n");
1134                 printf("    protected:\n");
1135                 for (const WaylandEvent &e : interface.events) {
1136                     printf("        virtual void %s_", interfaceNameStripped);
1137                     printEvent(e);
1138                     printf(";\n");
1139                 }
1140             }
1141 
1142             printf("\n");
1143             printf("    private:\n");
1144             if (hasEvents) {
1145                 printf("        void init_listener();\n");
1146                 printf("        static const struct %s_listener m_%s_listener;\n", interfaceName, interfaceName);
1147                 for (const WaylandEvent &e : interface.events) {
1148                     printf("        static void ");
1149 
1150                     printEventHandlerSignature(e, interfaceName);
1151                     printf(";\n");
1152                 }
1153             }
1154             printf("        struct ::%s *m_%s;\n", interfaceName, interfaceName);
1155             printf("    };\n");
1156         }
1157         printf("}\n");
1158         printf("\n");
1159         printf("QT_WARNING_POP\n");
1160         printf("QT_END_NAMESPACE\n");
1161         printf("\n");
1162         printf("#endif\n");
1163     }
1164 
1165     if (m_option == ClientCode) {
1166         if (m_headerPath.isEmpty())
1167             printf("#include \"qwayland-%s.h\"\n", QByteArray(m_protocolName).replace('_', '-').constData());
1168         else
1169             printf("#include <%s/qwayland-%s.h>\n", m_headerPath.constData(), QByteArray(m_protocolName).replace('_', '-').constData());
1170         printf("\n");
1171         printf("QT_BEGIN_NAMESPACE\n");
1172         printf("QT_WARNING_PUSH\n");
1173         printf("QT_WARNING_DISABLE_GCC(\"-Wmissing-field-initializers\")\n");
1174         printf("\n");
1175         printf("namespace QtWayland {\n");
1176         printf("\n");
1177 
1178         // wl_registry_bind is part of the protocol, so we can't use that... instead we use core
1179         // libwayland API to do the same thing a wayland-scanner generated wl_registry_bind would.
1180         printf("static inline void *wlRegistryBind(struct ::wl_registry *registry, uint32_t name, const struct ::wl_interface *interface, uint32_t version)\n");
1181         printf("{\n");
1182         printf("    const uint32_t bindOpCode = 0;\n");
1183         printf("#if (WAYLAND_VERSION_MAJOR == 1 && WAYLAND_VERSION_MINOR > 10) || WAYLAND_VERSION_MAJOR > 1\n");
1184         printf("    return (void *) wl_proxy_marshal_constructor_versioned((struct wl_proxy *) registry,\n");
1185         printf("        bindOpCode, interface, version, name, interface->name, version, nullptr);\n");
1186         printf("#else\n");
1187         printf("    return (void *) wl_proxy_marshal_constructor((struct wl_proxy *) registry,\n");
1188         printf("        bindOpCode, interface, name, interface->name, version, nullptr);\n");
1189         printf("#endif\n");
1190         printf("}\n");
1191         printf("\n");
1192 
1193         bool needsNewLine = false;
1194         for (const WaylandInterface &interface : interfaces) {
1195 
1196             if (ignoreInterface(interface.name))
1197                 continue;
1198 
1199             if (needsNewLine)
1200                 printf("\n");
1201             needsNewLine = true;
1202 
1203             const char *interfaceName = interface.name.constData();
1204 
1205             QByteArray stripped = stripInterfaceName(interface.name);
1206             const char *interfaceNameStripped = stripped.constData();
1207 
1208             bool hasEvents = !interface.events.empty();
1209 
1210             printf("    %s::%s(struct ::wl_registry *registry, int id, int version)\n", interfaceName, interfaceName);
1211             printf("    {\n");
1212             printf("        init(registry, id, version);\n");
1213             printf("    }\n");
1214             printf("\n");
1215 
1216             printf("    %s::%s(struct ::%s *obj)\n", interfaceName, interfaceName, interfaceName);
1217             printf("        : m_%s(obj)\n", interfaceName);
1218             printf("    {\n");
1219             if (hasEvents)
1220                 printf("        init_listener();\n");
1221             printf("    }\n");
1222             printf("\n");
1223 
1224             printf("    %s::%s()\n", interfaceName, interfaceName);
1225             printf("        : m_%s(nullptr)\n", interfaceName);
1226             printf("    {\n");
1227             printf("    }\n");
1228             printf("\n");
1229 
1230             printf("    %s::~%s()\n", interfaceName, interfaceName);
1231             printf("    {\n");
1232             printf("    }\n");
1233             printf("\n");
1234 
1235             printf("    void %s::init(struct ::wl_registry *registry, int id, int version)\n", interfaceName);
1236             printf("    {\n");
1237             printf("        m_%s = static_cast<struct ::%s *>(wlRegistryBind(registry, id, &%s_interface, version));\n", interfaceName, interfaceName, interfaceName);
1238             if (hasEvents)
1239                 printf("        init_listener();\n");
1240             printf("    }\n");
1241             printf("\n");
1242 
1243             printf("    void %s::init(struct ::%s *obj)\n", interfaceName, interfaceName);
1244             printf("    {\n");
1245             printf("        m_%s = obj;\n", interfaceName);
1246             if (hasEvents)
1247                 printf("        init_listener();\n");
1248             printf("    }\n");
1249             printf("\n");
1250 
1251             printf("    %s *%s::fromObject(struct ::%s *object)\n", interfaceName, interfaceName, interfaceName);
1252             printf("    {\n");
1253             if (hasEvents) {
1254                 printf("        if (wl_proxy_get_listener((struct ::wl_proxy *)object) != (void *)&m_%s_listener)\n", interfaceName);
1255                 printf("            return nullptr;\n");
1256             }
1257             printf("        return static_cast<%s *>(%s_get_user_data(object));\n", interfaceName, interfaceName);
1258             printf("    }\n");
1259             printf("\n");
1260 
1261             printf("    bool %s::isInitialized() const\n", interfaceName);
1262             printf("    {\n");
1263             printf("        return m_%s != nullptr;\n", interfaceName);
1264             printf("    }\n");
1265             printf("\n");
1266 
1267             printf("    const struct wl_interface *%s::interface()\n", interfaceName);
1268             printf("    {\n");
1269             printf("        return &::%s_interface;\n", interfaceName);
1270             printf("    }\n");
1271 
1272             for (const WaylandEvent &e : interface.requests) {
1273                 printf("\n");
1274                 const WaylandArgument *new_id = newIdArgument(e.arguments);
1275                 QByteArray new_id_str = "void ";
1276                 if (new_id) {
1277                     if (new_id->interface.isEmpty())
1278                         new_id_str = "void *";
1279                     else
1280                         new_id_str = "struct ::" + new_id->interface + " *";
1281                 }
1282                 printf("    %s%s::", new_id_str.constData(), interfaceName);
1283                 printEvent(e);
1284                 printf("\n");
1285                 printf("    {\n");
1286                 for (const WaylandArgument &a : e.arguments) {
1287                     if (a.type != "array")
1288                         continue;
1289                     QByteArray array = a.name + "_data";
1290                     const char *arrayName = array.constData();
1291                     const char *variableName = a.name.constData();
1292                     printf("        struct wl_array %s;\n", arrayName);
1293                     printf("        %s.size = %s.size();\n", arrayName, variableName);
1294                     printf("        %s.data = static_cast<void *>(const_cast<char *>(%s.constData()));\n", arrayName, variableName);
1295                     printf("        %s.alloc = 0;\n", arrayName);
1296                     printf("\n");
1297                 }
1298                 int actualArgumentCount = new_id ? int(e.arguments.size()) - 1 : int(e.arguments.size());
1299                 printf("        %s%s_%s(\n", new_id ? "return " : "", interfaceName, e.name.constData());
1300                 printf("            m_%s%s", interfaceName, actualArgumentCount > 0 ? "," : "");
1301                 bool needsComma = false;
1302                 for (const WaylandArgument &a : e.arguments) {
1303                     bool isNewId = a.type == "new_id";
1304                     if (isNewId && !a.interface.isEmpty())
1305                         continue;
1306                     if (needsComma)
1307                         printf(",");
1308                     needsComma = true;
1309                     printf("\n");
1310                     if (isNewId) {
1311                         printf("            interface,\n");
1312                         printf("            version");
1313                     } else {
1314                         QByteArray cType = waylandToCType(a.type, a.interface);
1315                         QByteArray qtType = waylandToQtType(a.type, a.interface, e.request);
1316                         if (a.type == "string")
1317                             printf("            %s.toUtf8().constData()", a.name.constData());
1318                         else if (a.type == "array")
1319                             printf("            &%s_data", a.name.constData());
1320                         else if (cType == qtType)
1321                             printf("            %s", a.name.constData());
1322                     }
1323                 }
1324                 printf(");\n");
1325                 if (e.type == "destructor")
1326                     printf("        m_%s = nullptr;\n", interfaceName);
1327                 printf("    }\n");
1328             }
1329 
1330             if (hasEvents) {
1331                 printf("\n");
1332                 for (const WaylandEvent &e : interface.events) {
1333                     printf("    void %s::%s_", interfaceName, interfaceNameStripped);
1334                     printEvent(e, true);
1335                     printf("\n");
1336                     printf("    {\n");
1337                     printf("    }\n");
1338                     printf("\n");
1339                     printf("    void %s::", interfaceName);
1340                     printEventHandlerSignature(e, interfaceName, false);
1341                     printf("\n");
1342                     printf("    {\n");
1343                     printf("        Q_UNUSED(object);\n");
1344                     printf("        static_cast<%s *>(data)->%s_%s(", interfaceName, interfaceNameStripped, e.name.constData());
1345                     bool needsComma = false;
1346                     for (const WaylandArgument &a : e.arguments) {
1347                         if (needsComma)
1348                             printf(",");
1349                         needsComma = true;
1350                         printf("\n");
1351                         const char *argumentName = a.name.constData();
1352                         if (a.type == "string")
1353                             printf("            QString::fromUtf8(%s)", argumentName);
1354                         else
1355                             printf("            %s", argumentName);
1356                     }
1357                     printf(");\n");
1358 
1359                     printf("    }\n");
1360                     printf("\n");
1361                 }
1362                 printf("    const struct %s_listener %s::m_%s_listener = {\n", interfaceName, interfaceName, interfaceName);
1363                 for (const WaylandEvent &e : interface.events) {
1364                     printf("        %s::handle_%s,\n", interfaceName, e.name.constData());
1365                 }
1366                 printf("    };\n");
1367                 printf("\n");
1368 
1369                 printf("    void %s::init_listener()\n", interfaceName);
1370                 printf("    {\n");
1371                 printf("        %s_add_listener(m_%s, &m_%s_listener, this);\n", interfaceName, interfaceName, interfaceName);
1372                 printf("    }\n");
1373             }
1374         }
1375         printf("}\n");
1376         printf("\n");
1377         printf("QT_WARNING_POP\n");
1378         printf("QT_END_NAMESPACE\n");
1379     }
1380 
1381     return true;
1382 }
1383 
1384 void Scanner::printErrors()
1385 {
1386     if (m_xml->hasError())
1387         fprintf(stderr, "XML error: %s\nLine %lld, column %lld\n", m_xml->errorString().toLocal8Bit().constData(), m_xml->lineNumber(), m_xml->columnNumber());
1388 }
1389 
1390 int main(int argc, char **argv)
1391 {
1392     QCoreApplication app(argc, argv);
1393     Scanner scanner;
1394 
1395     if (!scanner.parseArguments(argc, argv)) {
1396         scanner.printUsage();
1397         return EXIT_FAILURE;
1398     }
1399 
1400     if (!scanner.process()) {
1401         scanner.printErrors();
1402         return EXIT_FAILURE;
1403     }
1404 
1405     return EXIT_SUCCESS;
1406 }