1 /*
2 This file is part of the KDE Libraries
3
4 SPDX-FileCopyrightText: 2009 Lubos Lunak <l.lunak@kde.org>
5 SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org>
6
7 SPDX-License-Identifier: LGPL-2.1-or-later
8 */
9
10 #include "kmanagerselectiontest.h"
11
12 #include <QSignalSpy>
13 #include <kselectionowner.h>
14 #include <kselectionwatcher.h>
15 #include <qx11info_x11.h>
16
17 #define SNAME "_KDE_KMANAGERSELECTIONTEST"
18
19 using namespace QTest;
20
xSync()21 void KManagerSelectionTest::xSync()
22 {
23 xcb_connection_t *c = QX11Info::connection();
24 const xcb_get_input_focus_cookie_t cookie = xcb_get_input_focus(c);
25 xcb_generic_error_t *error = nullptr;
26 QScopedPointer<xcb_get_input_focus_reply_t, QScopedPointerPodDeleter> sync(xcb_get_input_focus_reply(c, cookie, &error));
27 if (error) {
28 free(error);
29 }
30 }
31
claim(KSelectionOwner * owner,bool force,bool forceKill)32 void KManagerSelectionTest::claim(KSelectionOwner *owner, bool force, bool forceKill)
33 {
34 QSignalSpy claimSpy(owner, SIGNAL(claimedOwnership()));
35 owner->claim(force, forceKill);
36 xSync();
37 QVERIFY(claimSpy.wait());
38 QCOMPARE(claimSpy.count(), 1);
39 }
40
testAcquireRelease()41 void KManagerSelectionTest::testAcquireRelease()
42 {
43 // test that newOwner() is emitted when there is a new selection owner
44 KSelectionWatcher watcher(SNAME);
45 KSelectionOwner owner(SNAME);
46 QVERIFY(owner.ownerWindow() == XCB_WINDOW_NONE);
47 QVERIFY(watcher.owner() == XCB_WINDOW_NONE);
48 SigCheckWatcher sw(watcher);
49 SigCheckOwner so(owner);
50 claim(&owner);
51 QSignalSpy newOwnerSpy(&watcher, SIGNAL(newOwner(xcb_window_t)));
52 QVERIFY(newOwnerSpy.wait());
53 QVERIFY(sw.newowner == true);
54 QVERIFY(sw.lostowner == false);
55 QVERIFY(so.lostownership == false);
56 }
57
testInitiallyOwned()58 void KManagerSelectionTest::testInitiallyOwned()
59 {
60 // test that lostOwner() is emitted when the selection is disowned
61 KSelectionOwner owner(SNAME);
62 SigCheckOwner so(owner);
63 claim(&owner);
64 KSelectionWatcher watcher(SNAME);
65 SigCheckWatcher sw(watcher);
66 owner.release();
67 QSignalSpy lostOwnerSpy(&watcher, SIGNAL(lostOwner()));
68 QVERIFY(lostOwnerSpy.wait(2000));
69 QVERIFY(sw.newowner == false);
70 QVERIFY(sw.lostowner == true);
71 QVERIFY(so.lostownership == false);
72 }
73
testLostOwnership()74 void KManagerSelectionTest::testLostOwnership()
75 {
76 // test that lostOwnership() is emitted when something else forces taking the ownership
77 KSelectionOwner owner1(SNAME);
78 KSelectionOwner owner2(SNAME);
79 claim(&owner1);
80
81 QSignalSpy claimSpy(&owner2, SIGNAL(failedToClaimOwnership()));
82 owner2.claim(false);
83 claimSpy.wait();
84 QCOMPARE(claimSpy.count(), 1);
85 claim(&owner2, true, false);
86
87 QEXPECT_FAIL("", "selectionClear event is not sent to the same X client", Abort);
88 QSignalSpy lostOwnershipSpy(&owner1, SIGNAL(lostOwnership()));
89 QVERIFY(lostOwnershipSpy.wait());
90 QVERIFY(owner1.ownerWindow() == XCB_WINDOW_NONE);
91 QVERIFY(owner2.ownerWindow() != XCB_WINDOW_NONE);
92 }
93
testWatching()94 void KManagerSelectionTest::testWatching()
95 {
96 // test that KSelectionWatcher reports changes properly
97 KSelectionWatcher watcher(SNAME);
98 KSelectionOwner owner1(SNAME);
99 KSelectionOwner owner2(SNAME);
100 SigCheckWatcher sw(watcher);
101 QSignalSpy newOwnerSpy(&watcher, SIGNAL(newOwner(xcb_window_t)));
102 QVERIFY(newOwnerSpy.isValid());
103 claim(&owner1);
104 if (newOwnerSpy.isEmpty()) {
105 QVERIFY(newOwnerSpy.wait());
106 }
107 QCOMPARE(newOwnerSpy.count(), 1);
108 QVERIFY(sw.newowner == true);
109 QVERIFY(sw.lostowner == false);
110 sw.newowner = sw.lostowner = false;
111 newOwnerSpy.clear();
112 QVERIFY(newOwnerSpy.isEmpty());
113 claim(&owner2, true, false);
114 xSync();
115 if (newOwnerSpy.isEmpty()) {
116 QVERIFY(newOwnerSpy.wait());
117 }
118 QCOMPARE(newOwnerSpy.count(), 1);
119 QVERIFY(sw.newowner == true);
120 QVERIFY(sw.lostowner == false);
121 sw.newowner = sw.lostowner = false;
122 QSignalSpy lostOwnerSpy(&watcher, SIGNAL(lostOwner()));
123 owner2.release();
124 xSync();
125 QVERIFY(lostOwnerSpy.wait());
126 QVERIFY(sw.newowner == false);
127 QVERIFY(sw.lostowner == true);
128 sw.newowner = sw.lostowner = false;
129 claim(&owner2);
130 QVERIFY(newOwnerSpy.wait(2000));
131 QVERIFY(sw.newowner == true);
132 QVERIFY(sw.lostowner == false);
133 }
134
SigCheckOwner(const KSelectionOwner & owner)135 SigCheckOwner::SigCheckOwner(const KSelectionOwner &owner)
136 : lostownership(false)
137 {
138 connect(&owner, SIGNAL(lostOwnership()), this, SLOT(lostOwnership()));
139 }
140
lostOwnership()141 void SigCheckOwner::lostOwnership()
142 {
143 lostownership = true;
144 }
145
SigCheckWatcher(const KSelectionWatcher & watcher)146 SigCheckWatcher::SigCheckWatcher(const KSelectionWatcher &watcher)
147 : newowner(false)
148 , lostowner(false)
149 {
150 connect(&watcher, SIGNAL(newOwner(xcb_window_t)), this, SLOT(newOwner()));
151 connect(&watcher, SIGNAL(lostOwner()), this, SLOT(lostOwner()));
152 }
153
newOwner()154 void SigCheckWatcher::newOwner()
155 {
156 newowner = true;
157 }
158
lostOwner()159 void SigCheckWatcher::lostOwner()
160 {
161 lostowner = true;
162 }
163
164 QTEST_MAIN(KManagerSelectionTest)
165