KWayland

textinput_interface_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 "display.h"
7 #include "resource_p.h"
8 #include "seat_interface_p.h"
9 #include "surface_interface.h"
10 #include "textinput_interface_p.h"
11 
12 #include <wayland-text-server-protocol.h>
13 
14 namespace KWayland
15 {
16 namespace Server
17 {
18 class TextInputUnstableV0Interface::Private : public TextInputInterface::Private
19 {
20 public:
21  Private(TextInputInterface *q, TextInputManagerUnstableV0Interface *c, wl_resource *parentResource);
22  ~Private() override;
23 
24  void activate(SeatInterface *seat, SurfaceInterface *surface);
25  void deactivate();
26 
27  void sendEnter(SurfaceInterface *surface, quint32 serial) override;
28  void sendLeave(quint32 serial, SurfaceInterface *surface) override;
29  void preEdit(const QByteArray &text, const QByteArray &commit) override;
30  void commit(const QByteArray &text) override;
31  void deleteSurroundingText(quint32 beforeLength, quint32 afterLength) override;
32  void setTextDirection(Qt::LayoutDirection direction) override;
33  void setPreEditCursor(qint32 index) override;
34  void setCursorPosition(qint32 index, qint32 anchor) override;
35  void keysymPressed(quint32 keysym, Qt::KeyboardModifiers modifiers) override;
36  void keysymReleased(quint32 keysym, Qt::KeyboardModifiers modifiers) override;
37  TextInputInterfaceVersion interfaceVersion() const override
38  {
40  }
41  void sendInputPanelState() override;
42  void sendLanguage() override;
43 
44 private:
45  static const struct wl_text_input_interface s_interface;
46  TextInputUnstableV0Interface *q_func()
47  {
48  return reinterpret_cast<TextInputUnstableV0Interface *>(q);
49  }
50 
51  static void activateCallback(wl_client *client, wl_resource *resource, wl_resource *seat, wl_resource *surface);
52  static void deactivateCallback(wl_client *client, wl_resource *resource, wl_resource *seat);
53  static void resetCallback(wl_client *client, wl_resource *resource);
54  static void setSurroundingTextUintCallback(wl_client *client, wl_resource *resource, const char *text, uint32_t cursor, uint32_t anchor);
55  static void commitStateCallback(wl_client *client, wl_resource *resource, uint32_t serial);
56  static void invokeActionCallback(wl_client *client, wl_resource *resource, uint32_t button, uint32_t index);
57 
58  // helpers
59  TextInputInterface::ContentHints convertContentHint(uint32_t hint) const override;
60  TextInputInterface::ContentPurpose convertContentPurpose(uint32_t purpose) const override;
61 
62  quint32 latestState = 0;
63 };
64 
65 #ifndef K_DOXYGEN
66 const struct wl_text_input_interface TextInputUnstableV0Interface::Private::s_interface = {activateCallback,
67  deactivateCallback,
68  showInputPanelCallback,
69  hideInputPanelCallback,
70  resetCallback,
71  setSurroundingTextUintCallback,
72  setContentTypeCallback,
73  setCursorRectangleCallback,
74  setPreferredLanguageCallback,
75  commitStateCallback,
76  invokeActionCallback};
77 #endif
78 
79 void TextInputUnstableV0Interface::Private::activate(SeatInterface *seat, SurfaceInterface *s)
80 {
81  surface = QPointer<SurfaceInterface>(s);
82  enabled = true;
83  Q_EMIT q_func()->enabledChanged();
84  Q_EMIT q_func()->requestActivate(seat, surface);
85 }
86 
87 void TextInputUnstableV0Interface::Private::deactivate()
88 {
89  surface.clear();
90  enabled = false;
91  Q_EMIT q_func()->enabledChanged();
92 }
93 
94 void TextInputUnstableV0Interface::Private::sendEnter(SurfaceInterface *surface, quint32 serial)
95 {
96  Q_UNUSED(serial)
97  if (!resource) {
98  return;
99  }
100  wl_text_input_send_enter(resource, surface->resource());
101 }
102 
103 void TextInputUnstableV0Interface::Private::sendLeave(quint32 serial, SurfaceInterface *surface)
104 {
105  Q_UNUSED(serial)
106  Q_UNUSED(surface)
107  if (!resource) {
108  return;
109  }
110  wl_text_input_send_leave(resource);
111 }
112 
113 void TextInputUnstableV0Interface::Private::preEdit(const QByteArray &text, const QByteArray &commit)
114 {
115  if (!resource) {
116  return;
117  }
118  wl_text_input_send_preedit_string(resource, latestState, text.constData(), commit.constData());
119 }
120 
121 void TextInputUnstableV0Interface::Private::commit(const QByteArray &text)
122 {
123  if (!resource) {
124  return;
125  }
126  wl_text_input_send_commit_string(resource, latestState, text.constData());
127 }
128 
129 void TextInputUnstableV0Interface::Private::keysymPressed(quint32 keysym, Qt::KeyboardModifiers modifiers)
130 {
131  Q_UNUSED(modifiers)
132  if (!resource) {
133  return;
134  }
135  wl_text_input_send_keysym(resource, latestState, seat ? seat->timestamp() : 0, keysym, WL_KEYBOARD_KEY_STATE_PRESSED, 0);
136 }
137 
138 void TextInputUnstableV0Interface::Private::keysymReleased(quint32 keysym, Qt::KeyboardModifiers modifiers)
139 {
140  Q_UNUSED(modifiers)
141  if (!resource) {
142  return;
143  }
144  wl_text_input_send_keysym(resource, latestState, seat ? seat->timestamp() : 0, keysym, WL_KEYBOARD_KEY_STATE_RELEASED, 0);
145 }
146 
147 void TextInputUnstableV0Interface::Private::deleteSurroundingText(quint32 beforeLength, quint32 afterLength)
148 {
149  if (!resource) {
150  return;
151  }
152  wl_text_input_send_delete_surrounding_text(resource, -1 * beforeLength, beforeLength + afterLength);
153 }
154 
155 void TextInputUnstableV0Interface::Private::setCursorPosition(qint32 index, qint32 anchor)
156 {
157  if (!resource) {
158  return;
159  }
160  wl_text_input_send_cursor_position(resource, index, anchor);
161 }
162 
163 void TextInputUnstableV0Interface::Private::setTextDirection(Qt::LayoutDirection direction)
164 {
165  if (!resource) {
166  return;
167  }
168  wl_text_input_text_direction wlDirection;
169  switch (direction) {
170  case Qt::LeftToRight:
171  wlDirection = WL_TEXT_INPUT_TEXT_DIRECTION_LTR;
172  break;
173  case Qt::RightToLeft:
174  wlDirection = WL_TEXT_INPUT_TEXT_DIRECTION_RTL;
175  break;
177  wlDirection = WL_TEXT_INPUT_TEXT_DIRECTION_AUTO;
178  break;
179  default:
180  Q_UNREACHABLE();
181  break;
182  }
183  wl_text_input_send_text_direction(resource, latestState, wlDirection);
184 }
185 
186 void TextInputUnstableV0Interface::Private::setPreEditCursor(qint32 index)
187 {
188  if (!resource) {
189  return;
190  }
191  wl_text_input_send_preedit_cursor(resource, index);
192 }
193 
194 void TextInputUnstableV0Interface::Private::sendInputPanelState()
195 {
196  if (!resource) {
197  return;
198  }
199  wl_text_input_send_input_panel_state(resource, inputPanelVisible);
200 }
201 
202 void TextInputUnstableV0Interface::Private::sendLanguage()
203 {
204  if (!resource) {
205  return;
206  }
207  wl_text_input_send_language(resource, latestState, language.constData());
208 }
209 
210 TextInputUnstableV0Interface::Private::Private(TextInputInterface *q, TextInputManagerUnstableV0Interface *c, wl_resource *parentResource)
211  : TextInputInterface::Private(q, c, parentResource, &wl_text_input_interface, &s_interface)
212 {
213 }
214 
215 TextInputUnstableV0Interface::Private::~Private() = default;
216 
217 void TextInputUnstableV0Interface::Private::activateCallback(wl_client *client, wl_resource *resource, wl_resource *seat, wl_resource *surface)
218 {
219  auto p = cast<Private>(resource);
220  Q_ASSERT(*p->client == client);
221  p->activate(SeatInterface::get(seat), SurfaceInterface::get(surface));
222 }
223 
224 void TextInputUnstableV0Interface::Private::deactivateCallback(wl_client *client, wl_resource *resource, wl_resource *seat)
225 {
226  Q_UNUSED(seat)
227  auto p = cast<Private>(resource);
228  Q_ASSERT(*p->client == client);
229  p->deactivate();
230 }
231 
232 void TextInputUnstableV0Interface::Private::resetCallback(wl_client *client, wl_resource *resource)
233 {
234  auto p = cast<Private>(resource);
235  Q_ASSERT(*p->client == client);
236  Q_EMIT p->q_func()->requestReset();
237 }
238 
239 void TextInputUnstableV0Interface::Private::setSurroundingTextUintCallback(wl_client *client,
240  wl_resource *resource,
241  const char *text,
242  uint32_t cursor,
243  uint32_t anchor)
244 {
245  setSurroundingTextCallback(client, resource, text, cursor, anchor);
246 }
247 
248 void TextInputUnstableV0Interface::Private::commitStateCallback(wl_client *client, wl_resource *resource, uint32_t serial)
249 {
250  auto p = cast<Private>(resource);
251  Q_ASSERT(*p->client == client);
252  p->latestState = serial;
253 }
254 
255 void TextInputUnstableV0Interface::Private::invokeActionCallback(wl_client *client, wl_resource *resource, uint32_t button, uint32_t index)
256 {
257  Q_UNUSED(button)
258  Q_UNUSED(index)
259  // TODO: implement
260  auto p = cast<Private>(resource);
261  Q_ASSERT(*p->client == client);
262 }
263 
264 TextInputInterface::ContentHints TextInputUnstableV0Interface::Private::convertContentHint(uint32_t hint) const
265 {
266  const auto hints = wl_text_input_content_hint(hint);
267  TextInputInterface::ContentHints ret = TextInputInterface::ContentHint::None;
268 
269  if (hints & WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION) {
271  }
272  if (hints & WL_TEXT_INPUT_CONTENT_HINT_AUTO_CORRECTION) {
274  }
275  if (hints & WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION) {
277  }
278  if (hints & WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE) {
280  }
281  if (hints & WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE) {
283  }
284  if (hints & WL_TEXT_INPUT_CONTENT_HINT_TITLECASE) {
286  }
287  if (hints & WL_TEXT_INPUT_CONTENT_HINT_HIDDEN_TEXT) {
289  }
290  if (hints & WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA) {
292  }
293  if (hints & WL_TEXT_INPUT_CONTENT_HINT_LATIN) {
295  }
296  if (hints & WL_TEXT_INPUT_CONTENT_HINT_MULTILINE) {
298  }
299  return ret;
300 }
301 
302 TextInputInterface::ContentPurpose TextInputUnstableV0Interface::Private::convertContentPurpose(uint32_t purpose) const
303 {
304  const auto wlPurpose = wl_text_input_content_purpose(purpose);
305 
306  switch (wlPurpose) {
307  case WL_TEXT_INPUT_CONTENT_PURPOSE_ALPHA:
309  case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
311  case WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER:
313  case WL_TEXT_INPUT_CONTENT_PURPOSE_PHONE:
315  case WL_TEXT_INPUT_CONTENT_PURPOSE_URL:
317  case WL_TEXT_INPUT_CONTENT_PURPOSE_EMAIL:
319  case WL_TEXT_INPUT_CONTENT_PURPOSE_NAME:
321  case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD:
323  case WL_TEXT_INPUT_CONTENT_PURPOSE_DATE:
325  case WL_TEXT_INPUT_CONTENT_PURPOSE_TIME:
327  case WL_TEXT_INPUT_CONTENT_PURPOSE_DATETIME:
329  case WL_TEXT_INPUT_CONTENT_PURPOSE_TERMINAL:
331  case WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL:
332  default:
334  }
335 }
336 
337 TextInputUnstableV0Interface::TextInputUnstableV0Interface(TextInputManagerUnstableV0Interface *parent, wl_resource *parentResource)
338  : TextInputInterface(new Private(this, parent, parentResource))
339 {
340 }
341 
342 TextInputUnstableV0Interface::~TextInputUnstableV0Interface() = default;
343 
344 class TextInputManagerUnstableV0Interface::Private : public TextInputManagerInterface::Private
345 {
346 public:
347  Private(TextInputManagerUnstableV0Interface *q, Display *d);
348 
349 private:
350  void bind(wl_client *client, uint32_t version, uint32_t id) override;
351 
352  static void unbind(wl_resource *resource);
353  static Private *cast(wl_resource *r)
354  {
355  return reinterpret_cast<Private *>(wl_resource_get_user_data(r));
356  }
357 
358  static void createTextInputCallback(wl_client *client, wl_resource *resource, uint32_t id);
359 
360  TextInputManagerUnstableV0Interface *q;
361  static const struct wl_text_input_manager_interface s_interface;
362  static const quint32 s_version;
363 };
364 const quint32 TextInputManagerUnstableV0Interface::Private::s_version = 1;
365 
366 #ifndef K_DOXYGEN
367 const struct wl_text_input_manager_interface TextInputManagerUnstableV0Interface::Private::s_interface = {createTextInputCallback};
368 #endif
369 
370 void TextInputManagerUnstableV0Interface::Private::createTextInputCallback(wl_client *client, wl_resource *resource, uint32_t id)
371 {
372  auto m = cast(resource);
373  auto *t = new TextInputUnstableV0Interface(m->q, resource);
374  m->inputs << t;
375  QObject::connect(t, &QObject::destroyed, m->q, [t, m] {
376  m->inputs.removeAll(t);
377  });
378  QObject::connect(t, &TextInputUnstableV0Interface::requestActivate, m->q, [t](SeatInterface *seat) {
379  // TODO: disallow for other seat
380  seat->d_func()->registerTextInput(t);
381  t->d_func()->seat = seat;
382  });
383  t->d->create(m->display->getConnection(client), version, id);
384 }
385 
386 TextInputManagerInterface::Private::Private(TextInputInterfaceVersion interfaceVersion,
387  TextInputManagerInterface *q,
388  Display *d,
389  const wl_interface *interface,
390  quint32 version)
391  : Global::Private(d, interface, version)
392  , interfaceVersion(interfaceVersion)
393  , q(q)
394 {
395 }
396 
397 TextInputManagerUnstableV0Interface::Private::Private(TextInputManagerUnstableV0Interface *q, Display *d)
398  : TextInputManagerInterface::Private(TextInputInterfaceVersion::UnstableV0, q, d, &wl_text_input_manager_interface, s_version)
399  , q(q)
400 {
401 }
402 
403 void TextInputManagerUnstableV0Interface::Private::bind(wl_client *client, uint32_t version, uint32_t id)
404 {
405  auto c = display->getConnection(client);
406  wl_resource *resource = c->createResource(&wl_text_input_manager_interface, qMin(version, s_version), id);
407  if (!resource) {
408  wl_client_post_no_memory(client);
409  return;
410  }
411  wl_resource_set_implementation(resource, &s_interface, this, unbind);
412  // TODO: should we track?
413 }
414 
415 void TextInputManagerUnstableV0Interface::Private::unbind(wl_resource *resource)
416 {
417  Q_UNUSED(resource)
418  // TODO: implement?
419 }
420 
421 TextInputManagerUnstableV0Interface::TextInputManagerUnstableV0Interface(Display *display, QObject *parent)
422  : TextInputManagerInterface(new Private(this, display), parent)
423 {
424 }
425 
426 TextInputManagerUnstableV0Interface::~TextInputManagerUnstableV0Interface() = default;
427 
428 }
429 }
@ UnstableV0
wl_text_input as the non-standardized version
@ TitleCase
prefer casing for titles and headings (can be language dependent)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
static SurfaceInterface * get(wl_resource *native)
@ SensitiveData
typed text should not be stored
void destroyed(QObject *obj)
ContentPurpose
The ContentPurpose allows to specify the primary purpose of a text input.
@ Latin
just latin characters should be entered
@ Number
input a number (including decimal separator and sign)
@ Normal
default input, allowing all characters
KDB_EXPORT KDbVersionInfo version()
const char * constData() const const
LayoutDirection
@ AutoCapitalization
switch to uppercase letters at the start of a sentence
TextInputInterfaceVersion
Enum describing the different InterfaceVersion encapsulated in this implementation.
typedef KeyboardModifiers
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Oct 3 2023 04:08:58 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.