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