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
10class Scanner
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 {
23 QByteArray name;
24 QByteArray value;
25 QByteArray summary;
26 };
27
28 struct WaylandEnum {
29 QByteArray name;
30
31 std::vector<WaylandEnumEntry> entries;
32 };
33
34 struct WaylandArgument {
35 QByteArray name;
36 QByteArray type;
37 QByteArray interface;
38 QByteArray summary;
39 bool allowNull;
40 };
41
42 struct WaylandEvent {
43 bool request;
44 QByteArray name;
45 QByteArray type;
46 std::vector<WaylandArgument> arguments;
47 };
48
49 struct WaylandInterface {
50 QByteArray name;
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{
97 QList<QByteArray> args;
98 args.reserve(asize: 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(str: args[1]))
105 return false;
106
107 m_protocolFilePath = args[2];
108
109 if (argc > 3 && !args[3].startsWith(c: '-')) {
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(bv: "--header-path=")) {
121 m_headerPath = option.mid(index: 14);
122 } else if (option.startsWith(bv: "--prefix=")) {
123 m_prefix = option.mid(index: 10);
124 } else if (option.startsWith(bv: "--build-macro=")) {
125 m_buildMacro = option.mid(index: 14);
126 } else if (option.startsWith(bv: "--add-include=")) {
127 auto include = option.mid(index: 14);
128 if (!include.isEmpty())
129 m_includes << include;
130 } else {
131 return false;
132 }
133 }
134 }
135
136 return true;
137}
138
139void Scanner::printUsage()
140{
141 fprintf(stderr, format: "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(qualifiedName: name))
168 return xml.attributes().value(qualifiedName: 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: &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: "name"),
189 .type = byteArrayValue(xml, name: "type"),
190 .arguments = {},
191 };
192 while (xml.readNextStartElement()) {
193 if (xml.name() == u"arg") {
194 WaylandArgument argument = {
195 .name = byteArrayValue(xml, name: "name"),
196 .type = byteArrayValue(xml, name: "type"),
197 .interface = byteArrayValue(xml, name: "interface"),
198 .summary = byteArrayValue(xml, name: "summary"),
199 .allowNull = boolValue(xml, name: "allowNull"),
200 };
201 event.arguments.push_back(x: 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: "name"),
213 .entries = {},
214 };
215
216 while (xml.readNextStartElement()) {
217 if (xml.name() == u"entry") {
218 WaylandEnumEntry entry = {
219 .name = byteArrayValue(xml, name: "name"),
220 .value = byteArrayValue(xml, name: "value"),
221 .summary = byteArrayValue(xml, name: "summary"),
222 };
223 result.entries.push_back(x: 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: "name"),
236 .version = intValue(xml, name: "version", defaultValue: 1),
237 .enums = {},
238 .events = {},
239 .requests = {},
240 };
241
242 while (xml.readNextStartElement()) {
243 if (xml.name() == u"event")
244 interface.events.push_back(x: readEvent(xml, request: false));
245 else if (xml.name() == u"request")
246 interface.requests.push_back(x: readEvent(xml, request: true));
247 else if (xml.name() == u"enum")
248 interface.enums.push_back(x: 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(format: "%s(", e.name.constData());
302 bool needsComma = false;
303 if (isServerSide()) {
304 if (e.request) {
305 printf(format: "Resource *%s", omitNames ? "" : "resource");
306 needsComma = true;
307 } else if (withResource) {
308 printf(format: "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(format: ", ");
318 needsComma = true;
319 if (isNewId) {
320 if (isServerSide()) {
321 if (e.request) {
322 printf(format: "uint32_t");
323 if (!omitNames)
324 printf(format: " %s", a.name.constData());
325 continue;
326 }
327 } else {
328 if (e.request) {
329 printf(format: "const struct ::wl_interface *%s, uint32_t%s", omitNames ? "" : "interface", omitNames ? "" : " version");
330 continue;
331 }
332 }
333 }
334
335 QByteArray qtType = waylandToQtType(waylandType: a.type, interface: a.interface, cStyleArray: e.request == isServerSide());
336 printf(format: "%s%s%s", qtType.constData(), qtType.endsWith(bv: "&") || qtType.endsWith(bv: "*") ? "" : " ", omitNames ? "" : a.name.constData());
337 }
338 printf(format: ")");
339}
340
341void Scanner::printEventHandlerSignature(const WaylandEvent &e, const char *interfaceName, bool deepIndent)
342{
343 const char *indent = deepIndent ? " " : "";
344 printf(format: "handle_%s(\n", e.name.constData());
345 if (isServerSide()) {
346 printf(format: " %s::wl_client *client,\n", indent);
347 printf(format: " %sstruct wl_resource *resource", indent);
348 } else {
349 printf(format: " %svoid *data,\n", indent);
350 printf(format: " %sstruct ::%s *object", indent, interfaceName);
351 }
352 for (const WaylandArgument &a : e.arguments) {
353 printf(format: ",\n");
354 bool isNewId = a.type == "new_id";
355 if (isServerSide() && isNewId) {
356 printf(format: " %suint32_t %s", indent, a.name.constData());
357 } else {
358 QByteArray cType = waylandToCType(waylandType: a.type, interface: a.interface);
359 printf(format: " %s%s%s%s", indent, cType.constData(), cType.endsWith(bv: "*") ? "" : " ", a.name.constData());
360 }
361 }
362 printf(format: ")");
363}
364
365void Scanner::printEnums(const std::vector<WaylandEnum> &enums)
366{
367 for (const WaylandEnum &e : enums) {
368 printf(format: "\n");
369 printf(format: " enum %s {\n", e.name.constData());
370 for (const WaylandEnumEntry &entry : e.entries) {
371 printf(format: " %s_%s = %s,", e.name.constData(), entry.name.constData(), entry.value.constData());
372 if (!entry.summary.isNull())
373 printf(format: " // %s", entry.summary.constData());
374 printf(format: "\n");
375 }
376 printf(format: " };\n");
377 }
378}
379
380QByteArray Scanner::stripInterfaceName(const QByteArray &name)
381{
382 if (!m_prefix.isEmpty() && name.startsWith(bv: m_prefix))
383 return name.mid(index: m_prefix.size());
384 if (name.startsWith(bv: "qt_") || name.startsWith(bv: "wl_"))
385 return name.mid(index: 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
396bool Scanner::process()
397{
398 QFile file(m_protocolFilePath);
399 if (!file.open(flags: QIODevice::ReadOnly | QIODevice::Text)) {
400 fprintf(stderr, format: "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(xml: *m_xml, name: "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(x: readInterface(xml&: *m_xml));
430 else
431 m_xml->skipCurrentElement();
432 }
433
434 if (m_xml->hasError())
435 return false;
436
437 printf(format: "// This file was generated by qtwaylandscanner\n");
438 printf(format: "// source file is %s\n\n", qPrintable(m_protocolFilePath));
439
440 for (auto b : std::as_const(t&: m_includes))
441 printf(format: "#include %s\n", b.constData());
442
443 auto printExportMacro = [this](const char *prefix, const QByteArray &preProcessorProtocolName) {
444 QByteArray exportMacro = prefix + preProcessorProtocolName + "_EXPORT";
445 printf(format: "#if !defined(%s)\n", exportMacro.constData());
446 printf(format: "# if defined(QT_SHARED) && !defined(QT_STATIC)\n");
447 if (m_buildMacro.isEmpty()) {
448 printf(format: "# define %s Q_DECL_EXPORT\n", exportMacro.constData());
449 } else {
450 printf(format: "# if defined(%s)\n", m_buildMacro.constData());
451 printf(format: "# define %s Q_DECL_EXPORT\n", exportMacro.constData());
452 printf(format: "# else\n");
453 printf(format: "# define %s Q_DECL_IMPORT\n", exportMacro.constData());
454 printf(format: "# endif\n");
455 }
456 printf(format: "# else\n");
457 printf(format: "# define %s\n", exportMacro.constData());
458 printf(format: "# endif\n");
459 printf(format: "#endif\n");
460 return exportMacro;
461 };
462
463 if (m_option == ServerHeader) {
464 QByteArray inclusionGuard = QByteArray("QT_WAYLAND_SERVER_") + preProcessorProtocolName.constData();
465 printf(format: "#ifndef %s\n", inclusionGuard.constData());
466 printf(format: "#define %s\n", inclusionGuard.constData());
467 printf(format: "\n");
468 printf(format: "#include \"wayland-server-core.h\"\n");
469 if (m_headerPath.isEmpty())
470 printf(format: "#include \"wayland-%s-server-protocol.h\"\n", QByteArray(m_protocolName).replace(before: '_', after: '-').constData());
471 else
472 printf(format: "#include <%s/wayland-%s-server-protocol.h>\n", m_headerPath.constData(), QByteArray(m_protocolName).replace(before: '_', after: '-').constData());
473 printf(format: "#include <QByteArray>\n");
474 printf(format: "#include <QMultiMap>\n");
475 printf(format: "#include <QString>\n");
476
477 printf(format: "\n");
478 printf(format: "#ifndef WAYLAND_VERSION_CHECK\n");
479 printf(format: "#define WAYLAND_VERSION_CHECK(major, minor, micro) \\\n");
480 printf(format: " ((WAYLAND_VERSION_MAJOR > (major)) || \\\n");
481 printf(format: " (WAYLAND_VERSION_MAJOR == (major) && WAYLAND_VERSION_MINOR > (minor)) || \\\n");
482 printf(format: " (WAYLAND_VERSION_MAJOR == (major) && WAYLAND_VERSION_MINOR == (minor) && WAYLAND_VERSION_MICRO >= (micro)))\n");
483 printf(format: "#endif\n");
484
485 printf(format: "\n");
486 printf(format: "QT_BEGIN_NAMESPACE\n");
487 printf(format: "QT_WARNING_PUSH\n");
488 printf(format: "QT_WARNING_DISABLE_GCC(\"-Wmissing-field-initializers\")\n");
489 printf(format: "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(format: "\n");
494 printf(format: "namespace QtWaylandServer {\n");
495
496 bool needsNewLine = false;
497 for (const WaylandInterface &interface : interfaces) {
498
499 if (ignoreInterface(name: interface.name))
500 continue;
501
502 if (needsNewLine)
503 printf(format: "\n");
504 needsNewLine = true;
505
506 const char *interfaceName = interface.name.constData();
507
508 QByteArray stripped = stripInterfaceName(name: interface.name);
509 const char *interfaceNameStripped = stripped.constData();
510
511 printf(format: " class %s %s\n {\n", serverExport.constData(), interfaceName);
512 printf(format: " public:\n");
513 printf(format: " %s(struct ::wl_client *client, uint32_t id, int version);\n", interfaceName);
514 printf(format: " %s(struct ::wl_display *display, int version);\n", interfaceName);
515 printf(format: " %s(struct ::wl_resource *resource);\n", interfaceName);
516 printf(format: " %s();\n", interfaceName);
517 printf(format: "\n");
518 printf(format: " virtual ~%s();\n", interfaceName);
519 printf(format: "\n");
520 printf(format: " class Resource\n");
521 printf(format: " {\n");
522 printf(format: " public:\n");
523 printf(format: " Resource() : %s_object(nullptr), handle(nullptr) {}\n", interfaceNameStripped);
524 printf(format: " virtual ~Resource() {}\n");
525 printf(format: "\n");
526 printf(format: " %s *%s_object;\n", interfaceName, interfaceNameStripped);
527 printf(format: " %s *object() { return %s_object; } \n", interfaceName, interfaceNameStripped);
528 printf(format: " struct ::wl_resource *handle;\n");
529 printf(format: "\n");
530 printf(format: " struct ::wl_client *client() const { return wl_resource_get_client(handle); }\n");
531 printf(format: " int version() const { return wl_resource_get_version(handle); }\n");
532 printf(format: "\n");
533 printf(format: " static Resource *fromResource(struct ::wl_resource *resource);\n");
534 printf(format: " };\n");
535 printf(format: "\n");
536 printf(format: " void init(struct ::wl_client *client, uint32_t id, int version);\n");
537 printf(format: " void init(struct ::wl_display *display, int version);\n");
538 printf(format: " void init(struct ::wl_resource *resource);\n");
539 printf(format: "\n");
540 printf(format: " Resource *add(struct ::wl_client *client, int version);\n");
541 printf(format: " Resource *add(struct ::wl_client *client, uint32_t id, int version);\n");
542 printf(format: " Resource *add(struct wl_list *resource_list, struct ::wl_client *client, uint32_t id, int version);\n");
543 printf(format: "\n");
544 printf(format: " Resource *resource() { return m_resource; }\n");
545 printf(format: " const Resource *resource() const { return m_resource; }\n");
546 printf(format: "\n");
547 printf(format: " QMultiMap<struct ::wl_client*, Resource*> resourceMap() { return m_resource_map; }\n");
548 printf(format: " const QMultiMap<struct ::wl_client*, Resource*> resourceMap() const { return m_resource_map; }\n");
549 printf(format: "\n");
550 printf(format: " bool isGlobal() const { return m_global != nullptr; }\n");
551 printf(format: " bool isResource() const { return m_resource != nullptr; }\n");
552 printf(format: "\n");
553 printf(format: " static const struct ::wl_interface *interface();\n");
554 printf(format: " static QByteArray interfaceName() { return interface()->name; }\n");
555 printf(format: " static int interfaceVersion() { return interface()->version; }\n");
556 printf(format: "\n");
557
558 printEnums(enums: interface.enums);
559
560 bool hasEvents = !interface.events.empty();
561
562 if (hasEvents) {
563 printf(format: "\n");
564 for (const WaylandEvent &e : interface.events) {
565 printf(format: " void send_");
566 printEvent(e);
567 printf(format: ";\n");
568 printf(format: " void send_");
569 printEvent(e, omitNames: false, withResource: true);
570 printf(format: ";\n");
571 }
572 }
573
574 printf(format: "\n");
575 printf(format: " protected:\n");
576 printf(format: " virtual Resource *%s_allocate();\n", interfaceNameStripped);
577 printf(format: "\n");
578 printf(format: " virtual void %s_bind_resource(Resource *resource);\n", interfaceNameStripped);
579 printf(format: " virtual void %s_destroy_resource(Resource *resource);\n", interfaceNameStripped);
580
581 bool hasRequests = !interface.requests.empty();
582
583 if (hasRequests) {
584 printf(format: "\n");
585 for (const WaylandEvent &e : interface.requests) {
586 printf(format: " virtual void %s_", interfaceNameStripped);
587 printEvent(e);
588 printf(format: ";\n");
589 }
590 }
591
592 printf(format: "\n");
593 printf(format: " private:\n");
594 printf(format: " static void bind_func(struct ::wl_client *client, void *data, uint32_t version, uint32_t id);\n");
595 printf(format: " static void destroy_func(struct ::wl_resource *client_resource);\n");
596 printf(format: " static void display_destroy_func(struct ::wl_listener *listener, void *data);\n");
597 printf(format: "\n");
598 printf(format: " Resource *bind(struct ::wl_client *client, uint32_t id, int version);\n");
599 printf(format: " Resource *bind(struct ::wl_resource *handle);\n");
600
601 if (hasRequests) {
602 printf(format: "\n");
603 printf(format: " static const struct ::%s_interface m_%s_interface;\n", interfaceName, interfaceName);
604
605 printf(format: "\n");
606 for (const WaylandEvent &e : interface.requests) {
607 printf(format: " static void ");
608
609 printEventHandlerSignature(e, interfaceName);
610 printf(format: ";\n");
611 }
612 }
613
614 printf(format: "\n");
615 printf(format: " QMultiMap<struct ::wl_client*, Resource*> m_resource_map;\n");
616 printf(format: " Resource *m_resource;\n");
617 printf(format: " struct ::wl_global *m_global;\n");
618 printf(format: " struct DisplayDestroyedListener : ::wl_listener {\n");
619 printf(format: " %s *parent;\n", interfaceName);
620 printf(format: " };\n");
621 printf(format: " DisplayDestroyedListener m_displayDestroyedListener;\n");
622 printf(format: " };\n");
623 }
624
625 printf(format: "}\n");
626 printf(format: "\n");
627 printf(format: "QT_WARNING_POP\n");
628 printf(format: "QT_END_NAMESPACE\n");
629 printf(format: "\n");
630 printf(format: "#endif\n");
631 }
632
633 if (m_option == ServerCode) {
634 if (m_headerPath.isEmpty())
635 printf(format: "#include \"qwayland-server-%s.h\"\n", QByteArray(m_protocolName).replace(before: '_', after: '-').constData());
636 else
637 printf(format: "#include <%s/qwayland-server-%s.h>\n", m_headerPath.constData(), QByteArray(m_protocolName).replace(before: '_', after: '-').constData());
638 printf(format: "\n");
639 printf(format: "QT_BEGIN_NAMESPACE\n");
640 printf(format: "QT_WARNING_PUSH\n");
641 printf(format: "QT_WARNING_DISABLE_GCC(\"-Wmissing-field-initializers\")\n");
642 printf(format: "QT_WARNING_DISABLE_CLANG(\"-Wmissing-field-initializers\")\n");
643 printf(format: "\n");
644 printf(format: "namespace QtWaylandServer {\n");
645
646 bool needsNewLine = false;
647 for (const WaylandInterface &interface : interfaces) {
648
649 if (ignoreInterface(name: interface.name))
650 continue;
651
652 if (needsNewLine)
653 printf(format: "\n");
654
655 needsNewLine = true;
656
657 const char *interfaceName = interface.name.constData();
658
659 QByteArray stripped = stripInterfaceName(name: interface.name);
660 const char *interfaceNameStripped = stripped.constData();
661
662 printf(format: " %s::%s(struct ::wl_client *client, uint32_t id, int version)\n", interfaceName, interfaceName);
663 printf(format: " : m_resource_map()\n");
664 printf(format: " , m_resource(nullptr)\n");
665 printf(format: " , m_global(nullptr)\n");
666 printf(format: " {\n");
667 printf(format: " init(client, id, version);\n");
668 printf(format: " }\n");
669 printf(format: "\n");
670
671 printf(format: " %s::%s(struct ::wl_display *display, int version)\n", interfaceName, interfaceName);
672 printf(format: " : m_resource_map()\n");
673 printf(format: " , m_resource(nullptr)\n");
674 printf(format: " , m_global(nullptr)\n");
675 printf(format: " {\n");
676 printf(format: " init(display, version);\n");
677 printf(format: " }\n");
678 printf(format: "\n");
679
680 printf(format: " %s::%s(struct ::wl_resource *resource)\n", interfaceName, interfaceName);
681 printf(format: " : m_resource_map()\n");
682 printf(format: " , m_resource(nullptr)\n");
683 printf(format: " , m_global(nullptr)\n");
684 printf(format: " {\n");
685 printf(format: " init(resource);\n");
686 printf(format: " }\n");
687 printf(format: "\n");
688
689 printf(format: " %s::%s()\n", interfaceName, interfaceName);
690 printf(format: " : m_resource_map()\n");
691 printf(format: " , m_resource(nullptr)\n");
692 printf(format: " , m_global(nullptr)\n");
693 printf(format: " {\n");
694 printf(format: " }\n");
695 printf(format: "\n");
696
697 printf(format: " %s::~%s()\n", interfaceName, interfaceName);
698 printf(format: " {\n");
699 printf(format: " for (auto resource : std::as_const(m_resource_map))\n");
700 printf(format: " resource->%s_object = nullptr;\n", interfaceNameStripped);
701 printf(format: "\n");
702 printf(format: " if (m_resource)\n");
703 printf(format: " m_resource->%s_object = nullptr;\n", interfaceNameStripped);
704 printf(format: "\n");
705 printf(format: " if (m_global) {\n");
706 printf(format: " wl_global_destroy(m_global);\n");
707 printf(format: " wl_list_remove(&m_displayDestroyedListener.link);\n");
708 printf(format: " }\n");
709 printf(format: " }\n");
710 printf(format: "\n");
711
712 printf(format: " void %s::init(struct ::wl_client *client, uint32_t id, int version)\n", interfaceName);
713 printf(format: " {\n");
714 printf(format: " m_resource = bind(client, id, version);\n");
715 printf(format: " }\n");
716 printf(format: "\n");
717
718 printf(format: " void %s::init(struct ::wl_resource *resource)\n", interfaceName);
719 printf(format: " {\n");
720 printf(format: " m_resource = bind(resource);\n");
721 printf(format: " }\n");
722 printf(format: "\n");
723
724 printf(format: " %s::Resource *%s::add(struct ::wl_client *client, int version)\n", interfaceName, interfaceName);
725 printf(format: " {\n");
726 printf(format: " Resource *resource = bind(client, 0, version);\n");
727 printf(format: " m_resource_map.insert(client, resource);\n");
728 printf(format: " return resource;\n");
729 printf(format: " }\n");
730 printf(format: "\n");
731
732 printf(format: " %s::Resource *%s::add(struct ::wl_client *client, uint32_t id, int version)\n", interfaceName, interfaceName);
733 printf(format: " {\n");
734 printf(format: " Resource *resource = bind(client, id, version);\n");
735 printf(format: " m_resource_map.insert(client, resource);\n");
736 printf(format: " return resource;\n");
737 printf(format: " }\n");
738 printf(format: "\n");
739
740 printf(format: " void %s::init(struct ::wl_display *display, int version)\n", interfaceName);
741 printf(format: " {\n");
742 printf(format: " m_global = wl_global_create(display, &::%s_interface, version, this, bind_func);\n", interfaceName);
743 printf(format: " m_displayDestroyedListener.notify = %s::display_destroy_func;\n", interfaceName);
744 printf(format: " m_displayDestroyedListener.parent = this;\n");
745 printf(format: " wl_display_add_destroy_listener(display, &m_displayDestroyedListener);\n");
746 printf(format: " }\n");
747 printf(format: "\n");
748
749 printf(format: " const struct wl_interface *%s::interface()\n", interfaceName);
750 printf(format: " {\n");
751 printf(format: " return &::%s_interface;\n", interfaceName);
752 printf(format: " }\n");
753 printf(format: "\n");
754
755 printf(format: " %s::Resource *%s::%s_allocate()\n", interfaceName, interfaceName, interfaceNameStripped);
756 printf(format: " {\n");
757 printf(format: " return new Resource;\n");
758 printf(format: " }\n");
759 printf(format: "\n");
760
761 printf(format: " void %s::%s_bind_resource(Resource *)\n", interfaceName, interfaceNameStripped);
762 printf(format: " {\n");
763 printf(format: " }\n");
764 printf(format: "\n");
765
766 printf(format: " void %s::%s_destroy_resource(Resource *)\n", interfaceName, interfaceNameStripped);
767 printf(format: " {\n");
768 printf(format: " }\n");
769 printf(format: "\n");
770
771 printf(format: " void %s::bind_func(struct ::wl_client *client, void *data, uint32_t version, uint32_t id)\n", interfaceName);
772 printf(format: " {\n");
773 printf(format: " %s *that = static_cast<%s *>(data);\n", interfaceName, interfaceName);
774 printf(format: " that->add(client, id, version);\n");
775 printf(format: " }\n");
776 printf(format: "\n");
777
778 printf(format: " void %s::display_destroy_func(struct ::wl_listener *listener, void *data)\n", interfaceName);
779 printf(format: " {\n");
780 printf(format: " Q_UNUSED(data);\n");
781 printf(format: " %s *that = static_cast<%s::DisplayDestroyedListener *>(listener)->parent;\n", interfaceName, interfaceName);
782 printf(format: " that->m_global = nullptr;\n");
783 printf(format: " }\n");
784 printf(format: "\n");
785
786 printf(format: " void %s::destroy_func(struct ::wl_resource *client_resource)\n", interfaceName);
787 printf(format: " {\n");
788 printf(format: " Resource *resource = Resource::fromResource(client_resource);\n");
789 printf(format: " Q_ASSERT(resource);\n");
790 printf(format: " %s *that = resource->%s_object;\n", interfaceName, interfaceNameStripped);
791 printf(format: " if (Q_LIKELY(that)) {\n");
792 printf(format: " that->m_resource_map.remove(resource->client(), resource);\n");
793 printf(format: " that->%s_destroy_resource(resource);\n", interfaceNameStripped);
794 printf(format: "\n");
795 printf(format: " that = resource->%s_object;\n", interfaceNameStripped);
796 printf(format: " if (that && that->m_resource == resource)\n");
797 printf(format: " that->m_resource = nullptr;\n");
798 printf(format: " }\n");
799 printf(format: " delete resource;\n");
800 printf(format: " }\n");
801 printf(format: "\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(format: " %s::Resource *%s::bind(struct ::wl_client *client, uint32_t id, int version)\n", interfaceName, interfaceName);
810 printf(format: " {\n");
811 printf(format: " 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(format: " struct ::wl_resource *handle = wl_resource_create(client, &::%s_interface, version, id);\n", interfaceName);
813 printf(format: " return bind(handle);\n");
814 printf(format: " }\n");
815 printf(format: "\n");
816
817 printf(format: " %s::Resource *%s::bind(struct ::wl_resource *handle)\n", interfaceName, interfaceName);
818 printf(format: " {\n");
819 printf(format: " Resource *resource = %s_allocate();\n", interfaceNameStripped);
820 printf(format: " resource->%s_object = this;\n", interfaceNameStripped);
821 printf(format: "\n");
822 printf(format: " wl_resource_set_implementation(handle, %s, resource, destroy_func);", interfaceMember.constData());
823 printf(format: "\n");
824 printf(format: " resource->handle = handle;\n");
825 printf(format: " %s_bind_resource(resource);\n", interfaceNameStripped);
826 printf(format: " return resource;\n");
827 printf(format: " }\n");
828
829 printf(format: " %s::Resource *%s::Resource::fromResource(struct ::wl_resource *resource)\n", interfaceName, interfaceName);
830 printf(format: " {\n");
831 printf(format: " if (Q_UNLIKELY(!resource))\n");
832 printf(format: " return nullptr;\n");
833 printf(format: " if (wl_resource_instance_of(resource, &::%s_interface, %s))\n", interfaceName, interfaceMember.constData());
834 printf(format: " return static_cast<Resource *>(wl_resource_get_user_data(resource));\n");
835 printf(format: " return nullptr;\n");
836 printf(format: " }\n");
837
838 if (hasRequests) {
839 printf(format: "\n");
840 printf(format: " 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(format: ",");
845 needsComma = true;
846 printf(format: "\n");
847 printf(format: " %s::handle_%s", interfaceName, e.name.constData());
848 }
849 printf(format: "\n");
850 printf(format: " };\n");
851
852 for (const WaylandEvent &e : interface.requests) {
853 printf(format: "\n");
854 printf(format: " void %s::%s_", interfaceName, interfaceNameStripped);
855 printEvent(e, omitNames: true);
856 printf(format: "\n");
857 printf(format: " {\n");
858 printf(format: " }\n");
859 }
860 printf(format: "\n");
861
862 for (const WaylandEvent &e : interface.requests) {
863 printf(format: "\n");
864 printf(format: " void %s::", interfaceName);
865
866 printEventHandlerSignature(e, interfaceName, deepIndent: false);
867
868 printf(format: "\n");
869 printf(format: " {\n");
870 printf(format: " Q_UNUSED(client);\n");
871 printf(format: " Resource *r = Resource::fromResource(resource);\n");
872 printf(format: " if (Q_UNLIKELY(!r->%s_object)) {\n", interfaceNameStripped);
873 if (e.type == "destructor")
874 printf(format: " wl_resource_destroy(resource);\n");
875 printf(format: " return;\n");
876 printf(format: " }\n");
877 printf(format: " static_cast<%s *>(r->%s_object)->%s_%s(\n", interfaceName, interfaceNameStripped, interfaceNameStripped, e.name.constData());
878 printf(format: " r");
879 for (const WaylandArgument &a : e.arguments) {
880 printf(format: ",\n");
881 QByteArray cType = waylandToCType(waylandType: a.type, interface: a.interface);
882 QByteArray qtType = waylandToQtType(waylandType: a.type, interface: a.interface, cStyleArray: e.request);
883 const char *argumentName = a.name.constData();
884 if (cType == qtType)
885 printf(format: " %s", argumentName);
886 else if (a.type == "string")
887 printf(format: " QString::fromUtf8(%s)", argumentName);
888 }
889 printf(format: ");\n");
890 printf(format: " }\n");
891 }
892 }
893
894 for (const WaylandEvent &e : interface.events) {
895 printf(format: "\n");
896 printf(format: " void %s::send_", interfaceName);
897 printEvent(e);
898 printf(format: "\n");
899 printf(format: " {\n");
900 printf(format: " Q_ASSERT_X(m_resource, \"%s::%s\", \"Uninitialised resource\");\n", interfaceName, e.name.constData());
901 printf(format: " if (Q_UNLIKELY(!m_resource)) {\n");
902 printf(format: " qWarning(\"could not call %s::%s as it's not initialised\");\n", interfaceName, e.name.constData());
903 printf(format: " return;\n");
904 printf(format: " }\n");
905 printf(format: " send_%s(\n", e.name.constData());
906 printf(format: " m_resource->handle");
907 for (const WaylandArgument &a : e.arguments) {
908 printf(format: ",\n");
909 printf(format: " %s", a.name.constData());
910 }
911 printf(format: ");\n");
912 printf(format: " }\n");
913 printf(format: "\n");
914
915 printf(format: " void %s::send_", interfaceName);
916 printEvent(e, omitNames: false, withResource: true);
917 printf(format: "\n");
918 printf(format: " {\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(format: " struct wl_array %s;\n", arrayName);
927 printf(format: " %s.size = %s.size();\n", arrayName, variableName);
928 printf(format: " %s.data = static_cast<void *>(const_cast<char *>(%s.constData()));\n", arrayName, variableName);
929 printf(format: " %s.alloc = 0;\n", arrayName);
930 printf(format: "\n");
931 }
932
933 printf(format: " %s_send_%s(\n", interfaceName, e.name.constData());
934 printf(format: " resource");
935
936 for (const WaylandArgument &a : e.arguments) {
937 printf(format: ",\n");
938 QByteArray cType = waylandToCType(waylandType: a.type, interface: a.interface);
939 QByteArray qtType = waylandToQtType(waylandType: a.type, interface: a.interface, cStyleArray: e.request);
940 if (a.type == "string")
941 printf(format: " %s.toUtf8().constData()", a.name.constData());
942 else if (a.type == "array")
943 printf(format: " &%s_data", a.name.constData());
944 else if (cType == qtType)
945 printf(format: " %s", a.name.constData());
946 }
947
948 printf(format: ");\n");
949 printf(format: " }\n");
950 printf(format: "\n");
951 }
952 }
953 printf(format: "}\n");
954 printf(format: "\n");
955 printf(format: "QT_WARNING_POP\n");
956 printf(format: "QT_END_NAMESPACE\n");
957 }
958
959 if (m_option == ClientHeader) {
960 QByteArray inclusionGuard = QByteArray("QT_WAYLAND_") + preProcessorProtocolName.constData();
961 printf(format: "#ifndef %s\n", inclusionGuard.constData());
962 printf(format: "#define %s\n", inclusionGuard.constData());
963 printf(format: "\n");
964 if (m_headerPath.isEmpty())
965 printf(format: "#include \"wayland-%s-client-protocol.h\"\n", QByteArray(m_protocolName).replace(before: '_', after: '-').constData());
966 else
967 printf(format: "#include <%s/wayland-%s-client-protocol.h>\n", m_headerPath.constData(), QByteArray(m_protocolName).replace(before: '_', after: '-').constData());
968 printf(format: "#include <QByteArray>\n");
969 printf(format: "#include <QString>\n");
970 printf(format: "\n");
971 printf(format: "struct wl_registry;\n");
972 printf(format: "\n");
973 printf(format: "QT_BEGIN_NAMESPACE\n");
974 printf(format: "QT_WARNING_PUSH\n");
975 printf(format: "QT_WARNING_DISABLE_GCC(\"-Wmissing-field-initializers\")\n");
976 printf(format: "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(format: "\n");
983 printf(format: "namespace QtWayland {\n");
984
985 bool needsNewLine = false;
986 for (const WaylandInterface &interface : interfaces) {
987
988 if (ignoreInterface(name: interface.name))
989 continue;
990
991 if (needsNewLine)
992 printf(format: "\n");
993 needsNewLine = true;
994
995 const char *interfaceName = interface.name.constData();
996
997 QByteArray stripped = stripInterfaceName(name: interface.name);
998 const char *interfaceNameStripped = stripped.constData();
999
1000 printf(format: " class %s %s\n {\n", clientExport.constData(), interfaceName);
1001 printf(format: " public:\n");
1002 printf(format: " %s(struct ::wl_registry *registry, uint32_t id, int version);\n", interfaceName);
1003 printf(format: " %s(struct ::%s *object);\n", interfaceName, interfaceName);
1004 printf(format: " %s();\n", interfaceName);
1005 printf(format: "\n");
1006 printf(format: " virtual ~%s();\n", interfaceName);
1007 printf(format: "\n");
1008 printf(format: " void init(struct ::wl_registry *registry, uint32_t id, int version);\n");
1009 printf(format: " void init(struct ::%s *object);\n", interfaceName);
1010 printf(format: "\n");
1011 printf(format: " struct ::%s *object() { return m_%s; }\n", interfaceName, interfaceName);
1012 printf(format: " const struct ::%s *object() const { return m_%s; }\n", interfaceName, interfaceName);
1013 printf(format: " static %s *fromObject(struct ::%s *object);\n", interfaceName, interfaceName);
1014 printf(format: "\n");
1015 printf(format: " bool isInitialized() const;\n");
1016 printf(format: "\n");
1017 printf(format: " uint32_t version() const;");
1018 printf(format: "\n");
1019 printf(format: " static const struct ::wl_interface *interface();\n");
1020
1021 printEnums(enums: interface.enums);
1022
1023 if (!interface.requests.empty()) {
1024 printf(format: "\n");
1025 for (const WaylandEvent &e : interface.requests) {
1026 const WaylandArgument *new_id = newIdArgument(arguments: 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(format: " %s", new_id_str.constData());
1035 printEvent(e);
1036 printf(format: ";\n");
1037 }
1038 }
1039
1040 bool hasEvents = !interface.events.empty();
1041
1042 if (hasEvents) {
1043 printf(format: "\n");
1044 printf(format: " protected:\n");
1045 for (const WaylandEvent &e : interface.events) {
1046 printf(format: " virtual void %s_", interfaceNameStripped);
1047 printEvent(e);
1048 printf(format: ";\n");
1049 }
1050 }
1051
1052 printf(format: "\n");
1053 printf(format: " private:\n");
1054 if (hasEvents) {
1055 printf(format: " void init_listener();\n");
1056 printf(format: " static const struct %s_listener m_%s_listener;\n", interfaceName, interfaceName);
1057 for (const WaylandEvent &e : interface.events) {
1058 printf(format: " static void ");
1059
1060 printEventHandlerSignature(e, interfaceName);
1061 printf(format: ";\n");
1062 }
1063 }
1064 printf(format: " struct ::%s *m_%s;\n", interfaceName, interfaceName);
1065 printf(format: " };\n");
1066 }
1067 printf(format: "}\n");
1068 printf(format: "\n");
1069 printf(format: "QT_WARNING_POP\n");
1070 printf(format: "QT_END_NAMESPACE\n");
1071 printf(format: "\n");
1072 printf(format: "#endif\n");
1073 }
1074
1075 if (m_option == ClientCode) {
1076 if (m_headerPath.isEmpty())
1077 printf(format: "#include \"qwayland-%s.h\"\n", QByteArray(m_protocolName).replace(before: '_', after: '-').constData());
1078 else
1079 printf(format: "#include <%s/qwayland-%s.h>\n", m_headerPath.constData(), QByteArray(m_protocolName).replace(before: '_', after: '-').constData());
1080 printf(format: "\n");
1081 printf(format: "QT_BEGIN_NAMESPACE\n");
1082 printf(format: "QT_WARNING_PUSH\n");
1083 printf(format: "QT_WARNING_DISABLE_GCC(\"-Wmissing-field-initializers\")\n");
1084 printf(format: "QT_WARNING_DISABLE_CLANG(\"-Wmissing-field-initializers\")\n");
1085 printf(format: "\n");
1086 printf(format: "namespace QtWayland {\n");
1087 printf(format: "\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(format: "static inline void *wlRegistryBind(struct ::wl_registry *registry, uint32_t name, const struct ::wl_interface *interface, uint32_t version)\n");
1092 printf(format: "{\n");
1093 printf(format: " const uint32_t bindOpCode = 0;\n");
1094 printf(format: " return (void *) wl_proxy_marshal_constructor_versioned((struct wl_proxy *) registry,\n");
1095 printf(format: " bindOpCode, interface, version, name, interface->name, version, nullptr);\n");
1096 printf(format: "}\n");
1097 printf(format: "\n");
1098
1099 bool needsNewLine = false;
1100 for (const WaylandInterface &interface : interfaces) {
1101
1102 if (ignoreInterface(name: interface.name))
1103 continue;
1104
1105 if (needsNewLine)
1106 printf(format: "\n");
1107 needsNewLine = true;
1108
1109 const char *interfaceName = interface.name.constData();
1110
1111 QByteArray stripped = stripInterfaceName(name: interface.name);
1112 const char *interfaceNameStripped = stripped.constData();
1113
1114 bool hasEvents = !interface.events.empty();
1115
1116 printf(format: " %s::%s(struct ::wl_registry *registry, uint32_t id, int version)\n", interfaceName, interfaceName);
1117 printf(format: " {\n");
1118 printf(format: " init(registry, id, version);\n");
1119 printf(format: " }\n");
1120 printf(format: "\n");
1121
1122 printf(format: " %s::%s(struct ::%s *obj)\n", interfaceName, interfaceName, interfaceName);
1123 printf(format: " : m_%s(obj)\n", interfaceName);
1124 printf(format: " {\n");
1125 if (hasEvents)
1126 printf(format: " init_listener();\n");
1127 printf(format: " }\n");
1128 printf(format: "\n");
1129
1130 printf(format: " %s::%s()\n", interfaceName, interfaceName);
1131 printf(format: " : m_%s(nullptr)\n", interfaceName);
1132 printf(format: " {\n");
1133 printf(format: " }\n");
1134 printf(format: "\n");
1135
1136 printf(format: " %s::~%s()\n", interfaceName, interfaceName);
1137 printf(format: " {\n");
1138 printf(format: " }\n");
1139 printf(format: "\n");
1140
1141 printf(format: " void %s::init(struct ::wl_registry *registry, uint32_t id, int version)\n", interfaceName);
1142 printf(format: " {\n");
1143 printf(format: " m_%s = static_cast<struct ::%s *>(wlRegistryBind(registry, id, &%s_interface, version));\n", interfaceName, interfaceName, interfaceName);
1144 if (hasEvents)
1145 printf(format: " init_listener();\n");
1146 printf(format: " }\n");
1147 printf(format: "\n");
1148
1149 printf(format: " void %s::init(struct ::%s *obj)\n", interfaceName, interfaceName);
1150 printf(format: " {\n");
1151 printf(format: " m_%s = obj;\n", interfaceName);
1152 if (hasEvents)
1153 printf(format: " init_listener();\n");
1154 printf(format: " }\n");
1155 printf(format: "\n");
1156
1157 printf(format: " %s *%s::fromObject(struct ::%s *object)\n", interfaceName, interfaceName, interfaceName);
1158 printf(format: " {\n");
1159 if (hasEvents) {
1160 printf(format: " if (wl_proxy_get_listener((struct ::wl_proxy *)object) != (void *)&m_%s_listener)\n", interfaceName);
1161 printf(format: " return nullptr;\n");
1162 }
1163 printf(format: " return static_cast<%s *>(%s_get_user_data(object));\n", interfaceName, interfaceName);
1164 printf(format: " }\n");
1165 printf(format: "\n");
1166
1167 printf(format: " bool %s::isInitialized() const\n", interfaceName);
1168 printf(format: " {\n");
1169 printf(format: " return m_%s != nullptr;\n", interfaceName);
1170 printf(format: " }\n");
1171 printf(format: "\n");
1172
1173 printf(format: " uint32_t %s::version() const\n", interfaceName);
1174 printf(format: " {\n");
1175 printf(format: " return wl_proxy_get_version(reinterpret_cast<wl_proxy*>(m_%s));\n", interfaceName);
1176 printf(format: " }\n");
1177 printf(format: "\n");
1178
1179 printf(format: " const struct wl_interface *%s::interface()\n", interfaceName);
1180 printf(format: " {\n");
1181 printf(format: " return &::%s_interface;\n", interfaceName);
1182 printf(format: " }\n");
1183
1184 for (const WaylandEvent &e : interface.requests) {
1185 printf(format: "\n");
1186 const WaylandArgument *new_id = newIdArgument(arguments: 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(format: " %s%s::", new_id_str.constData(), interfaceName);
1195 printEvent(e);
1196 printf(format: "\n");
1197 printf(format: " {\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(format: " struct wl_array %s;\n", arrayName);
1205 printf(format: " %s.size = %s.size();\n", arrayName, variableName);
1206 printf(format: " %s.data = static_cast<void *>(const_cast<char *>(%s.constData()));\n", arrayName, variableName);
1207 printf(format: " %s.alloc = 0;\n", arrayName);
1208 printf(format: "\n");
1209 }
1210 int actualArgumentCount = new_id ? int(e.arguments.size()) - 1 : int(e.arguments.size());
1211 printf(format: " %s::%s_%s(\n", new_id ? "return " : "", interfaceName, e.name.constData());
1212 printf(format: " 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(format: ",");
1220 needsComma = true;
1221 printf(format: "\n");
1222 if (isNewId) {
1223 printf(format: " interface,\n");
1224 printf(format: " version");
1225 } else {
1226 QByteArray cType = waylandToCType(waylandType: a.type, interface: a.interface);
1227 QByteArray qtType = waylandToQtType(waylandType: a.type, interface: a.interface, cStyleArray: e.request);
1228 if (a.type == "string")
1229 printf(format: " %s.toUtf8().constData()", a.name.constData());
1230 else if (a.type == "array")
1231 printf(format: " &%s_data", a.name.constData());
1232 else if (cType == qtType)
1233 printf(format: " %s", a.name.constData());
1234 }
1235 }
1236 printf(format: ");\n");
1237 if (e.type == "destructor")
1238 printf(format: " m_%s = nullptr;\n", interfaceName);
1239 printf(format: " }\n");
1240 }
1241
1242 if (hasEvents) {
1243 printf(format: "\n");
1244 for (const WaylandEvent &e : interface.events) {
1245 printf(format: " void %s::%s_", interfaceName, interfaceNameStripped);
1246 printEvent(e, omitNames: true);
1247 printf(format: "\n");
1248 printf(format: " {\n");
1249 printf(format: " }\n");
1250 printf(format: "\n");
1251 printf(format: " void %s::", interfaceName);
1252 printEventHandlerSignature(e, interfaceName, deepIndent: false);
1253 printf(format: "\n");
1254 printf(format: " {\n");
1255 printf(format: " Q_UNUSED(object);\n");
1256 printf(format: " 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(format: ",");
1261 needsComma = true;
1262 printf(format: "\n");
1263 const char *argumentName = a.name.constData();
1264 if (a.type == "string")
1265 printf(format: " QString::fromUtf8(%s)", argumentName);
1266 else
1267 printf(format: " %s", argumentName);
1268 }
1269 printf(format: ");\n");
1270
1271 printf(format: " }\n");
1272 printf(format: "\n");
1273 }
1274 printf(format: " const struct %s_listener %s::m_%s_listener = {\n", interfaceName, interfaceName, interfaceName);
1275 for (const WaylandEvent &e : interface.events) {
1276 printf(format: " %s::handle_%s,\n", interfaceName, e.name.constData());
1277 }
1278 printf(format: " };\n");
1279 printf(format: "\n");
1280
1281 printf(format: " void %s::init_listener()\n", interfaceName);
1282 printf(format: " {\n");
1283 printf(format: " %s_add_listener(m_%s, &m_%s_listener, this);\n", interfaceName, interfaceName, interfaceName);
1284 printf(format: " }\n");
1285 }
1286 }
1287 printf(format: "}\n");
1288 printf(format: "\n");
1289 printf(format: "QT_WARNING_POP\n");
1290 printf(format: "QT_END_NAMESPACE\n");
1291 }
1292
1293 return true;
1294}
1295
1296void Scanner::printErrors()
1297{
1298 if (m_xml->hasError())
1299 fprintf(stderr, format: "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}
1319

source code of qtwayland/src/qtwaylandscanner/qtwaylandscanner.cpp