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 <private/qwindowsurface_p.h>
44 #include <private/qwidget_p.h>
45 #include <private/qbackingstore_p.h>
46 #include <private/qapplication_p.h>
50 class QWindowSurfacePrivate
53 QWindowSurfacePrivate(QWidget *w)
59 #if !defined(Q_WS_QPA)
64 QRegion staticContents;
65 QList<QImage*> bufferImages;
75 \brief The QWindowSurface class provides the drawing area for top-level
81 \fn void QWindowSurface::beginPaint(const QRegion ®ion)
83 This function is called before painting onto the surface begins,
84 with the \a region in which the painting will occur.
86 \sa endPaint(), paintDevice()
90 \fn void QWindowSurface::endPaint(const QRegion ®ion)
92 This function is called after painting onto the surface has ended,
93 with the \a region in which the painting was performed.
95 \sa beginPaint(), paintDevice()
99 \fn void QWindowSurface::flush(QWidget *widget, const QRegion ®ion,
100 const QPoint &offset)
102 Flushes the given \a region from the specified \a widget onto the
105 Note that the \a offset parameter is currently unused.
109 \fn QPaintDevice* QWindowSurface::paintDevice()
111 Implement this function to return the appropriate paint device.
115 Constructs an empty surface for the given top-level \a window.
117 QWindowSurface::QWindowSurface(QWidget *window, bool setDefaultSurface)
118 : d_ptr(new QWindowSurfacePrivate(window))
120 if (!QApplicationPrivate::runtime_graphics_system) {
121 if(setDefaultSurface && window)
122 window->setWindowSurface(this);
127 Destroys this surface.
129 QWindowSurface::~QWindowSurface()
132 d_ptr->window->d_func()->extra->topextra->windowSurface = 0;
137 Returns a pointer to the top-level window associated with this
140 QWidget* QWindowSurface::window() const
142 return d_ptr->window;
145 void QWindowSurface::beginPaint(const QRegion &)
149 void QWindowSurface::endPaint(const QRegion &)
151 // QApplication::syncX();
152 qDeleteAll(d_ptr->bufferImages);
153 d_ptr->bufferImages.clear();
156 #if !defined(Q_WS_QPA)
158 Sets the currently allocated area to be the given \a rect.
160 This function is called whenever area covered by the top-level
165 void QWindowSurface::setGeometry(const QRect &rect)
167 d_ptr->geometry = rect;
171 Returns the currently allocated area on the screen.
173 QRect QWindowSurface::geometry() const
175 return d_ptr->geometry;
180 Sets the size of the windowsurface to be \a size.
184 void QWindowSurface::resize(const QSize &size)
190 Returns the current size of the windowsurface.
192 QSize QWindowSurface::size() const
199 Scrolls the given \a area \a dx pixels to the right and \a dy
200 downward; both \a dx and \a dy may be negative.
202 Returns true if the area was scrolled successfully; false otherwise.
204 bool QWindowSurface::scroll(const QRegion &area, int dx, int dy)
214 Returns a QImage pointer which represents the actual buffer the \a widget
215 is drawn into or 0 if this is unavailable.
217 You must call beginPaint() before you call this function and the returned
218 pointer is only valid until endPaint() is called.
220 QImage* QWindowSurface::buffer(const QWidget *widget)
222 if (widget->window() != window())
225 QPaintDevice *pdev = paintDevice();
226 if (!pdev || pdev->devType() != QInternal::Image)
229 const QPoint off = offset(widget);
230 QImage *img = static_cast<QImage*>(pdev);
232 QRect rect(off, widget->size());
233 rect &= QRect(QPoint(), img->size());
238 img = new QImage(img->scanLine(rect.y()) + rect.x() * img->depth() / 8,
239 rect.width(), rect.height(),
240 img->bytesPerLine(), img->format());
241 d_ptr->bufferImages.append(img);
247 Returns a QPixmap generated from the part of the backing store
248 corresponding to \a widget. Returns a null QPixmap if an error
249 occurs. The contents of the pixmap are only defined for the regions
250 of \a widget that have received paint events since the last resize
251 of the backing store.
253 If \a rectangle is a null rectangle (the default), the entire widget
254 is grabbed. Otherwise, the grabbed area is limited to \a rectangle.
256 The default implementation uses QWindowSurface::buffer().
258 \sa QPixmap::grabWidget()
260 QPixmap QWindowSurface::grabWidget(const QWidget *widget, const QRect &rectangle) const
264 if (widget->window() != window())
267 const QImage *img = const_cast<QWindowSurface *>(this)->buffer(widget->window());
269 if (!img || img->isNull())
272 QRect rect = rectangle.isEmpty() ? widget->rect() : (widget->rect() & rectangle);
274 rect.translate(offset(widget) - offset(widget->window()));
275 rect &= QRect(QPoint(), img->size());
280 QImage subimg(img->scanLine(rect.y()) + rect.x() * img->depth() / 8,
281 rect.width(), rect.height(),
282 img->bytesPerLine(), img->format());
283 subimg.detach(); //### expensive -- maybe we should have a real SubImage that shares reference count
285 result = QPixmap::fromImage(subimg);
290 Returns the offset of \a widget in the coordinates of this
293 QPoint QWindowSurface::offset(const QWidget *widget) const
295 QWidget *window = d_ptr->window;
296 QPoint offset = widget->mapTo(window, QPoint());
298 offset += window->geometry().topLeft() - window->frameGeometry().topLeft();
304 \fn QRect QWindowSurface::rect(const QWidget *widget) const
306 Returns the rectangle for \a widget in the coordinates of this
310 void QWindowSurface::setStaticContents(const QRegion ®ion)
312 d_ptr->staticContents = region;
315 QRegion QWindowSurface::staticContents() const
317 return d_ptr->staticContents;
320 bool QWindowSurface::hasStaticContents() const
322 return hasFeature(QWindowSurface::StaticContents) && !d_ptr->staticContents.isEmpty();
325 QWindowSurface::WindowSurfaceFeatures QWindowSurface::features() const
327 return PartialUpdates | PreservedContents;
331 #define Q_EXPORT_SCROLLRECT Q_GUI_EXPORT
333 #define Q_EXPORT_SCROLLRECT
336 void Q_EXPORT_SCROLLRECT qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset)
338 // make sure we don't detach
339 uchar *mem = const_cast<uchar*>(const_cast<const QImage &>(img).bits());
341 int lineskip = img.bytesPerLine();
342 int depth = img.depth() >> 3;
344 const QRect imageRect(0, 0, img.width(), img.height());
345 const QRect r = rect & imageRect & imageRect.translated(-offset);
346 const QPoint p = rect.topLeft() + offset;
354 if (r.top() < p.y()) {
355 src = mem + r.bottom() * lineskip + r.left() * depth;
356 dest = mem + (p.y() + r.height() - 1) * lineskip + p.x() * depth;
357 lineskip = -lineskip;
359 src = mem + r.top() * lineskip + r.left() * depth;
360 dest = mem + p.y() * lineskip + p.x() * depth;
363 const int w = r.width();
365 const int bytes = w * depth;
367 // overlapping segments?
368 if (offset.y() == 0 && qAbs(offset.x()) < w) {
370 ::memmove(dest, src, bytes);
376 ::memcpy(dest, src, bytes);