10#include <QtGui/qguiapplication.h>
11#include <QtGui/qtextformat.h>
12#include <QtGui/private/qguiapplication_p.h>
20QWaylandTextInputMethod::QWaylandTextInputMethod(QWaylandDisplay *display,
struct ::qt_text_input_method_v1 *textInputMethod)
21 : QtWayland::qt_text_input_method_v1(textInputMethod)
28 qt_text_input_method_v1_destroy(object());
33 if (m_isVisible != visible) {
34 m_isVisible = visible;
35 QGuiApplicationPrivate::platformIntegration()->inputContext()->emitInputPanelVisibleChanged();
41 m_locale = QLocale(localeName);
46 m_layoutDirection = Qt::LayoutDirection(inputDirection);
51 const QRectF keyboardRectangle(wl_fixed_to_double(x),
52 wl_fixed_to_double(y),
53 wl_fixed_to_double(width),
54 wl_fixed_to_double(height));
55 if (m_keyboardRect != keyboardRectangle) {
56 m_keyboardRect = keyboardRectangle;
57 QGuiApplicationPrivate::platformIntegration()->inputContext()->emitKeyboardRectChanged();
63 if (m_pendingInputMethodEvents.contains(serial)) {
64 qCWarning(qLcQpaInputMethods) <<
"Input method event with serial" << serial <<
"already started";
68 m_pendingInputMethodEvents[serial] = QList<QInputMethodEvent::Attribute>{};
69 m_offsetFromCompositor[serial] = surrounding_text_offset;
76 int size = text.size();
80 if (cursorPos > size - halfSize)
82 return cursorPos - halfSize;
102 if (!m_pendingInputMethodEvents.contains(serial)) {
103 qCWarning(qLcQpaInputMethods) <<
"Input method event with serial" << serial <<
"does not exist";
107 int startMapped = mapPositionFromCompositor(start, m_offsetFromCompositor[serial]);
108 QList<QInputMethodEvent::Attribute> &attributes = m_pendingInputMethodEvents[serial];
110 case QInputMethodEvent::Selection:
111 attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::AttributeType(type), startMapped, length));
113 case QInputMethodEvent::Cursor:
114 attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::AttributeType(type), start, length, QColor::fromString(value)));
116 case QInputMethodEvent::TextFormat:
118 QTextCharFormat textFormat;
119 textFormat.setProperty(QTextFormat::FontUnderline,
true);
120 textFormat.setProperty(QTextFormat::TextUnderlineStyle, QTextCharFormat::SingleUnderline);
121 attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::AttributeType(type), start, length, textFormat));
124 case QInputMethodEvent::Language:
125 case QInputMethodEvent::Ruby:
126 attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::AttributeType(type), start, length, value));
133 int cursorPosition = event->value(Qt::ImCursorPosition).toInt();
134 int anchorPosition = event->value(Qt::ImAnchorPosition).toInt();
135 QString surroundingText = event->value(Qt::ImSurroundingText).toString();
136 int offset = calculateOffset(surroundingText, cursorPosition);
138 if (queries & Qt::ImCursorPosition)
140 if (queries & Qt::ImSurroundingText)
141 update_surrounding_text(mapSurroundingTextToCompositor(surroundingText, offset), offset);
142 if (queries & Qt::ImAnchorPosition)
144 if (queries & Qt::ImAbsolutePosition)
145 update_absolute_position(event->value(Qt::ImAbsolutePosition).toInt());
151 if (!m_pendingInputMethodEvents.contains(serial)) {
152 qCWarning(qLcQpaInputMethods) <<
"Input method event with serial" << serial <<
"does not exist";
156 QList<QInputMethodEvent::Attribute> attributes = m_pendingInputMethodEvents.take(serial);
157 m_offsetFromCompositor.remove(serial);
158 if (QGuiApplication::focusObject() !=
nullptr) {
159 QInputMethodEvent event(preeditString, attributes);
160 event.setCommitString(commitString, replacementStart, replacementLength);
161 QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
165 if (QGuiApplication::focusObject() !=
nullptr) {
166 QInputMethodQueryEvent event(Qt::ImCursorPosition | Qt::ImSurroundingText | Qt::ImAnchorPosition | Qt::ImAbsolutePosition);
167 QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
168 sendInputState(&event);
171 acknowledge_input_method();
179 int32_t nativeScanCode,
180 int32_t nativeVirtualKey,
181 int32_t nativeModifiers,
184 if (QGuiApplication::focusObject() !=
nullptr) {
185 QKeyEvent event(QKeyEvent::Type(type),
187 Qt::KeyboardModifiers(modifiers),
194 QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
205 if (surface != m_surface) {
206 qCWarning(qLcQpaInputMethods) <<
"Got leave event for surface without corresponding enter";
223 return m_display->textInputMethodManager() !=
nullptr;
229 if (inputMethod !=
nullptr)
230 inputMethod->reset();
236 if (inputMethod !=
nullptr)
237 inputMethod->commit();
239 m_display->forceRoundTrip();
244 wl_surface *currentSurface = m_currentWindow !=
nullptr && m_currentWindow->handle() !=
nullptr
245 ?
static_cast<QWaylandWindow *>(m_currentWindow->handle())->wlSurface()
247 if (currentSurface !=
nullptr && !inputMethodAccepted()) {
248 textInputMethod()->disable(currentSurface);
249 m_currentWindow.clear();
250 }
else if (currentSurface ==
nullptr && inputMethodAccepted()) {
251 QWindow *window = QGuiApplication::focusWindow();
252 currentSurface = window !=
nullptr && window->handle() !=
nullptr
253 ?
static_cast<QWaylandWindow *>(window->handle())->wlSurface()
255 if (currentSurface !=
nullptr) {
256 textInputMethod()->disable(currentSurface);
257 m_currentWindow = window;
261 queries &= (Qt::ImEnabled
263 | Qt::ImCursorRectangle
264 | Qt::ImCursorPosition
265 | Qt::ImSurroundingText
266 | Qt::ImCurrentSelection
267 | Qt::ImAnchorPosition
268 | Qt::ImTextAfterCursor
269 | Qt::ImTextBeforeCursor
270 | Qt::ImPreferredLanguage);
272 const Qt::InputMethodQueries queriesNeedingOffset = Qt::ImCursorPosition | Qt::ImSurroundingText | Qt::ImAnchorPosition;
273 if (queries & queriesNeedingOffset)
274 queries |= queriesNeedingOffset;
277 if (inputMethod !=
nullptr && QGuiApplication::focusObject() !=
nullptr) {
278 QInputMethodQueryEvent event(queries);
279 QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
281 inputMethod->start_update(
int(queries));
283 if (queries & Qt::ImHints)
284 inputMethod->update_hints(event.value(Qt::ImHints).toInt());
286 if (queries & Qt::ImCursorRectangle) {
287 QRect rect = event.value(Qt::ImCursorRectangle).toRect();
288 inputMethod->update_cursor_rectangle(rect.x(), rect.y(), rect.width(), rect.height());
291 inputMethod->sendInputState(&event, queries);
293 if (queries & Qt::ImPreferredLanguage)
294 inputMethod->update_preferred_language(event.value(Qt::ImPreferredLanguage).toString());
296 inputMethod->end_update();
305 if (inputMethod !=
nullptr)
306 inputMethod->invoke_action(
int(action), cursorPosition);
312 if (inputMethod !=
nullptr)
313 inputMethod->show_input_panel();
319 if (inputMethod !=
nullptr)
320 inputMethod->hide_input_panel();
326 if (inputMethod !=
nullptr)
335 if (inputMethod !=
nullptr)
336 return inputMethod->keyboardRect();
344 if (inputMethod !=
nullptr)
345 return inputMethod->locale();
353 if (inputMethod !=
nullptr)
354 return inputMethod->inputDirection();
356 return Qt::LeftToRight;
362 if (inputMethod ==
nullptr)
366 inputMethod->hide_input_panel();
368 QWindow *window = QGuiApplication::focusWindow();
370 if (m_currentWindow !=
nullptr && m_currentWindow->handle() !=
nullptr) {
371 if (m_currentWindow.data() != window || !inputMethodAccepted()) {
372 auto *surface =
static_cast<QWaylandWindow *>(m_currentWindow->handle())->wlSurface();
374 inputMethod->disable(surface);
375 m_currentWindow.clear();
379 if (window !=
nullptr && window->handle() !=
nullptr && inputMethodAccepted()) {
380 if (m_currentWindow.data() != window) {
381 auto *surface =
static_cast<QWaylandWindow *>(window->handle())->wlSurface();
382 if (surface !=
nullptr) {
383 inputMethod->enable(surface);
384 m_currentWindow = window;
388 update(Qt::ImQueryAll);
394 return m_display->defaultInputDevice() ? m_display->defaultInputDevice()->textInputMethod() :
nullptr;
401#include "moc_qwaylandinputmethodcontext_p.cpp"
void update(Qt::InputMethodQueries) override
Notification on editor updates.
Qt::LayoutDirection inputDirection() const override
bool isInputPanelVisible() const override
Returns input panel visibility status.
void reset() override
Method to be called when input method needs to be reset.
void setFocusObject(QObject *object) override
This virtual method gets called to notify updated focus to object.
void hideInputPanel() override
Request to hide input panel.
QRectF keyboardRect() const override
This function can be reimplemented to return virtual keyboard rectangle in currently active window co...
~QWaylandInputMethodContext() override
void showInputPanel() override
Request to show input panel.
bool isValid() const override
Returns input context validity.
void invokeAction(QInputMethod::Action, int cursorPosition) override
Called when the word currently being composed in the input item is tapped by the user.
QLocale locale() const override
void text_input_method_v1_start_input_method_event(uint32_t serial, int32_t surrounding_text_offset) override
void text_input_method_v1_key(int32_t type, int32_t key, int32_t modifiers, int32_t autoRepeat, int32_t count, int32_t nativeScanCode, int32_t nativeVirtualKey, int32_t nativeModifiers, const QString &text) override
void text_input_method_v1_input_method_event_attribute(uint32_t serial, int32_t type, int32_t start, int32_t length, const QString &value) override
~QWaylandTextInputMethod() override
void text_input_method_v1_end_input_method_event(uint32_t serial, const QString &commitString, const QString &preeditString, int32_t replacementStart, int32_t replacementLength) override
void sendInputState(QInputMethodQueryEvent *state, Qt::InputMethodQueries queries=Qt::ImQueryInput)
void text_input_method_v1_keyboard_rectangle_changed(wl_fixed_t x, wl_fixed_t y, wl_fixed_t width, wl_fixed_t height) override
void text_input_method_v1_input_direction_changed(int32_t inputDirection) override
void text_input_method_v1_locale_changed(const QString &localeName) override
void text_input_method_v1_visible_changed(int32_t visible) override
Combined button and popup list for selecting options.
static int mapPositionFromCompositor(int pos, int offset)
static int calculateOffset(const QString &text, int cursorPos)
static constexpr int maxStringSize
static QString mapSurroundingTextToCompositor(const QString &s, int offset)
static int mapPositionToCompositor(int pos, int offset)