diff options
Diffstat (limited to 'src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp b/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp new file mode 100644 index 0000000000..23500eb4ab --- /dev/null +++ b/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp @@ -0,0 +1,315 @@ +/**************************************************************************** +** +** 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 "qxcbconnection.h" +#include "qcolormap_x11_p.h" +#include "qxcbnativepainting.h" +#include "qt_x11_p.h" + +QT_BEGIN_NAMESPACE + +QXcbX11Data *qt_x11Data = Q_NULLPTR; + +void qt_xcb_native_x11_info_init(QXcbConnection *conn) +{ + qt_x11Data = new QXcbX11Data; + X11->display = (Display *) conn->xlib_display(); + X11->defaultScreen = DefaultScreen(X11->display); + X11->screenCount = ScreenCount(X11->display); + + X11->screens = new QX11InfoData[X11->screenCount]; + X11->argbVisuals = new Visual *[X11->screenCount]; + X11->argbColormaps = new Colormap[X11->screenCount]; + + for (int s = 0; s < X11->screenCount; s++) { + QX11InfoData *screen = X11->screens + s; + //screen->ref = 1; // ensures it doesn't get deleted + screen->screen = s; + + int widthMM = DisplayWidthMM(X11->display, s); + if (widthMM != 0) { + screen->dpiX = (DisplayWidth(X11->display, s) * 254 + widthMM * 5) / (widthMM * 10); + } else { + screen->dpiX = 72; + } + + int heightMM = DisplayHeightMM(X11->display, s); + if (heightMM != 0) { + screen->dpiY = (DisplayHeight(X11->display, s) * 254 + heightMM * 5) / (heightMM * 10); + } else { + screen->dpiY = 72; + } + + X11->argbVisuals[s] = 0; + X11->argbColormaps[s] = 0; + } + + X11->use_xrender = conn->hasXRender() && !qEnvironmentVariableIsSet("QT_XCB_NATIVE_PAINTING_NO_XRENDER"); + +#if QT_CONFIG(xrender) + memset(X11->solid_fills, 0, sizeof(X11->solid_fills)); + for (int i = 0; i < X11->solid_fill_count; ++i) + X11->solid_fills[i].screen = -1; + memset(X11->pattern_fills, 0, sizeof(X11->pattern_fills)); + for (int i = 0; i < X11->pattern_fill_count; ++i) + X11->pattern_fills[i].screen = -1; +#endif + + QXcbColormap::initialize(); + +#if QT_CONFIG(xrender) + if (X11->use_xrender) { + // XRender is supported, let's see if we have a PictFormat for the + // default visual + XRenderPictFormat *format = + XRenderFindVisualFormat(X11->display, + (Visual *) QXcbX11Info::appVisual(X11->defaultScreen)); + + if (!format) { + X11->use_xrender = false; + } + } +#endif // QT_CONFIG(xrender) +} + +QVector<XRectangle> qt_region_to_xrectangles(const QRegion &r) +{ + const int numRects = r.rectCount(); + const QVector<QRect> input = r.rects(); + QVector<XRectangle> output(numRects); + for (int i = 0; i < numRects; ++i) { + const QRect &in = input[i]; + XRectangle &out = output[i]; + out.x = qMax(SHRT_MIN, in.x()); + out.y = qMax(SHRT_MIN, in.y()); + out.width = qMin((int)USHRT_MAX, in.width()); + out.height = qMin((int)USHRT_MAX, in.height()); + } + return output; +} + +class QXcbX11InfoData : public QSharedData, public QX11InfoData +{}; + +QXcbX11Info::QXcbX11Info() + : d(Q_NULLPTR) +{} + +QXcbX11Info::~QXcbX11Info() +{} + +QXcbX11Info::QXcbX11Info(const QXcbX11Info &other) + : d(other.d) +{} + +QXcbX11Info &QXcbX11Info::operator=(const QXcbX11Info &other) +{ + d = other.d; + return *this; +} + +QXcbX11Info QXcbX11Info::fromScreen(int screen) +{ + QXcbX11InfoData *xd = new QXcbX11InfoData; + xd->screen = screen; + xd->depth = QXcbX11Info::appDepth(screen); + xd->cells = QXcbX11Info::appCells(screen); + xd->colormap = QXcbX11Info::appColormap(screen); + xd->defaultColormap = QXcbX11Info::appDefaultColormap(screen); + xd->visual = (Visual *)QXcbX11Info::appVisual(screen); + xd->defaultVisual = QXcbX11Info::appDefaultVisual(screen); + + QXcbX11Info info; + info.d = xd; + return info; +} + +void QXcbX11Info::setDepth(int depth) +{ + if (!d) + *this = fromScreen(appScreen()); + + d->depth = depth; +} + +Display *QXcbX11Info::display() +{ + return X11 ? X11->display : 0; +} + +int QXcbX11Info::screen() const +{ + return d ? d->screen : QXcbX11Info::appScreen(); +} + +int QXcbX11Info::depth() const +{ + return d ? d->depth : QXcbX11Info::appDepth(); +} + +Colormap QXcbX11Info::colormap() const +{ + return d ? d->colormap : QXcbX11Info::appColormap(); +} + +void *QXcbX11Info::visual() const +{ + return d ? d->visual : QXcbX11Info::appVisual(); +} + +void QXcbX11Info::setVisual(void *visual) +{ + if (!d) + *this = fromScreen(appScreen()); + + d->visual = (Visual *) visual; +} + +int QXcbX11Info::appScreen() +{ + return X11 ? X11->defaultScreen : 0; +} + +int QXcbX11Info::appDepth(int screen) +{ + return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].depth : 32; +} + +int QXcbX11Info::appCells(int screen) +{ + return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].cells : 0; +} + +Colormap QXcbX11Info::appColormap(int screen) +{ + return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].colormap : 0; +} + +void *QXcbX11Info::appVisual(int screen) +{ + return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].visual : 0; +} + +Window QXcbX11Info::appRootWindow(int screen) +{ + return X11 ? RootWindow(X11->display, screen == -1 ? X11->defaultScreen : screen) : 0; +} + +bool QXcbX11Info::appDefaultColormap(int screen) +{ + return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].defaultColormap : true; +} + +bool QXcbX11Info::appDefaultVisual(int screen) +{ + return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].defaultVisual : true; +} + +int QXcbX11Info::appDpiX(int screen) +{ + if (!X11) + return 75; + if (screen < 0) + screen = X11->defaultScreen; + if (screen > X11->screenCount) + return 0; + return X11->screens[screen].dpiX; +} + +int QXcbX11Info::appDpiY(int screen) +{ + if (!X11) + return 75; + if (screen < 0) + screen = X11->defaultScreen; + if (screen > X11->screenCount) + return 0; + return X11->screens[screen].dpiY; +} + +#if QT_CONFIG(xrender) +Picture QXcbX11Data::getSolidFill(int screen, const QColor &c) +{ + if (!X11->use_xrender) + return XNone; + + XRenderColor color = preMultiply(c); + for (int i = 0; i < X11->solid_fill_count; ++i) { + if (X11->solid_fills[i].screen == screen + && X11->solid_fills[i].color.alpha == color.alpha + && X11->solid_fills[i].color.red == color.red + && X11->solid_fills[i].color.green == color.green + && X11->solid_fills[i].color.blue == color.blue) + return X11->solid_fills[i].picture; + } + // none found, replace one + int i = qrand() % 16; + + if (X11->solid_fills[i].screen != screen && X11->solid_fills[i].picture) { + XRenderFreePicture (X11->display, X11->solid_fills[i].picture); + X11->solid_fills[i].picture = 0; + } + + if (!X11->solid_fills[i].picture) { + Pixmap pixmap = XCreatePixmap (X11->display, RootWindow (X11->display, screen), 1, 1, 32); + XRenderPictureAttributes attrs; + attrs.repeat = True; + X11->solid_fills[i].picture = XRenderCreatePicture (X11->display, pixmap, + XRenderFindStandardFormat(X11->display, PictStandardARGB32), + CPRepeat, &attrs); + XFreePixmap (X11->display, pixmap); + } + + X11->solid_fills[i].color = color; + X11->solid_fills[i].screen = screen; + XRenderFillRectangle (X11->display, PictOpSrc, X11->solid_fills[i].picture, &color, 0, 0, 1, 1); + return X11->solid_fills[i].picture; +} + +XRenderColor QXcbX11Data::preMultiply(const QColor &c) +{ + XRenderColor color; + const uint A = c.alpha(), + R = c.red(), + G = c.green(), + B = c.blue(); + color.alpha = (A | A << 8); + color.red = (R | R << 8) * color.alpha / 0x10000; + color.green = (G | G << 8) * color.alpha / 0x10000; + color.blue = (B | B << 8) * color.alpha / 0x10000; + return color; +} +#endif // QT_CONFIG(xrender) + + +QT_END_NAMESPACE |