KWayland

textinput_interface_v2.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-input-unstable-v2-server-protocol.h>
13 
14 namespace KWayland
15 {
16 namespace Server
17 {
18 class TextInputUnstableV2Interface::Private : public TextInputInterface::Private
19 {
20 public:
21  Private(TextInputInterface *q, TextInputManagerUnstableV2Interface *c, wl_resource *parentResource);
22  ~Private() override;
23 
24  void sendEnter(SurfaceInterface *surface, quint32 serial) override;
25  void sendLeave(quint32 serial, SurfaceInterface *surface) override;
26  void preEdit(const QByteArray &text, const QByteArray &commit) override;
27  void commit(const QByteArray &text) override;
28  void deleteSurroundingText(quint32 beforeLength, quint32 afterLength) override;
29  void setTextDirection(Qt::LayoutDirection direction) override;
30  void setPreEditCursor(qint32 index) override;
31  void setCursorPosition(qint32 index, qint32 anchor) override;
32  void keysymPressed(quint32 keysym, Qt::KeyboardModifiers modifiers) override;
33  void keysymReleased(quint32 keysym, Qt::KeyboardModifiers modifiers) override;
34  TextInputInterfaceVersion interfaceVersion() const override
35  {
37  }
38  void sendInputPanelState() override;
39  void sendLanguage() override;
40 
41 private:
42  static const struct zwp_text_input_v2_interface s_interface;
43  TextInputUnstableV2Interface *q_func()
44  {
45  return reinterpret_cast<TextInputUnstableV2Interface *>(q);
46  }
47 
48  static void enableCallback(wl_client *client, wl_resource *resource, wl_resource *surface);
49  static void disableCallback(wl_client *client, wl_resource *resource, wl_resource *surface);
50  static void updateStateCallback(wl_client *client, wl_resource *resource, uint32_t serial, uint32_t reason);
51 
52  // helpers
53  TextInputInterface::ContentHints convertContentHint(uint32_t hint) const override;
54  TextInputInterface::ContentPurpose convertContentPurpose(uint32_t purpose) const override;
55 
56  void enable(SurfaceInterface *s);
57  void disable();
58 };
59 
60 #ifndef K_DOXYGEN
61 const struct zwp_text_input_v2_interface TextInputUnstableV2Interface::Private::s_interface = {resourceDestroyedCallback,
62  enableCallback,
63  disableCallback,
64  showInputPanelCallback,
65  hideInputPanelCallback,
66  setSurroundingTextCallback,
67  setContentTypeCallback,
68  setCursorRectangleCallback,
69  setPreferredLanguageCallback,
70  updateStateCallback};
71 #endif
72 
73 void TextInputUnstableV2Interface::Private::enable(SurfaceInterface *s)
74 {
75  surface = QPointer<SurfaceInterface>(s);
76  enabled = true;
77  Q_EMIT q_func()->enabledChanged();
78 }
79 
80 void TextInputUnstableV2Interface::Private::disable()
81 {
82  surface.clear();
83  enabled = false;
84  Q_EMIT q_func()->enabledChanged();
85 }
86 
87 void TextInputUnstableV2Interface::Private::sendEnter(SurfaceInterface *surface, quint32 serial)
88 {
89  if (!resource || !surface || !surface->resource()) {
90  return;
91  }
92  zwp_text_input_v2_send_enter(resource, serial, surface->resource());
93 }
94 
95 void TextInputUnstableV2Interface::Private::sendLeave(quint32 serial, SurfaceInterface *surface)
96 {
97  if (!resource || !surface || !surface->resource()) {
98  return;
99  }
100  zwp_text_input_v2_send_leave(resource, serial, surface->resource());
101 }
102 
103 void TextInputUnstableV2Interface::Private::preEdit(const QByteArray &text, const QByteArray &commit)
104 {
105  if (!resource) {
106  return;
107  }
108  zwp_text_input_v2_send_preedit_string(resource, text.constData(), commit.constData());
109 }
110 
111 void TextInputUnstableV2Interface::Private::commit(const QByteArray &text)
112 {
113  if (!resource) {
114  return;
115  }
116  zwp_text_input_v2_send_commit_string(resource, text.constData());
117 }
118 
119 void TextInputUnstableV2Interface::Private::keysymPressed(quint32 keysym, Qt::KeyboardModifiers modifiers)
120 {
121  Q_UNUSED(modifiers)
122  if (!resource) {
123  return;
124  }
125  zwp_text_input_v2_send_keysym(resource, seat ? seat->timestamp() : 0, keysym, WL_KEYBOARD_KEY_STATE_PRESSED, 0);
126 }
127 
128 void TextInputUnstableV2Interface::Private::keysymReleased(quint32 keysym, Qt::KeyboardModifiers modifiers)
129 {
130  Q_UNUSED(modifiers)
131  if (!resource) {
132  return;
133  }
134  zwp_text_input_v2_send_keysym(resource, seat ? seat->timestamp() : 0, keysym, WL_KEYBOARD_KEY_STATE_RELEASED, 0);
135 }
136 
137 void TextInputUnstableV2Interface::Private::deleteSurroundingText(quint32 beforeLength, quint32 afterLength)
138 {
139  if (!resource) {
140  return;
141  }
142  zwp_text_input_v2_send_delete_surrounding_text(resource, beforeLength, afterLength);
143 }
144 
145 void TextInputUnstableV2Interface::Private::setCursorPosition(qint32 index, qint32 anchor)
146 {
147  if (!resource) {
148  return;
149  }
150  zwp_text_input_v2_send_cursor_position(resource, index, anchor);
151 }
152 
153 void TextInputUnstableV2Interface::Private::setTextDirection(Qt::LayoutDirection direction)
154 {
155  if (!resource) {
156  return;
157  }
158  zwp_text_input_v2_text_direction wlDirection;
159  switch (direction) {
160  case Qt::LeftToRight:
161  wlDirection = ZWP_TEXT_INPUT_V2_TEXT_DIRECTION_LTR;
162  break;
163  case Qt::RightToLeft:
164  wlDirection = ZWP_TEXT_INPUT_V2_TEXT_DIRECTION_RTL;
165  break;
167  wlDirection = ZWP_TEXT_INPUT_V2_TEXT_DIRECTION_AUTO;
168  break;
169  default:
170  Q_UNREACHABLE();
171  break;
172  }
173  zwp_text_input_v2_send_text_direction(resource, wlDirection);
174 }
175 
176 void TextInputUnstableV2Interface::Private::setPreEditCursor(qint32 index)
177 {
178  if (!resource) {
179  return;
180  }
181  zwp_text_input_v2_send_preedit_cursor(resource, index);
182 }
183 
184 void TextInputUnstableV2Interface::Private::sendInputPanelState()
185 {
186  if (!resource) {
187  return;
188  }
189  zwp_text_input_v2_send_input_panel_state(resource,
190  inputPanelVisible ? ZWP_TEXT_INPUT_V2_INPUT_PANEL_VISIBILITY_VISIBLE
191  : ZWP_TEXT_INPUT_V2_INPUT_PANEL_VISIBILITY_HIDDEN,
192  overlappedSurfaceArea.x(),
193  overlappedSurfaceArea.y(),
194  overlappedSurfaceArea.width(),
195  overlappedSurfaceArea.height());
196 }
197 
198 void TextInputUnstableV2Interface::Private::sendLanguage()
199 {
200  if (!resource) {
201  return;
202  }
203  zwp_text_input_v2_send_language(resource, language.constData());
204 }
205 
206 TextInputUnstableV2Interface::Private::Private(TextInputInterface *q, TextInputManagerUnstableV2Interface *c, wl_resource *parentResource)
207  : TextInputInterface::Private(q, c, parentResource, &zwp_text_input_v2_interface, &s_interface)
208 {
209 }
210 
211 TextInputUnstableV2Interface::Private::~Private() = default;
212 
213 void TextInputUnstableV2Interface::Private::enableCallback(wl_client *client, wl_resource *resource, wl_resource *surface)
214 {
215  auto p = cast<Private>(resource);
216  Q_ASSERT(*p->client == client);
217  p->enable(SurfaceInterface::get(surface));
218 }
219 
220 void TextInputUnstableV2Interface::Private::disableCallback(wl_client *client, wl_resource *resource, wl_resource *surface)
221 {
222  Q_UNUSED(surface)
223  auto p = cast<Private>(resource);
224  Q_ASSERT(*p->client == client);
225  p->disable();
226 }
227 
228 void TextInputUnstableV2Interface::Private::updateStateCallback(wl_client *client, wl_resource *resource, uint32_t serial, uint32_t reason)
229 {
230  auto p = cast<Private>(resource);
231  Q_ASSERT(*p->client == client);
232  Q_UNUSED(serial)
233  // TODO: use other reason values reason
234  if (reason == ZWP_TEXT_INPUT_V2_UPDATE_STATE_RESET) {
235  Q_EMIT p->q_func()->requestReset();
236  }
237 }
238 
239 TextInputInterface::ContentHints TextInputUnstableV2Interface::Private::convertContentHint(uint32_t hint) const
240 {
241  const auto hints = zwp_text_input_v2_content_hint(hint);
242  TextInputInterface::ContentHints ret = TextInputInterface::ContentHint::None;
243 
244  if (hints & ZWP_TEXT_INPUT_V2_CONTENT_HINT_AUTO_COMPLETION) {
246  }
247  if (hints & ZWP_TEXT_INPUT_V2_CONTENT_HINT_AUTO_CORRECTION) {
249  }
250  if (hints & ZWP_TEXT_INPUT_V2_CONTENT_HINT_AUTO_CAPITALIZATION) {
252  }
253  if (hints & ZWP_TEXT_INPUT_V2_CONTENT_HINT_LOWERCASE) {
255  }
256  if (hints & ZWP_TEXT_INPUT_V2_CONTENT_HINT_UPPERCASE) {
258  }
259  if (hints & ZWP_TEXT_INPUT_V2_CONTENT_HINT_TITLECASE) {
261  }
262  if (hints & ZWP_TEXT_INPUT_V2_CONTENT_HINT_HIDDEN_TEXT) {
264  }
265  if (hints & ZWP_TEXT_INPUT_V2_CONTENT_HINT_SENSITIVE_DATA) {
267  }
268  if (hints & ZWP_TEXT_INPUT_V2_CONTENT_HINT_LATIN) {
270  }
271  if (hints & ZWP_TEXT_INPUT_V2_CONTENT_HINT_MULTILINE) {
273  }
274  return ret;
275 }
276 
277 TextInputInterface::ContentPurpose TextInputUnstableV2Interface::Private::convertContentPurpose(uint32_t purpose) const
278 {
279  const auto wlPurpose = zwp_text_input_v2_content_purpose(purpose);
280 
281  switch (wlPurpose) {
282  case ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_ALPHA:
284  case ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_DIGITS:
286  case ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_NUMBER:
288  case ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_PHONE:
290  case ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_URL:
292  case ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_EMAIL:
294  case ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_NAME:
296  case ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_PASSWORD:
298  case ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_DATE:
300  case ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_TIME:
302  case ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_DATETIME:
304  case ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_TERMINAL:
306  case ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_NORMAL:
307  default:
309  }
310 }
311 
312 TextInputUnstableV2Interface::TextInputUnstableV2Interface(TextInputManagerUnstableV2Interface *parent, wl_resource *parentResource)
313  : TextInputInterface(new Private(this, parent, parentResource))
314 {
315 }
316 
317 TextInputUnstableV2Interface::~TextInputUnstableV2Interface() = default;
318 
319 class TextInputManagerUnstableV2Interface::Private : public TextInputManagerInterface::Private
320 {
321 public:
322  Private(TextInputManagerUnstableV2Interface *q, Display *d);
323 
324 private:
325  void bind(wl_client *client, uint32_t version, uint32_t id) override;
326 
327  static void unbind(wl_resource *resource);
328  static Private *cast(wl_resource *r)
329  {
330  return reinterpret_cast<Private *>(wl_resource_get_user_data(r));
331  }
332 
333  static void destroyCallback(wl_client *client, wl_resource *resource);
334  static void getTextInputCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *seat);
335 
336  TextInputManagerUnstableV2Interface *q;
337  static const struct zwp_text_input_manager_v2_interface s_interface;
338  static const quint32 s_version;
339 };
340 const quint32 TextInputManagerUnstableV2Interface::Private::s_version = 1;
341 
342 #ifndef K_DOXYGEN
343 const struct zwp_text_input_manager_v2_interface TextInputManagerUnstableV2Interface::Private::s_interface = {destroyCallback, getTextInputCallback};
344 #endif
345 
346 void TextInputManagerUnstableV2Interface::Private::destroyCallback(wl_client *client, wl_resource *resource)
347 {
348  Q_UNUSED(client)
349  wl_resource_destroy(resource);
350 }
351 
352 void TextInputManagerUnstableV2Interface::Private::getTextInputCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *seat)
353 {
354  SeatInterface *s = SeatInterface::get(seat);
355  if (!s) {
356  // TODO: send error
357  return;
358  }
359  auto m = cast(resource);
360  auto *t = new TextInputUnstableV2Interface(m->q, resource);
361  t->d_func()->seat = s;
362  m->inputs << t;
363  QObject::connect(t, &QObject::destroyed, m->q, [t, m] {
364  m->inputs.removeAll(t);
365  });
366  t->d->create(m->display->getConnection(client), version, id);
367  s->d_func()->registerTextInput(t);
368 }
369 
370 TextInputManagerUnstableV2Interface::Private::Private(TextInputManagerUnstableV2Interface *q, Display *d)
371  : TextInputManagerInterface::Private(TextInputInterfaceVersion::UnstableV2, q, d, &zwp_text_input_manager_v2_interface, s_version)
372  , q(q)
373 {
374 }
375 
376 void TextInputManagerUnstableV2Interface::Private::bind(wl_client *client, uint32_t version, uint32_t id)
377 {
378  auto c = display->getConnection(client);
379  wl_resource *resource = c->createResource(&zwp_text_input_manager_v2_interface, qMin(version, s_version), id);
380  if (!resource) {
381  wl_client_post_no_memory(client);
382  return;
383  }
384  wl_resource_set_implementation(resource, &s_interface, this, unbind);
385  // TODO: should we track?
386 }
387 
388 void TextInputManagerUnstableV2Interface::Private::unbind(wl_resource *resource)
389 {
390  Q_UNUSED(resource)
391  // TODO: implement?
392 }
393 
394 TextInputManagerUnstableV2Interface::TextInputManagerUnstableV2Interface(Display *display, QObject *parent)
395  : TextInputManagerInterface(new Private(this, display), parent)
396 {
397 }
398 
399 TextInputManagerUnstableV2Interface::~TextInputManagerUnstableV2Interface() = default;
400 
401 }
402 }
@ TitleCase
prefer casing for titles and headings (can be language dependent)
@ UnstableV2
zwp_text_input_v2 as used by Qt 5.7
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
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 Sep 26 2023 03:48:29 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.