KWindowSystem

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

KDE's Doxygen guidelines are available online.