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-v0-client-protocol.h> 0013 0014 namespace KWayland 0015 { 0016 namespace Client 0017 { 0018 class TextInputUnstableV0::Private : public TextInput::Private 0019 { 0020 public: 0021 Private(TextInputUnstableV0 *q, Seat *seat); 0022 0023 void setup(wl_text_input *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<wl_text_input, wl_text_input_destroy> textinputunstablev0; 0037 0038 private: 0039 static void enterCallaback(void *data, wl_text_input *wl_text_input, wl_surface *surface); 0040 static void leaveCallback(void *data, wl_text_input *wl_text_input); 0041 static void modifiersMapCallback(void *data, wl_text_input *wl_text_input, wl_array *map); 0042 static void inputPanelStateCallback(void *data, wl_text_input *wl_text_input, uint32_t state); 0043 static void preeditStringCallback(void *data, wl_text_input *wl_text_input, uint32_t serial, const char *text, const char *commit); 0044 static void preeditStylingCallback(void *data, wl_text_input *wl_text_input, uint32_t index, uint32_t length, uint32_t style); 0045 static void preeditCursorCallback(void *data, wl_text_input *wl_text_input, int32_t index); 0046 static void commitStringCallback(void *data, wl_text_input *wl_text_input, uint32_t serial, const char *text); 0047 static void cursorPositionCallback(void *data, wl_text_input *wl_text_input, int32_t index, int32_t anchor); 0048 static void deleteSurroundingTextCallback(void *data, wl_text_input *wl_text_input, int32_t index, uint32_t length); 0049 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); 0050 static void languageCallback(void *data, wl_text_input *wl_text_input, uint32_t serial, const char *language); 0051 static void textDirectionCallback(void *data, wl_text_input *wl_text_input, uint32_t serial, uint32_t direction); 0052 0053 TextInputUnstableV0 *q; 0054 0055 static const wl_text_input_listener s_listener; 0056 }; 0057 0058 const wl_text_input_listener TextInputUnstableV0::Private::s_listener = {enterCallaback, 0059 leaveCallback, 0060 modifiersMapCallback, 0061 inputPanelStateCallback, 0062 preeditStringCallback, 0063 preeditStylingCallback, 0064 preeditCursorCallback, 0065 commitStringCallback, 0066 cursorPositionCallback, 0067 deleteSurroundingTextCallback, 0068 keysymCallback, 0069 languageCallback, 0070 textDirectionCallback}; 0071 0072 void TextInputUnstableV0::Private::enterCallaback(void *data, wl_text_input *wl_text_input, wl_surface *surface) 0073 { 0074 auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data); 0075 Q_ASSERT(t->textinputunstablev0 == wl_text_input); 0076 t->enteredSurface = Surface::get(surface); 0077 Q_EMIT t->q->entered(); 0078 } 0079 0080 void TextInputUnstableV0::Private::leaveCallback(void *data, wl_text_input *wl_text_input) 0081 { 0082 auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data); 0083 Q_ASSERT(t->textinputunstablev0 == wl_text_input); 0084 t->enteredSurface = nullptr; 0085 Q_EMIT t->q->left(); 0086 } 0087 0088 void TextInputUnstableV0::Private::modifiersMapCallback(void *data, wl_text_input *wl_text_input, wl_array *map) 0089 { 0090 Q_UNUSED(map) 0091 auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data); 0092 Q_ASSERT(t->textinputunstablev0 == wl_text_input); 0093 // TODO: implement 0094 } 0095 0096 void TextInputUnstableV0::Private::inputPanelStateCallback(void *data, wl_text_input *wl_text_input, uint32_t state) 0097 { 0098 auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data); 0099 Q_ASSERT(t->textinputunstablev0 == wl_text_input); 0100 if (t->inputPanelVisible != state) { 0101 t->inputPanelVisible = state; 0102 Q_EMIT t->q->inputPanelStateChanged(); 0103 } 0104 } 0105 0106 void TextInputUnstableV0::Private::preeditStringCallback(void *data, wl_text_input *wl_text_input, uint32_t serial, const char *text, const char *commit) 0107 { 0108 Q_UNUSED(serial) 0109 auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data); 0110 Q_ASSERT(t->textinputunstablev0 == wl_text_input); 0111 t->pendingPreEdit.commitText = QByteArray(commit); 0112 t->pendingPreEdit.text = QByteArray(text); 0113 if (!t->pendingPreEdit.cursorSet) { 0114 t->pendingPreEdit.cursor = t->pendingPreEdit.text.length(); 0115 } 0116 t->currentPreEdit = t->pendingPreEdit; 0117 t->pendingPreEdit = TextInput::Private::PreEdit(); 0118 Q_EMIT t->q->composingTextChanged(); 0119 } 0120 0121 void TextInputUnstableV0::Private::preeditStylingCallback(void *data, wl_text_input *wl_text_input, uint32_t index, uint32_t length, uint32_t style) 0122 { 0123 Q_UNUSED(index) 0124 Q_UNUSED(length) 0125 Q_UNUSED(style) 0126 // TODO: implement 0127 auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data); 0128 Q_ASSERT(t->textinputunstablev0 == wl_text_input); 0129 } 0130 0131 void TextInputUnstableV0::Private::preeditCursorCallback(void *data, wl_text_input *wl_text_input, int32_t index) 0132 { 0133 auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data); 0134 Q_ASSERT(t->textinputunstablev0 == wl_text_input); 0135 t->pendingPreEdit.cursor = index; 0136 t->pendingPreEdit.cursorSet = true; 0137 } 0138 0139 void TextInputUnstableV0::Private::commitStringCallback(void *data, wl_text_input *wl_text_input, uint32_t serial, const char *text) 0140 { 0141 Q_UNUSED(serial) 0142 auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data); 0143 Q_ASSERT(t->textinputunstablev0 == wl_text_input); 0144 t->pendingCommit.text = QByteArray(text); 0145 t->currentCommit = t->pendingCommit; 0146 // TODO: what are the proper values it should be set to? 0147 t->pendingCommit = TextInput::Private::Commit(); 0148 t->pendingCommit.deleteSurrounding.beforeLength = 0; 0149 t->pendingCommit.deleteSurrounding.afterLength = 0; 0150 Q_EMIT t->q->committed(); 0151 } 0152 0153 void TextInputUnstableV0::Private::cursorPositionCallback(void *data, wl_text_input *wl_text_input, int32_t index, int32_t anchor) 0154 { 0155 auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data); 0156 Q_ASSERT(t->textinputunstablev0 == wl_text_input); 0157 t->pendingCommit.cursor = index; 0158 t->pendingCommit.anchor = anchor; 0159 } 0160 0161 void TextInputUnstableV0::Private::deleteSurroundingTextCallback(void *data, wl_text_input *wl_text_input, int32_t index, uint32_t length) 0162 { 0163 auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data); 0164 Q_ASSERT(t->textinputunstablev0 == wl_text_input); 0165 t->pendingCommit.deleteSurrounding.beforeLength = qAbs(index); 0166 t->pendingCommit.deleteSurrounding.afterLength = length - t->pendingCommit.deleteSurrounding.beforeLength; 0167 } 0168 0169 void TextInputUnstableV0::Private::keysymCallback(void *data, 0170 wl_text_input *wl_text_input, 0171 uint32_t serial, 0172 uint32_t time, 0173 uint32_t sym, 0174 uint32_t wlState, 0175 uint32_t modifiers) 0176 { 0177 Q_UNUSED(serial) 0178 // TODO: add support for modifiers 0179 Q_UNUSED(modifiers) 0180 auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data); 0181 Q_ASSERT(t->textinputunstablev0 == wl_text_input); 0182 TextInput::KeyState state; 0183 switch (wlState) { 0184 case WL_KEYBOARD_KEY_STATE_RELEASED: 0185 state = TextInput::KeyState::Released; 0186 break; 0187 case WL_KEYBOARD_KEY_STATE_PRESSED: 0188 state = TextInput::KeyState::Pressed; 0189 break; 0190 default: 0191 // invalid 0192 return; 0193 } 0194 Q_EMIT t->q->keyEvent(sym, state, Qt::KeyboardModifiers(), time); 0195 } 0196 0197 void TextInputUnstableV0::Private::languageCallback(void *data, wl_text_input *wl_text_input, uint32_t serial, const char *language) 0198 { 0199 Q_UNUSED(serial) 0200 auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data); 0201 Q_ASSERT(t->textinputunstablev0 == wl_text_input); 0202 if (qstrcmp(t->language, language) != 0) { 0203 t->language = QByteArray(language); 0204 Q_EMIT t->q->languageChanged(); 0205 } 0206 } 0207 0208 void TextInputUnstableV0::Private::textDirectionCallback(void *data, wl_text_input *wl_text_input, uint32_t serial, uint32_t wlDirection) 0209 { 0210 Q_UNUSED(serial) 0211 auto t = reinterpret_cast<TextInputUnstableV0::Private *>(data); 0212 Q_ASSERT(t->textinputunstablev0 == wl_text_input); 0213 Qt::LayoutDirection direction; 0214 switch (wlDirection) { 0215 case WL_TEXT_INPUT_TEXT_DIRECTION_LTR: 0216 direction = Qt::LeftToRight; 0217 break; 0218 case WL_TEXT_INPUT_TEXT_DIRECTION_RTL: 0219 direction = Qt::RightToLeft; 0220 break; 0221 case WL_TEXT_INPUT_TEXT_DIRECTION_AUTO: 0222 direction = Qt::LayoutDirectionAuto; 0223 break; 0224 default: 0225 // invalid 0226 return; 0227 } 0228 if (direction != t->textDirection) { 0229 t->textDirection = direction; 0230 Q_EMIT t->q->textDirectionChanged(); 0231 } 0232 } 0233 0234 TextInputUnstableV0::Private::Private(TextInputUnstableV0 *q, Seat *seat) 0235 : TextInput::Private(seat) 0236 , q(q) 0237 { 0238 } 0239 0240 void TextInputUnstableV0::Private::setup(wl_text_input *ti) 0241 { 0242 Q_ASSERT(ti); 0243 Q_ASSERT(!textinputunstablev0); 0244 textinputunstablev0.setup(ti); 0245 wl_text_input_add_listener(ti, &s_listener, this); 0246 } 0247 0248 bool TextInputUnstableV0::Private::isValid() const 0249 { 0250 return textinputunstablev0.isValid(); 0251 } 0252 0253 void TextInputUnstableV0::Private::enable(Surface *surface) 0254 { 0255 wl_text_input_activate(textinputunstablev0, *seat, *surface); 0256 } 0257 0258 void TextInputUnstableV0::Private::disable(Surface *surface) 0259 { 0260 Q_UNUSED(surface) 0261 wl_text_input_deactivate(textinputunstablev0, *seat); 0262 } 0263 0264 void TextInputUnstableV0::Private::showInputPanel() 0265 { 0266 wl_text_input_show_input_panel(textinputunstablev0); 0267 } 0268 0269 void TextInputUnstableV0::Private::hideInputPanel() 0270 { 0271 wl_text_input_hide_input_panel(textinputunstablev0); 0272 } 0273 0274 void TextInputUnstableV0::Private::setCursorRectangle(const QRect &rect) 0275 { 0276 wl_text_input_set_cursor_rectangle(textinputunstablev0, rect.x(), rect.y(), rect.width(), rect.height()); 0277 } 0278 0279 void TextInputUnstableV0::Private::setPreferredLanguage(const QString &lang) 0280 { 0281 wl_text_input_set_preferred_language(textinputunstablev0, lang.toUtf8().constData()); 0282 } 0283 0284 void TextInputUnstableV0::Private::setSurroundingText(const QString &text, quint32 cursor, quint32 anchor) 0285 { 0286 const QStringView strView(text); 0287 0288 wl_text_input_set_surrounding_text(textinputunstablev0, 0289 text.toUtf8().constData(), 0290 strView.left(cursor).toUtf8().length(), 0291 strView.left(anchor).toUtf8().length()); 0292 } 0293 0294 void TextInputUnstableV0::Private::reset() 0295 { 0296 wl_text_input_reset(textinputunstablev0); 0297 } 0298 0299 void TextInputUnstableV0::Private::setContentType(ContentHints hints, ContentPurpose purpose) 0300 { 0301 uint32_t wlHints = 0; 0302 uint32_t wlPurpose = 0; 0303 if (hints.testFlag(ContentHint::AutoCompletion)) { 0304 wlHints |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION; 0305 } 0306 if (hints.testFlag(ContentHint::AutoCorrection)) { 0307 wlHints |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_CORRECTION; 0308 } 0309 if (hints.testFlag(ContentHint::AutoCapitalization)) { 0310 wlHints |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION; 0311 } 0312 if (hints.testFlag(ContentHint::LowerCase)) { 0313 wlHints |= WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE; 0314 } 0315 if (hints.testFlag(ContentHint::UpperCase)) { 0316 wlHints |= WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE; 0317 } 0318 if (hints.testFlag(ContentHint::TitleCase)) { 0319 wlHints |= WL_TEXT_INPUT_CONTENT_HINT_TITLECASE; 0320 } 0321 if (hints.testFlag(ContentHint::HiddenText)) { 0322 wlHints |= WL_TEXT_INPUT_CONTENT_HINT_HIDDEN_TEXT; 0323 } 0324 if (hints.testFlag(ContentHint::SensitiveData)) { 0325 wlHints |= WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA; 0326 } 0327 if (hints.testFlag(ContentHint::Latin)) { 0328 wlHints |= WL_TEXT_INPUT_CONTENT_HINT_LATIN; 0329 } 0330 if (hints.testFlag(ContentHint::MultiLine)) { 0331 wlHints |= WL_TEXT_INPUT_CONTENT_HINT_MULTILINE; 0332 } 0333 switch (purpose) { 0334 case ContentPurpose::Normal: 0335 wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL; 0336 break; 0337 case ContentPurpose::Alpha: 0338 wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_ALPHA; 0339 break; 0340 case ContentPurpose::Digits: 0341 wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS; 0342 break; 0343 case ContentPurpose::Number: 0344 wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER; 0345 break; 0346 case ContentPurpose::Phone: 0347 wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PHONE; 0348 break; 0349 case ContentPurpose::Url: 0350 wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_URL; 0351 break; 0352 case ContentPurpose::Email: 0353 wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_EMAIL; 0354 break; 0355 case ContentPurpose::Name: 0356 wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NAME; 0357 break; 0358 case ContentPurpose::Password: 0359 wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD; 0360 break; 0361 case ContentPurpose::Date: 0362 wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DATE; 0363 break; 0364 case ContentPurpose::Time: 0365 wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_TIME; 0366 break; 0367 case ContentPurpose::DateTime: 0368 wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DATETIME; 0369 break; 0370 case ContentPurpose::Terminal: 0371 wlPurpose = WL_TEXT_INPUT_CONTENT_PURPOSE_TERMINAL; 0372 break; 0373 } 0374 wl_text_input_set_content_type(textinputunstablev0, wlHints, wlPurpose); 0375 } 0376 0377 TextInputUnstableV0::TextInputUnstableV0(Seat *seat, QObject *parent) 0378 : TextInput(new Private(this, seat), parent) 0379 { 0380 } 0381 0382 TextInputUnstableV0::~TextInputUnstableV0() 0383 { 0384 release(); 0385 } 0386 0387 TextInputUnstableV0::Private *TextInputUnstableV0::d_func() const 0388 { 0389 return reinterpret_cast<Private *>(d.data()); 0390 } 0391 0392 void TextInputUnstableV0::setup(wl_text_input *textinputunstablev0) 0393 { 0394 Q_D(); 0395 d->setup(textinputunstablev0); 0396 } 0397 0398 void TextInputUnstableV0::release() 0399 { 0400 Q_D(); 0401 d->textinputunstablev0.release(); 0402 } 0403 0404 void TextInputUnstableV0::destroy() 0405 { 0406 Q_D(); 0407 d->textinputunstablev0.destroy(); 0408 } 0409 0410 TextInputUnstableV0::operator wl_text_input *() 0411 { 0412 Q_D(); 0413 return d->textinputunstablev0; 0414 } 0415 0416 TextInputUnstableV0::operator wl_text_input *() const 0417 { 0418 Q_D(); 0419 return d->textinputunstablev0; 0420 } 0421 0422 class TextInputManagerUnstableV0::Private : public TextInputManager::Private 0423 { 0424 public: 0425 Private() = default; 0426 0427 void release() override; 0428 void destroy() override; 0429 bool isValid() override; 0430 void setupV0(wl_text_input_manager *ti) override; 0431 TextInput *createTextInput(Seat *seat, QObject *parent = nullptr) override; 0432 using TextInputManager::Private::operator zwp_text_input_manager_v2 *; // overriding only one overload results in a compiler warning. This tells GCC we're 0433 // doing it deliberately 0434 operator wl_text_input_manager *() override 0435 { 0436 return textinputmanagerunstablev0; 0437 } 0438 operator wl_text_input_manager *() const override 0439 { 0440 return textinputmanagerunstablev0; 0441 } 0442 0443 WaylandPointer<wl_text_input_manager, wl_text_input_manager_destroy> textinputmanagerunstablev0; 0444 }; 0445 0446 void TextInputManagerUnstableV0::Private::release() 0447 { 0448 textinputmanagerunstablev0.release(); 0449 } 0450 0451 void TextInputManagerUnstableV0::Private::destroy() 0452 { 0453 textinputmanagerunstablev0.destroy(); 0454 } 0455 0456 bool TextInputManagerUnstableV0::Private::isValid() 0457 { 0458 return textinputmanagerunstablev0.isValid(); 0459 } 0460 0461 TextInputManagerUnstableV0::TextInputManagerUnstableV0(QObject *parent) 0462 : TextInputManager(new Private, parent) 0463 { 0464 } 0465 0466 TextInputManagerUnstableV0::Private *TextInputManagerUnstableV0::d_func() const 0467 { 0468 return reinterpret_cast<Private *>(d.data()); 0469 } 0470 0471 TextInputManagerUnstableV0::~TextInputManagerUnstableV0() 0472 { 0473 release(); 0474 } 0475 0476 void TextInputManagerUnstableV0::Private::setupV0(wl_text_input_manager *ti) 0477 { 0478 Q_ASSERT(ti); 0479 Q_ASSERT(!textinputmanagerunstablev0); 0480 textinputmanagerunstablev0.setup(ti); 0481 } 0482 0483 TextInput *TextInputManagerUnstableV0::Private::createTextInput(Seat *seat, QObject *parent) 0484 { 0485 Q_ASSERT(isValid()); 0486 TextInputUnstableV0 *t = new TextInputUnstableV0(seat, parent); 0487 auto w = wl_text_input_manager_create_text_input(textinputmanagerunstablev0); 0488 if (queue) { 0489 queue->addProxy(w); 0490 } 0491 t->setup(w); 0492 return t; 0493 } 0494 0495 } 0496 }