KWindowSystem

kxutils.cpp
1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2008 Lubos Lunak <l.lunak@kde.org>
4 SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.1-or-later
7*/
8
9#include "cptr_p.h"
10#include "kxutils_p.h"
11#include <QBitmap>
12#include <QDebug>
13
14#include <private/qtx11extras_p.h>
15
16#include <xcb/xcb.h>
17
18namespace KXUtils
19{
20template<typename T>
21T fromNative(xcb_pixmap_t pixmap, xcb_connection_t *c)
22{
23 const xcb_get_geometry_cookie_t geoCookie = xcb_get_geometry_unchecked(c, pixmap);
24 UniqueCPointer<xcb_get_geometry_reply_t> geo(xcb_get_geometry_reply(c, geoCookie, nullptr));
25 if (!geo) {
26 // getting geometry for the pixmap failed
27 return T();
28 }
29
30 const xcb_get_image_cookie_t imageCookie = xcb_get_image_unchecked(c, XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, 0, 0, geo->width, geo->height, ~0);
31 UniqueCPointer<xcb_get_image_reply_t> xImage(xcb_get_image_reply(c, imageCookie, nullptr));
32 if (!xImage) {
33 // request for image data failed
34 return T();
35 }
37 switch (xImage->depth) {
38 case 1:
40 break;
41 case 16:
42 format = QImage::Format_RGB16;
43 break;
44 case 24:
45 format = QImage::Format_RGB32;
46 break;
47 case 30: {
48 // Qt doesn't have a matching image format. We need to convert manually
49 uint32_t *pixels = reinterpret_cast<uint32_t *>(xcb_get_image_data(xImage.get()));
50 for (uint i = 0; i < xImage.get()->length; ++i) {
51 int r = (pixels[i] >> 22) & 0xff;
52 int g = (pixels[i] >> 12) & 0xff;
53 int b = (pixels[i] >> 2) & 0xff;
54
55 pixels[i] = qRgba(r, g, b, 0xff);
56 }
57 // fall through, Qt format is still Format_ARGB32_Premultiplied
58 Q_FALLTHROUGH();
59 }
60 case 32:
62 break;
63 default:
64 return T(); // we don't know
65 }
66 QImage image(xcb_get_image_data(xImage.get()), geo->width, geo->height, xcb_get_image_data_length(xImage.get()) / geo->height, format, free, xImage.get());
67 xImage.release();
68 if (image.isNull()) {
69 return T();
70 }
71 if (image.format() == QImage::Format_MonoLSB) {
72 // work around an abort in QImage::color
73 image.setColorCount(2);
74 image.setColor(0, QColor(Qt::white).rgb());
75 image.setColor(1, QColor(Qt::black).rgb());
76 }
77 return T::fromImage(image);
78}
79
80// Create QPixmap from X pixmap. Take care of different depths if needed.
81QPixmap createPixmapFromHandle(WId pixmap, WId pixmap_mask)
82{
83 return createPixmapFromHandle(QX11Info::connection(), pixmap, pixmap_mask);
84}
85
86QPixmap createPixmapFromHandle(xcb_connection_t *c, WId pixmap, WId pixmap_mask)
87{
88#if Q_BYTE_ORDER == Q_BIG_ENDIAN
89 qDebug() << "Byte order not supported";
90 return QPixmap();
91#endif
92 const xcb_setup_t *setup = xcb_get_setup(c);
93 if (setup->image_byte_order != XCB_IMAGE_ORDER_LSB_FIRST) {
94 qDebug() << "Byte order not supported";
95 return QPixmap();
96 }
97
98 QPixmap pix = fromNative<QPixmap>(pixmap, c);
99 if (pixmap_mask != XCB_PIXMAP_NONE) {
100 QBitmap mask = fromNative<QBitmap>(pixmap_mask, c);
101 if (mask.size() != pix.size()) {
102 return QPixmap();
103 }
104 pix.setMask(mask);
105 }
106 return pix;
107}
108
109// Functions for X timestamp comparing. For Time being 32bit they're fairly simple
110// (the #if 0 part), but on 64bit architectures Time is 64bit unsigned long,
111// so there special care needs to be taken to always use only the lower 32bits.
112#if 0
113int timestampCompare(Time time1, Time time2) // like strcmp()
114{
115 if (time1 == time2) {
116 return 0;
117 }
118 return (time1 - time2) < 0x7fffffffU ? 1 : -1; // time1 > time2 -> 1, handle wrapping
119}
120
121Time timestampDiff(Time time1, Time time2) // returns time2 - time1
122{
123 // no need to handle wrapping?
124 return time2 - time1;
125}
126#else
127int timestampCompare(unsigned long time1_, unsigned long time2_) // like strcmp()
128{
129 quint32 time1 = time1_;
130 quint32 time2 = time2_;
131 if (time1 == time2) {
132 return 0;
133 }
134 return quint32(time1 - time2) < 0x7fffffffU ? 1 : -1; // time1 > time2 -> 1, handle wrapping
135}
136
137int timestampDiff(unsigned long time1_, unsigned long time2_) // returns time2 - time1
138{
139 // no need to handle wrapping?
140 quint32 time1 = time1_;
141 quint32 time2 = time2_;
142 return quint32(time2 - time1);
143}
144#endif
145
146} // namespace
GeoCoordinates geo(const QVariant &location)
void setMask(const QBitmap &mask)
QSize size() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:15:04 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.