File indexing completed on 2024-05-05 08:01:48
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2008 Lubos Lunak <l.lunak@kde.org> 0004 SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.1-or-later 0007 */ 0008 0009 #include "cptr_p.h" 0010 #include "kxutils_p.h" 0011 #include <QBitmap> 0012 #include <QDebug> 0013 0014 #include <private/qtx11extras_p.h> 0015 0016 #include <xcb/xcb.h> 0017 0018 namespace KXUtils 0019 { 0020 template<typename T> 0021 T fromNative(xcb_pixmap_t pixmap, xcb_connection_t *c) 0022 { 0023 const xcb_get_geometry_cookie_t geoCookie = xcb_get_geometry_unchecked(c, pixmap); 0024 UniqueCPointer<xcb_get_geometry_reply_t> geo(xcb_get_geometry_reply(c, geoCookie, nullptr)); 0025 if (!geo) { 0026 // getting geometry for the pixmap failed 0027 return T(); 0028 } 0029 0030 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); 0031 UniqueCPointer<xcb_get_image_reply_t> xImage(xcb_get_image_reply(c, imageCookie, nullptr)); 0032 if (!xImage) { 0033 // request for image data failed 0034 return T(); 0035 } 0036 QImage::Format format = QImage::Format_Invalid; 0037 switch (xImage->depth) { 0038 case 1: 0039 format = QImage::Format_MonoLSB; 0040 break; 0041 case 16: 0042 format = QImage::Format_RGB16; 0043 break; 0044 case 24: 0045 format = QImage::Format_RGB32; 0046 break; 0047 case 30: { 0048 // Qt doesn't have a matching image format. We need to convert manually 0049 uint32_t *pixels = reinterpret_cast<uint32_t *>(xcb_get_image_data(xImage.get())); 0050 for (uint i = 0; i < xImage.get()->length; ++i) { 0051 int r = (pixels[i] >> 22) & 0xff; 0052 int g = (pixels[i] >> 12) & 0xff; 0053 int b = (pixels[i] >> 2) & 0xff; 0054 0055 pixels[i] = qRgba(r, g, b, 0xff); 0056 } 0057 // fall through, Qt format is still Format_ARGB32_Premultiplied 0058 Q_FALLTHROUGH(); 0059 } 0060 case 32: 0061 format = QImage::Format_ARGB32_Premultiplied; 0062 break; 0063 default: 0064 return T(); // we don't know 0065 } 0066 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()); 0067 xImage.release(); 0068 if (image.isNull()) { 0069 return T(); 0070 } 0071 if (image.format() == QImage::Format_MonoLSB) { 0072 // work around an abort in QImage::color 0073 image.setColorCount(2); 0074 image.setColor(0, QColor(Qt::white).rgb()); 0075 image.setColor(1, QColor(Qt::black).rgb()); 0076 } 0077 return T::fromImage(image); 0078 } 0079 0080 // Create QPixmap from X pixmap. Take care of different depths if needed. 0081 QPixmap createPixmapFromHandle(WId pixmap, WId pixmap_mask) 0082 { 0083 return createPixmapFromHandle(QX11Info::connection(), pixmap, pixmap_mask); 0084 } 0085 0086 QPixmap createPixmapFromHandle(xcb_connection_t *c, WId pixmap, WId pixmap_mask) 0087 { 0088 #if Q_BYTE_ORDER == Q_BIG_ENDIAN 0089 qDebug() << "Byte order not supported"; 0090 return QPixmap(); 0091 #endif 0092 const xcb_setup_t *setup = xcb_get_setup(c); 0093 if (setup->image_byte_order != XCB_IMAGE_ORDER_LSB_FIRST) { 0094 qDebug() << "Byte order not supported"; 0095 return QPixmap(); 0096 } 0097 0098 QPixmap pix = fromNative<QPixmap>(pixmap, c); 0099 if (pixmap_mask != XCB_PIXMAP_NONE) { 0100 QBitmap mask = fromNative<QBitmap>(pixmap_mask, c); 0101 if (mask.size() != pix.size()) { 0102 return QPixmap(); 0103 } 0104 pix.setMask(mask); 0105 } 0106 return pix; 0107 } 0108 0109 // Functions for X timestamp comparing. For Time being 32bit they're fairly simple 0110 // (the #if 0 part), but on 64bit architectures Time is 64bit unsigned long, 0111 // so there special care needs to be taken to always use only the lower 32bits. 0112 #if 0 0113 int timestampCompare(Time time1, Time time2) // like strcmp() 0114 { 0115 if (time1 == time2) { 0116 return 0; 0117 } 0118 return (time1 - time2) < 0x7fffffffU ? 1 : -1; // time1 > time2 -> 1, handle wrapping 0119 } 0120 0121 Time timestampDiff(Time time1, Time time2) // returns time2 - time1 0122 { 0123 // no need to handle wrapping? 0124 return time2 - time1; 0125 } 0126 #else 0127 int timestampCompare(unsigned long time1_, unsigned long time2_) // like strcmp() 0128 { 0129 quint32 time1 = time1_; 0130 quint32 time2 = time2_; 0131 if (time1 == time2) { 0132 return 0; 0133 } 0134 return quint32(time1 - time2) < 0x7fffffffU ? 1 : -1; // time1 > time2 -> 1, handle wrapping 0135 } 0136 0137 int timestampDiff(unsigned long time1_, unsigned long time2_) // returns time2 - time1 0138 { 0139 // no need to handle wrapping? 0140 quint32 time1 = time1_; 0141 quint32 time2 = time2_; 0142 return quint32(time2 - time1); 0143 } 0144 #endif 0145 0146 } // namespace