1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtGui/QPaintDevice>
43 #include <QtGui/QPainter>
44 #include <QtGui/QPixmap>
45 #include <QtGui/QWidget>
47 #include "private/qt_x11_p.h"
48 #include "private/qpixmap_x11_p.h"
49 #include "private/qwidget_p.h"
50 #include "qx11info_x11.h"
51 #include "qwindowsurface_x11_p.h"
55 extern void *qt_getClipRects(const QRegion &r, int &num); // in qpaintengine_x11.cpp
57 struct QX11WindowSurfacePrivate
62 bool translucentBackground;
66 QX11WindowSurface::QX11WindowSurface(QWidget *widget)
67 : QWindowSurface(widget), d_ptr(new QX11WindowSurfacePrivate), gc(0)
69 d_ptr->widget = widget;
71 d_ptr->translucentBackground = X11->use_xrender
72 && widget->x11Info().depth() == 32;
77 QX11WindowSurface::~QX11WindowSurface()
81 XFreeGC(X11->display, gc);
86 QPaintDevice *QX11WindowSurface::paintDevice()
88 return &d_ptr->device;
91 void QX11WindowSurface::beginPaint(const QRegion &rgn)
94 Q_ASSERT(!d_ptr->device.isNull());
96 if (d_ptr->translucentBackground) {
97 if (d_ptr->device.depth() != 32)
98 static_cast<QX11PixmapData *>(d_ptr->device.data_ptr().data())->convertToARGB32();
99 ::Picture src = X11->getSolidFill(d_ptr->device.x11Info().screen(), Qt::transparent);
100 ::Picture dst = d_ptr->device.x11PictureHandle();
101 const QVector<QRect> rects = rgn.rects();
102 const int w = d_ptr->device.width();
103 const int h = d_ptr->device.height();
104 for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it)
105 XRenderComposite(X11->display, PictOpSrc, src, 0, dst,
106 0, 0, w, h, it->x(), it->y(),
107 it->width(), it->height());
112 void QX11WindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset)
114 if (d_ptr->device.isNull())
117 QPoint wOffset = qt_qwidget_data(widget)->wrect.topLeft();
119 QRect br = rgn.boundingRect();
120 if (!wOffset.isNull())
121 wrgn.translate(-wOffset);
122 QRect wbr = wrgn.boundingRect();
125 XRectangle *rects = (XRectangle *)qt_getClipRects(wrgn, num);
128 // qDebug() << "XSetClipRectangles";
129 // for (int i = 0; i < num; ++i)
130 // qDebug() << ' ' << i << rects[i].x << rects[i].x << rects[i].y << rects[i].width << rects[i].height;
132 XSetClipRectangles(X11->display, gc, 0, 0, rects, num, YXBanded);
133 XCopyArea(X11->display, d_ptr->device.handle(), widget->handle(), gc,
134 br.x() + offset.x(), br.y() + offset.y(), br.width(), br.height(), wbr.x(), wbr.y());
136 XSetClipMask(X11->display, gc, XNone);
139 void QX11WindowSurface::setGeometry(const QRect &rect)
141 QWindowSurface::setGeometry(rect);
143 const QSize size = rect.size();
145 if (d_ptr->device.size() == size || size.width() <= 0 || size.height() <= 0)
147 #ifndef QT_NO_XRENDER
148 if (d_ptr->translucentBackground) {
149 QPixmap::x11SetDefaultScreen(d_ptr->widget->x11Info().screen());
151 QX11PixmapData *data = new QX11PixmapData(QPixmapData::PixmapType);
152 data->xinfo = d_ptr->widget->x11Info();
153 data->resize(size.width(), size.height());
154 d_ptr->device = QPixmap(data);
158 QPixmap::x11SetDefaultScreen(d_ptr->widget->x11Info().screen());
160 QX11PixmapData *oldData = static_cast<QX11PixmapData *>(d_ptr->device.pixmapData());
162 if (oldData && !(oldData->flags & QX11PixmapData::Uninitialized) && hasStaticContents()) {
163 // Copy the content of the old pixmap into the new one.
164 QX11PixmapData *newData = new QX11PixmapData(QPixmapData::PixmapType);
165 newData->resize(size.width(), size.height());
166 Q_ASSERT(oldData->d == newData->d);
168 QRegion staticRegion(staticContents());
169 // Make sure we're inside the boundaries of the old pixmap.
170 staticRegion &= QRect(0, 0, oldData->w, oldData->h);
171 const QRect boundingRect(staticRegion.boundingRect());
172 const int dx = boundingRect.x();
173 const int dy = boundingRect.y();
176 XRectangle *rects = (XRectangle *)qt_getClipRects(staticRegion, num);
177 GC tmpGc = XCreateGC(X11->display, oldData->hd, 0, 0);
178 XSetClipRectangles(X11->display, tmpGc, 0, 0, rects, num, YXBanded);
179 XCopyArea(X11->display, oldData->hd, newData->hd, tmpGc,
180 dx, dy, qMin(boundingRect.width(), size.width()),
181 qMin(boundingRect.height(), size.height()), dx, dy);
182 XFreeGC(X11->display, tmpGc);
183 newData->flags &= ~QX11PixmapData::Uninitialized;
185 d_ptr->device = QPixmap(newData);
187 d_ptr->device = QPixmap(size);
192 XFreeGC(X11->display, gc);
195 if (!d_ptr->device.isNull()) {
196 gc = XCreateGC(X11->display, d_ptr->device.handle(), 0, 0);
197 XSetGraphicsExposures(X11->display, gc, False);
201 bool QX11WindowSurface::scroll(const QRegion &area, int dx, int dy)
203 QRect rect = area.boundingRect();
205 if (d_ptr->device.isNull())
208 GC gc = XCreateGC(X11->display, d_ptr->device.handle(), 0, 0);
209 XCopyArea(X11->display, d_ptr->device.handle(), d_ptr->device.handle(), gc,
210 rect.x(), rect.y(), rect.width(), rect.height(),
211 rect.x()+dx, rect.y()+dy);
212 XFreeGC(X11->display, gc);
217 QPixmap QX11WindowSurface::grabWidget(const QWidget *widget,
218 const QRect& rect) const
220 if (!widget || d_ptr->device.isNull())
225 // make sure the rect is inside the widget & clip to widget's rect
227 srcRect = rect & widget->rect();
229 srcRect = widget->rect();
231 if (srcRect.isEmpty())
234 // If it's a child widget we have to translate the coordinates
235 if (widget != window())
236 srcRect.translate(widget->mapTo(window(), QPoint(0, 0)));
238 QPixmap::x11SetDefaultScreen(widget->x11Info().screen());
239 QPixmap px(srcRect.width(), srcRect.height());
241 GC tmpGc = XCreateGC(X11->display, d_ptr->device.handle(), 0, 0);
243 // Copy srcRect from the backing store to the new pixmap
244 XSetGraphicsExposures(X11->display, tmpGc, False);
245 XCopyArea(X11->display, d_ptr->device.handle(), px.handle(), tmpGc,
246 srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height(), 0, 0);
248 XFreeGC(X11->display, tmpGc);
253 QWindowSurface::WindowSurfaceFeatures QX11WindowSurface::features() const
255 WindowSurfaceFeatures features = QWindowSurface::PartialUpdates | QWindowSurface::PreservedContents;
256 #ifndef QT_NO_XRENDER
257 if (!d_ptr->translucentBackground)
258 features |= QWindowSurface::StaticContents;
260 features |= QWindowSurface::StaticContents;