1/*****************************************************************
2This file is part of the KDE project.
3
4Copyright (C) 2009 Lubos Lunak <l.lunak@kde.org>
5Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
6
7Permission is hereby granted, free of charge, to any person obtaining a
8copy of this software and associated documentation files (the "Software"),
9to deal in the Software without restriction, including without limitation
10the rights to use, copy, modify, merge, publish, distribute, sublicense,
11and/or sell copies of the Software, and to permit persons to whom the
12Software is furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in
15all copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23DEALINGS IN THE SOFTWARE.
24******************************************************************/
25
26#ifndef PAINTREDIRECTOR_H
27#define PAINTREDIRECTOR_H
28
29#include <qregion.h>
30#include <qtimer.h>
31#include <qwidget.h>
32#include <qbasictimer.h>
33// xcb
34#include <xcb/render.h>
35
36namespace KWin
37{
38
39// forward declarations
40class Client;
41class Deleted;
42class XRenderPicture;
43class GLTexture;
44
45// This class redirects all painting of a given widget (including its children)
46// into a paint device (QPixmap).
47class PaintRedirector
48 : public QObject
49{
50 Q_OBJECT
51public:
52 enum DecorationPixmap {
53 TopPixmap,
54 RightPixmap,
55 BottomPixmap,
56 LeftPixmap,
57 PixmapCount
58 };
59 virtual ~PaintRedirector();
60 virtual bool eventFilter(QObject* o, QEvent* e);
61 QRegion pendingRegion() const;
62 QRegion scheduledRepaintRegion();
63
64 void markAsRepainted() {
65 m_requiresRepaint = false;
66 }
67 bool requiresRepaint() const {
68 return m_requiresRepaint;
69 }
70 void resizePixmaps();
71
72 template <typename T>
73 T topDecoPixmap() const;
74 template <typename T>
75 T leftDecoPixmap() const;
76 template <typename T>
77 T bottomDecoPixmap() const;
78 template <typename T>
79 T rightDecoPixmap() const;
80
81 /**
82 * Used by Deleted::copyToDeleted() to move the PaintRedirector to the Deleted.
83 * The actual redirecting ends as the decoration gets destroyed after the Deleted
84 * is created.
85 **/
86 void reparent(Deleted *d);
87 static PaintRedirector *create(Client *c, QWidget* widget);
88
89public slots:
90 void ensurePixmapsPainted();
91protected:
92 PaintRedirector(Client *c, QWidget* widget);
93 virtual xcb_render_picture_t picture(DecorationPixmap border) const;
94 virtual GLTexture *texture(DecorationPixmap border) const;
95 virtual void resizePixmaps(const QRect *rects);
96 virtual void resize(DecorationPixmap border, const QSize &size);
97 virtual void preparePaint(const QPixmap &pending);
98 virtual void updatePixmaps(const QRect *rects, const QRegion &region);
99 virtual void paint(DecorationPixmap border, const QRect& r, const QRect &b, const QRegion &reg);
100 virtual QPaintDevice *scratch() = 0;
101 virtual QPaintDevice *recreateScratch(const QSize &size) = 0;
102 virtual void fillScratch(Qt::GlobalColor color) = 0;
103 virtual void discardScratch() = 0;
104
105private:
106 void added(QWidget* widget);
107 void removed(QWidget* widget);
108 bool isToolTip(QWidget* widget) const;
109 void timerEvent(QTimerEvent* event);
110
111 void performPendingPaint();
112 void repaintPixmap(DecorationPixmap border, const QRect& r, QRegion reg);
113 QWidget* widget;
114 QRegion pending;
115 QRegion scheduled;
116 bool recursionCheck;
117 QBasicTimer cleanupTimer;
118
119 Client *m_client;
120 bool m_requiresRepaint;
121};
122
123class ImageBasedPaintRedirector : public PaintRedirector
124{
125 Q_OBJECT
126public:
127 virtual ~ImageBasedPaintRedirector();
128protected:
129 ImageBasedPaintRedirector(Client *c, QWidget *widget);
130 virtual QPaintDevice *recreateScratch(const QSize &size);
131 virtual QPaintDevice *scratch();
132 virtual void fillScratch(Qt::GlobalColor color);
133 virtual void discardScratch();
134 const QImage &scratchImage() const;
135private:
136 QImage m_scratchImage;
137};
138
139class OpenGLPaintRedirector : public ImageBasedPaintRedirector
140{
141 Q_OBJECT
142
143 enum Texture { LeftRight = 0, TopBottom, TextureCount };
144
145public:
146 OpenGLPaintRedirector(Client *c, QWidget *widget);
147 virtual ~OpenGLPaintRedirector();
148
149 GLTexture *leftRightTexture() const { return m_textures[LeftRight]; }
150 GLTexture *topBottomTexture() const { return m_textures[TopBottom]; }
151
152protected:
153 virtual void resizePixmaps(const QRect *rects);
154 virtual void updatePixmaps(const QRect *rects, const QRegion &region);
155 virtual void preparePaint(const QPixmap &pending);
156
157private:
158 QImage m_tempImage;
159 GLTexture *m_textures[2];
160};
161
162class NativeXRenderPaintRedirector : public PaintRedirector
163{
164 Q_OBJECT
165public:
166 NativeXRenderPaintRedirector(Client *c, QWidget *widget);
167 virtual ~NativeXRenderPaintRedirector();
168
169protected:
170 virtual xcb_render_picture_t picture(DecorationPixmap border) const;
171 virtual void resize(DecorationPixmap border, const QSize &size);
172 virtual void paint(DecorationPixmap border, const QRect &r, const QRect &b, const QRegion &reg);
173 virtual void fillScratch(Qt::GlobalColor color);
174 virtual QPaintDevice *recreateScratch(const QSize &size);
175 virtual QPaintDevice *scratch();
176 virtual void discardScratch();
177private:
178 QPixmap m_pixmaps[PixmapCount];
179 QPixmap m_scratch;
180};
181
182class RasterXRenderPaintRedirector : public ImageBasedPaintRedirector
183{
184 Q_OBJECT
185public:
186 RasterXRenderPaintRedirector(Client *c, QWidget *widget);
187 virtual ~RasterXRenderPaintRedirector();
188
189protected:
190 virtual xcb_render_picture_t picture(DecorationPixmap border) const;
191 virtual void resize(DecorationPixmap border, const QSize &size);
192 virtual void paint(DecorationPixmap border, const QRect &r, const QRect &b, const QRegion &reg);
193 virtual void preparePaint(const QPixmap &pending);
194private:
195 QSize m_sizes[PixmapCount];
196 xcb_pixmap_t m_pixmaps[PixmapCount];
197 xcb_gcontext_t m_gc;
198 XRenderPicture* m_pictures[PixmapCount];
199 QImage m_tempImage;
200};
201
202template <>
203inline
204GLTexture *PaintRedirector::bottomDecoPixmap() const
205{
206 return texture(BottomPixmap);
207}
208
209template <>
210inline
211GLTexture *PaintRedirector::leftDecoPixmap() const
212{
213 return texture(LeftPixmap);
214}
215
216template <>
217inline
218GLTexture *PaintRedirector::rightDecoPixmap() const
219{
220 return texture(RightPixmap);
221}
222
223template <>
224inline
225GLTexture *PaintRedirector::topDecoPixmap() const
226{
227 return texture(TopPixmap);
228}
229
230template <>
231inline
232xcb_render_picture_t PaintRedirector::bottomDecoPixmap() const
233{
234 return picture(BottomPixmap);
235}
236
237template <>
238inline
239xcb_render_picture_t PaintRedirector::leftDecoPixmap() const
240{
241 return picture(LeftPixmap);
242}
243
244template <>
245inline
246xcb_render_picture_t PaintRedirector::rightDecoPixmap() const
247{
248 return picture(RightPixmap);
249}
250
251template <>
252inline
253xcb_render_picture_t PaintRedirector::topDecoPixmap() const
254{
255 return picture(TopPixmap);
256}
257
258inline
259const QImage &ImageBasedPaintRedirector::scratchImage() const
260{
261 return m_scratchImage;
262}
263
264} // namespace
265
266#endif
267