Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qtwaylandscanner.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3// Qt-Security score:critical reason:network-protocol
4
5#include <QCoreApplication>
6#include <QFile>
7#include <QFileInfo>
8#include <QXmlStreamReader>
9
10#include <vector>
11
13{
14public:
15 explicit Scanner() {}
16 ~Scanner() { delete m_xml; }
17
18 bool parseArguments(int argc, char **argv);
19 void printUsage();
20 bool process();
22
23private:
24 struct WaylandEnumEntry {
25 QByteArray name;
26 QByteArray value;
27 QByteArray summary;
28 };
29
30 struct WaylandEnum {
31 QByteArray name;
32
33 std::vector<WaylandEnumEntry> entries;
34 };
35
36 struct WaylandArgument {
37 QByteArray name;
38 QByteArray type;
39 QByteArray interface;
40 QByteArray summary;
41 bool allowNull;
42 };
43
44 struct WaylandEvent {
45 bool request;
46 QByteArray name;
47 QByteArray type;
48 std::vector<WaylandArgument> arguments;
49 };
50
51 struct WaylandInterface {
52 QByteArray name;
53 int version;
54
55 std::vector<WaylandEnum> enums;
56 std::vector<WaylandEvent> events;
57 std::vector<WaylandEvent> requests;
58 };
59
60 bool isServerSide();
61 bool parseOption(const QByteArray &str);
62
63 QByteArray byteArrayValue(const QXmlStreamReader &xml, const char *name);
64 int intValue(const QXmlStreamReader &xml, const char *name, int defaultValue = 0);
65 bool boolValue(const QXmlStreamReader &xml, const char *name);
66 WaylandEvent readEvent(QXmlStreamReader &xml, bool request);
67 Scanner::WaylandEnum readEnum(QXmlStreamReader &xml);
68 Scanner::WaylandInterface readInterface(QXmlStreamReader &xml);
69 QByteArray waylandToCType(const QByteArray &waylandType, const QByteArray &interface);
70 QByteArray waylandToQtType(const QByteArray &waylandType, const QByteArray &interface, bool cStyleArray);
71 const Scanner::WaylandArgument *newIdArgument(const std::vector<WaylandArgument> &arguments);
72
73 void printEvent(const WaylandEvent &e, bool omitNames = false, bool withResource = false);
74 void printEventHandlerSignature(const WaylandEvent &e, const char *interfaceName, bool deepIndent = true);
75 void printEnums(const std::vector<WaylandEnum> &enums);
76
77 QByteArray stripInterfaceName(const QByteArray &name);
78 bool ignoreInterface(const QByteArray &name);
79
80 enum Option {
81 ClientHeader,
82 ServerHeader,
83 ClientCode,
84 ServerCode
85 } m_option;
86
87 QByteArray m_protocolName;
88 QByteArray m_protocolFilePath;
89 QByteArray m_scannerName;
90 QByteArray m_headerPath;
91 QByteArray m_prefix;
92 QByteArray m_buildMacro;
93 QList <QByteArray> m_includes;
94 QXmlStreamReader *m_xml = nullptr;
95};
96
97bool Scanner::parseArguments(int argc, char **argv)
98{
99 QList<QByteArray> args;
100 args.reserve(argc);
101 for (int i = 0; i < argc; ++i)
102 args << QByteArray(argv[i]);
103
104 m_scannerName = args[0];
105
106 if (argc <= 2 || !parseOption(args[1]))
107 return false;
108
109 m_protocolFilePath = args[2];
110
111 if (argc > 3 && !args[3].startsWith('-')) {
112 // legacy positional arguments
113 m_headerPath = args[3];
114 if (argc == 5)
115 m_prefix = args[4];
116 } else {
117 // --header-path=<path> (14 characters)
118 // --prefix=<prefix> (9 characters)
119 // --add-include=<include> (14 characters)
120 for (int pos = 3; pos < argc; pos++) {
121 const QByteArray &option = args[pos];
122 if (option.startsWith("--header-path=")) {
123 m_headerPath = option.mid(14);
124 } else if (option.startsWith("--prefix=")) {
125 m_prefix = option.mid(10);
126 } else if (option.startsWith("--build-macro=")) {
127 m_buildMacro = option.mid(14);
128 } else if (option.startsWith("--add-include=")) {
129 auto include = option.mid(14);
130 if (!include.isEmpty())
131 m_includes << include;
132 } else {
133 return false;
134 }
135 }
136 }
137
138 return true;
139}
140
142{
143 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());
144}
145
146bool Scanner::isServerSide()
147{
148 return m_option == ServerHeader || m_option == ServerCode;
149}
150
151bool Scanner::parseOption(const QByteArray &str)
152{
153 if (str == "client-header")
154 m_option = ClientHeader;
155 else if (str == "server-header")
156 m_option = ServerHeader;
157 else if (str == "client-code")
158 m_option = ClientCode;
159 else if (str == "server-code")
160 m_option = ServerCode;
161 else
162 return false;
163
164 return true;
165}
166
167QByteArray Scanner::byteArrayValue(const QXmlStreamReader &xml, const char *name)
168{
169 if (xml.attributes().hasAttribute(name))
170 return xml.attributes().value(name).toUtf8();
171 return QByteArray();
172}
173
174int Scanner::intValue(const QXmlStreamReader &xml, const char *name, int defaultValue)
175{
176 bool ok;
177 int result = byteArrayValue(xml, name).toInt(&ok);
178 return ok ? result : defaultValue;
179}
180
181bool Scanner::boolValue(const QXmlStreamReader &xml, const char *name)
182{
183 return byteArrayValue(xml, name) == "true";
184}
185
186Scanner::WaylandEvent Scanner::readEvent(QXmlStreamReader &xml, bool request)
187{
188 WaylandEvent event = {
189 .request = request,
190 .name = byteArrayValue(xml, "name"),
191 .type = byteArrayValue(xml, "type"),
192 .arguments = {},
193 };
194 while (xml.readNextStartElement()) {
195 if (xml.name() == u"arg") {
196 WaylandArgument argument = {
197 .name = byteArrayValue(xml, "name"),
198 .type = byteArrayValue(xml, "type"),
199 .interface = byteArrayValue(xml, "interface"),
200 .summary = byteArrayValue(xml, "summary"),
201 .allowNull = boolValue(xml, "allow-null"),
202 };
203 event.arguments.push_back(std::move(argument));
204 }
205
206 xml.skipCurrentElement();
207 }
208 return event;
209}
210
211Scanner::WaylandEnum Scanner::readEnum(QXmlStreamReader &xml)
212{
213 WaylandEnum result = {
214 .name = byteArrayValue(xml, "name"),
215 .entries = {},
216 };
217
218 while (xml.readNextStartElement()) {
219 if (xml.name() == u"entry") {
220 WaylandEnumEntry entry = {
221 .name = byteArrayValue(xml, "name"),
222 .value = byteArrayValue(xml, "value"),
223 .summary = byteArrayValue(xml, "summary"),
224 };
225 result.entries.push_back(std::move(entry));
226 }
227
228 xml.skipCurrentElement();
229 }
230
231 return result;
232}
233
234Scanner::WaylandInterface Scanner::readInterface(QXmlStreamReader &xml)
235{
236 WaylandInterface interface = {
237 .name = byteArrayValue(xml, "name"),
238 .version = intValue(xml, "version", 1),
239 .enums = {},
240 .events = {},
241 .requests = {},
242 };
243
244 while (xml.readNextStartElement()) {
245 if (xml.name() == u"event")
246 interface.events.push_back(readEvent(xml, false));
247 else if (xml.name() == u"request")
248 interface.requests.push_back(readEvent(xml, true));
249 else if (xml.name() == u"enum")
250 interface.enums.push_back(readEnum(xml));
251 else
252 xml.skipCurrentElement();
253 }
254
255 return interface;
256}
257
258QByteArray Scanner::waylandToCType(const QByteArray &waylandType, const QByteArray &interface)
259{
260 if (waylandType == "string")
261 return "const char *";
262 else if (waylandType == "int")
263 return "int32_t";
264 else if (waylandType == "uint")
265 return "uint32_t";
266 else if (waylandType == "fixed")
267 return "wl_fixed_t";
268 else if (waylandType == "fd")
269 return "int32_t";
270 else if (waylandType == "array")
271 return "wl_array *";
272 else if (waylandType == "object" || waylandType == "new_id") {
273 if (isServerSide())
274 return "struct ::wl_resource *";
275 if (interface.isEmpty())
276 return "struct ::wl_object *";
277 return "struct ::" + interface + " *";
278 }
279 return waylandType;
280}
281
282QByteArray Scanner::waylandToQtType(const QByteArray &waylandType, const QByteArray &interface, bool cStyleArray)
283{
284 if (waylandType == "string")
285 return "const QString &";
286 else if (waylandType == "array")
287 return cStyleArray ? "wl_array *" : "const QByteArray &";
288 else
289 return waylandToCType(waylandType, interface);
290}
291
292const Scanner::WaylandArgument *Scanner::newIdArgument(const std::vector<WaylandArgument> &arguments)
293{
294 for (const WaylandArgument &a : arguments) {
295 if (a.type == "new_id")
296 return &a;
297 }
298 return nullptr;
299}
300
301void Scanner::printEvent(const WaylandEvent &e, bool omitNames, bool withResource)
302{
303 printf("%s(", e.name.constData());
304 bool needsComma = false;
305 if (isServerSide()) {
306 if (e.request) {
307 printf("Resource *%s", omitNames ? "" : "resource");
308 needsComma = true;
309 } else if (withResource) {
310 printf("struct ::wl_resource *%s", omitNames ? "" : "resource");
311 needsComma = true;
312 }
313 }
314 for (const WaylandArgument &a : e.arguments) {
315 bool isNewId = a.type == "new_id";
316 if (isNewId && !isServerSide() && (a.interface.isEmpty() != e.request))
317 continue;
318 if (needsComma)
319 printf(", ");
320 needsComma = true;
321 if (isNewId) {
322 if (isServerSide()) {
323 if (e.request) {
324 printf("uint32_t");
325 if (!omitNames)
326 printf(" %s", a.name.constData());
327 continue;
328 }
329 } else {
330 if (e.request) {
331 printf("const struct ::wl_interface *%s, uint32_t%s", omitNames ? "" : "interface", omitNames ? "" : " version");
332 continue;
333 }
334 }
335 }
336
337 QByteArray qtType = waylandToQtType(a.type, a.interface, e.request == isServerSide());
338 printf("%s%s%s", qtType.constData(), qtType.endsWith("&") || qtType.endsWith("*") ? "" : " ", omitNames ? "" : a.name.constData());
339 }
340 printf(")");
341}
342
343void Scanner::printEventHandlerSignature(const WaylandEvent &e, const char *interfaceName, bool deepIndent)
344{
345 const char *indent = deepIndent ? " " : "";
346 printf("handle_%s(\n", e.name.constData());
347 if (isServerSide()) {
348 printf(" %s::wl_client *client,\n", indent);
349 printf(" %sstruct wl_resource *resource", indent);
350 } else {
351 printf(" %svoid *data,\n", indent);
352 printf(" %sstruct ::%s *object", indent, interfaceName);
353 }
354 for (const WaylandArgument &a : e.arguments) {
355 printf(",\n");
356 bool isNewId = a.type == "new_id";
357 if (isServerSide() && isNewId) {
358 printf(" %suint32_t %s", indent, a.name.constData());
359 } else {
360 QByteArray cType = waylandToCType(a.type, a.interface);
361 printf(" %s%s%s%s", indent, cType.constData(), cType.endsWith("*") ? "" : " ", a.name.constData());
362 }
363 }
364 printf(")");
365}
366
367void Scanner::printEnums(const std::vector<WaylandEnum> &enums)
368{
369 for (const WaylandEnum &e : enums) {
370 printf("\n");
371 printf(" enum %s {\n", e.name.constData());
372 for (const WaylandEnumEntry &entry : e.entries) {
373 printf(" %s_%s = %s,", e.name.constData(), entry.name.constData(), entry.value.constData());
374 if (!entry.summary.isNull())
375 printf(" // %s", entry.summary.constData());
376 printf("\n");
377 }
378 printf(" };\n");
379 }
380}
381
382QByteArray Scanner::stripInterfaceName(const QByteArray &name)
383{
384 if (!m_prefix.isEmpty() && name.startsWith(m_prefix))
385 return name.mid(m_prefix.size());
386 if (name.startsWith("qt_") || name.startsWith("wl_"))
387 return name.mid(3);
388
389 return name;
390}
391
392bool Scanner::ignoreInterface(const QByteArray &name)
393{
394 return name == "wl_display"
395 || (isServerSide() && name == "wl_registry");
396}
397
399{
400 QFile file(m_protocolFilePath);
401 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
402 fprintf(stderr, "Unable to open file %s\n", m_protocolFilePath.constData());
403 return false;
404 }
405
406 m_xml = new QXmlStreamReader(&file);
407 if (!m_xml->readNextStartElement())
408 return false;
409
410 if (m_xml->name() != u"protocol") {
411 m_xml->raiseError(QStringLiteral("The file is not a wayland protocol file."));
412 return false;
413 }
414
415 m_protocolName = byteArrayValue(*m_xml, "name");
416
417 if (m_protocolName.isEmpty()) {
418 m_xml->raiseError(QStringLiteral("Missing protocol name."));
419 return false;
420 }
421
422 //We should convert - to _ so that the preprocessor wont generate code which will lead to unexpected behavior
423 //However, the wayland-scanner doesn't do so we will do the same for now
424 //QByteArray preProcessorProtocolName = QByteArray(m_protocolName).replace('-', '_').toUpper();
425 QByteArray preProcessorProtocolName = QByteArray(m_protocolName).toUpper();
426
427 const QByteArray fileBaseName = QFileInfo(file).completeBaseName().toLocal8Bit();
428
429 std::vector<WaylandInterface> interfaces;
430
431 while (m_xml->readNextStartElement()) {
432 if (m_xml->name() == u"interface")
433 interfaces.push_back(readInterface(*m_xml));
434 else
435 m_xml->skipCurrentElement();
436 }
437
438 if (m_xml->hasError())
439 return false;
440
441 printf("// This file was generated by qtwaylandscanner\n");
442 printf("// source file is %s\n\n", qPrintable(QFileInfo(file).fileName()));
443
444 for (auto b : std::as_const(m_includes))
445 printf("#include %s\n", b.constData());
446
447 auto printExportMacro = [this](const char *prefix, const QByteArray &preProcessorProtocolName) {
448 QByteArray exportMacro = prefix + preProcessorProtocolName + "_EXPORT";
449 printf("#if !defined(%s)\n", exportMacro.constData());
450 printf("# if defined(QT_SHARED) && !defined(QT_STATIC)\n");
451 if (m_buildMacro.isEmpty()) {
452 printf("# define %s Q_DECL_EXPORT\n", exportMacro.constData());
453 } else {
454 printf("# if defined(%s)\n", m_buildMacro.constData());
455 printf("# define %s Q_DECL_EXPORT\n", exportMacro.constData());
456 printf("# else\n");
457 printf("# define %s Q_DECL_IMPORT\n", exportMacro.constData());
458 printf("# endif\n");
459 }
460 printf("# else\n");
461 printf("# define %s\n", exportMacro.constData());
462 printf("# endif\n");
463 printf("#endif\n");
464 return exportMacro;
465 };
466
467 if (m_option == ServerHeader) {
468 QByteArray inclusionGuard = QByteArray("QT_WAYLAND_SERVER_") + preProcessorProtocolName.constData();
469 printf("#ifndef %s\n", inclusionGuard.constData());
470 printf("#define %s\n", inclusionGuard.constData());
471 printf("\n");
472 printf("#include \"wayland-server-core.h\"\n");
473 if (m_headerPath.isEmpty())
474 printf("#include \"wayland-%s-server-protocol.h\"\n", fileBaseName.constData());
475 else
476 printf("#include <%s/wayland-%s-server-protocol.h>\n", m_headerPath.constData(), fileBaseName.constData());
477 printf("#include <QByteArray>\n");
478 printf("#include <QMultiMap>\n");
479 printf("#include <QString>\n");
480
481 printf("\n");
482 printf("#ifndef WAYLAND_VERSION_CHECK\n");
483 printf("#define WAYLAND_VERSION_CHECK(major, minor, micro) \\\n");
484 printf(" ((WAYLAND_VERSION_MAJOR > (major)) || \\\n");
485 printf(" (WAYLAND_VERSION_MAJOR == (major) && WAYLAND_VERSION_MINOR > (minor)) || \\\n");
486 printf(" (WAYLAND_VERSION_MAJOR == (major) && WAYLAND_VERSION_MINOR == (minor) && WAYLAND_VERSION_MICRO >= (micro)))\n");
487 printf("#endif\n");
488
489 printf("\n");
490 printf("QT_BEGIN_NAMESPACE\n");
491 printf("QT_WARNING_PUSH\n");
492 printf("QT_WARNING_DISABLE_GCC(\"-Wmissing-field-initializers\")\n");
493 printf("QT_WARNING_DISABLE_CLANG(\"-Wmissing-field-initializers\")\n");
494 QByteArray serverExport;
495 if (m_headerPath.size())
496 serverExport = printExportMacro("Q_WAYLAND_SERVER_", preProcessorProtocolName);
497 printf("\n");
498 printf("namespace QtWaylandServer {\n");
499
500 bool needsNewLine = false;
501 for (const WaylandInterface &interface : interfaces) {
502
503 if (ignoreInterface(interface.name))
504 continue;
505
506 if (needsNewLine)
507 printf("\n");
508 needsNewLine = true;
509
510 const char *interfaceName = interface.name.constData();
511
512 QByteArray stripped = stripInterfaceName(interface.name);
513 const char *interfaceNameStripped = stripped.constData();
514
515 printf(" class %s %s\n {\n", serverExport.constData(), interfaceName);
516 printf(" public:\n");
517 printf(" %s(struct ::wl_client *client, uint32_t id, int version);\n", interfaceName);
518 printf(" %s(struct ::wl_display *display, int version);\n", interfaceName);
519 printf(" %s(struct ::wl_resource *resource);\n", interfaceName);
520 printf(" %s();\n", interfaceName);
521 printf("\n");
522 printf(" virtual ~%s();\n", interfaceName);
523 printf("\n");
524 printf(" class Resource\n");
525 printf(" {\n");
526 printf(" public:\n");
527 printf(" Resource() : %s_object(nullptr), handle(nullptr) {}\n", interfaceNameStripped);
528 printf(" virtual ~Resource() {}\n");
529 printf("\n");
530 printf(" %s *%s_object;\n", interfaceName, interfaceNameStripped);
531 printf(" %s *object() { return %s_object; } \n", interfaceName, interfaceNameStripped);
532 printf(" struct ::wl_resource *handle;\n");
533 printf("\n");
534 printf(" struct ::wl_client *client() const { return wl_resource_get_client(handle); }\n");
535 printf(" int version() const { return wl_resource_get_version(handle); }\n");
536 printf("\n");
537 printf(" static Resource *fromResource(struct ::wl_resource *resource);\n");
538 printf(" };\n");
539 printf("\n");
540 printf(" void init(struct ::wl_client *client, uint32_t id, int version);\n");
541 printf(" void init(struct ::wl_display *display, int version);\n");
542 printf(" void init(struct ::wl_resource *resource);\n");
543 printf("\n");
544 printf(" Resource *add(struct ::wl_client *client, int version);\n");
545 printf(" Resource *add(struct ::wl_client *client, uint32_t id, int version);\n");
546 printf(" Resource *add(struct wl_list *resource_list, struct ::wl_client *client, uint32_t id, int version);\n");
547 printf("\n");
548 printf(" Resource *resource() { return m_resource; }\n");
549 printf(" const Resource *resource() const { return m_resource; }\n");
550 printf("\n");
551 printf(" QMultiMap<struct ::wl_client*, Resource*> resourceMap() { return m_resource_map; }\n");
552 printf(" const QMultiMap<struct ::wl_client*, Resource*> resourceMap() const { return m_resource_map; }\n");
553 printf("\n");
554 printf(" bool isGlobal() const { return m_global != nullptr; }\n");
555 printf(" bool isResource() const { return m_resource != nullptr; }\n");
556 printf("\n");
557 printf(" static const struct ::wl_interface *interface();\n");
558 printf(" static QByteArray interfaceName() { return interface()->name; }\n");
559 printf(" static int interfaceVersion() { return interface()->version; }\n");
560 printf("\n");
561
562 printEnums(interface.enums);
563
564 bool hasEvents = !interface.events.empty();
565
566 if (hasEvents) {
567 printf("\n");
568 for (const WaylandEvent &e : interface.events) {
569 printf(" void send_");
570 printEvent(e);
571 printf(";\n");
572 printf(" void send_");
573 printEvent(e, false, true);
574 printf(";\n");
575 }
576 }
577
578 printf("\n");
579 printf(" protected:\n");
580 printf(" virtual Resource *%s_allocate();\n", interfaceNameStripped);
581 printf("\n");
582 printf(" virtual void %s_bind_resource(Resource *resource);\n", interfaceNameStripped);
583 printf(" virtual void %s_destroy_resource(Resource *resource);\n", interfaceNameStripped);
584
585 bool hasRequests = !interface.requests.empty();
586
587 if (hasRequests) {
588 printf("\n");
589 for (const WaylandEvent &e : interface.requests) {
590 printf(" virtual void %s_", interfaceNameStripped);
591 printEvent(e);
592 printf(";\n");
593 }
594 }
595
596 printf("\n");
597 printf(" private:\n");
598 printf(" static void bind_func(struct ::wl_client *client, void *data, uint32_t version, uint32_t id);\n");
599 printf(" static void destroy_func(struct ::wl_resource *client_resource);\n");
600 printf(" static void display_destroy_func(struct ::wl_listener *listener, void *data);\n");
601 printf("\n");
602 printf(" Resource *bind(struct ::wl_client *client, uint32_t id, int version);\n");
603 printf(" Resource *bind(struct ::wl_resource *handle);\n");
604
605 if (hasRequests) {
606 printf("\n");
607 printf(" static const struct ::%s_interface m_%s_interface;\n", interfaceName, interfaceName);
608
609 printf("\n");
610 for (const WaylandEvent &e : interface.requests) {
611 printf(" static void ");
612
613 printEventHandlerSignature(e, interfaceName);
614 printf(";\n");
615 }
616 }
617
618 printf("\n");
619 printf(" QMultiMap<struct ::wl_client*, Resource*> m_resource_map;\n");
620 printf(" Resource *m_resource;\n");
621 printf(" struct ::wl_global *m_global;\n");
622 printf(" struct DisplayDestroyedListener : ::wl_listener {\n");
623 printf(" %s *parent;\n", interfaceName);
624 printf(" };\n");
625 printf(" DisplayDestroyedListener m_displayDestroyedListener;\n");
626 printf(" };\n");
627 }
628
629 printf("}\n");
630 printf("\n");
631 printf("QT_WARNING_POP\n");
632 printf("QT_END_NAMESPACE\n");
633 printf("\n");
634 printf("#endif\n");
635 }
636
637 if (m_option == ServerCode) {
638 if (m_headerPath.isEmpty())
639 printf("#include \"qwayland-server-%s.h\"\n", fileBaseName.constData());
640 else
641 printf("#include <%s/qwayland-server-%s.h>\n", m_headerPath.constData(), fileBaseName.constData());
642 printf("\n");
643 printf("QT_BEGIN_NAMESPACE\n");
644 printf("QT_WARNING_PUSH\n");
645 printf("QT_WARNING_DISABLE_GCC(\"-Wmissing-field-initializers\")\n");
646 printf("QT_WARNING_DISABLE_CLANG(\"-Wmissing-field-initializers\")\n");
647 printf("\n");
648 printf("namespace QtWaylandServer {\n");
649
650 bool needsNewLine = false;
651 for (const WaylandInterface &interface : interfaces) {
652
653 if (ignoreInterface(interface.name))
654 continue;
655
656 if (needsNewLine)
657 printf("\n");
658
659 needsNewLine = true;
660
661 const char *interfaceName = interface.name.constData();
662
663 QByteArray stripped = stripInterfaceName(interface.name);
664 const char *interfaceNameStripped = stripped.constData();
665
666 printf(" %s::%s(struct ::wl_client *client, uint32_t id, int version)\n", interfaceName, interfaceName);
667 printf(" : m_resource_map()\n");
668 printf(" , m_resource(nullptr)\n");
669 printf(" , m_global(nullptr)\n");
670 printf(" {\n");
671 printf(" init(client, id, version);\n");
672 printf(" }\n");
673 printf("\n");
674
675 printf(" %s::%s(struct ::wl_display *display, int version)\n", interfaceName, interfaceName);
676 printf(" : m_resource_map()\n");
677 printf(" , m_resource(nullptr)\n");
678 printf(" , m_global(nullptr)\n");
679 printf(" {\n");
680 printf(" init(display, version);\n");
681 printf(" }\n");
682 printf("\n");
683
684 printf(" %s::%s(struct ::wl_resource *resource)\n", interfaceName, interfaceName);
685 printf(" : m_resource_map()\n");
686 printf(" , m_resource(nullptr)\n");
687 printf(" , m_global(nullptr)\n");
688 printf(" {\n");
689 printf(" init(resource);\n");
690 printf(" }\n");
691 printf("\n");
692
693 printf(" %s::%s()\n", interfaceName, interfaceName);
694 printf(" : m_resource_map()\n");
695 printf(" , m_resource(nullptr)\n");
696 printf(" , m_global(nullptr)\n");
697 printf(" {\n");
698 printf(" }\n");
699 printf("\n");
700
701 printf(" %s::~%s()\n", interfaceName, interfaceName);
702 printf(" {\n");
703 printf(" for (auto resource : std::as_const(m_resource_map))\n");
704 printf(" resource->%s_object = nullptr;\n", interfaceNameStripped);
705 printf("\n");
706 printf(" if (m_resource)\n");
707 printf(" m_resource->%s_object = nullptr;\n", interfaceNameStripped);
708 printf("\n");
709 printf(" if (m_global) {\n");
710 printf(" wl_global_destroy(m_global);\n");
711 printf(" wl_list_remove(&m_displayDestroyedListener.link);\n");
712 printf(" }\n");
713 printf(" }\n");
714 printf("\n");
715
716 printf(" void %s::init(struct ::wl_client *client, uint32_t id, int version)\n", interfaceName);
717 printf(" {\n");
718 printf(" m_resource = bind(client, id, version);\n");
719 printf(" }\n");
720 printf("\n");
721
722 printf(" void %s::init(struct ::wl_resource *resource)\n", interfaceName);
723 printf(" {\n");
724 printf(" m_resource = bind(resource);\n");
725 printf(" }\n");
726 printf("\n");
727
728 printf(" %s::Resource *%s::add(struct ::wl_client *client, int version)\n", interfaceName, interfaceName);
729 printf(" {\n");
730 printf(" Resource *resource = bind(client, 0, version);\n");
731 printf(" m_resource_map.insert(client, resource);\n");
732 printf(" return resource;\n");
733 printf(" }\n");
734 printf("\n");
735
736 printf(" %s::Resource *%s::add(struct ::wl_client *client, uint32_t id, int version)\n", interfaceName, interfaceName);
737 printf(" {\n");
738 printf(" Resource *resource = bind(client, id, version);\n");
739 printf(" m_resource_map.insert(client, resource);\n");
740 printf(" return resource;\n");
741 printf(" }\n");
742 printf("\n");
743
744 printf(" void %s::init(struct ::wl_display *display, int version)\n", interfaceName);
745 printf(" {\n");
746 printf(" m_global = wl_global_create(display, &::%s_interface, version, this, bind_func);\n", interfaceName);
747 printf(" m_displayDestroyedListener.notify = %s::display_destroy_func;\n", interfaceName);
748 printf(" m_displayDestroyedListener.parent = this;\n");
749 printf(" wl_display_add_destroy_listener(display, &m_displayDestroyedListener);\n");
750 printf(" }\n");
751 printf("\n");
752
753 printf(" const struct wl_interface *%s::interface()\n", interfaceName);
754 printf(" {\n");
755 printf(" return &::%s_interface;\n", interfaceName);
756 printf(" }\n");
757 printf("\n");
758
759 printf(" %s::Resource *%s::%s_allocate()\n", interfaceName, interfaceName, interfaceNameStripped);
760 printf(" {\n");
761 printf(" return new Resource;\n");
762 printf(" }\n");
763 printf("\n");
764
765 printf(" void %s::%s_bind_resource(Resource *)\n", interfaceName, interfaceNameStripped);
766 printf(" {\n");
767 printf(" }\n");
768 printf("\n");
769
770 printf(" void %s::%s_destroy_resource(Resource *)\n", interfaceName, interfaceNameStripped);
771 printf(" {\n");
772 printf(" }\n");
773 printf("\n");
774
775 printf(" void %s::bind_func(struct ::wl_client *client, void *data, uint32_t version, uint32_t id)\n", interfaceName);
776 printf(" {\n");
777 printf(" %s *that = static_cast<%s *>(data);\n", interfaceName, interfaceName);
778 printf(" that->add(client, id, version);\n");
779 printf(" }\n");
780 printf("\n");
781
782 printf(" void %s::display_destroy_func(struct ::wl_listener *listener, void *data)\n", interfaceName);
783 printf(" {\n");
784 printf(" Q_UNUSED(data);\n");
785 printf(" %s *that = static_cast<%s::DisplayDestroyedListener *>(listener)->parent;\n", interfaceName, interfaceName);
786 printf(" that->m_global = nullptr;\n");
787 printf(" }\n");
788 printf("\n");
789
790 printf(" void %s::destroy_func(struct ::wl_resource *client_resource)\n", interfaceName);
791 printf(" {\n");
792 printf(" Resource *resource = Resource::fromResource(client_resource);\n");
793 printf(" Q_ASSERT(resource);\n");
794 printf(" %s *that = resource->%s_object;\n", interfaceName, interfaceNameStripped);
795 printf(" if (Q_LIKELY(that)) {\n");
796 printf(" that->m_resource_map.remove(resource->client(), resource);\n");
797 printf(" that->%s_destroy_resource(resource);\n", interfaceNameStripped);
798 printf("\n");
799 printf(" that = resource->%s_object;\n", interfaceNameStripped);
800 printf(" if (that && that->m_resource == resource)\n");
801 printf(" that->m_resource = nullptr;\n");
802 printf(" }\n");
803 printf(" delete resource;\n");
804 printf(" }\n");
805 printf("\n");
806
807 bool hasRequests = !interface.requests.empty();
808
809 QByteArray interfaceMember = hasRequests ? "&m_" + interface.name + "_interface" : QByteArray("nullptr");
810
811 //We should consider changing bind so that it doesn't special case id == 0
812 //and use function overloading instead. Jan do you have a lot of code dependent on this behavior?
813 printf(" %s::Resource *%s::bind(struct ::wl_client *client, uint32_t id, int version)\n", interfaceName, interfaceName);
814 printf(" {\n");
815 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");
816 printf(" struct ::wl_resource *handle = wl_resource_create(client, &::%s_interface, version, id);\n", interfaceName);
817 printf(" return bind(handle);\n");
818 printf(" }\n");
819 printf("\n");
820
821 printf(" %s::Resource *%s::bind(struct ::wl_resource *handle)\n", interfaceName, interfaceName);
822 printf(" {\n");
823 printf(" Resource *resource = %s_allocate();\n", interfaceNameStripped);
824 printf(" resource->%s_object = this;\n", interfaceNameStripped);
825 printf("\n");
826 printf(" wl_resource_set_implementation(handle, %s, resource, destroy_func);", interfaceMember.constData());
827 printf("\n");
828 printf(" resource->handle = handle;\n");
829 printf(" %s_bind_resource(resource);\n", interfaceNameStripped);
830 printf(" return resource;\n");
831 printf(" }\n");
832
833 printf(" %s::Resource *%s::Resource::fromResource(struct ::wl_resource *resource)\n", interfaceName, interfaceName);
834 printf(" {\n");
835 printf(" if (Q_UNLIKELY(!resource))\n");
836 printf(" return nullptr;\n");
837 printf(" if (wl_resource_instance_of(resource, &::%s_interface, %s))\n", interfaceName, interfaceMember.constData());
838 printf(" return static_cast<Resource *>(wl_resource_get_user_data(resource));\n");
839 printf(" return nullptr;\n");
840 printf(" }\n");
841
842 if (hasRequests) {
843 printf("\n");
844 printf(" const struct ::%s_interface %s::m_%s_interface = {", interfaceName, interfaceName, interfaceName);
845 bool needsComma = false;
846 for (const WaylandEvent &e : interface.requests) {
847 if (needsComma)
848 printf(",");
849 needsComma = true;
850 printf("\n");
851 printf(" %s::handle_%s", interfaceName, e.name.constData());
852 }
853 printf("\n");
854 printf(" };\n");
855
856 for (const WaylandEvent &e : interface.requests) {
857 printf("\n");
858 printf(" void %s::%s_", interfaceName, interfaceNameStripped);
859 printEvent(e, true);
860 printf("\n");
861 printf(" {\n");
862 printf(" }\n");
863 }
864 printf("\n");
865
866 for (const WaylandEvent &e : interface.requests) {
867 printf("\n");
868 printf(" void %s::", interfaceName);
869
870 printEventHandlerSignature(e, interfaceName, false);
871
872 printf("\n");
873 printf(" {\n");
874 printf(" Q_UNUSED(client);\n");
875 printf(" Resource *r = Resource::fromResource(resource);\n");
876 printf(" if (Q_UNLIKELY(!r->%s_object)) {\n", interfaceNameStripped);
877 if (e.type == "destructor")
878 printf(" wl_resource_destroy(resource);\n");
879 printf(" return;\n");
880 printf(" }\n");
881 printf(" static_cast<%s *>(r->%s_object)->%s_%s(\n", interfaceName, interfaceNameStripped, interfaceNameStripped, e.name.constData());
882 printf(" r");
883 for (const WaylandArgument &a : e.arguments) {
884 printf(",\n");
885 QByteArray cType = waylandToCType(a.type, a.interface);
886 QByteArray qtType = waylandToQtType(a.type, a.interface, e.request);
887 const char *argumentName = a.name.constData();
888 if (cType == qtType)
889 printf(" %s", argumentName);
890 else if (a.type == "string")
891 printf(" QString::fromUtf8(%s)", argumentName);
892 }
893 printf(");\n");
894 printf(" }\n");
895 }
896 }
897
898 for (const WaylandEvent &e : interface.events) {
899 printf("\n");
900 printf(" void %s::send_", interfaceName);
901 printEvent(e);
902 printf("\n");
903 printf(" {\n");
904 printf(" Q_ASSERT_X(m_resource, \"%s::%s\", \"Uninitialised resource\");\n", interfaceName, e.name.constData());
905 printf(" if (Q_UNLIKELY(!m_resource)) {\n");
906 printf(" qWarning(\"could not call %s::%s as it's not initialised\");\n", interfaceName, e.name.constData());
907 printf(" return;\n");
908 printf(" }\n");
909 printf(" send_%s(\n", e.name.constData());
910 printf(" m_resource->handle");
911 for (const WaylandArgument &a : e.arguments) {
912 printf(",\n");
913 printf(" %s", a.name.constData());
914 }
915 printf(");\n");
916 printf(" }\n");
917 printf("\n");
918
919 printf(" void %s::send_", interfaceName);
920 printEvent(e, false, true);
921 printf("\n");
922 printf(" {\n");
923
924 for (const WaylandArgument &a : e.arguments) {
925 if (a.type != "array")
926 continue;
927 QByteArray array = a.name + "_data";
928 const char *arrayName = array.constData();
929 const char *variableName = a.name.constData();
930 printf(" struct wl_array %s;\n", arrayName);
931 printf(" %s.size = %s.size();\n", arrayName, variableName);
932 printf(" %s.data = static_cast<void *>(const_cast<char *>(%s.constData()));\n", arrayName, variableName);
933 printf(" %s.alloc = 0;\n", arrayName);
934 printf("\n");
935 }
936
937 printf(" %s_send_%s(\n", interfaceName, e.name.constData());
938 printf(" resource");
939
940 for (const WaylandArgument &a : e.arguments) {
941 printf(",\n");
942 QByteArray cType = waylandToCType(a.type, a.interface);
943 QByteArray qtType = waylandToQtType(a.type, a.interface, e.request);
944 if (a.type == "string") {
945 printf(" ");
946 if (a.allowNull)
947 printf("%s.isNull() ? nullptr : ", a.name.constData());
948 printf("%s.toUtf8().constData()", a.name.constData());
949 } else if (a.type == "array")
950 printf(" &%s_data", a.name.constData());
951 else if (cType == qtType)
952 printf(" %s", a.name.constData());
953 }
954
955 printf(");\n");
956 printf(" }\n");
957 printf("\n");
958 }
959 }
960 printf("}\n");
961 printf("\n");
962 printf("QT_WARNING_POP\n");
963 printf("QT_END_NAMESPACE\n");
964 }
965
966 if (m_option == ClientHeader) {
967 QByteArray inclusionGuard = QByteArray("QT_WAYLAND_") + preProcessorProtocolName.constData();
968 printf("#ifndef %s\n", inclusionGuard.constData());
969 printf("#define %s\n", inclusionGuard.constData());
970 printf("\n");
971 if (m_headerPath.isEmpty())
972 printf("#include \"wayland-%s-client-protocol.h\"\n", fileBaseName.constData());
973 else
974 printf("#include <%s/wayland-%s-client-protocol.h>\n", m_headerPath.constData(), fileBaseName.constData());
975 printf("#include <QByteArray>\n");
976 printf("#include <QString>\n");
977 printf("\n");
978 printf("struct wl_registry;\n");
979 printf("\n");
980 printf("QT_BEGIN_NAMESPACE\n");
981 printf("QT_WARNING_PUSH\n");
982 printf("QT_WARNING_DISABLE_GCC(\"-Wmissing-field-initializers\")\n");
983 printf("QT_WARNING_DISABLE_CLANG(\"-Wmissing-field-initializers\")\n");
984
985 QByteArray clientExport;
986 if (m_headerPath.size())
987 clientExport = printExportMacro("Q_WAYLAND_CLIENT_", preProcessorProtocolName);
988
989 printf("\n");
990 printf("namespace QtWayland {\n");
991
992 bool needsNewLine = false;
993 for (const WaylandInterface &interface : interfaces) {
994
995 if (ignoreInterface(interface.name))
996 continue;
997
998 if (needsNewLine)
999 printf("\n");
1000 needsNewLine = true;
1001
1002 const char *interfaceName = interface.name.constData();
1003
1004 QByteArray stripped = stripInterfaceName(interface.name);
1005 const char *interfaceNameStripped = stripped.constData();
1006
1007 printf(" class %s %s\n {\n", clientExport.constData(), interfaceName);
1008 printf(" public:\n");
1009 printf(" %s(struct ::wl_registry *registry, uint32_t id, int version);\n", interfaceName);
1010 printf(" %s(struct ::%s *object);\n", interfaceName, interfaceName);
1011 printf(" %s();\n", interfaceName);
1012 printf("\n");
1013 printf(" virtual ~%s();\n", interfaceName);
1014 printf("\n");
1015 printf(" void init(struct ::wl_registry *registry, uint32_t id, int version);\n");
1016 printf(" void init(struct ::%s *object);\n", interfaceName);
1017 printf("\n");
1018 printf(" struct ::%s *object() { return m_%s; }\n", interfaceName, interfaceName);
1019 printf(" const struct ::%s *object() const { return m_%s; }\n", interfaceName, interfaceName);
1020 printf(" static %s *fromObject(struct ::%s *object);\n", interfaceName, interfaceName);
1021 printf("\n");
1022 printf(" bool isInitialized() const;\n");
1023 printf("\n");
1024 printf(" uint32_t version() const;");
1025 printf("\n");
1026 printf(" static const struct ::wl_interface *interface();\n");
1027
1028 printEnums(interface.enums);
1029
1030 if (!interface.requests.empty()) {
1031 printf("\n");
1032 for (const WaylandEvent &e : interface.requests) {
1033 const WaylandArgument *new_id = newIdArgument(e.arguments);
1034 QByteArray new_id_str = "void ";
1035 if (new_id) {
1036 if (new_id->interface.isEmpty())
1037 new_id_str = "void *";
1038 else
1039 new_id_str = "struct ::" + new_id->interface + " *";
1040 }
1041 printf(" %s", new_id_str.constData());
1042 printEvent(e);
1043 printf(";\n");
1044 }
1045 }
1046
1047 bool hasEvents = !interface.events.empty();
1048
1049 if (hasEvents) {
1050 printf("\n");
1051 printf(" protected:\n");
1052 for (const WaylandEvent &e : interface.events) {
1053 printf(" virtual void %s_", interfaceNameStripped);
1054 printEvent(e);
1055 printf(";\n");
1056 }
1057 }
1058
1059 printf("\n");
1060 printf(" private:\n");
1061 if (hasEvents) {
1062 printf(" void init_listener();\n");
1063 printf(" static const struct %s_listener m_%s_listener;\n", interfaceName, interfaceName);
1064 for (const WaylandEvent &e : interface.events) {
1065 printf(" static void ");
1066
1067 printEventHandlerSignature(e, interfaceName);
1068 printf(";\n");
1069 }
1070 }
1071 printf(" struct ::%s *m_%s;\n", interfaceName, interfaceName);
1072 printf(" };\n");
1073 }
1074 printf("}\n");
1075 printf("\n");
1076 printf("QT_WARNING_POP\n");
1077 printf("QT_END_NAMESPACE\n");
1078 printf("\n");
1079 printf("#endif\n");
1080 }
1081
1082 if (m_option == ClientCode) {
1083 if (m_headerPath.isEmpty())
1084 printf("#include \"qwayland-%s.h\"\n", fileBaseName.constData());
1085 else
1086 printf("#include <%s/qwayland-%s.h>\n", m_headerPath.constData(), fileBaseName.constData());
1087 printf("\n");
1088 printf("QT_BEGIN_NAMESPACE\n");
1089 printf("QT_WARNING_PUSH\n");
1090 printf("QT_WARNING_DISABLE_GCC(\"-Wmissing-field-initializers\")\n");
1091 printf("QT_WARNING_DISABLE_CLANG(\"-Wmissing-field-initializers\")\n");
1092 printf("\n");
1093 printf("namespace QtWayland {\n");
1094 printf("\n");
1095
1096 // wl_registry_bind is part of the protocol, so we can't use that... instead we use core
1097 // libwayland API to do the same thing a wayland-scanner generated wl_registry_bind would.
1098 printf("static inline void *wlRegistryBind(struct ::wl_registry *registry, uint32_t name, const struct ::wl_interface *interface, uint32_t version)\n");
1099 printf("{\n");
1100 printf(" const uint32_t bindOpCode = 0;\n");
1101 printf(" return (void *) wl_proxy_marshal_constructor_versioned((struct wl_proxy *) registry,\n");
1102 printf(" bindOpCode, interface, version, name, interface->name, version, nullptr);\n");
1103 printf("}\n");
1104 printf("\n");
1105
1106 bool needsNewLine = false;
1107 for (const WaylandInterface &interface : interfaces) {
1108
1109 if (ignoreInterface(interface.name))
1110 continue;
1111
1112 if (needsNewLine)
1113 printf("\n");
1114 needsNewLine = true;
1115
1116 const char *interfaceName = interface.name.constData();
1117
1118 QByteArray stripped = stripInterfaceName(interface.name);
1119 const char *interfaceNameStripped = stripped.constData();
1120
1121 bool hasEvents = !interface.events.empty();
1122
1123 printf(" %s::%s(struct ::wl_registry *registry, uint32_t id, int version)\n", interfaceName, interfaceName);
1124 printf(" {\n");
1125 printf(" init(registry, id, version);\n");
1126 printf(" }\n");
1127 printf("\n");
1128
1129 printf(" %s::%s(struct ::%s *obj)\n", interfaceName, interfaceName, interfaceName);
1130 printf(" : m_%s(obj)\n", interfaceName);
1131 printf(" {\n");
1132 if (hasEvents)
1133 printf(" init_listener();\n");
1134 printf(" }\n");
1135 printf("\n");
1136
1137 printf(" %s::%s()\n", interfaceName, interfaceName);
1138 printf(" : m_%s(nullptr)\n", interfaceName);
1139 printf(" {\n");
1140 printf(" }\n");
1141 printf("\n");
1142
1143 printf(" %s::~%s()\n", interfaceName, interfaceName);
1144 printf(" {\n");
1145 printf(" }\n");
1146 printf("\n");
1147
1148 printf(" void %s::init(struct ::wl_registry *registry, uint32_t id, int version)\n", interfaceName);
1149 printf(" {\n");
1150 printf(" m_%s = static_cast<struct ::%s *>(wlRegistryBind(registry, id, &%s_interface, version));\n", interfaceName, interfaceName, interfaceName);
1151 if (hasEvents)
1152 printf(" init_listener();\n");
1153 printf(" }\n");
1154 printf("\n");
1155
1156 printf(" void %s::init(struct ::%s *obj)\n", interfaceName, interfaceName);
1157 printf(" {\n");
1158 printf(" m_%s = obj;\n", interfaceName);
1159 if (hasEvents)
1160 printf(" init_listener();\n");
1161 printf(" }\n");
1162 printf("\n");
1163
1164 printf(" %s *%s::fromObject(struct ::%s *object)\n", interfaceName, interfaceName, interfaceName);
1165 printf(" {\n");
1166 if (hasEvents) {
1167 printf(" if (wl_proxy_get_listener((struct ::wl_proxy *)object) != (void *)&m_%s_listener)\n", interfaceName);
1168 printf(" return nullptr;\n");
1169 }
1170 printf(" return static_cast<%s *>(%s_get_user_data(object));\n", interfaceName, interfaceName);
1171 printf(" }\n");
1172 printf("\n");
1173
1174 printf(" bool %s::isInitialized() const\n", interfaceName);
1175 printf(" {\n");
1176 printf(" return m_%s != nullptr;\n", interfaceName);
1177 printf(" }\n");
1178 printf("\n");
1179
1180 printf(" uint32_t %s::version() const\n", interfaceName);
1181 printf(" {\n");
1182 printf(" return wl_proxy_get_version(reinterpret_cast<wl_proxy*>(m_%s));\n", interfaceName);
1183 printf(" }\n");
1184 printf("\n");
1185
1186 printf(" const struct wl_interface *%s::interface()\n", interfaceName);
1187 printf(" {\n");
1188 printf(" return &::%s_interface;\n", interfaceName);
1189 printf(" }\n");
1190
1191 for (const WaylandEvent &e : interface.requests) {
1192 printf("\n");
1193 const WaylandArgument *new_id = newIdArgument(e.arguments);
1194 QByteArray new_id_str = "void ";
1195 if (new_id) {
1196 if (new_id->interface.isEmpty())
1197 new_id_str = "void *";
1198 else
1199 new_id_str = "struct ::" + new_id->interface + " *";
1200 }
1201 printf(" %s%s::", new_id_str.constData(), interfaceName);
1202 printEvent(e);
1203 printf("\n");
1204 printf(" {\n");
1205 for (const WaylandArgument &a : e.arguments) {
1206 if (a.type != "array")
1207 continue;
1208 QByteArray array = a.name + "_data";
1209 const char *arrayName = array.constData();
1210 const char *variableName = a.name.constData();
1211 printf(" struct wl_array %s;\n", arrayName);
1212 printf(" %s.size = %s.size();\n", arrayName, variableName);
1213 printf(" %s.data = static_cast<void *>(const_cast<char *>(%s.constData()));\n", arrayName, variableName);
1214 printf(" %s.alloc = 0;\n", arrayName);
1215 printf("\n");
1216 }
1217 int actualArgumentCount = new_id ? int(e.arguments.size()) - 1 : int(e.arguments.size());
1218 if (new_id)
1219 printf(" %s %s = ::%s_%s(\n", new_id_str.constData(), new_id->name.constData(), interfaceName, e.name.constData());
1220 else
1221 printf(" ::%s_%s(\n", interfaceName, e.name.constData());
1222 printf(" m_%s%s", interfaceName, actualArgumentCount > 0 ? "," : "");
1223 bool needsComma = false;
1224 for (const WaylandArgument &a : e.arguments) {
1225 bool isNewId = a.type == "new_id";
1226 if (isNewId && !a.interface.isEmpty())
1227 continue;
1228 if (needsComma)
1229 printf(",");
1230 needsComma = true;
1231 printf("\n");
1232 if (isNewId) {
1233 printf(" interface,\n");
1234 printf(" version");
1235 } else {
1236 QByteArray cType = waylandToCType(a.type, a.interface);
1237 QByteArray qtType = waylandToQtType(a.type, a.interface, e.request);
1238 if (a.type == "string") {
1239 printf(" ");
1240 if (a.allowNull)
1241 printf("%s.isNull() ? nullptr : ", a.name.constData());
1242 printf("%s.toUtf8().constData()", a.name.constData());
1243 } else if (a.type == "array")
1244 printf(" &%s_data", a.name.constData());
1245 else if (cType == qtType)
1246 printf(" %s", a.name.constData());
1247 }
1248 }
1249 printf(");\n");
1250 if (e.type == "destructor")
1251 printf(" m_%s = nullptr;\n", interfaceName);
1252 if (new_id)
1253 printf(" return %s;\n", new_id->name.constData());
1254 printf(" }\n");
1255 }
1256
1257 if (hasEvents) {
1258 printf("\n");
1259 for (const WaylandEvent &e : interface.events) {
1260 printf(" void %s::%s_", interfaceName, interfaceNameStripped);
1261 printEvent(e, true);
1262 printf("\n");
1263 printf(" {\n");
1264 printf(" }\n");
1265 printf("\n");
1266 printf(" void %s::", interfaceName);
1267 printEventHandlerSignature(e, interfaceName, false);
1268 printf("\n");
1269 printf(" {\n");
1270 printf(" Q_UNUSED(object);\n");
1271 printf(" static_cast<%s *>(data)->%s_%s(", interfaceName, interfaceNameStripped, e.name.constData());
1272 bool needsComma = false;
1273 for (const WaylandArgument &a : e.arguments) {
1274 if (needsComma)
1275 printf(",");
1276 needsComma = true;
1277 printf("\n");
1278 const char *argumentName = a.name.constData();
1279 if (a.type == "string")
1280 printf(" QString::fromUtf8(%s)", argumentName);
1281 else
1282 printf(" %s", argumentName);
1283 }
1284 printf(");\n");
1285
1286 printf(" }\n");
1287 printf("\n");
1288 }
1289 printf(" const struct %s_listener %s::m_%s_listener = {\n", interfaceName, interfaceName, interfaceName);
1290 for (const WaylandEvent &e : interface.events) {
1291 printf(" %s::handle_%s,\n", interfaceName, e.name.constData());
1292 }
1293 printf(" };\n");
1294 printf("\n");
1295
1296 printf(" void %s::init_listener()\n", interfaceName);
1297 printf(" {\n");
1298 printf(" %s_add_listener(m_%s, &m_%s_listener, this);\n", interfaceName, interfaceName, interfaceName);
1299 printf(" }\n");
1300 }
1301 }
1302 printf("}\n");
1303 printf("\n");
1304 printf("QT_WARNING_POP\n");
1305 printf("QT_END_NAMESPACE\n");
1306 }
1307
1308 return true;
1309}
1310
1312{
1313 if (m_xml->hasError())
1314 fprintf(stderr, "XML error: %s\nLine %lld, column %lld\n", m_xml->errorString().toLocal8Bit().constData(), m_xml->lineNumber(), m_xml->columnNumber());
1315}
1316
1317int main(int argc, char **argv)
1318{
1319 QCoreApplication app(argc, argv);
1320 Scanner scanner;
1321
1322 if (!scanner.parseArguments(argc, argv)) {
1323 scanner.printUsage();
1324 return EXIT_FAILURE;
1325 }
1326
1327 if (!scanner.process()) {
1328 scanner.printErrors();
1329 return EXIT_FAILURE;
1330 }
1331
1332 return EXIT_SUCCESS;
1333}
bool parseArguments(int argc, char **argv)
int main(int argc, char *argv[])
[ctor_close]