File indexing completed on 2024-11-10 04:57:27
0001 /* 0002 SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez <aleixpol@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include "inputmethod_v1.h" 0008 #include "display.h" 0009 #include "keyboard.h" 0010 #include "keyboard_p.h" 0011 #include "output.h" 0012 #include "seat.h" 0013 #include "surface.h" 0014 #include "utils/common.h" 0015 #include "utils/ramfile.h" 0016 0017 #include <QHash> 0018 0019 #include <unistd.h> 0020 0021 #include "qwayland-server-input-method-unstable-v1.h" 0022 #include "qwayland-server-text-input-unstable-v1.h" 0023 #include "qwayland-server-wayland.h" 0024 0025 namespace KWin 0026 { 0027 static int s_version = 1; 0028 0029 class InputKeyboardV1InterfacePrivate : public QtWaylandServer::wl_keyboard 0030 { 0031 public: 0032 InputKeyboardV1InterfacePrivate() 0033 { 0034 } 0035 }; 0036 0037 InputMethodGrabV1::InputMethodGrabV1(QObject *parent) 0038 : QObject(parent) 0039 , d(new InputKeyboardV1InterfacePrivate) 0040 { 0041 } 0042 0043 InputMethodGrabV1::~InputMethodGrabV1() 0044 { 0045 } 0046 0047 void InputMethodGrabV1::sendKeymap(const QByteArray &keymap) 0048 { 0049 RamFile keymapFile("kwin-xkb-input-method-grab-keymap", keymap.constData(), keymap.size() + 1); // include QByteArray null terminator 0050 0051 const auto resources = d->resourceMap(); 0052 for (auto r : resources) { 0053 d->send_keymap(r->handle, QtWaylandServer::wl_keyboard::keymap_format::keymap_format_xkb_v1, keymapFile.fd(), keymapFile.size()); 0054 } 0055 } 0056 0057 void InputMethodGrabV1::sendKey(quint32 serial, quint32 timestamp, quint32 key, KeyboardKeyState state) 0058 { 0059 const auto resources = d->resourceMap(); 0060 for (auto r : resources) { 0061 d->send_key(r->handle, serial, timestamp, key, quint32(state)); 0062 } 0063 } 0064 0065 void InputMethodGrabV1::sendModifiers(quint32 serial, quint32 depressed, quint32 latched, quint32 locked, quint32 group) 0066 { 0067 const auto resources = d->resourceMap(); 0068 for (auto r : resources) { 0069 d->send_modifiers(r->handle, serial, depressed, latched, locked, group); 0070 } 0071 } 0072 0073 class InputMethodContextV1InterfacePrivate : public QtWaylandServer::zwp_input_method_context_v1 0074 { 0075 public: 0076 InputMethodContextV1InterfacePrivate(InputMethodContextV1Interface *q) 0077 : zwp_input_method_context_v1() 0078 , q(q) 0079 { 0080 } 0081 0082 ~InputMethodContextV1InterfacePrivate() 0083 { 0084 } 0085 0086 void zwp_input_method_context_v1_commit_string(Resource *, uint32_t serial, const QString &text) override 0087 { 0088 Q_EMIT q->commitString(serial, text); 0089 } 0090 void zwp_input_method_context_v1_preedit_string(Resource *, uint32_t serial, const QString &text, const QString &commit) override 0091 { 0092 Q_EMIT q->preeditString(serial, text, commit); 0093 } 0094 0095 void zwp_input_method_context_v1_preedit_styling(Resource *, uint32_t index, uint32_t length, uint32_t style) override 0096 { 0097 Q_EMIT q->preeditStyling(index, length, style); 0098 } 0099 void zwp_input_method_context_v1_preedit_cursor(Resource *, int32_t index) override 0100 { 0101 Q_EMIT q->preeditCursor(index); 0102 } 0103 void zwp_input_method_context_v1_delete_surrounding_text(Resource *, int32_t index, uint32_t length) override 0104 { 0105 Q_EMIT q->deleteSurroundingText(index, length); 0106 } 0107 void zwp_input_method_context_v1_cursor_position(Resource *, int32_t index, int32_t anchor) override 0108 { 0109 Q_EMIT q->cursorPosition(index, anchor); 0110 } 0111 void zwp_input_method_context_v1_modifiers_map(Resource *, wl_array *map) override 0112 { 0113 const auto mods = QByteArray::fromRawData(static_cast<const char *>(map->data), map->size); 0114 0115 Q_EMIT q->modifiersMap(mods); 0116 } 0117 void zwp_input_method_context_v1_keysym(Resource *, uint32_t serial, uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers) override 0118 { 0119 Q_EMIT q->keysym(serial, time, sym, state == WL_KEYBOARD_KEY_STATE_PRESSED, modifiers); 0120 } 0121 void zwp_input_method_context_v1_grab_keyboard(Resource *resource, uint32_t id) override 0122 { 0123 m_keyboardGrab.reset(new InputMethodGrabV1(q)); 0124 m_keyboardGrab->d->add(resource->client(), id, 1); 0125 Q_EMIT q->keyboardGrabRequested(m_keyboardGrab.get()); 0126 } 0127 void zwp_input_method_context_v1_key(Resource *, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) override 0128 { 0129 Q_EMIT q->key(serial, time, key, state == WL_KEYBOARD_KEY_STATE_PRESSED); 0130 } 0131 void zwp_input_method_context_v1_modifiers(Resource *, 0132 uint32_t serial, 0133 uint32_t mods_depressed, 0134 uint32_t mods_latched, 0135 uint32_t mods_locked, 0136 uint32_t group) override 0137 { 0138 Q_EMIT q->modifiers(serial, mods_depressed, mods_latched, mods_locked, group); 0139 } 0140 void zwp_input_method_context_v1_language(Resource *, uint32_t serial, const QString &language) override 0141 { 0142 Q_EMIT q->language(serial, language); 0143 } 0144 void zwp_input_method_context_v1_text_direction(Resource *, uint32_t serial, uint32_t direction) override 0145 { 0146 Qt::LayoutDirection qtDirection; 0147 switch (direction) { 0148 case ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_LTR: 0149 qtDirection = Qt::LeftToRight; 0150 break; 0151 case ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_RTL: 0152 qtDirection = Qt::RightToLeft; 0153 break; 0154 case ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_AUTO: 0155 qtDirection = Qt::LayoutDirectionAuto; 0156 break; 0157 default: 0158 Q_UNREACHABLE(); 0159 break; 0160 } 0161 Q_EMIT q->textDirection(serial, qtDirection); 0162 } 0163 0164 void zwp_input_method_context_v1_destroy(Resource *resource) override 0165 { 0166 wl_resource_destroy(resource->handle); 0167 } 0168 0169 InputMethodContextV1Interface *const q; 0170 std::unique_ptr<InputMethodGrabV1> m_keyboardGrab; 0171 }; 0172 0173 InputMethodContextV1Interface::InputMethodContextV1Interface(InputMethodV1Interface *parent) 0174 : QObject(parent) 0175 , d(new InputMethodContextV1InterfacePrivate(this)) 0176 { 0177 } 0178 0179 InputMethodContextV1Interface::~InputMethodContextV1Interface() = default; 0180 0181 void InputMethodContextV1Interface::sendCommitState(uint32_t serial) 0182 { 0183 for (auto r : d->resourceMap()) { 0184 d->send_commit_state(r->handle, serial); 0185 } 0186 } 0187 0188 void InputMethodContextV1Interface::sendContentType(TextInputContentHints hint, TextInputContentPurpose purpose) 0189 { 0190 quint32 contentHint = QtWaylandServer::zwp_text_input_v1::content_hint_none; 0191 quint32 contentPurpose; 0192 0193 if (hint.testFlag(TextInputContentHint::AutoCapitalization)) { 0194 contentHint |= QtWaylandServer::zwp_text_input_v1::content_hint_auto_capitalization; 0195 } 0196 if (hint.testFlag(TextInputContentHint::AutoCorrection)) { 0197 contentHint |= QtWaylandServer::zwp_text_input_v1::content_hint_auto_correction; 0198 } 0199 if (hint.testFlag(TextInputContentHint::AutoCompletion)) { 0200 contentHint |= QtWaylandServer::zwp_text_input_v1::content_hint_auto_completion; 0201 } 0202 if (hint.testFlag(TextInputContentHint::LowerCase)) { 0203 contentHint |= QtWaylandServer::zwp_text_input_v1::content_hint_lowercase; 0204 } 0205 if (hint.testFlag(TextInputContentHint::UpperCase)) { 0206 contentHint |= QtWaylandServer::zwp_text_input_v1::content_hint_uppercase; 0207 } 0208 if (hint.testFlag(TextInputContentHint::TitleCase)) { 0209 contentHint |= QtWaylandServer::zwp_text_input_v1::content_hint_titlecase; 0210 } 0211 if (hint.testFlag(TextInputContentHint::HiddenText)) { 0212 contentHint |= QtWaylandServer::zwp_text_input_v1::content_hint_hidden_text; 0213 } 0214 if (hint.testFlag(TextInputContentHint::SensitiveData)) { 0215 contentHint |= QtWaylandServer::zwp_text_input_v1::content_hint_lowercase; 0216 } 0217 if (hint.testFlag(TextInputContentHint::Latin)) { 0218 contentHint |= QtWaylandServer::zwp_text_input_v1::content_hint_latin; 0219 } 0220 if (hint.testFlag(TextInputContentHint::MultiLine)) { 0221 contentHint |= QtWaylandServer::zwp_text_input_v1::content_hint_multiline; 0222 } 0223 if (hint.testFlag(TextInputContentHint::None)) { 0224 contentHint |= QtWaylandServer::zwp_text_input_v1::content_hint_none; 0225 } 0226 0227 switch (purpose) { 0228 case TextInputContentPurpose::Alpha: 0229 contentPurpose = QtWaylandServer::zwp_text_input_v1::content_purpose_alpha; 0230 break; 0231 case TextInputContentPurpose::Digits: 0232 contentPurpose = QtWaylandServer::zwp_text_input_v1::content_purpose_digits; 0233 break; 0234 case TextInputContentPurpose::Number: 0235 contentPurpose = QtWaylandServer::zwp_text_input_v1::content_purpose_number; 0236 break; 0237 case TextInputContentPurpose::Phone: 0238 contentPurpose = QtWaylandServer::zwp_text_input_v1::content_purpose_phone; 0239 break; 0240 case TextInputContentPurpose::Url: 0241 contentPurpose = QtWaylandServer::zwp_text_input_v1::content_purpose_url; 0242 break; 0243 case TextInputContentPurpose::Email: 0244 contentPurpose = QtWaylandServer::zwp_text_input_v1::content_purpose_email; 0245 break; 0246 case TextInputContentPurpose::Name: 0247 contentPurpose = QtWaylandServer::zwp_text_input_v1::content_purpose_name; 0248 break; 0249 case TextInputContentPurpose::Password: 0250 contentPurpose = QtWaylandServer::zwp_text_input_v1::content_purpose_password; 0251 break; 0252 case TextInputContentPurpose::Date: 0253 contentPurpose = QtWaylandServer::zwp_text_input_v1::content_purpose_date; 0254 break; 0255 case TextInputContentPurpose::Time: 0256 contentPurpose = QtWaylandServer::zwp_text_input_v1::content_purpose_time; 0257 break; 0258 case TextInputContentPurpose::DateTime: 0259 contentPurpose = QtWaylandServer::zwp_text_input_v1::content_purpose_datetime; 0260 break; 0261 case TextInputContentPurpose::Terminal: 0262 contentPurpose = QtWaylandServer::zwp_text_input_v1::content_purpose_terminal; 0263 break; 0264 case TextInputContentPurpose::Normal: 0265 default: 0266 contentPurpose = QtWaylandServer::zwp_text_input_v1::content_purpose_normal; 0267 } 0268 0269 for (auto r : d->resourceMap()) { 0270 d->send_content_type(r->handle, contentHint, contentPurpose); 0271 } 0272 } 0273 0274 void InputMethodContextV1Interface::sendInvokeAction(uint32_t button, uint32_t index) 0275 { 0276 for (auto r : d->resourceMap()) { 0277 d->send_invoke_action(r->handle, button, index); 0278 } 0279 } 0280 0281 void InputMethodContextV1Interface::sendPreferredLanguage(const QString &language) 0282 { 0283 for (auto r : d->resourceMap()) { 0284 d->send_preferred_language(r->handle, language); 0285 } 0286 } 0287 0288 void InputMethodContextV1Interface::sendReset() 0289 { 0290 for (auto r : d->resourceMap()) { 0291 d->send_reset(r->handle); 0292 } 0293 } 0294 0295 void InputMethodContextV1Interface::sendSurroundingText(const QString &text, uint32_t cursor, uint32_t anchor) 0296 { 0297 for (auto r : d->resourceMap()) { 0298 d->send_surrounding_text(r->handle, text, cursor, anchor); 0299 } 0300 } 0301 0302 InputMethodGrabV1 *InputMethodContextV1Interface::keyboardGrab() const 0303 { 0304 return d->m_keyboardGrab.get(); 0305 } 0306 0307 class InputPanelSurfaceV1InterfacePrivate : public QtWaylandServer::zwp_input_panel_surface_v1 0308 { 0309 friend class InputPanelSurfaceV1Interface; 0310 0311 public: 0312 InputPanelSurfaceV1InterfacePrivate(SurfaceInterface *surface, quint32 id, InputPanelSurfaceV1Interface *q) 0313 : zwp_input_panel_surface_v1() 0314 , q(q) 0315 , surface(surface) 0316 { 0317 } 0318 0319 void zwp_input_panel_surface_v1_set_overlay_panel(Resource *) override 0320 { 0321 Q_EMIT q->overlayPanel(); 0322 } 0323 0324 void zwp_input_panel_surface_v1_set_toplevel(Resource *, struct ::wl_resource *output, uint32_t position) override 0325 { 0326 Q_EMIT q->topLevel(OutputInterface::get(output), InputPanelSurfaceV1Interface::Position(position)); 0327 } 0328 0329 void zwp_input_panel_surface_v1_destroy_resource(Resource *) override 0330 { 0331 delete q; 0332 } 0333 0334 InputPanelSurfaceV1Interface *const q; 0335 QPointer<SurfaceInterface> surface; 0336 }; 0337 0338 InputPanelSurfaceV1Interface::InputPanelSurfaceV1Interface(SurfaceInterface *surface, quint32 id, QObject *parent) 0339 : QObject(parent) 0340 , d(new InputPanelSurfaceV1InterfacePrivate(surface, id, this)) 0341 { 0342 } 0343 0344 InputPanelSurfaceV1Interface::~InputPanelSurfaceV1Interface() 0345 { 0346 Q_EMIT aboutToBeDestroyed(); 0347 } 0348 0349 SurfaceRole *InputPanelSurfaceV1Interface::role() 0350 { 0351 static SurfaceRole role(QByteArrayLiteral("input_panel_surface_v1")); 0352 return &role; 0353 } 0354 0355 class InputPanelV1InterfacePrivate : public QtWaylandServer::zwp_input_panel_v1 0356 { 0357 public: 0358 InputPanelV1InterfacePrivate(InputPanelV1Interface *q, Display *d) 0359 : zwp_input_panel_v1(*d, s_version) 0360 , q(q) 0361 { 0362 } 0363 0364 void zwp_input_panel_v1_get_input_panel_surface(Resource *resource, uint32_t id, struct ::wl_resource *surfaceResource) override 0365 { 0366 auto surface = SurfaceInterface::get(surfaceResource); 0367 0368 if (const SurfaceRole *role = surface->role()) { 0369 if (role != InputPanelSurfaceV1Interface::role()) { 0370 wl_resource_post_error(resource->handle, 0, "the surface already has a role assigned %s", role->name().constData()); 0371 return; 0372 } 0373 } else { 0374 surface->setRole(InputPanelSurfaceV1Interface::role()); 0375 } 0376 0377 auto interface = new InputPanelSurfaceV1Interface(surface, id, nullptr); 0378 interface->d->init(resource->client(), id, resource->version()); 0379 0380 Q_EMIT q->inputPanelSurfaceAdded(interface); 0381 } 0382 0383 InputPanelV1Interface *const q; 0384 }; 0385 0386 InputPanelV1Interface::InputPanelV1Interface(Display *display, QObject *parent) 0387 : QObject(parent) 0388 , d(new InputPanelV1InterfacePrivate(this, display)) 0389 { 0390 } 0391 0392 InputPanelV1Interface::~InputPanelV1Interface() = default; 0393 0394 SurfaceInterface *InputPanelSurfaceV1Interface::surface() const 0395 { 0396 return d->surface; 0397 } 0398 0399 class InputMethodV1InterfacePrivate : public QtWaylandServer::zwp_input_method_v1 0400 { 0401 public: 0402 InputMethodV1InterfacePrivate(Display *d, InputMethodV1Interface *q) 0403 : zwp_input_method_v1(*d, s_version) 0404 , q(q) 0405 , m_display(d) 0406 { 0407 } 0408 0409 void zwp_input_method_v1_bind_resource(Resource *resource) override 0410 { 0411 if (!m_context) { 0412 return; 0413 } 0414 0415 auto addedResource = m_context->d->add(resource->client(), resource->version()); 0416 send_activate(resource->handle, addedResource->handle); 0417 } 0418 0419 std::unique_ptr<InputMethodContextV1Interface> m_context; 0420 InputMethodV1Interface *const q; 0421 Display *const m_display; 0422 }; 0423 0424 InputMethodV1Interface::InputMethodV1Interface(Display *d, QObject *parent) 0425 : QObject(parent) 0426 , d(new InputMethodV1InterfacePrivate(d, this)) 0427 { 0428 } 0429 0430 InputMethodV1Interface::~InputMethodV1Interface() = default; 0431 0432 void InputMethodV1Interface::sendActivate() 0433 { 0434 if (d->m_context) { 0435 return; 0436 } 0437 0438 d->m_context.reset(new InputMethodContextV1Interface(this)); 0439 0440 for (auto resource : d->resourceMap()) { 0441 auto connection = d->m_context->d->add(resource->client(), resource->version()); 0442 d->send_activate(resource->handle, connection->handle); 0443 } 0444 } 0445 0446 void InputMethodV1Interface::sendDeactivate() 0447 { 0448 if (!d->m_context) { 0449 return; 0450 } 0451 0452 for (auto resource : d->resourceMap()) { 0453 auto connection = d->m_context->d->resourceMap().value(resource->client()); 0454 if (connection) { 0455 d->send_deactivate(resource->handle, connection->handle); 0456 } 0457 } 0458 d->m_context.reset(); 0459 } 0460 0461 InputMethodContextV1Interface *InputMethodV1Interface::context() const 0462 { 0463 return d->m_context.get(); 0464 } 0465 0466 } 0467 0468 #include "moc_inputmethod_v1.cpp"