feat(wayland): text input through zwp_text_input_v3

A window can now say that a text field has the focus and where its caret
is — Window::SetTextInput(active, caret rectangle in physical pixels,
purpose) — which is what opens the on-screen keyboard on a phone (Maliit
under KWin, squeekboard under phoc). What the input method produces comes
back as events: committed text as onTextInput, the composing text as
onPreedit (empty clears it), deletions around the cursor as
onTextInputDelete; done() applies them in the protocol's order. The state
a window wants is remembered and sent again whenever the keyboard focus
returns to it. The protocol's client code is generated with wayland-scanner
1.26.0 from wayland-protocols' text-input-unstable-v3.xml, under lib/ like
the others.
This commit is contained in:
Jorijn van der Graaf 2026-10-18 01:50:39 +02:00
commit 678f38964f
Signed by: jorijnvdgraaf
GPG key ID: 2937E59CDCC1BCFB
8 changed files with 1355 additions and 0 deletions

View file

@ -11,6 +11,7 @@ module;
#include "../lib/wayland-xdg-decoration-unstable-v1-client-protocol.h"
#include "../lib/fractional-scale-v1.h"
#include "../lib/viewporter.h"
#include "../lib/text-input-unstable-v3-client-protocol.h"
#include <string.h>
#include <cassert>
#include <linux/input.h>
@ -561,6 +562,7 @@ Window::~Window() {
Device::touchWindow = nullptr;
Device::touchPositions.clear();
}
if (Device::textInputWindow == this) Device::textInputWindow = nullptr;
#endif
}
#endif
@ -618,6 +620,18 @@ void Window::SetTitle(const std::string_view title) {
#endif
}
void Window::SetTextInput(bool active, std::int32_t x, std::int32_t y, std::int32_t width, std::int32_t height, TextInputPurpose purpose) {
#ifdef CRAFTER_GRAPHICS_WINDOW_WAYLAND
textInputActive_ = active;
textInputRect_[0] = x;
textInputRect_[1] = y;
textInputRect_[2] = width;
textInputRect_[3] = height;
textInputPurpose_ = purpose;
Device::ApplyTextInput(this);
#endif
}
void Window::SetCursorImage(std::uint16_t width, std::uint16_t height,
std::uint16_t hotspotX, std::uint16_t hotspotY,
const std::uint8_t* pixels) {