/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** As a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qbackingstore_x11_p.h" #include "qxcbwindow.h" #include "qpixmap_x11_p.h" #include #include #if QT_CONFIG(xrender) # include #endif #include #ifndef None #define None 0L #endif QT_BEGIN_NAMESPACE QXcbNativeBackingStore::QXcbNativeBackingStore(QWindow *window) : QPlatformBackingStore(window) , m_translucentBackground(false) { if (QXcbWindow *w = static_cast(window->handle())) m_translucentBackground = w->connection()->hasXRender() && QImage::toPixelFormat(w->imageFormat()).alphaSize() > 0; } QXcbNativeBackingStore::~QXcbNativeBackingStore() {} QPaintDevice *QXcbNativeBackingStore::paintDevice() { return &m_pixmap; } void QXcbNativeBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) { if (m_pixmap.isNull()) return; QSize pixmapSize = m_pixmap.size(); QRegion clipped = region; clipped &= QRect(QPoint(), QHighDpi::toNativePixels(window->size(), window)); clipped &= QRect(0, 0, pixmapSize.width(), pixmapSize.height()).translated(-offset); QRect br = clipped.boundingRect(); if (br.isNull()) return; QXcbWindow *platformWindow = static_cast(window->handle()); if (!platformWindow) { qWarning("QXcbBackingStore::flush: QWindow has no platform window (QTBUG-32681)"); return; } Window wid = platformWindow->xcb_window(); Pixmap pid = qt_x11PixmapHandle(m_pixmap); QVector clipRects = qt_region_to_xrectangles(clipped); #if QT_CONFIG(xrender) if (m_translucentBackground) { XWindowAttributes attrib; XGetWindowAttributes(display(), wid, &attrib); XRenderPictFormat *format = XRenderFindVisualFormat(display(), attrib.visual); Picture srcPic = qt_x11PictureHandle(m_pixmap); Picture dstPic = XRenderCreatePicture(display(), wid, format, 0, 0); XRenderSetPictureClipRectangles(display(), dstPic, 0, 0, clipRects.constData(), clipRects.size()); XRenderComposite(display(), PictOpSrc, srcPic, None, dstPic, br.x() + offset.x(), br.y() + offset.y(), 0, 0, br.x(), br.y(), br.width(), br.height()); XRenderFreePicture(display(), dstPic); } else #endif { GC gc = XCreateGC(display(), wid, 0, Q_NULLPTR); if (clipRects.size() != 1) XSetClipRectangles(display(), gc, 0, 0, clipRects.data(), clipRects.size(), YXBanded); XCopyArea(display(), pid, wid, gc, br.x() + offset.x(), br.y() + offset.y(), br.width(), br.height(), br.x(), br.y()); XFreeGC(display(), gc); } if (platformWindow->needsSync()) { platformWindow->updateSyncRequestCounter(); } else { XFlush(display()); } } QImage QXcbNativeBackingStore::toImage() const { return m_pixmap.toImage(); } void QXcbNativeBackingStore::resize(const QSize &size, const QRegion &staticContents) { if (size == m_pixmap.size()) return; QPixmap newPixmap(size); #if QT_CONFIG(xrender) if (m_translucentBackground && newPixmap.depth() != 32) qt_x11Pixmap(newPixmap)->convertToARGB32(); #endif if (!m_pixmap.isNull()) { Pixmap from = qt_x11PixmapHandle(m_pixmap); Pixmap to = qt_x11PixmapHandle(newPixmap); QRect br = staticContents.boundingRect().intersected(QRect(QPoint(0, 0), size)); if (!br.isEmpty()) { GC gc = XCreateGC(display(), to, 0, Q_NULLPTR); XCopyArea(display(), from, to, gc, br.x(), br.y(), br.width(), br.height(), br.x(), br.y()); XFreeGC(display(), gc); } } m_pixmap = newPixmap; } bool QXcbNativeBackingStore::scroll(const QRegion &area, int dx, int dy) { if (m_pixmap.isNull()) return false; QRect rect = area.boundingRect(); Pixmap pix = qt_x11PixmapHandle(m_pixmap); GC gc = XCreateGC(display(), pix, 0, Q_NULLPTR); XCopyArea(display(), pix, pix, gc, rect.x(), rect.y(), rect.width(), rect.height(), rect.x()+dx, rect.y()+dy); XFreeGC(display(), gc); return true; } void QXcbNativeBackingStore::beginPaint(const QRegion ®ion) { #if QT_CONFIG(xrender) if (m_translucentBackground) { const QVector xrects = qt_region_to_xrectangles(region); const XRenderColor color = { 0, 0, 0, 0 }; XRenderFillRectangles(display(), PictOpSrc, qt_x11PictureHandle(m_pixmap), &color, xrects.constData(), xrects.size()); } #else Q_UNUSED(region); #endif } Display *QXcbNativeBackingStore::display() const { return static_cast(static_cast(window()->handle())->connection()->xlib_display()); } QT_END_NAMESPACE