1 /* 2 quickscreengrabber.h 3 4 This file is part of GammaRay, the Qt application inspection and 5 manipulation tool. 6 7 Copyright (C) 2010-2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com 8 Author: Filipe Azevedo <filipe.azevedo@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 #ifndef GAMMARAY_QUICKINSPECTOR_QUICKSCREENGRABBER_H 30 #define GAMMARAY_QUICKINSPECTOR_QUICKSCREENGRABBER_H 31 32 #include "quickdecorationsdrawer.h" 33 34 #include <QObject> 35 #include <QPointer> 36 #include <QQuickItem> 37 #include <QMutex> 38 39 #include <memory> 40 41 QT_BEGIN_NAMESPACE 42 class QQuickWindow; 43 #ifndef QT_NO_OPENGL 44 class QOpenGLPaintDevice; 45 #endif 46 class QSGSoftwareRenderer; 47 QT_END_NAMESPACE 48 49 namespace GammaRay { 50 51 class ItemOrLayoutFacade 52 { 53 public: 54 ItemOrLayoutFacade() = default; 55 ItemOrLayoutFacade(QQuickItem *item); //krazy:exclude=explicit 56 57 /// Get either the layout of the widget or the this-pointer 58 QQuickItem *layout() const; 59 60 /// Get either the parent widget of the layout or the this-pointer 61 QQuickItem *item() const; 62 63 QRectF geometry() const; 64 bool isVisible() const; 65 QPointF pos() const; 66 isNull()67 inline bool isNull() const 68 { 69 return !m_object; 70 } 71 data()72 inline QQuickItem *data() 73 { 74 return m_object; 75 } 76 77 inline QQuickItem *operator->() const 78 { 79 Q_ASSERT(!isNull()); 80 return m_object; 81 } 82 clear()83 inline void clear() 84 { 85 m_object = nullptr; 86 } 87 88 private: 89 bool isLayout() const; asLayout()90 inline QQuickItem *asLayout() const 91 { 92 return m_object; 93 } 94 asItem()95 inline QQuickItem *asItem() const 96 { 97 return m_object; 98 } 99 100 QPointer<QQuickItem> m_object; 101 }; 102 103 class GrabbedFrame 104 { 105 public: 106 QImage image; 107 QTransform transform; 108 QRectF itemsGeometryRect; 109 QVector<QuickItemGeometry> itemsGeometry; 110 }; 111 112 class AbstractScreenGrabber : public QObject 113 { 114 Q_OBJECT 115 public: 116 struct RenderInfo { 117 // Keep in sync with QSGRendererInterface::GraphicsApi 118 enum GraphicsApi { 119 Unknown, 120 Software, 121 OpenGL, 122 Direct3D12 123 }; 124 RenderInfoRenderInfo125 RenderInfo() 126 : dpr(qQNaN()) 127 { 128 } 129 130 qreal dpr; 131 QSize windowSize; 132 GraphicsApi graphicsApi = Unknown; 133 }; 134 135 explicit AbstractScreenGrabber(QQuickWindow *window); 136 ~AbstractScreenGrabber() override; 137 138 static RenderInfo::GraphicsApi graphicsApiFor(QQuickWindow *window); 139 static std::unique_ptr<AbstractScreenGrabber> get(QQuickWindow *window); 140 141 QQuickWindow *window() const; 142 143 QuickDecorationsSettings settings() const; 144 void setSettings(const QuickDecorationsSettings &settings); 145 146 bool decorationsEnabled() const; 147 void setDecorationsEnabled(bool enabled); 148 149 /** 150 * Place the overlay on @p item 151 * 152 * @param item The overlay can be cover a widget or a layout of the current window 153 */ 154 void placeOn(const ItemOrLayoutFacade &item); 155 156 virtual void requestGrabWindow(const QRectF &userViewport) = 0; 157 158 signals: 159 void grabberReadyChanged(bool ready); 160 void sceneChanged(); 161 void sceneGrabbed(const GammaRay::GrabbedFrame &frame); 162 163 protected: 164 void doDrawDecorations(QPainter &painter); 165 void gatherRenderInfo(); 166 167 virtual void drawDecorations() = 0; 168 169 virtual void updateOverlay(); 170 static QuickItemGeometry initFromItem(QQuickItem *item); 171 172 private: 173 void itemParentChanged(QQuickItem *parent); 174 void itemWindowChanged(QQuickWindow *window); 175 void connectItemChanges(QQuickItem *item); 176 void disconnectItemChanges(QQuickItem *item); 177 void connectTopItemChanges(QQuickItem *item); 178 void disconnectTopItemChanges(QQuickItem *item); 179 180 protected: 181 QPointer<QQuickWindow> m_window; 182 QPointer<QQuickItem> m_currentToplevelItem; 183 ItemOrLayoutFacade m_currentItem; 184 QuickDecorationsSettings m_settings; 185 bool m_decorationsEnabled = true; 186 QRectF m_userViewport; 187 GrabbedFrame m_grabbedFrame; 188 RenderInfo m_renderInfo; 189 }; 190 191 #ifndef QT_NO_OPENGL 192 class OpenGLScreenGrabber : public AbstractScreenGrabber 193 { 194 Q_OBJECT 195 public: 196 explicit OpenGLScreenGrabber(QQuickWindow *window); 197 ~OpenGLScreenGrabber() override; 198 199 void requestGrabWindow(const QRectF &userViewport) override; 200 void drawDecorations() override; 201 202 private: 203 void setGrabbingMode(bool isGrabbingMode, const QRectF &userViewport); 204 void windowAfterSynchronizing(); 205 void windowAfterRendering(); 206 207 bool m_isGrabbing; 208 QMutex m_mutex; 209 }; 210 #endif 211 212 #if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) 213 class SoftwareScreenGrabber : public AbstractScreenGrabber 214 { 215 Q_OBJECT 216 public: 217 explicit SoftwareScreenGrabber(QQuickWindow *window); 218 ~SoftwareScreenGrabber() override; 219 220 void requestGrabWindow(const QRectF &userViewport) override; 221 void drawDecorations() override; 222 223 private: 224 void windowAfterRendering(); 225 void windowBeforeRendering(); 226 void updateOverlay() override; 227 228 QSGSoftwareRenderer *softwareRenderer() const; 229 230 bool m_isGrabbing = false; 231 QPointF m_lastItemPosition; 232 }; 233 #endif 234 235 } 236 237 Q_DECLARE_METATYPE(GammaRay::GrabbedFrame) 238 239 #endif 240