1/*
2 SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5*/
6#ifndef KWAYLAND_CLIENT_TEXTINPUT_H
7#define KWAYLAND_CLIENT_TEXTINPUT_H
8
9#include <QObject>
10
11#include "KWayland/Client/kwaylandclient_export.h"
12
13struct wl_text_input;
14struct wl_text_input_manager;
15struct zwp_text_input_manager_v2;
16
17namespace KWayland
18{
19namespace Client
20{
21class EventQueue;
22class Surface;
23class Seat;
24
25/**
26 * @brief TextInput represents a Wayland interface for text input.
27 *
28 * The TextInput allows to have text composed by the Compositor and be sent to
29 * the client.
30 *
31 * Depending on the interface the TextInputManager got created for this class
32 * encapsulates one of the following interfaces:
33 * @li wl_text_input
34 * @li zwp_text_input_v2
35 *
36 * @since 5.23
37 **/
38class KWAYLANDCLIENT_EXPORT TextInput : public QObject
39{
40 Q_OBJECT
41public:
42 ~TextInput() override;
43 /**
44 * @returns @c true if managing a resource.
45 **/
46 bool isValid() const;
47
48 /**
49 * @returns The Surface which has the text input focus on this TextInput.
50 * @see entered
51 * @see left
52 **/
53 Surface *enteredSurface() const;
54
55 void setEventQueue(EventQueue *queue);
56 EventQueue *eventQueue() const;
57
58 /**
59 * @returns whether the input panel (virtual keyboard) is currently visible on the screen
60 * @see inputPanelStateChanged
61 **/
62 bool isInputPanelVisible() const;
63
64 /**
65 * Enable text input in a @p surface (usually when a text entry inside of it has focus).
66 *
67 * This can be called before or after a surface gets text (or keyboard) focus via the
68 * enter event. Text input to a surface is only active when it has the current
69 * text (or keyboard) focus and is enabled.
70 * @see deactivate
71 **/
72 void enable(Surface *surface);
73
74 /**
75 * Disable text input in a @p surface (typically when there is no focus on any
76 * text entry inside the surface).
77 * @see enable
78 **/
79 void disable(Surface *surface);
80
81 /**
82 * Requests input panels (virtual keyboard) to show.
83 * @see hideInputPanel
84 **/
85 void showInputPanel();
86
87 /**
88 * Requests input panels (virtual keyboard) to hide.
89 * @see showInputPanel
90 **/
91 void hideInputPanel();
92
93 /**
94 * Should be called by an editor widget when the input state should be
95 * reset, for example after the text was changed outside of the normal
96 * input method flow.
97 **/
98 void reset();
99
100 /**
101 * Sets the plain surrounding text around the input position.
102 *
103 * @param text The text surrounding the cursor position
104 * @param cursor Index in the text describing the cursor position
105 * @param anchor Index of the selection anchor, if no selection same as cursor
106 **/
107 void setSurroundingText(const QString &text, quint32 cursor, quint32 anchor);
108
109 /**
110 * The possible states for a keyEvent.
111 * @see keyEvent
112 **/
113 enum class KeyState {
114 Pressed,
115 Released,
116 };
117
118 /**
119 * ContentHint allows to modify the behavior of the text input.
120 **/
121 enum class ContentHint : uint32_t {
122 /**
123 * no special behaviour
124 */
125 None = 0,
126 /**
127 * suggest word completions
128 */
129 AutoCompletion = 1 << 0,
130 /**
131 * suggest word corrections
132 */
133 AutoCorrection = 1 << 1,
134 /**
135 * switch to uppercase letters at the start of a sentence
136 */
137 AutoCapitalization = 1 << 2,
138 /**
139 * prefer lowercase letters
140 */
141 LowerCase = 1 << 3,
142 /**
143 * prefer uppercase letters
144 */
145 UpperCase = 1 << 4,
146 /**
147 * prefer casing for titles and headings (can be language dependent)
148 */
149 TitleCase = 1 << 5,
150 /**
151 * characters should be hidden
152 */
153 HiddenText = 1 << 6,
154 /**
155 * typed text should not be stored
156 */
157 SensitiveData = 1 << 7,
158 /**
159 * just latin characters should be entered
160 */
161 Latin = 1 << 8,
162 /**
163 * the text input is multi line
164 */
165 MultiLine = 1 << 9,
166 };
167 Q_DECLARE_FLAGS(ContentHints, ContentHint)
168
169 /**
170 * The ContentPurpose allows to specify the primary purpose of a text input.
171 *
172 * This allows an input method to show special purpose input panels with
173 * extra characters or to disallow some characters.
174 */
175 enum class ContentPurpose : uint32_t {
176 /**
177 * default input, allowing all characters
178 */
179 Normal,
180 /**
181 * allow only alphabetic characters
182 **/
183 Alpha,
184 /**
185 * allow only digits
186 */
187 Digits,
188 /**
189 * input a number (including decimal separator and sign)
190 */
191 Number,
192 /**
193 * input a phone number
194 */
195 Phone,
196 /**
197 * input an URL
198 */
199 Url,
200 /**
201 * input an email address
202 **/
203 Email,
204 /**
205 * input a name of a person
206 */
207 Name,
208 /**
209 * input a password
210 */
211 Password,
212 /**
213 * input a date
214 */
215 Date,
216 /**
217 * input a time
218 */
219 Time,
220 /**
221 * input a date and time
222 */
223 DateTime,
224 /**
225 * input for a terminal
226 */
227 Terminal,
228 };
229 /**
230 * Sets the content @p purpose and content @p hints.
231 * While the @p purpose is the basic purpose of an input field, the @p hints flags allow
232 * to modify some of the behavior.
233 **/
234 void setContentType(ContentHints hints, ContentPurpose purpose);
235
236 /**
237 * Sets the cursor outline @p rect in surface local coordinates.
238 *
239 * Allows the compositor to e.g. put a window with word suggestions
240 * near the cursor.
241 **/
242 void setCursorRectangle(const QRect &rect);
243
244 /**
245 * Sets a specific @p language.
246 *
247 * This allows for example a virtual keyboard to show a language specific layout.
248 * The @p language argument is a RFC-3066 format language tag.
249 **/
250 void setPreferredLanguage(const QString &language);
251
252 /**
253 * The text direction of input text.
254 *
255 * It is mainly needed for showing input cursor on correct side of the
256 * editor when there is no input yet done and making sure neutral
257 * direction text is laid out properly.
258 * @see textDirectionChnaged
259 **/
260 Qt::LayoutDirection textDirection() const;
261
262 /**
263 * The language of the input text.
264 *
265 * As long as the server has not emitted the language, the code will be empty.
266 *
267 * @returns a RFC-3066 format language tag in utf-8.
268 * @see languageChanged
269 **/
270 QByteArray language() const;
271
272 /**
273 * The cursor position inside the {@link composingText} (as byte offset) relative
274 * to the start of the {@link composingText}.
275 * If index is a negative number no cursor is shown.
276 * @see composingText
277 * @see composingTextChanged
278 **/
279 qint32 composingTextCursorPosition() const;
280
281 /**
282 * The currently being composed text around the {@link composingTextCursorPosition}.
283 * @see composingTextCursorPosition
284 * @see composingTextChanged
285 **/
286 QByteArray composingText() const;
287
288 /**
289 * The fallback text can be used to replace the {@link composingText} in some cases
290 * (for example when losing focus).
291 *
292 * @see composingText
293 * @see composingTextChanged
294 **/
295 QByteArray composingFallbackText() const;
296
297 /**
298 * The commit text to be inserted.
299 *
300 * The commit text might be empty if only text should be deleted or the cursor be moved.
301 * @see cursorPosition
302 * @see anchorPosition
303 * @see deleteSurroundingText
304 * @see committed
305 **/
306 QByteArray commitText() const;
307
308 /**
309 * The cursor position in bytes at which the {@link commitText} should be inserted.
310 * @see committed
311 **/
312 qint32 cursorPosition() const;
313
314 /**
315 * The text between anchorPosition and {@link cursorPosition} should be selected.
316 * @see cursorPosition
317 * @see committed
318 **/
319 qint32 anchorPosition() const;
320
321 /**
322 * Holds the length before and after the cursor position to be deleted.
323 **/
324 struct DeleteSurroundingText {
325 quint32 beforeLength;
326 quint32 afterLength;
327 };
328 /**
329 * @returns The length in bytes which should be deleted around the cursor position
330 * @see committed
331 **/
332 DeleteSurroundingText deleteSurroundingText() const;
333
334Q_SIGNALS:
335 /**
336 * Emitted whenever a Surface is focused on this TextInput.
337 * @see enteredSurface
338 * @see left
339 **/
340 void entered();
341 /**
342 * Emitted whenever a Surface loses the focus on this TextInput.
343 * @see enteredSurface
344 * @see entered
345 **/
346 void left();
347 /**
348 * Emitted whenever the state of the input panel (virtual keyboard changes).
349 * @see isInputPanelVisible
350 **/
351 void inputPanelStateChanged();
352 /**
353 * Emitted whenever the text direction changes.
354 * @see textDirection
355 **/
356 void textDirectionChanged();
357 /**
358 * Emitted whenever the language changes.
359 * @see language
360 **/
361 void languageChanged();
362
363 /**
364 * Emitted when a key event was sent.
365 * Key events are not used for normal text input operations, but for specific key symbols
366 * which are not composable through text.
367 *
368 * @param xkbKeySym The XKB key symbol, not a key code
369 * @param state Whether the event represents a press or release event
370 * @param modifiers The hold modifiers on this event
371 * @param time Timestamp of this event
372 **/
373 void keyEvent(quint32 xkbKeySym, KWayland::Client::TextInput::KeyState state, Qt::KeyboardModifiers modifiers, quint32 time);
374
375 /**
376 * Emitted whenever the composing text and related states changed.
377 * @see composingText
378 * @see composingTextCursorPosition
379 * @see composingFallbackText
380 **/
381 void composingTextChanged();
382
383 /**
384 * Emitted when the currently composing text got committed.
385 * The {@link commitText} should get inserted at the {@link cursorPosition} and
386 * the text around {@link deleteSurroundingText} should be deleted.
387 *
388 * @see commitText
389 * @see cursorPosition
390 * @see anchorPosition
391 * @see deleteSurroundingText
392 **/
393 void committed();
394
395protected:
396 class Private;
397 QScopedPointer<Private> d;
398 explicit TextInput(Private *p, QObject *parent = nullptr);
399};
400
401/**
402 * @brief Manager class for the TextInputManager interfaces.
403 *
404 * The TextInputManager supports multiple interfaces:
405 * @li wl_text_input_manager
406 * @li zwp_text_input_manager_v2
407 *
408 * Due to that it is different to other manager classes. It can only be created through
409 * the corresponding factory method in Registry. A manual setup is not directly possible.
410 *
411 * The only task of a TextInputManager is to create TextInput for a given Seat.
412 *
413 * @since 5.23
414 **/
415class KWAYLANDCLIENT_EXPORT TextInputManager : public QObject
416{
417 Q_OBJECT
418public:
419 ~TextInputManager() override;
420
421 /**
422 * Setup this TextInputManager to manage the @p textinputmanagerunstablev0.
423 * When using Registry::createTextInputManager there is no need to call this
424 * method.
425 **/
426 void setup(wl_text_input_manager *textinputmanagerunstablev0);
427 /**
428 * Setup this TextInputManager to manage the @p textinputmanagerunstablev0.
429 * When using Registry::createTextInputManager there is no need to call this
430 * method.
431 **/
432 void setup(zwp_text_input_manager_v2 *textinputmanagerunstablev2);
433 /**
434 * @returns @c true if managing a resource.
435 **/
436 bool isValid() const;
437 /**
438 * Releases the interface.
439 * After the interface has been released the TextInputManager instance is no
440 * longer valid and can be setup with another interface.
441 **/
442 void release();
443 /**
444 * Destroys the data held by this TextInputManager.
445 * This method is supposed to be used when the connection to the Wayland
446 * server goes away. If the connection is not valid anymore, it's not
447 * possible to call release anymore as that calls into the Wayland
448 * connection and the call would fail. This method cleans up the data, so
449 * that the instance can be deleted or set up to a new interface
450 * once there is a new connection available.
451 *
452 * This method is automatically invoked when the Registry which created this
453 * TextInput gets destroyed.
454 *
455 * @see release
456 **/
457 void destroy();
458
459 /**
460 * Sets the @p queue to use for creating objects with this TextInputManager.
461 **/
462 void setEventQueue(EventQueue *queue);
463 /**
464 * @returns The event queue to use for creating objects with this TextInputManager.
465 **/
466 EventQueue *eventQueue();
467
468 /**
469 * Creates a TextInput for the @p seat.
470 *
471 * @param seat The Seat to create the TextInput for
472 * @param parent The parent to use for the TextInput
473 **/
474 TextInput *createTextInput(Seat *seat, QObject *parent = nullptr);
475
476 /**
477 * @returns @c null if not for a wl_text_input_manager
478 **/
479 operator wl_text_input_manager *();
480 /**
481 * @returns @c null if not for a wl_text_input_manager
482 **/
483 operator wl_text_input_manager *() const;
484 /**
485 * @returns @c null if not for a zwp_text_input_manager_v2
486 **/
487 operator zwp_text_input_manager_v2 *();
488 /**
489 * @returns @c null if not for a zwp_text_input_manager_v2
490 **/
491 operator zwp_text_input_manager_v2 *() const;
492
493Q_SIGNALS:
494 /**
495 * The corresponding global for this interface on the Registry got removed.
496 *
497 * This signal gets only emitted if the TextInputManager got created by
498 * Registry::createTextInputManager
499 **/
500 void removed();
501
502protected:
503 class Private;
504 explicit TextInputManager(Private *p, QObject *parent = nullptr);
505
506 QScopedPointer<Private> d;
507};
508
509Q_DECLARE_OPERATORS_FOR_FLAGS(TextInput::ContentHints)
510
511}
512}
513
514Q_DECLARE_METATYPE(KWayland::Client::TextInput::KeyState)
515Q_DECLARE_METATYPE(KWayland::Client::TextInput::ContentHint)
516Q_DECLARE_METATYPE(KWayland::Client::TextInput::ContentPurpose)
517Q_DECLARE_METATYPE(KWayland::Client::TextInput::ContentHints)
518
519#endif
520

source code of kwayland/src/client/textinput.h