1 /*
2 resourceinfo.cpp
3
4 This file is part of GammaRay, the Qt application inspection and
5 manipulation tool.
6
7 Copyright (C) 2016-2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
8 Author: Giulio Camuffo <giulio.camuffo@kdab.com>
9
10 Licensees holding valid commercial KDAB GammaRay licenses may use this file in
11 accordance with GammaRay Commercial License Agreement provided with the Software.
12
13 Contact info@kdab.com if any conditions of this licensing are not clear to you.
14
15 This program is free software; you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation, either version 2 of the License, or
18 (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 */
28
29 #include "resourceinfo.h"
30
31 #include <functional>
32
33 #include <QWaylandSurface>
34 #include <QWaylandWlShellSurface>
35 #include <QWaylandOutput>
36 #include <QMetaEnum>
37
38 #include <wayland-server.h>
39
40 namespace GammaRay
41 {
42
43 class ResourceInfoExtractors
44 {
45 Q_DECLARE_TR_FUNCTIONS(GammaRay::ResourceInfoExtractors)
46 public:
47 using Function = std::function<void (wl_resource *, QStringList &)>;
48
ResourceInfoExtractors()49 ResourceInfoExtractors()
50 {
51 m_infoExtractors[wl_surface_interface.name] = wlsurfaceInfo;
52 m_infoExtractors[wl_shell_surface_interface.name] = wlshellsurfaceInfo;
53 m_infoExtractors[wl_output_interface.name] = wloutputInfo;
54 }
55
extractor(wl_resource * res) const56 Function extractor(wl_resource *res) const
57 {
58 return m_infoExtractors.value(wl_resource_get_class(res));
59 }
60
wlsurfaceInfo(wl_resource * res,QStringList & lines)61 static void wlsurfaceInfo(wl_resource *res, QStringList &lines)
62 {
63 QWaylandSurface *surface = QWaylandSurface::fromResource(res);
64 lines << tr("Role: %1").arg(surface->role() ? QString(surface->role()->name()) : QStringLiteral("none"));
65 lines << tr("Buffer size: (%1x%2)").arg(QString::number(surface->size().width()), QString::number(surface->size().height()));
66 #if QT_VERSION < QT_VERSION_CHECK(5, 8, 0)
67 lines << tr("Is mapped: %1").arg(surface->isMapped() ? QStringLiteral("true") : QStringLiteral("false"));
68 #else
69 lines << tr("Has content: %1").arg(surface->hasContent() ? QStringLiteral("true") : QStringLiteral("false"));
70 #endif
71 }
wlshellsurfaceInfo(wl_resource * res,QStringList & lines)72 static void wlshellsurfaceInfo(wl_resource *res, QStringList &lines)
73 {
74 QWaylandWlShellSurface *ss = QWaylandWlShellSurface::fromResource(res);
75 if (!ss) {
76 return;
77 }
78
79 lines << tr("Title: \"%1\"").arg(ss->title());
80 lines << tr("Class name: \"%1\"").arg(ss->className());
81
82 ResourceInfo resinfo(ss->surface()->resource());
83 lines << tr("Surface: %1").arg(resinfo.name());
84 foreach (const QString &line, resinfo.infoLines()) {
85 lines << QStringLiteral(" ") + line;
86 }
87 }
wloutputInfo(wl_resource * res,QStringList & lines)88 static void wloutputInfo(wl_resource *res, QStringList &lines)
89 {
90 QWaylandOutput *output = QWaylandOutput::fromResource(res);
91
92 lines << tr("Manufacturer: %1").arg(output->manufacturer());
93 lines << tr("Model: %1").arg(output->model());
94 lines << tr("Physical size: (%1x%2)").arg(QString::number(output->physicalSize().width()), QString::number(output->physicalSize().height()));
95 lines << tr("Position: (%1x%2)").arg(QString::number(output->position().x()), QString::number(output->position().y()));
96 #if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
97 const auto mode = output->currentMode();
98 lines << tr("Current mode: %1x%2@%3Hz").arg(QString::number(mode.size().width()), QString::number(mode.size().height()), QString::number(mode.refreshRate() / 1000.0f));
99 #endif
100 lines << tr("Scale factor: %1").arg(QString::number(output->scaleFactor()));
101 lines << tr("Transform: %1").arg(QMetaEnum::fromType<QWaylandOutput::Transform>().valueToKey(output->transform()));
102 lines << tr("Subpixel: %1").arg(QMetaEnum::fromType<QWaylandOutput::Subpixel>().valueToKey(output->subpixel()));
103 }
104
105 QHash<QByteArray, Function> m_infoExtractors;
106 };
107
Q_GLOBAL_STATIC(ResourceInfoExtractors,s_infoExtractors)108 Q_GLOBAL_STATIC(ResourceInfoExtractors, s_infoExtractors)
109
110 ResourceInfo::ResourceInfo(wl_resource *resource)
111 : m_resource(resource)
112 {
113 }
114
id() const115 uint32_t ResourceInfo::id() const
116 {
117 return wl_resource_get_id(m_resource);
118 }
119
interfaceName() const120 const char *ResourceInfo::interfaceName() const
121 {
122 return wl_resource_get_class(m_resource);
123 }
124
isInterface(const wl_interface * iface) const125 bool ResourceInfo::isInterface(const wl_interface *iface) const
126 {
127 return strcmp(interfaceName(), iface->name) == 0;
128 }
129
name() const130 QString ResourceInfo::name() const
131 {
132 return QString("%1@%2").arg(interfaceName(), QString::number(id()));
133 }
134
info() const135 QString ResourceInfo::info() const
136 {
137 const QStringList lines = infoLines();
138 QString str;
139 for (const QString &line : lines) {
140 if (!str.isEmpty()) {
141 str += QLatin1Char('\n');
142 }
143 str += line;
144 }
145 return str;
146 }
147
infoLines() const148 QStringList ResourceInfo::infoLines() const
149 {
150 QStringList lines;
151 lines << tr("Version: %1").arg(QString::number(wl_resource_get_version(m_resource)));
152
153 if (const auto &func = s_infoExtractors->extractor(m_resource)) {
154 func(m_resource, lines);
155 }
156
157 return lines;
158 }
159
160 }
161