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

KDE's Doxygen guidelines are available online.