KWin
Loading...
Searching...
No Matches
test_textinputv1_interface.cpp
Go to the documentation of this file.
1/*
2 SPDX-FileCopyrightText: 2020 Bhushan Shah <bshah@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5*/
6
7#include <QSignalSpy>
8#include <QTest>
9#include <QThread>
10
11#include "wayland/compositor.h"
12#include "wayland/display.h"
13#include "wayland/seat.h"
14#include "wayland/surface.h"
16
17#include "KWayland/Client/compositor.h"
18#include "KWayland/Client/connection_thread.h"
19#include "KWayland/Client/event_queue.h"
20#include "KWayland/Client/registry.h"
21#include "KWayland/Client/seat.h"
22#include "KWayland/Client/surface.h"
23
24#include "qwayland-text-input-unstable-v1.h"
25
26using namespace KWin;
27
28Q_DECLARE_METATYPE(QtWayland::zwp_text_input_v1::content_purpose)
29Q_DECLARE_METATYPE(QtWayland::zwp_text_input_v1::content_hint)
30
31class TextInputV1 : public QObject, public QtWayland::zwp_text_input_v1
32{
33 Q_OBJECT
34Q_SIGNALS:
35 void surface_enter(wl_surface *surface);
37 void commit_string(const QString &text);
38 void delete_surrounding_text(qint32 index, quint32 length);
39 void preedit_string(const QString &text, const QString &commit);
40
41public:
42 void zwp_text_input_v1_enter(struct ::wl_surface *surface) override
43 {
44 Q_EMIT surface_enter(surface);
45 }
47 {
48 Q_EMIT surface_leave();
49 }
50 void zwp_text_input_v1_commit_string(uint32_t serial, const QString &text) override
51 {
52 Q_EMIT commit_string(text);
53 }
54 void zwp_text_input_v1_delete_surrounding_text(int32_t index, uint32_t length) override
55 {
56 Q_EMIT delete_surrounding_text(index, length);
57 }
58 void zwp_text_input_v1_preedit_string(uint32_t serial, const QString &text, const QString &commit) override
59 {
60 Q_EMIT preedit_string(text, commit);
61 }
62};
63
64class TextInputManagerV1 : public QtWayland::zwp_text_input_manager_v1
65{
66public:
68 {
69 }
70};
71
72class TestTextInputV1Interface : public QObject
73{
74 Q_OBJECT
75
76public:
78
79private Q_SLOTS:
80 void initTestCase();
81 void testEnableDisable();
82 void testEvents();
83 void testContentPurpose_data();
84 void testContentPurpose();
85 void testContentHints_data();
86 void testContentHints();
87
88private:
89 KWayland::Client::ConnectionThread *m_connection = nullptr;
90 KWayland::Client::EventQueue *m_queue = nullptr;
91 KWayland::Client::Compositor *m_clientCompositor = nullptr;
92 KWayland::Client::Seat *m_clientSeat = nullptr;
93
94 SeatInterface *m_seat;
95 QThread *m_thread;
96 KWin::Display m_display;
97 TextInputV1 *m_clientTextInputV1;
98 CompositorInterface *m_serverCompositor;
99 TextInputV1Interface *m_serverTextInputV1;
100 TextInputManagerV1 *m_clientTextInputManagerV1;
101
102 quint32 m_totalCommits = 0;
103};
104
105static const QString s_socketName = QStringLiteral("kwin-wayland-server-text-input-v1-test-0");
106
107void TestTextInputV1Interface::initTestCase()
108{
109 m_display.addSocketName(s_socketName);
110 m_display.start();
111 QVERIFY(m_display.isRunning());
112
113 m_seat = new SeatInterface(&m_display, this);
114 m_seat->setHasKeyboard(true);
115
116 m_serverCompositor = new CompositorInterface(&m_display, this);
117 new TextInputManagerV1Interface(&m_display);
118
119 m_connection = new KWayland::Client::ConnectionThread;
120 QSignalSpy connectedSpy(m_connection, &KWayland::Client::ConnectionThread::connected);
121 m_connection->setSocketName(s_socketName);
122
123 m_thread = new QThread(this);
124 m_connection->moveToThread(m_thread);
125 m_thread->start();
126
127 m_connection->initConnection();
128 QVERIFY(connectedSpy.wait());
129 QVERIFY(!m_connection->connections().isEmpty());
130
131 m_queue = new KWayland::Client::EventQueue(this);
132 QVERIFY(!m_queue->isValid());
133 m_queue->setup(m_connection);
134 QVERIFY(m_queue->isValid());
135
136 auto registry = new KWayland::Client::Registry(this);
137 connect(registry, &KWayland::Client::Registry::interfaceAnnounced, this, [this, registry](const QByteArray &interface, quint32 id, quint32 version) {
138 if (interface == QByteArrayLiteral("zwp_text_input_manager_v1")) {
139 m_clientTextInputManagerV1 = new TextInputManagerV1();
140 m_clientTextInputManagerV1->init(*registry, id, version);
141 }
142 });
143
144 connect(registry, &KWayland::Client::Registry::seatAnnounced, this, [this, registry](quint32 name, quint32 version) {
145 m_clientSeat = registry->createSeat(name, version);
146 });
147
148 QSignalSpy allAnnouncedSpy(registry, &KWayland::Client::Registry::interfaceAnnounced);
149 QSignalSpy compositorSpy(registry, &KWayland::Client::Registry::compositorAnnounced);
150 QSignalSpy shmSpy(registry, &KWayland::Client::Registry::shmAnnounced);
151 registry->setEventQueue(m_queue);
152 registry->create(m_connection->display());
153 QVERIFY(registry->isValid());
154 registry->setup();
155 QVERIFY(allAnnouncedSpy.wait());
156
157 m_clientCompositor = registry->createCompositor(compositorSpy.first().first().value<quint32>(), compositorSpy.first().last().value<quint32>(), this);
158 QVERIFY(m_clientCompositor->isValid());
159 // create a text input v1
160 m_clientTextInputV1 = new TextInputV1();
161 m_clientTextInputV1->init(m_clientTextInputManagerV1->create_text_input());
162 QVERIFY(m_clientTextInputV1);
163}
164
166{
167 if (m_clientTextInputV1) {
168 delete m_clientTextInputV1;
169 m_clientTextInputV1 = nullptr;
170 }
171 if (m_clientTextInputManagerV1) {
172 delete m_clientTextInputManagerV1;
173 m_clientTextInputManagerV1 = nullptr;
174 }
175 if (m_queue) {
176 delete m_queue;
177 m_queue = nullptr;
178 }
179 if (m_thread) {
180 m_thread->quit();
181 m_thread->wait();
182 delete m_thread;
183 m_thread = nullptr;
184 }
185 m_connection->deleteLater();
186 m_connection = nullptr;
187}
188
189// Ensures that enable disable events don't fire without commit
190void TestTextInputV1Interface::testEnableDisable()
191{
192 // create a surface
193 QSignalSpy serverSurfaceCreatedSpy(m_serverCompositor, &CompositorInterface::surfaceCreated);
194 std::unique_ptr<KWayland::Client::Surface> clientSurface(m_clientCompositor->createSurface(this));
195 QVERIFY(serverSurfaceCreatedSpy.wait());
196 SurfaceInterface *serverSurface = serverSurfaceCreatedSpy.first().first().value<SurfaceInterface *>();
197 QVERIFY(serverSurface);
198
199 m_serverTextInputV1 = m_seat->textInputV1();
200 QVERIFY(m_serverTextInputV1);
201
202 QSignalSpy focusedSurfaceChangedSpy(m_seat, &SeatInterface::focusedTextInputSurfaceChanged);
203 QSignalSpy textInputEnabledSpy(m_serverTextInputV1, &TextInputV1Interface::enabledChanged);
204 QSignalSpy cursorRectangleChangedSpy(m_serverTextInputV1, &TextInputV1Interface::cursorRectangleChanged);
205
206 QSignalSpy surfaceEnterSpy(m_clientTextInputV1, &TextInputV1::surface_enter);
207 QSignalSpy surfaceLeaveSpy(m_clientTextInputV1, &TextInputV1::surface_leave);
208
209 // Enter the textinput
210
211 QCOMPARE(focusedSurfaceChangedSpy.count(), 0);
212
213 // Make sure that entering surface does not trigger the text input
214 m_seat->setFocusedTextInputSurface(serverSurface);
215 QCOMPARE(focusedSurfaceChangedSpy.count(), 1);
216 QCOMPARE(surfaceEnterSpy.count(), 0);
217 QCOMPARE(textInputEnabledSpy.count(), 0);
218
219 // Now enable the textInput, we should not get event just yet
220 m_clientTextInputV1->activate(*m_clientSeat, *clientSurface);
221 m_clientTextInputV1->set_cursor_rectangle(0, 0, 20, 20);
222 m_clientTextInputV1->set_surrounding_text("KDE Plasma Desktop", 0, 3);
223 QVERIFY(surfaceEnterSpy.wait());
224
225 QCOMPARE(textInputEnabledSpy.count(), 1);
226 QCOMPARE(cursorRectangleChangedSpy.count(), 1);
227 QCOMPARE(m_serverTextInputV1->cursorRectangle(), QRect(0, 0, 20, 20));
228 QCOMPARE(m_serverTextInputV1->surroundingText(), QString("KDE Plasma Desktop"));
229 QCOMPARE(m_serverTextInputV1->surroundingTextCursorPosition(), 0);
230 QCOMPARE(m_serverTextInputV1->surroundingTextSelectionAnchor(), 3);
231
232 // disabling we should get the event
233 m_clientTextInputV1->deactivate(*m_clientSeat);
234 QVERIFY(textInputEnabledSpy.wait());
235 QCOMPARE(textInputEnabledSpy.count(), 2);
236 QVERIFY(surfaceLeaveSpy.wait());
237
238 // Lets try leaving the surface and make sure event propogage
239 m_seat->setFocusedTextInputSurface(nullptr);
240 QCOMPARE(surfaceLeaveSpy.count(), 1);
241}
242
243void TestTextInputV1Interface::testEvents()
244{
245 // create a surface
246 QSignalSpy serverSurfaceCreatedSpy(m_serverCompositor, &CompositorInterface::surfaceCreated);
247 std::unique_ptr<KWayland::Client::Surface> clientSurface(m_clientCompositor->createSurface(this));
248 QVERIFY(serverSurfaceCreatedSpy.wait());
249 SurfaceInterface *serverSurface = serverSurfaceCreatedSpy.first().first().value<SurfaceInterface *>();
250 QVERIFY(serverSurface);
251
252 m_serverTextInputV1 = m_seat->textInputV1();
253 QVERIFY(m_serverTextInputV1);
254
255 QSignalSpy focusedSurfaceChangedSpy(m_seat, &SeatInterface::focusedTextInputSurfaceChanged);
256 QSignalSpy textInputEnabledSpy(m_serverTextInputV1, &TextInputV1Interface::enabledChanged);
257
258 // Enter the textinput
259 QCOMPARE(focusedSurfaceChangedSpy.count(), 0);
260
261 // Make sure that entering surface does not trigger the text input
262 m_seat->setFocusedTextInputSurface(serverSurface);
263 // FIXME: somehow this triggers BEFORE setFocusedTextInputSurface returns :(
264 // QVERIFY(focusedSurfaceChangedSpy.wait());
265 QCOMPARE(focusedSurfaceChangedSpy.count(), 1);
266
267 // Now enable the textInput
268 m_clientTextInputV1->activate(*m_clientSeat, *clientSurface);
269 QVERIFY(textInputEnabledSpy.wait());
270
271 QSignalSpy preEditSpy(m_clientTextInputV1, &TextInputV1::preedit_string);
272 QSignalSpy commitStringSpy(m_clientTextInputV1, &TextInputV1::commit_string);
273 QSignalSpy deleteSurroundingSpy(m_clientTextInputV1, &TextInputV1::delete_surrounding_text);
274
275 m_serverTextInputV1->preEdit("Hello KDE community!", "Hello");
276 m_serverTextInputV1->deleteSurroundingText(6, 10);
277 m_serverTextInputV1->commitString("Plasma");
278
279 // Wait for the last update
280 QVERIFY(commitStringSpy.wait());
281
282 QCOMPARE(preEditSpy.last().at(0).value<QString>(), "Hello KDE community!");
283 QCOMPARE(preEditSpy.last().at(1).value<QString>(), "Hello");
284 QCOMPARE(commitStringSpy.last().at(0).value<QString>(), "Plasma");
285 QCOMPARE(deleteSurroundingSpy.last().at(0).value<quint32>(), 6);
286 QCOMPARE(deleteSurroundingSpy.last().at(1).value<quint32>(), 10);
287
288 // Now disable the textInput
289 m_clientTextInputV1->deactivate(*m_clientSeat);
290 QVERIFY(textInputEnabledSpy.wait());
291}
292
293void TestTextInputV1Interface::testContentPurpose_data()
294{
295 QTest::addColumn<QtWayland::zwp_text_input_v1::content_purpose>("clientPurpose");
296 QTest::addColumn<KWin::TextInputContentPurpose>("serverPurpose");
297
298 QTest::newRow("Alpha") << QtWayland::zwp_text_input_v1::content_purpose_alpha << TextInputContentPurpose::Alpha;
299 QTest::newRow("Digits") << QtWayland::zwp_text_input_v1::content_purpose_digits << TextInputContentPurpose::Digits;
300 QTest::newRow("Number") << QtWayland::zwp_text_input_v1::content_purpose_number << TextInputContentPurpose::Number;
301 QTest::newRow("Phone") << QtWayland::zwp_text_input_v1::content_purpose_phone << TextInputContentPurpose::Phone;
302 QTest::newRow("Url") << QtWayland::zwp_text_input_v1::content_purpose_url << TextInputContentPurpose::Url;
303 QTest::newRow("Email") << QtWayland::zwp_text_input_v1::content_purpose_email << TextInputContentPurpose::Email;
304 QTest::newRow("Name") << QtWayland::zwp_text_input_v1::content_purpose_name << TextInputContentPurpose::Name;
305 QTest::newRow("Password") << QtWayland::zwp_text_input_v1::content_purpose_password << TextInputContentPurpose::Password;
306 QTest::newRow("Date") << QtWayland::zwp_text_input_v1::content_purpose_date << TextInputContentPurpose::Date;
307 QTest::newRow("Time") << QtWayland::zwp_text_input_v1::content_purpose_time << TextInputContentPurpose::Time;
308 QTest::newRow("DateTime") << QtWayland::zwp_text_input_v1::content_purpose_datetime << TextInputContentPurpose::DateTime;
309 QTest::newRow("Terminal") << QtWayland::zwp_text_input_v1::content_purpose_terminal << TextInputContentPurpose::Terminal;
310}
311
312void TestTextInputV1Interface::testContentPurpose()
313{
314 // create a surface
315 QSignalSpy serverSurfaceCreatedSpy(m_serverCompositor, &CompositorInterface::surfaceCreated);
316 std::unique_ptr<KWayland::Client::Surface> clientSurface(m_clientCompositor->createSurface(this));
317 QVERIFY(serverSurfaceCreatedSpy.wait());
318 SurfaceInterface *serverSurface = serverSurfaceCreatedSpy.first().first().value<SurfaceInterface *>();
319 QVERIFY(serverSurface);
320
321 m_serverTextInputV1 = m_seat->textInputV1();
322 QVERIFY(m_serverTextInputV1);
323
324 QSignalSpy focusedSurfaceChangedSpy(m_seat, &SeatInterface::focusedTextInputSurfaceChanged);
325 QSignalSpy textInputEnabledSpy(m_serverTextInputV1, &TextInputV1Interface::enabledChanged);
326
327 // Enter the textinput
328 QCOMPARE(focusedSurfaceChangedSpy.count(), 0);
329
330 // Make sure that entering surface does not trigger the text input
331 m_seat->setFocusedTextInputSurface(serverSurface);
332 // FIXME: somehow this triggers BEFORE setFocusedTextInputSurface returns :(
333 // QVERIFY(focusedSurfaceChangedSpy.wait());
334 QCOMPARE(focusedSurfaceChangedSpy.count(), 1);
335
336 // Now enable the textInput
337 m_clientTextInputV1->activate(*m_clientSeat, *clientSurface);
338 QVERIFY(textInputEnabledSpy.wait());
339 m_totalCommits++;
340
341 // Default should be normal content purpose
342 QCOMPARE(m_serverTextInputV1->contentPurpose(), TextInputContentPurpose::Normal);
343
344 QSignalSpy contentTypeChangedSpy(m_serverTextInputV1, &TextInputV1Interface::contentTypeChanged);
345
346 QFETCH(QtWayland::zwp_text_input_v1::content_purpose, clientPurpose);
347 m_clientTextInputV1->activate(*m_clientSeat, *clientSurface);
348 m_clientTextInputV1->set_content_type(QtWayland::zwp_text_input_v1::content_hint_none, clientPurpose);
349 QVERIFY(contentTypeChangedSpy.wait());
350 QTEST(m_serverTextInputV1->contentPurpose(), "serverPurpose");
351 m_totalCommits++;
352
353 // Setting same thing should not trigger update
354 m_clientTextInputV1->activate(*m_clientSeat, *clientSurface);
355 m_clientTextInputV1->set_content_type(QtWayland::zwp_text_input_v1::content_hint_none, clientPurpose);
356 QVERIFY(!contentTypeChangedSpy.wait(100));
357 m_totalCommits++;
358
359 // unset to normal
360 m_clientTextInputV1->activate(*m_clientSeat, *clientSurface);
361 m_clientTextInputV1->set_content_type(QtWayland::zwp_text_input_v1::content_hint_none, QtWayland::zwp_text_input_v1::content_purpose_normal);
362 QVERIFY(contentTypeChangedSpy.wait());
363 m_totalCommits++;
364 QCOMPARE(m_serverTextInputV1->contentPurpose(), TextInputContentPurpose::Normal);
365
366 // Now disable the textInput
367 m_clientTextInputV1->deactivate(*m_clientSeat);
368 m_totalCommits++;
369 QVERIFY(textInputEnabledSpy.wait());
370}
371
372void TestTextInputV1Interface::testContentHints_data()
373{
374 QTest::addColumn<quint32>("clientHint");
375 QTest::addColumn<KWin::TextInputContentHints>("serverHints");
376
377 QTest::addRow("Spellcheck") << quint32(QtWayland::zwp_text_input_v1::content_hint_auto_correction)
378 << TextInputContentHints(TextInputContentHint::AutoCorrection);
379 QTest::addRow("Completion") << quint32(QtWayland::zwp_text_input_v1::content_hint_auto_completion)
380 << TextInputContentHints(TextInputContentHint::AutoCompletion);
381 QTest::addRow("AutoCapital") << quint32(QtWayland::zwp_text_input_v1::content_hint_auto_capitalization)
382 << TextInputContentHints(TextInputContentHint::AutoCapitalization);
383 QTest::addRow("Lowercase") << quint32(QtWayland::zwp_text_input_v1::content_hint_lowercase) << TextInputContentHints(TextInputContentHint::LowerCase);
384 QTest::addRow("Uppercase") << quint32(QtWayland::zwp_text_input_v1::content_hint_uppercase) << TextInputContentHints(TextInputContentHint::UpperCase);
385 QTest::addRow("Titlecase") << quint32(QtWayland::zwp_text_input_v1::content_hint_titlecase) << TextInputContentHints(TextInputContentHint::TitleCase);
386 QTest::addRow("HiddenText") << quint32(QtWayland::zwp_text_input_v1::content_hint_hidden_text) << TextInputContentHints(TextInputContentHint::HiddenText);
387 QTest::addRow("SensitiveData") << quint32(QtWayland::zwp_text_input_v1::content_hint_sensitive_data)
388 << TextInputContentHints(TextInputContentHint::SensitiveData);
389 QTest::addRow("Latin") << quint32(QtWayland::zwp_text_input_v1::content_hint_latin) << TextInputContentHints(TextInputContentHint::Latin);
390 QTest::addRow("Multiline") << quint32(QtWayland::zwp_text_input_v1::content_hint_multiline) << TextInputContentHints(TextInputContentHint::MultiLine);
391 QTest::addRow("Auto") << quint32(QtWayland::zwp_text_input_v1::content_hint_auto_completion | QtWayland::zwp_text_input_v1::content_hint_auto_correction
392 | QtWayland::zwp_text_input_v1::content_hint_auto_capitalization)
393 << TextInputContentHints(TextInputContentHint::AutoCompletion | TextInputContentHint::AutoCorrection
394 | TextInputContentHint::AutoCapitalization);
395}
396
397void TestTextInputV1Interface::testContentHints()
398{
399 // create a surface
400 QSignalSpy serverSurfaceCreatedSpy(m_serverCompositor, &CompositorInterface::surfaceCreated);
401 std::unique_ptr<KWayland::Client::Surface> clientSurface(m_clientCompositor->createSurface(this));
402 QVERIFY(serverSurfaceCreatedSpy.wait());
403 SurfaceInterface *serverSurface = serverSurfaceCreatedSpy.first().first().value<SurfaceInterface *>();
404 QVERIFY(serverSurface);
405
406 m_serverTextInputV1 = m_seat->textInputV1();
407 QVERIFY(m_serverTextInputV1);
408
409 QSignalSpy focusedSurfaceChangedSpy(m_seat, &SeatInterface::focusedTextInputSurfaceChanged);
410 QSignalSpy textInputEnabledSpy(m_serverTextInputV1, &TextInputV1Interface::enabledChanged);
411
412 // Enter the textinput
413 QCOMPARE(focusedSurfaceChangedSpy.count(), 0);
414
415 // Make sure that entering surface does not trigger the text input
416 m_seat->setFocusedTextInputSurface(serverSurface);
417 // FIXME: somehow this triggers BEFORE setFocusedTextInputSurface returns :(
418 // QVERIFY(focusedSurfaceChangedSpy.wait());
419 QCOMPARE(focusedSurfaceChangedSpy.count(), 1);
420
421 // Now enable the textInput
422 m_clientTextInputV1->activate(*m_clientSeat, *clientSurface);
423 QVERIFY(textInputEnabledSpy.wait());
424 m_totalCommits++;
425
426 QCOMPARE(m_serverTextInputV1->contentHints(), TextInputContentHint::None);
427
428 // Now disable the textInput
429 m_clientTextInputV1->deactivate(*m_clientSeat);
430 QVERIFY(textInputEnabledSpy.wait());
431 m_totalCommits++;
432
433 QSignalSpy contentTypeChangedSpy(m_serverTextInputV1, &TextInputV1Interface::contentTypeChanged);
434
435 QFETCH(quint32, clientHint);
436 m_clientTextInputV1->activate(*m_clientSeat, *clientSurface);
437 m_clientTextInputV1->set_content_type(clientHint, QtWayland::zwp_text_input_v1::content_purpose_normal);
438 QVERIFY(contentTypeChangedSpy.wait());
439 QTEST(m_serverTextInputV1->contentHints(), "serverHints");
440 m_totalCommits++;
441
442 // Setting same thing should not trigger update
443 m_clientTextInputV1->activate(*m_clientSeat, *clientSurface);
444 m_clientTextInputV1->set_content_type(clientHint, QtWayland::zwp_text_input_v1::content_purpose_normal);
445 QVERIFY(!contentTypeChangedSpy.wait(100));
446 m_totalCommits++;
447
448 // unset to normal
449 m_clientTextInputV1->activate(*m_clientSeat, *clientSurface);
450 m_clientTextInputV1->set_content_type(QtWayland::zwp_text_input_v1::content_hint_none, QtWayland::zwp_text_input_v1::content_purpose_normal);
451 QVERIFY(contentTypeChangedSpy.wait());
452 m_totalCommits++;
453
454 // Now disable the textInput
455 m_clientTextInputV1->deactivate(*m_clientSeat);
456 QVERIFY(textInputEnabledSpy.wait());
457 m_totalCommits++;
458}
459
460QTEST_GUILESS_MAIN(TestTextInputV1Interface)
461
462#include "test_textinputv1_interface.moc"
void surfaceCreated(KWin::SurfaceInterface *surface)
Class holding the Wayland server display loop.
Definition display.h:34
bool addSocketName(const QString &name=QString())
Definition display.cpp:68
bool isRunning() const
Definition display.cpp:144
bool start()
Definition display.cpp:92
Represents a Seat on the Wayland Display.
Definition seat.h:134
TextInputV1Interface * textInputV1() const
Definition seat.cpp:1264
void setHasKeyboard(bool has)
Definition seat.cpp:342
void focusedTextInputSurfaceChanged()
void setFocusedTextInputSurface(SurfaceInterface *surface)
Definition seat.cpp:1231
Resource representing a wl_surface.
Definition surface.h:80
Represent the Global for the interface.
Represents a generic Resource for a text input object.
qint32 surroundingTextSelectionAnchor() const
TextInputContentPurpose contentPurpose() const
void cursorRectangleChanged(const QRect &rect)
qint32 surroundingTextCursorPosition() const
void preEdit(const QString &text, const QString &commitText)
void commitString(const QString &text)
void deleteSurroundingText(quint32 beforeLength, quint32 afterLength)
TextInputContentHints contentHints() const
QString surroundingText() const
void zwp_text_input_v1_delete_surrounding_text(int32_t index, uint32_t length) override
void delete_surrounding_text(qint32 index, quint32 length)
void zwp_text_input_v1_preedit_string(uint32_t serial, const QString &text, const QString &commit) override
void preedit_string(const QString &text, const QString &commit)
void commit_string(const QString &text)
void surface_enter(wl_surface *surface)
void zwp_text_input_v1_leave() override
void surface_leave()
void zwp_text_input_v1_enter(struct ::wl_surface *surface) override
void zwp_text_input_v1_commit_string(uint32_t serial, const QString &text) override
Q_DECLARE_METATYPE(KWin::SwitchEvent::State)
KWayland::Client::Registry * registry
constexpr int version