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