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