11#include <QtGui/qguiapplication.h>
12#include <QtGui/qtextformat.h>
13#include <QtGui/private/qguiapplication_p.h>
14#include <QtGui/private/qhighdpiscaling_p.h>
22QWaylandTextInputMethod::QWaylandTextInputMethod(QWaylandDisplay *display,
struct ::qt_text_input_method_v1 *textInputMethod)
23 : QtWayland::qt_text_input_method_v1(textInputMethod)
30 qt_text_input_method_v1_destroy(object());
35 if (m_isVisible != visible) {
36 m_isVisible = visible;
37 QGuiApplicationPrivate::platformIntegration()->inputContext()->emitInputPanelVisibleChanged();
43 m_locale = QLocale(localeName);
48 m_layoutDirection = Qt::LayoutDirection(inputDirection);
53 const QRectF keyboardRectangle(wl_fixed_to_double(x),
54 wl_fixed_to_double(y),
55 wl_fixed_to_double(width),
56 wl_fixed_to_double(height));
57 if (m_keyboardRect != keyboardRectangle) {
58 m_keyboardRect = keyboardRectangle;
59 QGuiApplicationPrivate::platformIntegration()->inputContext()->emitKeyboardRectChanged();
65 if (m_pendingInputMethodEvents.contains(serial)) {
66 qCWarning(qLcQpaInputMethods) <<
"Input method event with serial" << serial <<
"already started";
70 m_pendingInputMethodEvents[serial] = QList<QInputMethodEvent::Attribute>{};
71 m_offsetFromCompositor[serial] = surrounding_text_offset;
78 int size = text.size();
82 if (cursorPos > size - halfSize)
84 return cursorPos - halfSize;
104 if (!m_pendingInputMethodEvents.contains(serial)) {
105 qCWarning(qLcQpaInputMethods) <<
"Input method event with serial" << serial <<
"does not exist";
109 int startMapped = mapPositionFromCompositor(start, m_offsetFromCompositor[serial]);
110 QList<QInputMethodEvent::Attribute> &attributes = m_pendingInputMethodEvents[serial];
112 case QInputMethodEvent::Selection:
113 attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::AttributeType(type), startMapped, length));
115 case QInputMethodEvent::Cursor:
116 attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::AttributeType(type), start, length, QColor::fromString(value)));
118 case QInputMethodEvent::TextFormat:
120 QTextCharFormat textFormat;
121 textFormat.setProperty(QTextFormat::FontUnderline,
true);
122 textFormat.setProperty(QTextFormat::TextUnderlineStyle, QTextCharFormat::SingleUnderline);
123 attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::AttributeType(type), start, length, textFormat));
126 case QInputMethodEvent::Language:
127 case QInputMethodEvent::Ruby:
128 attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::AttributeType(type), start, length, value));
135 int cursorPosition = event->value(Qt::ImCursorPosition).toInt();
136 int anchorPosition = event->value(Qt::ImAnchorPosition).toInt();
137 QString surroundingText = event->value(Qt::ImSurroundingText).toString();
138 int offset = calculateOffset(surroundingText, cursorPosition);
140 if (queries & Qt::ImCursorPosition)
142 if (queries & Qt::ImSurroundingText)
143 update_surrounding_text(mapSurroundingTextToCompositor(surroundingText, offset), offset);
144 if (queries & Qt::ImAnchorPosition)
146 if (queries & Qt::ImAbsolutePosition)
147 update_absolute_position(event->value(Qt::ImAbsolutePosition).toInt());
153 if (!m_pendingInputMethodEvents.contains(serial)) {
154 qCWarning(qLcQpaInputMethods) <<
"Input method event with serial" << serial <<
"does not exist";
158 QList<QInputMethodEvent::Attribute> attributes = m_pendingInputMethodEvents.take(serial);
159 m_offsetFromCompositor.remove(serial);
160 if (QGuiApplication::focusObject() !=
nullptr) {
161 QInputMethodEvent event(preeditString, attributes);
162 event.setCommitString(commitString, replacementStart, replacementLength);
163 QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
167 if (QGuiApplication::focusObject() !=
nullptr) {
168 QInputMethodQueryEvent event(Qt::ImCursorPosition | Qt::ImSurroundingText | Qt::ImAnchorPosition | Qt::ImAbsolutePosition);
169 QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
170 sendInputState(&event);
173 acknowledge_input_method();
181 int32_t nativeScanCode,
182 int32_t nativeVirtualKey,
183 int32_t nativeModifiers,
186 if (QGuiApplication::focusObject() !=
nullptr) {
187 QKeyEvent event(QKeyEvent::Type(type),
189 Qt::KeyboardModifiers(modifiers),
196 QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
207 if (surface != m_surface) {
208 qCWarning(qLcQpaInputMethods) <<
"Got leave event for surface without corresponding enter";
225 return m_display->textInputMethodManager() !=
nullptr;
231 if (inputMethod !=
nullptr)
232 inputMethod->reset();
238 if (inputMethod !=
nullptr)
239 inputMethod->commit();
241 m_display->forceRoundTrip();
246 wl_surface *currentSurface = m_currentWindow !=
nullptr && m_currentWindow->handle() !=
nullptr
247 ?
static_cast<QWaylandWindow *>(m_currentWindow->handle())->wlSurface()
249 if (currentSurface !=
nullptr && !inputMethodAccepted()) {
250 textInputMethod()->disable(currentSurface);
251 m_currentWindow.clear();
252 }
else if (currentSurface ==
nullptr && inputMethodAccepted()) {
253 QWindow *window = QGuiApplication::focusWindow();
254 currentSurface = window !=
nullptr && window->handle() !=
nullptr
255 ?
static_cast<QWaylandWindow *>(window->handle())->wlSurface()
257 if (currentSurface !=
nullptr) {
258 textInputMethod()->disable(currentSurface);
259 m_currentWindow = window;
263 queries &= (Qt::ImEnabled
265 | Qt::ImCursorRectangle
266 | Qt::ImCursorPosition
267 | Qt::ImSurroundingText
268 | Qt::ImCurrentSelection
269 | Qt::ImAnchorPosition
270 | Qt::ImTextAfterCursor
271 | Qt::ImTextBeforeCursor
272 | Qt::ImPreferredLanguage);
274 const Qt::InputMethodQueries queriesNeedingOffset = Qt::ImCursorPosition | Qt::ImSurroundingText | Qt::ImAnchorPosition;
275 if (queries & queriesNeedingOffset)
276 queries |= queriesNeedingOffset;
279 if (inputMethod !=
nullptr && QGuiApplication::focusObject() !=
nullptr) {
280 QInputMethodQueryEvent event(queries);
281 QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
283 inputMethod->start_update(
int(queries));
285 if (queries & Qt::ImHints)
286 inputMethod->update_hints(event.value(Qt::ImHints).toInt());
288 if (queries & Qt::ImCursorRectangle) {
289 QRect cRect = event.value(Qt::ImCursorRectangle).toRect();
290 QWindow *window = QGuiApplication::focusWindow();
292 const QRect windowRect = QGuiApplication::inputMethod()->inputItemTransform().mapRect(cRect);
293 const QRect nativeRect = QHighDpi::toNativePixels(windowRect, window);
294 auto *waylandWindow =
static_cast<QWaylandWindow *>(window->handle());
296 const QMargins margins = waylandWindow->clientSideMargins();
297 cRect = nativeRect.translated(margins.left(), margins.top());
302 inputMethod->update_cursor_rectangle(cRect.x(), cRect.y(), cRect.width(), cRect.height());
305 inputMethod->sendInputState(&event, queries);
307 if (queries & Qt::ImPreferredLanguage)
308 inputMethod->update_preferred_language(event.value(Qt::ImPreferredLanguage).toString());
310 inputMethod->end_update();
319 if (inputMethod !=
nullptr)
320 inputMethod->invoke_action(
int(action), cursorPosition);
326 if (inputMethod !=
nullptr)
327 inputMethod->show_input_panel();
333 if (inputMethod !=
nullptr)
334 inputMethod->hide_input_panel();
340 if (inputMethod !=
nullptr)
349 if (inputMethod !=
nullptr)
350 return inputMethod->keyboardRect();
358 if (inputMethod !=
nullptr)
359 return inputMethod->locale();
367 if (inputMethod !=
nullptr)
368 return inputMethod->inputDirection();
370 return Qt::LeftToRight;
376 if (inputMethod ==
nullptr)
380 inputMethod->hide_input_panel();
382 QWindow *window = QGuiApplication::focusWindow();
384 if (m_currentWindow !=
nullptr && m_currentWindow->handle() !=
nullptr) {
385 if (m_currentWindow.data() != window || !inputMethodAccepted()) {
386 auto *surface =
static_cast<QWaylandWindow *>(m_currentWindow->handle())->wlSurface();
388 inputMethod->disable(surface);
389 m_currentWindow.clear();
393 if (window !=
nullptr && window->handle() !=
nullptr && inputMethodAccepted()) {
394 if (m_currentWindow.data() != window) {
395 auto *surface =
static_cast<QWaylandWindow *>(window->handle())->wlSurface();
396 if (surface !=
nullptr) {
397 inputMethod->enable(surface);
398 m_currentWindow = window;
402 update(Qt::ImQueryAll);
408 return m_display->defaultInputDevice() ? m_display->defaultInputDevice()->textInputMethod() :
nullptr;
415#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_leave(struct ::wl_surface *surface) 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_enter(struct ::wl_surface *surface) 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)