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