KWayland

textinput_v0.cpp
1 /*
2  SPDX-FileCopyrightText: 2016 Martin Gräßlin <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6 #include "event_queue.h"
7 #include "seat.h"
8 #include "surface.h"
9 #include "textinput_p.h"
10 #include "wayland_pointer_p.h"
11 
12 #include <wayland-text-input-v0-client-protocol.h>
13 
14 namespace KWayland
15 {
16 namespace Client
17 {
18 class TextInputUnstableV0::Private : public TextInput::Private
19 {
20 public:
21  Private(TextInputUnstableV0 *q, Seat *seat);
22 
23  void setup(wl_text_input *textinputmanagerunstablev0);
24 
25  bool isValid() const override;
26  void enable(Surface *surface) override;
27  void disable(Surface *surface) override;
28  void showInputPanel() override;
29  void hideInputPanel() override;
30  void setCursorRectangle(const QRect &rect) override;
31  void setPreferredLanguage(const QString &lang) override;
32  void setSurroundingText(const QString &text, quint32 cursor, quint32 anchor) override;
33  void reset() override;
34  void setContentType(ContentHints hint, ContentPurpose purpose) override;
35 
36  WaylandPointer<wl_text_input, wl_text_input_destroy> textinputunstablev0;
37 
38 private:
39  static void enterCallaback(void *data, wl_text_input *wl_text_input, wl_surface *surface);
40  static void leaveCallback(void *data, wl_text_input *wl_text_input);
41  static void modifiersMapCallback(void *data, wl_text_input *wl_text_input, wl_array *map);
42  static void inputPanelStateCallback(void *data, wl_text_input *wl_text_input, uint32_t state);
43  static void preeditStringCallback(void *data, wl_text_input *wl_text_input, uint32_t serial, const char *text, const char *commit);
44  static void preeditStylingCallback(void *data, wl_text_input *wl_text_input, uint32_t index, uint32_t length, uint32_t style);
45  static void preeditCursorCallback(void *data, wl_text_input *wl_text_input, int32_t index);
46  static void commitStringCallback(void *data, wl_text_input *wl_text_input, uint32_t serial, const char *text);
47  static void cursorPositionCallback(void *data, wl_text_input *wl_text_input, int32_t index, int32_t anchor);
48  static void deleteSurroundingTextCallback(void *data, wl_text_input *wl_text_input, int32_t index, uint32_t length);
49  static void keysymCallback(void *data, wl_text_input *wl_text_input, uint32_t serial, uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers);
50  static void languageCallback(void *data, wl_text_input *wl_text_input, uint32_t serial, const char *language);
51  static void textDirectionCallback(void *data, wl_text_input *wl_text_input, uint32_t serial, uint32_t direction);
52 
53  TextInputUnstableV0 *q;
54 
55  static const wl_text_input_listener s_listener;
56 };
57 
58 const wl_text_input_listener TextInputUnstableV0::Private::s_listener = {enterCallaback,
59  leaveCallback,
60  modifiersMapCallback,
61  inputPanelStateCallback,
62  preeditStringCallback,
63  preeditStylingCallback,
64  preeditCursorCallback,
65  commitStringCallback,
66  cursorPositionCallback,
67  deleteSurroundingTextCallback,
68  keysymCallback,
69  languageCallback,
70  textDirectionCallback};
71 
72 void TextInputUnstableV0::Private::enterCallaback(void *data, wl_text_input *wl_text_input, wl_surface *surface)
73 {
74  auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data);
75  Q_ASSERT(t->textinputunstablev0 == wl_text_input);
76  t->enteredSurface = Surface::get(surface);
77  Q_EMIT t->q->entered();
78 }
79 
80 void TextInputUnstableV0::Private::leaveCallback(void *data, wl_text_input *wl_text_input)
81 {
82  auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data);
83  Q_ASSERT(t->textinputunstablev0 == wl_text_input);
84  t->enteredSurface = nullptr;
85  Q_EMIT t->q->left();
86 }
87 
88 void TextInputUnstableV0::Private::modifiersMapCallback(void *data, wl_text_input *wl_text_input, wl_array *map)
89 {
90  Q_UNUSED(map)
91  auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data);
92  Q_ASSERT(t->textinputunstablev0 == wl_text_input);
93  // TODO: implement
94 }
95 
96 void TextInputUnstableV0::Private::inputPanelStateCallback(void *data, wl_text_input *wl_text_input, uint32_t state)
97 {
98  auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data);
99  Q_ASSERT(t->textinputunstablev0 == wl_text_input);
100  if (t->inputPanelVisible != state) {
101  t->inputPanelVisible = state;
102  Q_EMIT t->q->inputPanelStateChanged();
103  }
104 }
105 
106 void TextInputUnstableV0::Private::preeditStringCallback(void *data, wl_text_input *wl_text_input, uint32_t serial, const char *text, const char *commit)
107 {
108  Q_UNUSED(serial)
109  auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data);
110  Q_ASSERT(t->textinputunstablev0 == wl_text_input);
111  t->pendingPreEdit.commitText = QByteArray(commit);
112  t->pendingPreEdit.text = QByteArray(text);
113  if (!t->pendingPreEdit.cursorSet) {
114  t->pendingPreEdit.cursor = t->pendingPreEdit.text.length();
115  }
116  t->currentPreEdit = t->pendingPreEdit;
117  t->pendingPreEdit = TextInput::Private::PreEdit();
118  Q_EMIT t->q->composingTextChanged();
119 }
120 
121 void TextInputUnstableV0::Private::preeditStylingCallback(void *data, wl_text_input *wl_text_input, uint32_t index, uint32_t length, uint32_t style)
122 {
123  Q_UNUSED(index)
124  Q_UNUSED(length)
125  Q_UNUSED(style)
126  // TODO: implement
127  auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data);
128  Q_ASSERT(t->textinputunstablev0 == wl_text_input);
129 }
130 
131 void TextInputUnstableV0::Private::preeditCursorCallback(void *data, wl_text_input *wl_text_input, int32_t index)
132 {
133  auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data);
134  Q_ASSERT(t->textinputunstablev0 == wl_text_input);
135  t->pendingPreEdit.cursor = index;
136  t->pendingPreEdit.cursorSet = true;
137 }
138 
139 void TextInputUnstableV0::Private::commitStringCallback(void *data, wl_text_input *wl_text_input, uint32_t serial, const char *text)
140 {
141  Q_UNUSED(serial)
142  auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data);
143  Q_ASSERT(t->textinputunstablev0 == wl_text_input);
144  t->pendingCommit.text = QByteArray(text);
145  t->currentCommit = t->pendingCommit;
146  // TODO: what are the proper values it should be set to?
147  t->pendingCommit = TextInput::Private::Commit();
148  t->pendingCommit.deleteSurrounding.beforeLength = 0;
149  t->pendingCommit.deleteSurrounding.afterLength = 0;
150  Q_EMIT t->q->committed();
151 }
152 
153 void TextInputUnstableV0::Private::cursorPositionCallback(void *data, wl_text_input *wl_text_input, int32_t index, int32_t anchor)
154 {
155  auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data);
156  Q_ASSERT(t->textinputunstablev0 == wl_text_input);
157  t->pendingCommit.cursor = index;
158  t->pendingCommit.anchor = anchor;
159 }
160 
161 void TextInputUnstableV0::Private::deleteSurroundingTextCallback(void *data, wl_text_input *wl_text_input, int32_t index, uint32_t length)
162 {
163  auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data);
164  Q_ASSERT(t->textinputunstablev0 == wl_text_input);
165  t->pendingCommit.deleteSurrounding.beforeLength = qAbs(index);
166  t->pendingCommit.deleteSurrounding.afterLength = length - t->pendingCommit.deleteSurrounding.beforeLength;
167 }
168 
169 void TextInputUnstableV0::Private::keysymCallback(void *data,
170  wl_text_input *wl_text_input,
171  uint32_t serial,
172  uint32_t time,
173  uint32_t sym,
174  uint32_t wlState,
175  uint32_t modifiers)
176 {
177  Q_UNUSED(serial)
178  // TODO: add support for modifiers
179  Q_UNUSED(modifiers)
180  auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data);
181  Q_ASSERT(t->textinputunstablev0 == wl_text_input);
182  TextInput::KeyState state;
183  switch (wlState) {
184  case WL_KEYBOARD_KEY_STATE_RELEASED:
185  state = TextInput::KeyState::Released;
186  break;
187  case WL_KEYBOARD_KEY_STATE_PRESSED:
188  state = TextInput::KeyState::Pressed;
189  break;
190  default:
191  // invalid
192  return;
193  }
194  Q_EMIT t->q->keyEvent(sym, state, Qt::KeyboardModifiers(), time);
195 }
196 
197 void TextInputUnstableV0::Private::languageCallback(void *data, wl_text_input *wl_text_input, uint32_t serial, const char *language)
198 {
199  Q_UNUSED(serial)
200  auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data);
201  Q_ASSERT(t->textinputunstablev0 == wl_text_input);
202  if (qstrcmp(t->language, language) != 0) {
203  t->language = QByteArray(language);
204  Q_EMIT t->q->languageChanged();
205  }
206 }
207 
208 void TextInputUnstableV0::Private::textDirectionCallback(void *data, wl_text_input *wl_text_input, uint32_t serial, uint32_t wlDirection)
209 {
210  Q_UNUSED(serial)
211  auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data);
212  Q_ASSERT(t->textinputunstablev0 == wl_text_input);
213  Qt::LayoutDirection direction;
214  switch (wlDirection) {
215  case WL_TEXT_INPUT_TEXT_DIRECTION_LTR:
216  direction = Qt::LeftToRight;
217  break;
218  case WL_TEXT_INPUT_TEXT_DIRECTION_RTL:
219  direction = Qt::RightToLeft;
220  break;
221  case WL_TEXT_INPUT_TEXT_DIRECTION_AUTO:
222  direction = Qt::LayoutDirectionAuto;
223  break;
224  default:
225  // invalid
226  return;
227  }
228  if (direction != t->textDirection) {
229  t->textDirection = direction;
230  Q_EMIT t->q->textDirectionChanged();
231  }
232 }
233 
234 TextInputUnstableV0::Private::Private(TextInputUnstableV0 *q, Seat *seat)
235  : TextInput::Private(seat)
236  , q(q)
237 {
238 }
239 
240 void TextInputUnstableV0::Private::setup(wl_text_input *ti)
241 {
242  Q_ASSERT(ti);
243  Q_ASSERT(!textinputunstablev0);
244  textinputunstablev0.setup(ti);
245  wl_text_input_add_listener(ti, &s_listener, this);
246 }
247 
248 bool TextInputUnstableV0::Private::isValid() const
249 {
250  return textinputunstablev0.isValid();
251 }
252 
253 void TextInputUnstableV0::Private::enable(Surface *surface)
254 {
255  wl_text_input_activate(textinputunstablev0, *seat, *surface);
256 }
257 
258 void TextInputUnstableV0::Private::disable(Surface *surface)
259 {
260  Q_UNUSED(surface)
261  wl_text_input_deactivate(textinputunstablev0, *seat);
262 }
263 
264 void TextInputUnstableV0::Private::showInputPanel()
265 {
266  wl_text_input_show_input_panel(textinputunstablev0);
267 }
268 
269 void TextInputUnstableV0::Private::hideInputPanel()
270 {
271  wl_text_input_hide_input_panel(textinputunstablev0);
272 }
273 
274 void TextInputUnstableV0::Private::setCursorRectangle(const QRect &rect)
275 {
276  wl_text_input_set_cursor_rectangle(textinputunstablev0, rect.x(), rect.y(), rect.width(), rect.height());
277 }
278 
279 void TextInputUnstableV0::Private::setPreferredLanguage(const QString &lang)
280 {
281  wl_text_input_set_preferred_language(textinputunstablev0, lang.toUtf8().constData());
282 }
283 
284 void TextInputUnstableV0::Private::setSurroundingText(const QString &text, quint32 cursor, quint32 anchor)
285 {
286  const QStringView strView(text);
287 
288  wl_text_input_set_surrounding_text(textinputunstablev0,
289  text.toUtf8().constData(),
290  strView.left(cursor).toUtf8().length(),
291  strView.left(anchor).toUtf8().length());
292 }
293 
294 void TextInputUnstableV0::Private::reset()
295 {
296  wl_text_input_reset(textinputunstablev0);
297 }
298 
299 void TextInputUnstableV0::Private::setContentType(ContentHints hints, ContentPurpose purpose)
300 {
301  uint32_t wlHints = 0;
302  uint32_t wlPurpose = 0;
303  if (hints.testFlag(ContentHint::AutoCompletion)) {
304  wlHints |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
305  }
306  if (hints.testFlag(ContentHint::AutoCorrection)) {
307  wlHints |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_CORRECTION;
308  }
309  if (hints.testFlag(ContentHint::AutoCapitalization)) {
310  wlHints |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION;
311  }
312  if (hints.testFlag(ContentHint::LowerCase)) {
313  wlHints |= WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE;
314  }
315  if (hints.testFlag(ContentHint::UpperCase)) {
316  wlHints |= WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE;
317  }
318  if (hints.testFlag(ContentHint::TitleCase)) {
319  wlHints |= WL_TEXT_INPUT_CONTENT_HINT_TITLECASE;
320  }
321  if (hints.testFlag(ContentHint::HiddenText)) {
322  wlHints |= WL_TEXT_INPUT_CONTENT_HINT_HIDDEN_TEXT;
323  }
324  if (hints.testFlag(ContentHint::SensitiveData)) {
325  wlHints |= WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA;
326  }
327  if (hints.testFlag(ContentHint::Latin)) {
328  wlHints |= WL_TEXT_INPUT_CONTENT_HINT_LATIN;
329  }
330  if (hints.testFlag(ContentHint::MultiLine)) {
331  wlHints |= WL_TEXT_INPUT_CONTENT_HINT_MULTILINE;
332  }
333  switch (purpose) {
334  case ContentPurpose::Normal:
335  wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL;
336  break;
337  case ContentPurpose::Alpha:
338  wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_ALPHA;
339  break;
340  case ContentPurpose::Digits:
341  wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS;
342  break;
343  case ContentPurpose::Number:
344  wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER;
345  break;
346  case ContentPurpose::Phone:
347  wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PHONE;
348  break;
349  case ContentPurpose::Url:
350  wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_URL;
351  break;
352  case ContentPurpose::Email:
353  wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_EMAIL;
354  break;
355  case ContentPurpose::Name:
356  wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NAME;
357  break;
358  case ContentPurpose::Password:
359  wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD;
360  break;
361  case ContentPurpose::Date:
362  wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DATE;
363  break;
364  case ContentPurpose::Time:
365  wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_TIME;
366  break;
367  case ContentPurpose::DateTime:
368  wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DATETIME;
369  break;
370  case ContentPurpose::Terminal:
371  wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_TERMINAL;
372  break;
373  }
374  wl_text_input_set_content_type(textinputunstablev0, wlHints, wlPurpose);
375 }
376 
377 TextInputUnstableV0::TextInputUnstableV0(Seat *seat, QObject *parent)
378  : TextInput(new Private(this, seat), parent)
379 {
380 }
381 
382 TextInputUnstableV0::~TextInputUnstableV0()
383 {
384  release();
385 }
386 
387 TextInputUnstableV0::Private *TextInputUnstableV0::d_func() const
388 {
389  return reinterpret_cast<Private *>(d.data());
390 }
391 
392 void TextInputUnstableV0::setup(wl_text_input *textinputunstablev0)
393 {
394  Q_D();
395  d->setup(textinputunstablev0);
396 }
397 
399 {
400  Q_D();
401  d->textinputunstablev0.release();
402 }
403 
404 void TextInputUnstableV0::destroy()
405 {
406  Q_D();
407  d->textinputunstablev0.destroy();
408 }
409 
410 TextInputUnstableV0::operator wl_text_input *()
411 {
412  Q_D();
413  return d->textinputunstablev0;
414 }
415 
416 TextInputUnstableV0::operator wl_text_input *() const
417 {
418  Q_D();
419  return d->textinputunstablev0;
420 }
421 
422 class TextInputManagerUnstableV0::Private : public TextInputManager::Private
423 {
424 public:
425  Private() = default;
426 
427  void release() override;
428  void destroy() override;
429  bool isValid() override;
430  void setupV0(wl_text_input_manager *ti) override;
431  TextInput *createTextInput(Seat *seat, QObject *parent = nullptr) override;
432  using TextInputManager::Private::operator zwp_text_input_manager_v2 *; // overriding only one overload results in a compiler warning. This tells GCC we're
433  // doing it deliberately
434  operator wl_text_input_manager *() override
435  {
436  return textinputmanagerunstablev0;
437  }
438  operator wl_text_input_manager *() const override
439  {
440  return textinputmanagerunstablev0;
441  }
442 
443  WaylandPointer<wl_text_input_manager, wl_text_input_manager_destroy> textinputmanagerunstablev0;
444 };
445 
447 {
448  textinputmanagerunstablev0.release();
449 }
450 
451 void TextInputManagerUnstableV0::Private::destroy()
452 {
453  textinputmanagerunstablev0.destroy();
454 }
455 
456 bool TextInputManagerUnstableV0::Private::isValid()
457 {
458  return textinputmanagerunstablev0.isValid();
459 }
460 
461 TextInputManagerUnstableV0::TextInputManagerUnstableV0(QObject *parent)
462  : TextInputManager(new Private, parent)
463 {
464 }
465 
466 TextInputManagerUnstableV0::Private *TextInputManagerUnstableV0::d_func() const
467 {
468  return reinterpret_cast<Private *>(d.data());
469 }
470 
471 TextInputManagerUnstableV0::~TextInputManagerUnstableV0()
472 {
473  release();
474 }
475 
476 void TextInputManagerUnstableV0::Private::setupV0(wl_text_input_manager *ti)
477 {
478  Q_ASSERT(ti);
479  Q_ASSERT(!textinputmanagerunstablev0);
480  textinputmanagerunstablev0.setup(ti);
481 }
482 
483 TextInput *TextInputManagerUnstableV0::Private::createTextInput(Seat *seat, QObject *parent)
484 {
485  Q_ASSERT(isValid());
486  TextInputUnstableV0 *t = new TextInputUnstableV0(seat, parent);
487  auto w = wl_text_input_manager_create_text_input(textinputmanagerunstablev0);
488  if (queue) {
489  queue->addProxy(w);
490  }
491  t->setup(w);
492  return t;
493 }
494 
495 }
496 }
virtual void release(quint64 objid)
static Surface * get(wl_surface *native)
Definition: surface.cpp:212
int width() const const
int x() const const
int y() const const
KeyState
The possible states for a keyEvent.
Definition: textinput.h:113
QByteArray toUtf8() const const
int height() const const
const char * constData() const const
bool isValid(QStringView ifopt)
LayoutDirection
KGuiItem reset()
typedef KeyboardModifiers
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Jan 30 2023 03:56:25 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.