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

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