File indexing completed on 2024-12-22 05:09:25
0001 /* 0002 SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 #include "event_queue.h" 0007 #include "seat.h" 0008 #include "surface.h" 0009 #include "textinput_p.h" 0010 #include "wayland_pointer_p.h" 0011 0012 #include <wayland-text-input-v2-client-protocol.h> 0013 0014 namespace KWayland 0015 { 0016 namespace Client 0017 { 0018 class TextInputUnstableV2::Private : public TextInput::Private 0019 { 0020 public: 0021 Private(TextInputUnstableV2 *q, Seat *seat); 0022 0023 void setup(zwp_text_input_v2 *textinputmanagerunstablev0); 0024 0025 bool isValid() const override; 0026 void enable(Surface *surface) override; 0027 void disable(Surface *surface) override; 0028 void showInputPanel() override; 0029 void hideInputPanel() override; 0030 void setCursorRectangle(const QRect &rect) override; 0031 void setPreferredLanguage(const QString &lang) override; 0032 void setSurroundingText(const QString &text, quint32 cursor, quint32 anchor) override; 0033 void reset() override; 0034 void setContentType(ContentHints hint, ContentPurpose purpose) override; 0035 0036 WaylandPointer<zwp_text_input_v2, zwp_text_input_v2_destroy> textinputunstablev2; 0037 0038 private: 0039 static void enterCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, uint32_t serial, wl_surface *surface); 0040 static void leaveCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, uint32_t serial, wl_surface *surface); 0041 static void inputPanelStateCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, uint32_t state, int32_t x, int32_t y, int32_t width, int32_t height); 0042 static void preeditStringCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, const char *text, const char *commit); 0043 static void preeditStylingCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, uint32_t index, uint32_t length, uint32_t style); 0044 static void preeditCursorCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, int32_t index); 0045 static void commitStringCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, const char *text); 0046 static void cursorPositionCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, int32_t index, int32_t anchor); 0047 static void deleteSurroundingTextCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, uint32_t before_length, uint32_t after_length); 0048 static void modifiersMapCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, wl_array *map); 0049 static void keysymCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers); 0050 static void languageCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, const char *language); 0051 static void textDirectionCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, uint32_t direction); 0052 static void configureSurroundingTextCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, int32_t before_cursor, int32_t after_cursor); 0053 static void inputMethodChangedCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, uint32_t serial, uint32_t flags); 0054 0055 TextInputUnstableV2 *q; 0056 0057 static const zwp_text_input_v2_listener s_listener; 0058 }; 0059 0060 const zwp_text_input_v2_listener TextInputUnstableV2::Private::s_listener = {enterCallback, 0061 leaveCallback, 0062 inputPanelStateCallback, 0063 preeditStringCallback, 0064 preeditStylingCallback, 0065 preeditCursorCallback, 0066 commitStringCallback, 0067 cursorPositionCallback, 0068 deleteSurroundingTextCallback, 0069 modifiersMapCallback, 0070 keysymCallback, 0071 languageCallback, 0072 textDirectionCallback, 0073 configureSurroundingTextCallback, 0074 inputMethodChangedCallback}; 0075 0076 void TextInputUnstableV2::Private::enterCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, uint32_t serial, wl_surface *surface) 0077 { 0078 auto t = reinterpret_cast<TextInputUnstableV2::Private *>(data); 0079 Q_ASSERT(t->textinputunstablev2 == zwp_text_input_v2); 0080 t->latestSerial = serial; 0081 t->enteredSurface = Surface::get(surface); 0082 Q_EMIT t->q->entered(); 0083 } 0084 0085 void TextInputUnstableV2::Private::leaveCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, uint32_t serial, wl_surface *surface) 0086 { 0087 Q_UNUSED(surface) 0088 auto t = reinterpret_cast<TextInputUnstableV2::Private *>(data); 0089 Q_ASSERT(t->textinputunstablev2 == zwp_text_input_v2); 0090 t->enteredSurface = nullptr; 0091 t->latestSerial = serial; 0092 Q_EMIT t->q->left(); 0093 } 0094 0095 void TextInputUnstableV2::Private::inputPanelStateCallback(void *data, 0096 zwp_text_input_v2 *zwp_text_input_v2, 0097 uint32_t state, 0098 int32_t x, 0099 int32_t y, 0100 int32_t width, 0101 int32_t height) 0102 { 0103 Q_UNUSED(x) 0104 Q_UNUSED(y) 0105 Q_UNUSED(width) 0106 Q_UNUSED(height) 0107 auto t = reinterpret_cast<TextInputUnstableV2::Private *>(data); 0108 Q_ASSERT(t->textinputunstablev2 == zwp_text_input_v2); 0109 // TODO: add rect 0110 if (t->inputPanelVisible != state) { 0111 t->inputPanelVisible = state; 0112 Q_EMIT t->q->inputPanelStateChanged(); 0113 } 0114 } 0115 0116 void TextInputUnstableV2::Private::preeditStringCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, const char *text, const char *commit) 0117 { 0118 auto t = reinterpret_cast<TextInputUnstableV2::Private *>(data); 0119 Q_ASSERT(t->textinputunstablev2 == zwp_text_input_v2); 0120 t->pendingPreEdit.commitText = QByteArray(commit); 0121 t->pendingPreEdit.text = QByteArray(text); 0122 if (!t->pendingPreEdit.cursorSet) { 0123 t->pendingPreEdit.cursor = t->pendingPreEdit.text.length(); 0124 } 0125 t->currentPreEdit = t->pendingPreEdit; 0126 t->pendingPreEdit = TextInput::Private::PreEdit(); 0127 Q_EMIT t->q->composingTextChanged(); 0128 } 0129 0130 void TextInputUnstableV2::Private::preeditStylingCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, uint32_t index, uint32_t length, uint32_t style) 0131 { 0132 Q_UNUSED(index) 0133 Q_UNUSED(length) 0134 Q_UNUSED(style) 0135 // TODO: implement 0136 auto t = reinterpret_cast<TextInputUnstableV2::Private *>(data); 0137 Q_ASSERT(t->textinputunstablev2 == zwp_text_input_v2); 0138 } 0139 0140 void TextInputUnstableV2::Private::preeditCursorCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, int32_t index) 0141 { 0142 auto t = reinterpret_cast<TextInputUnstableV2::Private *>(data); 0143 Q_ASSERT(t->textinputunstablev2 == zwp_text_input_v2); 0144 t->pendingPreEdit.cursor = index; 0145 t->pendingPreEdit.cursorSet = true; 0146 } 0147 0148 void TextInputUnstableV2::Private::commitStringCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, const char *text) 0149 { 0150 auto t = reinterpret_cast<TextInputUnstableV2::Private *>(data); 0151 Q_ASSERT(t->textinputunstablev2 == zwp_text_input_v2); 0152 t->pendingCommit.text = QByteArray(text); 0153 t->currentCommit = t->pendingCommit; 0154 // TODO: what are the proper values it should be set to? 0155 t->pendingCommit = TextInput::Private::Commit(); 0156 t->pendingCommit.deleteSurrounding.beforeLength = 0; 0157 t->pendingCommit.deleteSurrounding.afterLength = 0; 0158 Q_EMIT t->q->committed(); 0159 } 0160 0161 void TextInputUnstableV2::Private::cursorPositionCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, int32_t index, int32_t anchor) 0162 { 0163 auto t = reinterpret_cast<TextInputUnstableV2::Private *>(data); 0164 Q_ASSERT(t->textinputunstablev2 == zwp_text_input_v2); 0165 t->pendingCommit.cursor = index; 0166 t->pendingCommit.anchor = anchor; 0167 } 0168 0169 void TextInputUnstableV2::Private::deleteSurroundingTextCallback(void *data, 0170 zwp_text_input_v2 *zwp_text_input_v2, 0171 uint32_t before_length, 0172 uint32_t after_length) 0173 { 0174 auto t = reinterpret_cast<TextInputUnstableV2::Private *>(data); 0175 Q_ASSERT(t->textinputunstablev2 == zwp_text_input_v2); 0176 t->pendingCommit.deleteSurrounding.beforeLength = before_length; 0177 t->pendingCommit.deleteSurrounding.afterLength = after_length; 0178 } 0179 0180 void TextInputUnstableV2::Private::modifiersMapCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, wl_array *map) 0181 { 0182 // TODO: implement 0183 Q_UNUSED(map) 0184 auto t = reinterpret_cast<TextInputUnstableV2::Private *>(data); 0185 Q_ASSERT(t->textinputunstablev2 == zwp_text_input_v2); 0186 } 0187 0188 void TextInputUnstableV2::Private::keysymCallback(void *data, 0189 zwp_text_input_v2 *zwp_text_input_v2, 0190 uint32_t time, 0191 uint32_t sym, 0192 uint32_t wlState, 0193 uint32_t modifiers) 0194 { 0195 // TODO: add support for modifiers 0196 Q_UNUSED(modifiers) 0197 auto t = reinterpret_cast<TextInputUnstableV2::Private *>(data); 0198 Q_ASSERT(t->textinputunstablev2 == zwp_text_input_v2); 0199 TextInput::KeyState state; 0200 switch (wlState) { 0201 case WL_KEYBOARD_KEY_STATE_RELEASED: 0202 state = TextInput::KeyState::Released; 0203 break; 0204 case WL_KEYBOARD_KEY_STATE_PRESSED: 0205 state = TextInput::KeyState::Pressed; 0206 break; 0207 default: 0208 // invalid 0209 return; 0210 } 0211 Q_EMIT t->q->keyEvent(sym, state, Qt::KeyboardModifiers(), time); 0212 } 0213 0214 void TextInputUnstableV2::Private::languageCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, const char *language) 0215 { 0216 auto t = reinterpret_cast<TextInputUnstableV2::Private *>(data); 0217 Q_ASSERT(t->textinputunstablev2 == zwp_text_input_v2); 0218 if (qstrcmp(t->language, language) != 0) { 0219 t->language = QByteArray(language); 0220 Q_EMIT t->q->languageChanged(); 0221 } 0222 } 0223 0224 void TextInputUnstableV2::Private::textDirectionCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, uint32_t wlDirection) 0225 { 0226 auto t = reinterpret_cast<TextInputUnstableV2::Private *>(data); 0227 Q_ASSERT(t->textinputunstablev2 == zwp_text_input_v2); 0228 Qt::LayoutDirection direction; 0229 switch (wlDirection) { 0230 case ZWP_TEXT_INPUT_V2_TEXT_DIRECTION_LTR: 0231 direction = Qt::LeftToRight; 0232 break; 0233 case ZWP_TEXT_INPUT_V2_TEXT_DIRECTION_RTL: 0234 direction = Qt::RightToLeft; 0235 break; 0236 case ZWP_TEXT_INPUT_V2_TEXT_DIRECTION_AUTO: 0237 direction = Qt::LayoutDirectionAuto; 0238 break; 0239 default: 0240 // invalid 0241 return; 0242 } 0243 if (direction != t->textDirection) { 0244 t->textDirection = direction; 0245 Q_EMIT t->q->textDirectionChanged(); 0246 } 0247 } 0248 0249 void TextInputUnstableV2::Private::configureSurroundingTextCallback(void *data, 0250 zwp_text_input_v2 *zwp_text_input_v2, 0251 int32_t before_cursor, 0252 int32_t after_cursor) 0253 { 0254 // TODO: implement 0255 Q_UNUSED(before_cursor) 0256 Q_UNUSED(after_cursor) 0257 auto t = reinterpret_cast<TextInputUnstableV2::Private *>(data); 0258 Q_ASSERT(t->textinputunstablev2 == zwp_text_input_v2); 0259 } 0260 0261 void TextInputUnstableV2::Private::inputMethodChangedCallback(void *data, zwp_text_input_v2 *zwp_text_input_v2, uint32_t serial, uint32_t flags) 0262 { 0263 Q_UNUSED(serial) 0264 Q_UNUSED(flags) 0265 // TODO: implement 0266 auto t = reinterpret_cast<TextInputUnstableV2::Private *>(data); 0267 Q_ASSERT(t->textinputunstablev2 == zwp_text_input_v2); 0268 } 0269 0270 TextInputUnstableV2::Private::Private(TextInputUnstableV2 *q, Seat *seat) 0271 : TextInput::Private(seat) 0272 , q(q) 0273 { 0274 } 0275 0276 void TextInputUnstableV2::Private::setup(zwp_text_input_v2 *ti) 0277 { 0278 Q_ASSERT(ti); 0279 Q_ASSERT(!textinputunstablev2); 0280 textinputunstablev2.setup(ti); 0281 zwp_text_input_v2_add_listener(ti, &s_listener, this); 0282 } 0283 0284 bool TextInputUnstableV2::Private::isValid() const 0285 { 0286 return textinputunstablev2.isValid(); 0287 } 0288 0289 void TextInputUnstableV2::Private::enable(Surface *surface) 0290 { 0291 zwp_text_input_v2_enable(textinputunstablev2, *surface); 0292 } 0293 0294 void TextInputUnstableV2::Private::disable(Surface *surface) 0295 { 0296 zwp_text_input_v2_disable(textinputunstablev2, *surface); 0297 } 0298 0299 void TextInputUnstableV2::Private::showInputPanel() 0300 { 0301 zwp_text_input_v2_show_input_panel(textinputunstablev2); 0302 } 0303 0304 void TextInputUnstableV2::Private::hideInputPanel() 0305 { 0306 zwp_text_input_v2_hide_input_panel(textinputunstablev2); 0307 } 0308 0309 void TextInputUnstableV2::Private::setCursorRectangle(const QRect &rect) 0310 { 0311 zwp_text_input_v2_set_cursor_rectangle(textinputunstablev2, rect.x(), rect.y(), rect.width(), rect.height()); 0312 } 0313 0314 void TextInputUnstableV2::Private::setPreferredLanguage(const QString &lang) 0315 { 0316 zwp_text_input_v2_set_preferred_language(textinputunstablev2, lang.toUtf8().constData()); 0317 } 0318 0319 void TextInputUnstableV2::Private::setSurroundingText(const QString &text, quint32 cursor, quint32 anchor) 0320 { 0321 const QStringView strView(text); 0322 0323 zwp_text_input_v2_set_surrounding_text(textinputunstablev2, 0324 text.toUtf8().constData(), 0325 strView.left(cursor).toUtf8().length(), 0326 strView.left(anchor).toUtf8().length()); 0327 } 0328 0329 void TextInputUnstableV2::Private::reset() 0330 { 0331 zwp_text_input_v2_update_state(textinputunstablev2, latestSerial, ZWP_TEXT_INPUT_V2_UPDATE_STATE_RESET); 0332 } 0333 0334 void TextInputUnstableV2::Private::setContentType(ContentHints hints, ContentPurpose purpose) 0335 { 0336 uint32_t wlHints = 0; 0337 uint32_t wlPurpose = 0; 0338 if (hints.testFlag(ContentHint::AutoCompletion)) { 0339 wlHints |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_AUTO_COMPLETION; 0340 } 0341 if (hints.testFlag(ContentHint::AutoCorrection)) { 0342 wlHints |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_AUTO_CORRECTION; 0343 } 0344 if (hints.testFlag(ContentHint::AutoCapitalization)) { 0345 wlHints |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_AUTO_CAPITALIZATION; 0346 } 0347 if (hints.testFlag(ContentHint::LowerCase)) { 0348 wlHints |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_LOWERCASE; 0349 } 0350 if (hints.testFlag(ContentHint::UpperCase)) { 0351 wlHints |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_UPPERCASE; 0352 } 0353 if (hints.testFlag(ContentHint::TitleCase)) { 0354 wlHints |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_TITLECASE; 0355 } 0356 if (hints.testFlag(ContentHint::HiddenText)) { 0357 wlHints |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_HIDDEN_TEXT; 0358 } 0359 if (hints.testFlag(ContentHint::SensitiveData)) { 0360 wlHints |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_SENSITIVE_DATA; 0361 } 0362 if (hints.testFlag(ContentHint::Latin)) { 0363 wlHints |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_LATIN; 0364 } 0365 if (hints.testFlag(ContentHint::MultiLine)) { 0366 wlHints |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_MULTILINE; 0367 } 0368 switch (purpose) { 0369 case ContentPurpose::Normal: 0370 wlPurpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_NORMAL; 0371 break; 0372 case ContentPurpose::Alpha: 0373 wlPurpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_ALPHA; 0374 break; 0375 case ContentPurpose::Digits: 0376 wlPurpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_DIGITS; 0377 break; 0378 case ContentPurpose::Number: 0379 wlPurpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_NUMBER; 0380 break; 0381 case ContentPurpose::Phone: 0382 wlPurpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_PHONE; 0383 break; 0384 case ContentPurpose::Url: 0385 wlPurpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_URL; 0386 break; 0387 case ContentPurpose::Email: 0388 wlPurpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_EMAIL; 0389 break; 0390 case ContentPurpose::Name: 0391 wlPurpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_NAME; 0392 break; 0393 case ContentPurpose::Password: 0394 wlPurpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_PASSWORD; 0395 break; 0396 case ContentPurpose::Date: 0397 wlPurpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_DATE; 0398 break; 0399 case ContentPurpose::Time: 0400 wlPurpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_TIME; 0401 break; 0402 case ContentPurpose::DateTime: 0403 wlPurpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_DATETIME; 0404 break; 0405 case ContentPurpose::Terminal: 0406 wlPurpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_TERMINAL; 0407 break; 0408 } 0409 zwp_text_input_v2_set_content_type(textinputunstablev2, wlHints, wlPurpose); 0410 } 0411 0412 TextInputUnstableV2::TextInputUnstableV2(Seat *seat, QObject *parent) 0413 : TextInput(new Private(this, seat), parent) 0414 { 0415 } 0416 0417 TextInputUnstableV2::~TextInputUnstableV2() 0418 { 0419 release(); 0420 } 0421 0422 TextInputUnstableV2::Private *TextInputUnstableV2::d_func() const 0423 { 0424 return reinterpret_cast<Private *>(d.data()); 0425 } 0426 0427 void TextInputUnstableV2::setup(zwp_text_input_v2 *textinputunstablev2) 0428 { 0429 Q_D(); 0430 d->setup(textinputunstablev2); 0431 } 0432 0433 void TextInputUnstableV2::release() 0434 { 0435 Q_D(); 0436 d->textinputunstablev2.release(); 0437 } 0438 0439 void TextInputUnstableV2::destroy() 0440 { 0441 Q_D(); 0442 d->textinputunstablev2.destroy(); 0443 } 0444 0445 TextInputUnstableV2::operator zwp_text_input_v2 *() 0446 { 0447 Q_D(); 0448 return d->textinputunstablev2; 0449 } 0450 0451 TextInputUnstableV2::operator zwp_text_input_v2 *() const 0452 { 0453 Q_D(); 0454 return d->textinputunstablev2; 0455 } 0456 0457 class TextInputManagerUnstableV2::Private : public TextInputManager::Private 0458 { 0459 public: 0460 Private() = default; 0461 0462 void release() override; 0463 void destroy() override; 0464 bool isValid() override; 0465 void setupV2(zwp_text_input_manager_v2 *ti) override; 0466 TextInput *createTextInput(Seat *seat, QObject *parent = nullptr) override; 0467 using TextInputManager::Private::operator wl_text_input_manager *; 0468 operator zwp_text_input_manager_v2 *() override 0469 { 0470 return textinputmanagerunstablev2; 0471 } 0472 operator zwp_text_input_manager_v2 *() const override 0473 { 0474 return textinputmanagerunstablev2; 0475 } 0476 0477 WaylandPointer<zwp_text_input_manager_v2, zwp_text_input_manager_v2_destroy> textinputmanagerunstablev2; 0478 }; 0479 0480 void TextInputManagerUnstableV2::Private::release() 0481 { 0482 textinputmanagerunstablev2.release(); 0483 } 0484 0485 void TextInputManagerUnstableV2::Private::destroy() 0486 { 0487 textinputmanagerunstablev2.destroy(); 0488 } 0489 0490 bool TextInputManagerUnstableV2::Private::isValid() 0491 { 0492 return textinputmanagerunstablev2.isValid(); 0493 } 0494 0495 TextInputManagerUnstableV2::TextInputManagerUnstableV2(QObject *parent) 0496 : TextInputManager(new Private, parent) 0497 { 0498 } 0499 0500 TextInputManagerUnstableV2::~TextInputManagerUnstableV2() = default; 0501 0502 void TextInputManagerUnstableV2::Private::setupV2(zwp_text_input_manager_v2 *ti) 0503 { 0504 Q_ASSERT(ti); 0505 Q_ASSERT(!textinputmanagerunstablev2); 0506 textinputmanagerunstablev2.setup(ti); 0507 } 0508 0509 TextInput *TextInputManagerUnstableV2::Private::createTextInput(Seat *seat, QObject *parent) 0510 { 0511 Q_ASSERT(isValid()); 0512 TextInputUnstableV2 *t = new TextInputUnstableV2(seat, parent); 0513 auto w = zwp_text_input_manager_v2_get_text_input(textinputmanagerunstablev2, *seat); 0514 if (queue) { 0515 queue->addProxy(w); 0516 } 0517 t->setup(w); 0518 return t; 0519 } 0520 0521 } 0522 }