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

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

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