Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qxcbxsettings.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qxcbxsettings.h"
5
6#include <QtCore/QByteArray>
7#include <QtCore/QtEndian>
8
9#include <vector>
10#include <algorithm>
11
13/* Implementation of http://standards.freedesktop.org/xsettings-spec/xsettings-0.5.html */
14
20
26
28{
29public:
33
35 {
36 if (last_change_serial <= this->last_change_serial)
37 return;
38 this->value = value;
39 this->last_change_serial = last_change_serial;
40 for (const auto &callback : callback_links)
41 callback.func(screen, name, value, callback.handle);
42 }
43
45 {
46 QXcbXSettingsCallback callback = { func, handle };
47 callback_links.push_back(callback);
48 }
49
52 std::vector<QXcbXSettingsCallback> callback_links;
53
54};
55
57{
58public:
64
66 {
67 QXcbConnectionGrabber connectionGrabber(screen->connection());
68
69 int offset = 0;
71 xcb_atom_t _xsettings_atom = screen->connection()->atom(QXcbAtom::Atom_XSETTINGS_SETTINGS);
72 while (1) {
73 auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property,
75 false,
77 _xsettings_atom,
78 _xsettings_atom,
79 offset/4,
80 8192);
81 bool more = false;
82 if (!reply)
83 return settings;
84
85 const auto property_value_length = xcb_get_property_value_length(reply.get());
86 settings.append(static_cast<const char *>(xcb_get_property_value(reply.get())), property_value_length);
87 offset += property_value_length;
88 more = reply->bytes_after != 0;
89
90 if (!more)
91 break;
92 }
93
94 return settings;
95 }
96
98 {
99 int remainder = value % 4;
100 if (!remainder)
101 return value;
102 return value + 4 - remainder;
103 }
104
105 void populateSettings(const QByteArray &xSettings)
106 {
107 if (xSettings.size() < 12)
108 return;
109 char byteOrder = xSettings.at(0);
110 if (byteOrder != XCB_IMAGE_ORDER_LSB_FIRST && byteOrder != XCB_IMAGE_ORDER_MSB_FIRST) {
111 qWarning("ByteOrder byte %d not 0 or 1", byteOrder);
112 return;
113 }
114
115#define ADJUST_BO(b, t, x) \
116 ((b == XCB_IMAGE_ORDER_LSB_FIRST) ? \
117 qFromLittleEndian<t>(x) : \
118 qFromBigEndian<t>(x))
119#define VALIDATE_LENGTH(x) \
120 if ((size_t)xSettings.length() < (offset + local_offset + 12 + x)) { \
121 qWarning("Length %d runs past end of data", x); \
122 return; \
123 }
124
125 uint number_of_settings = ADJUST_BO(byteOrder, quint32, xSettings.mid(8,4).constData());
126 const char *data = xSettings.constData() + 12;
127 size_t offset = 0;
128 for (uint i = 0; i < number_of_settings; i++) {
129 int local_offset = 0;
131 XSettingsType type = static_cast<XSettingsType>(*reinterpret_cast<const quint8 *>(data + offset));
132 local_offset += 2;
133
135 quint16 name_len = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
136 local_offset += 2;
137
138 VALIDATE_LENGTH(name_len);
139 QByteArray name(data + offset + local_offset, name_len);
140 local_offset += round_to_nearest_multiple_of_4(name_len);
141
143 int last_change_serial = ADJUST_BO(byteOrder, qint32, data + offset + local_offset);
144 Q_UNUSED(last_change_serial);
145 local_offset += 4;
146
148 if (type == XSettingsTypeString) {
150 int value_length = ADJUST_BO(byteOrder, qint32, data + offset + local_offset);
151 local_offset+=4;
152 VALIDATE_LENGTH(value_length);
153 QByteArray value_string(data + offset + local_offset, value_length);
154 value.setValue(value_string);
155 local_offset += round_to_nearest_multiple_of_4(value_length);
156 } else if (type == XSettingsTypeInteger) {
158 int value_length = ADJUST_BO(byteOrder, qint32, data + offset + local_offset);
159 local_offset += 4;
160 value.setValue(value_length);
161 } else if (type == XSettingsTypeColor) {
162 VALIDATE_LENGTH(2*4);
163 quint16 red = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
164 local_offset += 2;
165 quint16 green = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
166 local_offset += 2;
167 quint16 blue = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
168 local_offset += 2;
169 quint16 alpha= ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
170 local_offset += 2;
171 QColor color_value(red,green,blue,alpha);
172 value.setValue(color_value);
173 }
174 offset += local_offset;
175 settings[name].updateValue(screen,name,value,last_change_serial);
176 }
177
178 }
179
181 xcb_window_t x_settings_window;
182 QMap<QByteArray, QXcbXSettingsPropertyValue> settings;
184};
185
186
188 : d_ptr(new QXcbXSettingsPrivate(screen))
189{
190 QByteArray settings_atom_for_screen("_XSETTINGS_S");
191 settings_atom_for_screen.append(QByteArray::number(screen->number()));
192 auto atom_reply = Q_XCB_REPLY(xcb_intern_atom,
193 screen->xcb_connection(),
194 true,
195 settings_atom_for_screen.size(),
196 settings_atom_for_screen.constData());
197 if (!atom_reply)
198 return;
199
200 xcb_atom_t selection_owner_atom = atom_reply->atom;
201
202 xcb_window_t owner = screen->connection()->selectionOwner(selection_owner_atom);
203 if (owner == XCB_NONE)
204 return;
205
206 d_ptr->x_settings_window = owner;
207 if (!d_ptr->x_settings_window)
208 return;
209
210 screen->connection()->addWindowEventListener(d_ptr->x_settings_window, this);
211 const uint32_t event = XCB_CW_EVENT_MASK;
212 const uint32_t event_mask[] = { XCB_EVENT_MASK_STRUCTURE_NOTIFY|XCB_EVENT_MASK_PROPERTY_CHANGE };
213 xcb_change_window_attributes(screen->xcb_connection(),d_ptr->x_settings_window,event,event_mask);
214
215 d_ptr->populateSettings(d_ptr->getSettings());
216 d_ptr->initialized = true;
217}
218
220{
221 delete d_ptr;
222 d_ptr = nullptr;
223}
224
226{
227 Q_D(const QXcbXSettings);
228 return d->initialized;
229}
230
231void QXcbXSettings::handlePropertyNotifyEvent(const xcb_property_notify_event_t *event)
232{
233 Q_D(QXcbXSettings);
234 if (event->window != d->x_settings_window)
235 return;
236
237 d->populateSettings(d->getSettings());
238}
239
245
247{
248 Q_D(QXcbXSettings);
249 auto &callbacks = d->settings[property].callback_links;
250
251 auto isCallbackForHandle = [handle](const QXcbXSettingsCallback &cb) { return cb.handle == handle; };
252
253 callbacks.erase(std::remove_if(callbacks.begin(), callbacks.end(),
254 isCallbackForHandle),
255 callbacks.end());
256}
257
266
268{
269 Q_D(const QXcbXSettings);
270 return d->settings.value(property).value;
271}
272
\inmodule QtCore
Definition qbytearray.h:57
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:494
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
char at(qsizetype i) const
Returns the byte at index position i in the byte array.
Definition qbytearray.h:600
static QByteArray number(int, int base=10)
Returns a byte-array representing the whole number n as text.
QByteArray mid(qsizetype index, qsizetype len=-1) const &
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
QSize size
the pixel resolution of the screen
Definition qscreen.h:41
QPlatformScreen * handle() const
Get the platform screen handle.
Definition qscreen.cpp:83
const_iterator cend() const noexcept
Definition qset.h:142
const_iterator cbegin() const noexcept
Definition qset.h:138
\inmodule QtCore
Definition qvariant.h:65
@ Atom_XSETTINGS_SETTINGS
Definition qxcbatom.h:197
xcb_atom_t atom(QXcbAtom::Atom qatom) const
QXcbConnection * connection() const
Definition qxcbobject.h:17
xcb_connection_t * xcb_connection() const
Definition qxcbobject.h:20
QMap< QByteArray, QXcbXSettingsPropertyValue > settings
void populateSettings(const QByteArray &xSettings)
QXcbVirtualDesktop * screen
QXcbXSettingsPrivate(QXcbVirtualDesktop *screen)
xcb_window_t x_settings_window
static int round_to_nearest_multiple_of_4(int value)
std::vector< QXcbXSettingsCallback > callback_links
void updateValue(QXcbVirtualDesktop *screen, const QByteArray &name, const QVariant &value, int last_change_serial)
void addCallback(QXcbXSettings::PropertyChangeFunc func, void *handle)
QXcbXSettings(QXcbVirtualDesktop *screen)
void removeCallbackForHandle(const QByteArray &property, void *handle)
void registerCallbackForProperty(const QByteArray &property, PropertyChangeFunc func, void *handle)
QVariant setting(const QByteArray &property) const
bool initialized() const
void(* PropertyChangeFunc)(QXcbVirtualDesktop *screen, const QByteArray &name, const QVariant &property, void *handle)
void handlePropertyNotifyEvent(const xcb_property_notify_event_t *event) override
QSet< QString >::iterator it
Combined button and popup list for selecting options.
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qWarning
Definition qlogging.h:166
GLuint64 GLenum void * handle
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum type
GLenum GLuint GLintptr offset
GLuint name
struct _cl_event * event
GLbyte GLbyte blue
Definition qopenglext.h:385
GLenum func
Definition qopenglext.h:663
GLfloat GLfloat GLfloat alpha
Definition qopenglext.h:418
GLbyte green
Definition qopenglext.h:385
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
PromiseCallbacks callbacks
Definition qstdweb.cpp:275
QScreen * screen
[1]
Definition main.cpp:29
#define Q_UNUSED(x)
unsigned int quint32
Definition qtypes.h:50
unsigned short quint16
Definition qtypes.h:48
int qint32
Definition qtypes.h:49
unsigned int uint
Definition qtypes.h:34
unsigned char quint8
Definition qtypes.h:46
const char property[13]
Definition qwizard.cpp:101
#define Q_XCB_REPLY(call,...)
#define Q_XCB_REPLY_UNCHECKED(call,...)
#define VALIDATE_LENGTH(x)
#define ADJUST_BO(b, t, x)
XSettingsType
@ XSettingsTypeColor
@ XSettingsTypeInteger
@ XSettingsTypeString
QNetworkReply * reply
QGraphicsSvgItem * red
QXcbXSettings::PropertyChangeFunc func