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 | |
13 | struct wl_text_input; |
14 | struct wl_text_input_manager; |
15 | struct zwp_text_input_manager_v2; |
16 | |
17 | namespace KWayland |
18 | { |
19 | namespace Client |
20 | { |
21 | class EventQueue; |
22 | class Surface; |
23 | class 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 | **/ |
38 | class KWAYLANDCLIENT_EXPORT TextInput : public QObject |
39 | { |
40 | Q_OBJECT |
41 | public: |
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 | |
334 | Q_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 | |
395 | protected: |
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 | **/ |
415 | class KWAYLANDCLIENT_EXPORT TextInputManager : public QObject |
416 | { |
417 | Q_OBJECT |
418 | public: |
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 | |
493 | Q_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 | |
502 | protected: |
503 | class Private; |
504 | explicit TextInputManager(Private *p, QObject *parent = nullptr); |
505 | |
506 | QScopedPointer<Private> d; |
507 | }; |
508 | |
509 | Q_DECLARE_OPERATORS_FOR_FLAGS(TextInput::ContentHints) |
510 | |
511 | } |
512 | } |
513 | |
514 | Q_DECLARE_METATYPE(KWayland::Client::TextInput::KeyState) |
515 | Q_DECLARE_METATYPE(KWayland::Client::TextInput::ContentHint) |
516 | Q_DECLARE_METATYPE(KWayland::Client::TextInput::ContentPurpose) |
517 | Q_DECLARE_METATYPE(KWayland::Client::TextInput::ContentHints) |
518 | |
519 | #endif |
520 | |