13#include <QApplication>
16#include <private/qtx11extras_p.h>
32 void copyCtorBeforeRetrieve();
33 void copyCtorAfterRetrieve();
34 void assignementEmpty();
35 void assignmentBeforeRetrieve();
36 void assignmentAfterRetrieve();
39 void testCurrentInput();
40 void testTransientFor();
41 void testPropertyByteArray();
42 void testPropertyBool();
44 void testMotifEmpty();
45 void testMotif_data();
54void TestXcbWrapper::initTestCase()
56 qApp->setProperty(
"x11RootWindow", QVariant::fromValue<quint32>(QX11Info::appRootWindow()));
57 qApp->setProperty(
"x11Connection", QVariant::fromValue<void *>(QX11Info::connection()));
60void TestXcbWrapper::init()
62 const uint32_t values[] = {
true};
63 m_testWindow.
create(QRect(0, 0, 10, 10), XCB_WINDOW_CLASS_INPUT_ONLY, XCB_CW_OVERRIDE_REDIRECT, values);
64 QVERIFY(m_testWindow.
isValid());
67void TestXcbWrapper::cleanup()
74 QCOMPARE(geometry.
window(), KWin::noneWindow());
75 QVERIFY(!geometry.
data());
76 QCOMPARE(geometry.
isNull(),
true);
77 QCOMPARE(geometry.
rect(), QRect());
83 QCOMPARE(geometry.
window(), (xcb_window_t)m_testWindow);
85 QCOMPARE(geometry.
rect(), rect);
87 QCOMPARE(geometry.
isNull(),
false);
89 QVERIFY(geometry.
data());
90 QCOMPARE(geometry.
data()->x, int16_t(rect.x()));
91 QCOMPARE(geometry.
data()->y, int16_t(rect.y()));
92 QCOMPARE(geometry.
data()->width, uint16_t(rect.width()));
93 QCOMPARE(geometry.
data()->height, uint16_t(rect.height()));
96void TestXcbWrapper::defaultCtor()
103void TestXcbWrapper::normalCtor()
107 testGeometry(geometry, QRect(0, 0, 10, 10));
110void TestXcbWrapper::copyCtorEmpty()
117 QVERIFY(!other.isRetrieved());
120void TestXcbWrapper::copyCtorBeforeRetrieve()
128 QVERIFY(!other.isRetrieved());
129 testGeometry(other, QRect(0, 0, 10, 10));
132void TestXcbWrapper::copyCtorAfterRetrieve()
137 QCOMPARE(geometry.
rect(), QRect(0, 0, 10, 10));
142 QVERIFY(other.isRetrieved());
143 testGeometry(other, QRect(0, 0, 10, 10));
146void TestXcbWrapper::assignementEmpty()
160 QT_WARNING_DISABLE_CLANG(
"-Wself-assign-overloaded")
173 QVERIFY(geometry.isRetrieved());
176 QVERIFY(!other.isRetrieved());
177 testGeometry(other, QRect(0, 0, 10, 10));
180 QVERIFY(!other.isRetrieved());
181 QCOMPARE(other.window(), (xcb_window_t)m_testWindow);
186 QT_WARNING_DISABLE_CLANG(
"-Wself-assign-overloaded")
198 QVERIFY(geometry.isRetrieved());
202 QVERIFY(other.isRetrieved());
203 testGeometry(other, QRect(0, 0, 10, 10));
206 QT_WARNING_DISABLE_CLANG(
"-Wself-assign-overloaded")
211 testGeometry(other, QRect(0, 0, 10, 10));
215 other = Xcb::WindowGeometry();
231 QVERIFY(geometry->data());
235void TestXcbWrapper::testQueryTree()
239 QCOMPARE(tree.parent(),
static_cast<xcb_window_t
>(QX11Info::appRootWindow()));
241 QCOMPARE(tree->children_len, uint16_t(0));
242 QVERIFY(!tree.children());
245 Xcb::Tree root(QX11Info::appRootWindow());
247 QCOMPARE(root.parent(), xcb_window_t(XCB_WINDOW_NONE));
248 QVERIFY(root->children_len > 0);
249 xcb_window_t *children = root.children();
251 for (
int i = 0; i < xcb_query_tree_children_length(root.data()); ++i) {
252 if (children[i] == tree.window()) {
261 QCOMPARE(doesntExist.parent(), xcb_window_t(XCB_WINDOW_NONE));
262 QVERIFY(doesntExist.isNull());
263 QVERIFY(doesntExist.isRetrieved());
266void TestXcbWrapper::testCurrentInput()
268 xcb_connection_t *c = QX11Info::connection();
270 QX11Info::setAppTime(QX11Info::getTimestamp());
273 m_testWindow.
focus(XCB_INPUT_FOCUS_PARENT, QX11Info::appTime());
277 QCOMPARE(
input.window(), (xcb_window_t)m_testWindow);
281 QCOMPARE(input2.window(), (xcb_window_t)m_testWindow);
282 QCOMPARE(
input.window(), xcb_window_t(XCB_WINDOW_NONE));
285void TestXcbWrapper::testTransientFor()
288 QCOMPARE(transient.window(), (xcb_window_t)m_testWindow);
290 xcb_window_t compareWindow = XCB_WINDOW_NONE;
291 QVERIFY(!transient.getTransientFor(&compareWindow));
292 QCOMPARE(compareWindow, xcb_window_t(XCB_WINDOW_NONE));
294 QCOMPARE(transient.value<xcb_window_t>(32, XCB_ATOM_WINDOW, XCB_WINDOW_NONE, &ok), xcb_window_t(XCB_WINDOW_NONE));
297 QCOMPARE(transient.value<xcb_window_t>(XCB_WINDOW_NONE, &ok), xcb_window_t(XCB_WINDOW_NONE));
302 xcb_window_t testWindowId = m_testWindow;
303 transientWindow.
changeProperty(XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32, 1, &testWindowId);
307 QVERIFY(realTransient.getTransientFor(&compareWindow));
308 QCOMPARE(compareWindow, (xcb_window_t)m_testWindow);
310 QCOMPARE(realTransient.value<xcb_window_t>(32, XCB_ATOM_WINDOW, XCB_WINDOW_NONE, &ok), (xcb_window_t)m_testWindow);
313 QCOMPARE(realTransient.value<xcb_window_t>(XCB_WINDOW_NONE, &ok), (xcb_window_t)m_testWindow);
316 QCOMPARE(realTransient.value<xcb_window_t>(), (xcb_window_t)m_testWindow);
317 QCOMPARE(realTransient.value<xcb_window_t *>(
nullptr, &ok)[0], (xcb_window_t)m_testWindow);
319 QCOMPARE(realTransient.value<xcb_window_t *>()[0], (xcb_window_t)m_testWindow);
323 QVERIFY(!doesntExist.getTransientFor(&compareWindow));
326void TestXcbWrapper::testPropertyByteArray()
329 Xcb::Property prop(
false, testWindow, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 0, 100000);
330 QCOMPARE(prop.toByteArray(), QByteArray());
332 QCOMPARE(prop.toByteArray(&ok), QByteArray());
335 QVERIFY(!prop.value<
const char *>());
336 QCOMPARE(prop.value<
const char *>(
"bar", &ok),
"bar");
340 testWindow.changeProperty(XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, 3,
"foo");
341 prop =
Xcb::Property(
false, testWindow, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 0, 100000);
342 QCOMPARE(prop.toByteArray(), QByteArrayLiteral(
"foo"));
343 QCOMPARE(prop.toByteArray(&ok), QByteArrayLiteral(
"foo"));
345 QCOMPARE(prop.value<
const char *>(
nullptr, &ok),
"foo");
347 QCOMPARE(QByteArray(
Xcb::StringProperty(testWindow, XCB_ATOM_WM_NAME)), QByteArrayLiteral(
"foo"));
350 QCOMPARE(prop.toByteArray(32), QByteArray());
351 QCOMPARE(prop.toByteArray(8, XCB_ATOM_CARDINAL), QByteArray());
354 testWindow.changeProperty(XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, 0,
nullptr);
355 prop =
Xcb::Property(
false, testWindow, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 0, 100000);
356 QCOMPARE(prop.toByteArray(), QByteArray());
357 QCOMPARE(prop.toByteArray(&ok), QByteArray());
361 QVERIFY(prop.toByteArray().isEmpty());
363 QVERIFY(!prop.toByteArray().isNull());
364 QVERIFY(!prop.value<
const char *>());
368 Xcb::Atom invalid(QByteArrayLiteral(
"INVALID_ATOM"));
369 prop =
Xcb::Property(
false, testWindow, invalid, XCB_ATOM_STRING, 0, 100000);
370 QCOMPARE(prop.toByteArray(), QByteArray());
371 QCOMPARE(prop.toByteArray(&ok), QByteArray());
375 QVERIFY(prop.toByteArray().isEmpty());
377 QVERIFY(prop.toByteArray().isNull());
378 QVERIFY(!prop.value<
const char *>());
382void TestXcbWrapper::testPropertyBool()
385 Xcb::Atom blockCompositing(QByteArrayLiteral(
"_KDE_NET_WM_BLOCK_COMPOSITING"));
386 QVERIFY(blockCompositing != XCB_ATOM_NONE);
387 NETWinInfo info(QX11Info::connection(), testWindow, QX11Info::appRootWindow(), NET::Properties(), NET::WM2BlockCompositing);
389 Xcb::Property prop(
false, testWindow, blockCompositing, XCB_ATOM_CARDINAL, 0, 100000);
391 QVERIFY(!prop.toBool());
392 QVERIFY(!prop.toBool(&ok));
395 info.setBlockingCompositing(
true);
396 xcb_flush(QX11Info::connection());
397 prop =
Xcb::Property(
false, testWindow, blockCompositing, XCB_ATOM_CARDINAL, 0, 100000);
398 QVERIFY(prop.toBool());
399 QVERIFY(prop.toBool(&ok));
403 QVERIFY(!prop.toBool(8));
404 QVERIFY(!prop.toBool(32, blockCompositing));
405 QVERIFY(!prop.toBool(32, blockCompositing, &ok));
409 uint32_t d[] = {1, 0};
410 testWindow.changeProperty(blockCompositing, XCB_ATOM_CARDINAL, 32, 2, d);
411 prop =
Xcb::Property(
false, testWindow, blockCompositing, XCB_ATOM_CARDINAL, 0, 100000);
412 QVERIFY(!prop.toBool());
414 QVERIFY(!prop.toBool(&ok));
418void TestXcbWrapper::testAtom()
420 Xcb::Atom atom(QByteArrayLiteral(
"WM_CLIENT_MACHINE"));
421 QCOMPARE(atom.name(), QByteArrayLiteral(
"WM_CLIENT_MACHINE"));
422 QVERIFY(atom == XCB_ATOM_WM_CLIENT_MACHINE);
423 QVERIFY(atom.isValid());
427 QVERIFY(atom2.isValid());
428 QVERIFY(atom2 == XCB_ATOM_WM_CLIENT_MACHINE);
429 QCOMPARE(atom2.name(), QByteArrayLiteral(
"WM_CLIENT_MACHINE"));
432 Xcb::Atom atom3(QByteArrayLiteral(
"WM_CLIENT_MACHINE"));
433 QCOMPARE(atom3.name(), QByteArrayLiteral(
"WM_CLIENT_MACHINE"));
436void TestXcbWrapper::testMotifEmpty()
438 Xcb::Atom atom(QByteArrayLiteral(
"_MOTIF_WM_HINTS"));
441 QCOMPARE(hints.hasDecoration(),
false);
442 QCOMPARE(hints.noBorder(),
false);
443 QCOMPARE(hints.resize(),
true);
444 QCOMPARE(hints.move(),
true);
445 QCOMPARE(hints.minimize(),
true);
446 QCOMPARE(hints.maximize(),
true);
447 QCOMPARE(hints.close(),
true);
449 hints.init(m_testWindow);
450 QCOMPARE(hints.hasDecoration(),
false);
451 QCOMPARE(hints.noBorder(),
false);
452 QCOMPARE(hints.resize(),
true);
453 QCOMPARE(hints.move(),
true);
454 QCOMPARE(hints.minimize(),
true);
455 QCOMPARE(hints.maximize(),
true);
456 QCOMPARE(hints.close(),
true);
459 QCOMPARE(hints.hasDecoration(),
false);
460 QCOMPARE(hints.noBorder(),
false);
461 QCOMPARE(hints.resize(),
true);
462 QCOMPARE(hints.move(),
true);
463 QCOMPARE(hints.minimize(),
true);
464 QCOMPARE(hints.maximize(),
true);
465 QCOMPARE(hints.close(),
true);
468void TestXcbWrapper::testMotif_data()
470 QTest::addColumn<quint32>(
"flags");
471 QTest::addColumn<quint32>(
"functions");
472 QTest::addColumn<quint32>(
"decorations");
474 QTest::addColumn<bool>(
"expectedHasDecoration");
475 QTest::addColumn<bool>(
"expectedNoBorder");
476 QTest::addColumn<bool>(
"expectedResize");
477 QTest::addColumn<bool>(
"expectedMove");
478 QTest::addColumn<bool>(
"expectedMinimize");
479 QTest::addColumn<bool>(
"expectedMaximize");
480 QTest::addColumn<bool>(
"expectedClose");
482 QTest::newRow(
"none") << 0u << 0u << 0u <<
false <<
false <<
true <<
true <<
true <<
true <<
true;
483 QTest::newRow(
"noborder") << 2u << 5u << 0u <<
true <<
true <<
true <<
true <<
true <<
true <<
true;
484 QTest::newRow(
"border") << 2u << 5u << 1u <<
true <<
false <<
true <<
true <<
true <<
true <<
true;
485 QTest::newRow(
"resize") << 1u << 2u << 1u <<
false <<
false <<
true <<
false <<
false <<
false <<
false;
486 QTest::newRow(
"move") << 1u << 4u << 1u <<
false <<
false <<
false <<
true <<
false <<
false <<
false;
487 QTest::newRow(
"minimize") << 1u << 8u << 1u <<
false <<
false <<
false <<
false <<
true <<
false <<
false;
488 QTest::newRow(
"maximize") << 1u << 16u << 1u <<
false <<
false <<
false <<
false <<
false <<
true <<
false;
489 QTest::newRow(
"close") << 1u << 32u << 1u <<
false <<
false <<
false <<
false <<
false <<
false <<
true;
491 QTest::newRow(
"resize/all") << 1u << 3u << 1u <<
false <<
false <<
false <<
true <<
true <<
true <<
true;
492 QTest::newRow(
"move/all") << 1u << 5u << 1u <<
false <<
false <<
true <<
false <<
true <<
true <<
true;
493 QTest::newRow(
"minimize/all") << 1u << 9u << 1u <<
false <<
false <<
true <<
true <<
false <<
true <<
true;
494 QTest::newRow(
"maximize/all") << 1u << 17u << 1u <<
false <<
false <<
true <<
true <<
true <<
false <<
true;
495 QTest::newRow(
"close/all") << 1u << 33u << 1u <<
false <<
false <<
true <<
true <<
true <<
true <<
false;
497 QTest::newRow(
"all") << 1u << 62u << 1u <<
false <<
false <<
true <<
true <<
true <<
true <<
true;
498 QTest::newRow(
"all/all") << 1u << 63u << 1u <<
false <<
false <<
false <<
false <<
false <<
false <<
false;
499 QTest::newRow(
"all/all/deco") << 3u << 63u << 1u <<
true <<
false <<
false <<
false <<
false <<
false <<
false;
502void TestXcbWrapper::testMotif()
504 Xcb::Atom atom(QByteArrayLiteral(
"_MOTIF_WM_HINTS"));
505 QFETCH(quint32, flags);
506 QFETCH(quint32, functions);
507 QFETCH(quint32, decorations);
514 xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, m_testWindow, atom, atom, 32, 5, data);
515 xcb_flush(QX11Info::connection());
517 hints.init(m_testWindow);
519 QTEST(hints.hasDecoration(),
"expectedHasDecoration");
520 QTEST(hints.noBorder(),
"expectedNoBorder");
521 QTEST(hints.resize(),
"expectedResize");
522 QTEST(hints.move(),
"expectedMove");
523 QTEST(hints.minimize(),
"expectedMinimize");
524 QTEST(hints.maximize(),
"expectedMaximize");
525 QTEST(hints.close(),
"expectedClose");
528Q_CONSTRUCTOR_FUNCTION(forceXcb)
530#include "test_xcb_wrapper.moc"
void changeProperty(xcb_atom_t property, xcb_atom_t type, uint8_t format, uint32_t length, const void *data, uint8_t mode=XCB_PROP_MODE_REPLACE)
void create(const QRectF &geometry, uint32_t mask=0, const uint32_t *values=nullptr, xcb_window_t parent=rootWindow())
void reset(xcb_window_t window=XCB_WINDOW_NONE, bool destroy=true)
void focus(uint8_t revertTo=XCB_INPUT_FOCUS_POINTER_ROOT, xcb_timestamp_t time=XCB_TIME_CURRENT_TIME)
InputRedirection * input()
QTEST_MAIN(OnScreenNotificationTest)