Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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();
20 void printErrors();
21
22private:
23 struct WaylandEnumEntry {
26 QByteArray summary;
27 };
28
29 struct WaylandEnum {
31
32 std::vector<WaylandEnumEntry> entries;
33 };
34
35 struct WaylandArgument {
38 QByteArray interface;
39 QByteArray summary;
40 bool allowNull;
41 };
42
43 struct WaylandEvent {
44 bool request;
47 std::vector<WaylandArgument> arguments;
48 };
49
50 struct WaylandInterface {
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);
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 printf(" %s::%s_%s(\n", new_id ? "return " : "", interfaceName, e.name.constData());
1218 printf(" m_%s%s", interfaceName, actualArgumentCount > 0 ? "," : "");
1219 bool needsComma = false;
1220 for (const WaylandArgument &a : e.arguments) {
1221 bool isNewId = a.type == "new_id";
1222 if (isNewId && !a.interface.isEmpty())
1223 continue;
1224 if (needsComma)
1225 printf(",");
1226 needsComma = true;
1227 printf("\n");
1228 if (isNewId) {
1229 printf(" interface,\n");
1230 printf(" version");
1231 } else {
1232 QByteArray cType = waylandToCType(a.type, a.interface);
1233 QByteArray qtType = waylandToQtType(a.type, a.interface, e.request);
1234 if (a.type == "string") {
1235 printf(" ");
1236 if (a.allowNull)
1237 printf("%s.isNull() ? nullptr : ", a.name.constData());
1238 printf("%s.toUtf8().constData()", a.name.constData());
1239 } else if (a.type == "array")
1240 printf(" &%s_data", a.name.constData());
1241 else if (cType == qtType)
1242 printf(" %s", a.name.constData());
1243 }
1244 }
1245 printf(");\n");
1246 if (e.type == "destructor")
1247 printf(" m_%s = nullptr;\n", interfaceName);
1248 printf(" }\n");
1249 }
1250
1251 if (hasEvents) {
1252 printf("\n");
1253 for (const WaylandEvent &e : interface.events) {
1254 printf(" void %s::%s_", interfaceName, interfaceNameStripped);
1255 printEvent(e, true);
1256 printf("\n");
1257 printf(" {\n");
1258 printf(" }\n");
1259 printf("\n");
1260 printf(" void %s::", interfaceName);
1261 printEventHandlerSignature(e, interfaceName, false);
1262 printf("\n");
1263 printf(" {\n");
1264 printf(" Q_UNUSED(object);\n");
1265 printf(" static_cast<%s *>(data)->%s_%s(", interfaceName, interfaceNameStripped, e.name.constData());
1266 bool needsComma = false;
1267 for (const WaylandArgument &a : e.arguments) {
1268 if (needsComma)
1269 printf(",");
1270 needsComma = true;
1271 printf("\n");
1272 const char *argumentName = a.name.constData();
1273 if (a.type == "string")
1274 printf(" QString::fromUtf8(%s)", argumentName);
1275 else
1276 printf(" %s", argumentName);
1277 }
1278 printf(");\n");
1279
1280 printf(" }\n");
1281 printf("\n");
1282 }
1283 printf(" const struct %s_listener %s::m_%s_listener = {\n", interfaceName, interfaceName, interfaceName);
1284 for (const WaylandEvent &e : interface.events) {
1285 printf(" %s::handle_%s,\n", interfaceName, e.name.constData());
1286 }
1287 printf(" };\n");
1288 printf("\n");
1289
1290 printf(" void %s::init_listener()\n", interfaceName);
1291 printf(" {\n");
1292 printf(" %s_add_listener(m_%s, &m_%s_listener, this);\n", interfaceName, interfaceName, interfaceName);
1293 printf(" }\n");
1294 }
1295 }
1296 printf("}\n");
1297 printf("\n");
1298 printf("QT_WARNING_POP\n");
1299 printf("QT_END_NAMESPACE\n");
1300 }
1301
1302 return true;
1303}
1304
1306{
1307 if (m_xml->hasError())
1308 fprintf(stderr, "XML error: %s\nLine %lld, column %lld\n", m_xml->errorString().toLocal8Bit().constData(), m_xml->lineNumber(), m_xml->columnNumber());
1309}
1310
1311int main(int argc, char **argv)
1312{
1313 QCoreApplication app(argc, argv);
1314 Scanner scanner;
1315
1316 if (!scanner.parseArguments(argc, argv)) {
1317 scanner.printUsage();
1318 return EXIT_FAILURE;
1319 }
1320
1321 if (!scanner.process()) {
1322 scanner.printErrors();
1323 return EXIT_FAILURE;
1324 }
1325
1326 return EXIT_SUCCESS;
1327}
\inmodule QtCore
Definition qbytearray.h:57
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:494
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
int toInt(bool *ok=nullptr, int base=10) const
Returns the byte array converted to an int using base base, which is ten by default.
void push_back(char c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qbytearray.h:466
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:107
QByteArray mid(qsizetype index, qsizetype len=-1) const &
\inmodule QtCore
QString completeBaseName() const
Returns the complete base name of the file without the path.
\inmodule QtCore
Definition qfile.h:93
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:904
void reserve(qsizetype size)
Definition qlist.h:753
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QByteArray toLocal8Bit() const &
Definition qstring.h:638
bool parseArguments(int argc, char **argv)
QString str
[2]
int main()
[0]
QList< QVariant > arguments
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char * interface
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static glyph_t stripped(glyph_t glyph)
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint object
[3]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum type
GLuint name
GLfloat n
struct _cl_event * event
GLdouble s
[6]
Definition qopenglext.h:235
GLuint entry
GLenum array
GLuint64EXT * result
[6]
GLuint GLenum option
QAnyStringView interfaceName(const Interface &iface)
#define qPrintable(string)
Definition qstring.h:1531
#define QStringLiteral(str)
QFile file
[0]
QXmlStreamReader xml
[0]
QApplication app(argc, argv)
[0]
QNetworkRequest request(url)
QDBusArgument argument
QJSValueList args