33 #include <QAbstractButton>
48 #include <QApplication>
56 static QString _window_manager;
57 static QHash<QString, xcb_atom_t> _xcb_atom_cache;
61 xcb_atom_t xcb_get_atom(
const char *name)
63 if (!QX11Info::isPlatformX11())
67 auto key = QString(name);
68 if(_xcb_atom_cache.contains(key))
70 return _xcb_atom_cache[
key];
72 xcb_connection_t *connection = QX11Info::connection();
73 xcb_intern_atom_cookie_t request = xcb_intern_atom(connection, 1, strlen(name), name);
74 xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection, request, NULL);
79 xcb_atom_t atom = reply->atom;
80 if(atom == XCB_ATOM_NONE)
82 ADS_PRINT(
"Unknown Atom response from XServer: " << name);
86 _xcb_atom_cache.insert(key, atom);
94 void xcb_update_prop(
bool set, WId window,
const char *type,
const char *prop,
const char *prop2)
96 auto connection = QX11Info::connection();
97 xcb_atom_t type_atom = xcb_get_atom(type);
98 xcb_atom_t prop_atom = xcb_get_atom(prop);
99 xcb_client_message_event_t event;
100 event.response_type = XCB_CLIENT_MESSAGE;
103 event.window = window;
104 event.type = type_atom;
105 event.data.data32[0] =
set ? 1 : 0;
106 event.data.data32[1] = prop_atom;
107 event.data.data32[2] = prop2 ? xcb_get_atom(prop2) : 0;
108 event.data.data32[3] = 0;
109 event.data.data32[4] = 0;
111 xcb_send_event(connection, 0, window,
112 XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_PROPERTY_CHANGE,
113 (
const char *)&event);
114 xcb_flush(connection);
119 xcb_get_property_reply_t* _xcb_get_props(WId window,
const char *type,
unsigned int atom_type)
121 if (!QX11Info::isPlatformX11())
125 xcb_connection_t *connection = QX11Info::connection();
126 xcb_atom_t type_atom = xcb_get_atom(type);
127 if (type_atom == XCB_ATOM_NONE)
131 xcb_get_property_cookie_t request = xcb_get_property_unchecked(connection, 0, window, type_atom, atom_type, 0, 1024);
132 xcb_get_property_reply_t *reply = xcb_get_property_reply(connection, request,
nullptr);
133 if(reply && reply->type != atom_type)
135 ADS_PRINT(
"ATOM TYPE MISMATCH (" << type <<
"). Expected: " << atom_type <<
" but got " << reply->type);
144 template <
typename T>
145 void xcb_get_prop_list(WId window,
const char *type,
QVector<T> &
ret,
unsigned int atom_type)
147 xcb_get_property_reply_t *reply = _xcb_get_props(window, type, atom_type);
148 if (reply && reply->format == 32 && reply->type == atom_type && reply->value_len > 0)
150 const xcb_atom_t *
data =
static_cast<const T *
>(xcb_get_property_value(reply));
151 ret.resize(reply->value_len);
152 memcpy((
void *)&
ret.first(), (
void *)
data, reply->value_len *
sizeof(T));
159 QString xcb_get_prop_string(WId window,
const char *type)
163 xcb_atom_t utf_atom = xcb_get_atom(
"UTF8_STRING");
164 if(utf_atom != XCB_ATOM_NONE)
166 xcb_get_property_reply_t *reply = _xcb_get_props(window, type, utf_atom);
167 if (reply && reply->format == 8 && reply->type == utf_atom)
169 const char *
value =
reinterpret_cast<const char *
>(xcb_get_property_value(reply));
170 ret = QString::fromUtf8(value, xcb_get_property_value_length(reply));
177 xcb_get_property_reply_t *reply = _xcb_get_props(window, type, XCB_ATOM_STRING);
178 if (reply && reply->format == 8 && reply->type == XCB_ATOM_STRING)
180 const char *
value =
reinterpret_cast<const char *
>(xcb_get_property_value(reply));
181 ret = QString::fromLatin1(value, xcb_get_property_value_length(reply));
189 bool xcb_dump_props(WId window,
const char *type)
192 xcb_get_prop_list(window, type, atoms, XCB_ATOM_ATOM);
193 qDebug() <<
"\n\n!!!" <<
type <<
" - " << atoms.length();
194 xcb_connection_t *connection = QX11Info::connection();
195 for (
auto atom : atoms)
197 auto foo = xcb_get_atom_name(connection, atom);
198 auto bar = xcb_get_atom_name_reply(connection, foo,
nullptr);
199 qDebug() <<
"\t" << xcb_get_atom_name_name(bar);
207 void xcb_add_prop(
bool state, WId window,
const char *type,
const char *prop)
209 if (!QX11Info::isPlatformX11())
213 xcb_atom_t prop_atom = xcb_get_atom(prop);
214 xcb_atom_t type_atom = xcb_get_atom(type);
215 if (prop_atom == XCB_ATOM_NONE || type_atom == XCB_ATOM_NONE)
220 xcb_get_prop_list(window, type, atoms, XCB_ATOM_ATOM);
221 int index = atoms.indexOf(prop_atom);
222 if (
state && index == -1)
224 atoms.push_back(prop_atom);
226 else if (!
state && index >= 0)
230 xcb_connection_t *connection = QX11Info::connection();
231 xcb_change_property(connection, XCB_PROP_MODE_REPLACE, window, type_atom, XCB_ATOM_ATOM, 32, atoms.count(), atoms.constData());
232 xcb_flush(connection);
237 QString detectWindowManagerX11()
241 if (!QX11Info::isPlatformX11())
245 xcb_connection_t *connection = QX11Info::connection();
246 xcb_screen_t *first_screen = xcb_setup_roots_iterator (xcb_get_setup (connection)).data;
253 xcb_window_t root = first_screen->root;
254 xcb_window_t support_win = 0;
256 xcb_get_prop_list(root,
"_NET_SUPPORTING_WM_CHECK", sup_windows, XCB_ATOM_WINDOW);
257 if(sup_windows.length() == 0)
261 xcb_get_prop_list(root,
"_WIN_SUPPORTING_WM_CHECK", sup_windows, XCB_ATOM_CARDINAL);
263 if(sup_windows.length() == 0)
265 ADS_PRINT(
"Failed to get the supporting window on non EWMH comform WM.");
268 support_win = sup_windows[0];
269 QString
ret = xcb_get_prop_string(support_win,
"_NET_WM_NAME");
270 if(
ret.length() == 0)
279 QString windowManager()
281 if(_window_manager.length() == 0)
283 _window_manager = detectWindowManagerX11();
285 return _window_manager;
293 int index = Splitter->indexOf(From);
294 From->setParent(
nullptr);
295 Splitter->insertWidget(index, To);
318 QPixmap TransparentPixmap(Source.size());
319 TransparentPixmap.fill(Qt::transparent);
320 QPainter p(&TransparentPixmap);
321 p.setOpacity(Opacity);
322 p.drawPixmap(0, 0, Source);
323 return TransparentPixmap;
330 while (Splitter && Splitter->isVisible())
336 Splitter = internal::findParent<CDockSplitter*>(Splitter);
342 void setButtonIcon(QAbstractButton* Button, QStyle::StandardPixmap StandarPixmap,
349 Button->setIcon(Icon);
354 Button->setIcon(Button->style()->standardIcon(StandarPixmap));
358 QPixmap normalPixmap = Button->style()->standardPixmap(StandarPixmap, 0, Button);
360 Icon.addPixmap(normalPixmap, QIcon::Normal);
361 Button->setIcon(Icon);
373 w->style()->unpolish(w);
374 w->style()->polish(w);
383 for (
auto Widget : Children)
385 Widget->style()->unpolish(Widget);
386 Widget->style()->polish(Widget);