1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qplatforminputcontext.h"
5#include <qguiapplication.h>
6#include <QRect>
7#include "private/qkeymapper_p.h"
8#include "private/qhighdpiscaling_p.h"
9#include <qpa/qplatforminputcontext_p.h>
10
11#include <QtGui/qtransform.h>
12
13QT_BEGIN_NAMESPACE
14
15/*!
16 \class QPlatformInputContext
17 \since 5.0
18 \internal
19 \preliminary
20 \ingroup qpa
21 \brief The QPlatformInputContext class abstracts the input method dependent data and composing state.
22
23 An input method is responsible for inputting complex text that cannot
24 be inputted via simple keymap. It converts a sequence of input
25 events (typically key events) into a text string through the input
26 method specific converting process. The class of the processes are
27 widely ranging from simple finite state machine to complex text
28 translator that pools a whole paragraph of a text with text
29 editing capability to perform grammar and semantic analysis.
30
31 To abstract such different input method specific intermediate
32 information, Qt offers the QPlatformInputContext as base class. The
33 concept is well known as 'input context' in the input method
34 domain. An input context is created for a text widget in response
35 to a demand. It is ensured that an input context is prepared for
36 an input method before input to a text widget.
37
38 QPlatformInputContext provides an interface the actual input methods
39 can derive from by reimplementing methods.
40
41 \sa QInputMethod
42*/
43
44/*!
45 \internal
46 */
47QPlatformInputContext::QPlatformInputContext()
48 : QObject(*(new QPlatformInputContextPrivate))
49{
50}
51
52/*!
53 \internal
54 */
55QPlatformInputContext::~QPlatformInputContext()
56{
57}
58
59/*!
60 Returns input context validity. Deriving implementations should return true.
61 */
62bool QPlatformInputContext::isValid() const
63{
64 return false;
65}
66
67/*!
68 Returns whether the implementation supports \a capability.
69 \internal
70 \since 5.4
71 */
72bool QPlatformInputContext::hasCapability(Capability capability) const
73{
74 Q_UNUSED(capability);
75 return true;
76}
77
78/*!
79 Method to be called when input method needs to be reset. Called by QInputMethod::reset().
80 No further QInputMethodEvents should be sent as response.
81 */
82void QPlatformInputContext::reset()
83{
84}
85
86void QPlatformInputContext::commit()
87{
88}
89
90/*!
91 Notification on editor updates. Called by QInputMethod::update().
92 */
93void QPlatformInputContext::update(Qt::InputMethodQueries)
94{
95}
96
97/*!
98 Called when the word currently being composed in the input item is tapped by
99 the user. Input methods often use this information to offer more word
100 suggestions to the user.
101 */
102void QPlatformInputContext::invokeAction(QInputMethod::Action action, int cursorPosition)
103{
104 Q_UNUSED(cursorPosition);
105 // Default behavior for simple ephemeral input contexts. Some
106 // complex input contexts should not be reset here.
107 if (action == QInputMethod::Click)
108 reset();
109}
110
111/*!
112 This function can be reimplemented to filter input events.
113 Return true if the event has been consumed. Otherwise, the unfiltered event will
114 be forwarded to widgets as ordinary way. Although the input events have accept()
115 and ignore() methods, leave it untouched.
116*/
117bool QPlatformInputContext::filterEvent(const QEvent *event)
118{
119 Q_UNUSED(event);
120 return false;
121}
122
123/*!
124 This function can be reimplemented to return virtual keyboard rectangle in currently active
125 window coordinates. Default implementation returns invalid rectangle.
126 */
127QRectF QPlatformInputContext::keyboardRect() const
128{
129 return QRectF();
130}
131
132/*!
133 Active QPlatformInputContext is responsible for providing keyboardRectangle property to QInputMethod.
134 In addition of providing the value in keyboardRect function, it also needs to call this emit
135 function whenever the property changes.
136 */
137void QPlatformInputContext::emitKeyboardRectChanged()
138{
139 emit QGuiApplication::inputMethod()->keyboardRectangleChanged();
140}
141
142/*!
143 This function can be reimplemented to return true whenever input method is animating
144 shown or hidden. Default implementation returns \c false.
145 */
146bool QPlatformInputContext::isAnimating() const
147{
148 return false;
149}
150
151/*!
152 Active QPlatformInputContext is responsible for providing animating property to QInputMethod.
153 In addition of providing the value in isAnimation function, it also needs to call this emit
154 function whenever the property changes.
155 */
156void QPlatformInputContext::emitAnimatingChanged()
157{
158 emit QGuiApplication::inputMethod()->animatingChanged();
159}
160
161/*!
162 Request to show input panel.
163 */
164void QPlatformInputContext::showInputPanel()
165{
166}
167
168/*!
169 Request to hide input panel.
170 */
171void QPlatformInputContext::hideInputPanel()
172{
173}
174
175/*!
176 Returns input panel visibility status. Default implementation returns \c false.
177 */
178bool QPlatformInputContext::isInputPanelVisible() const
179{
180 return false;
181}
182
183/*!
184 Active QPlatformInputContext is responsible for providing visible property to QInputMethod.
185 In addition of providing the value in isInputPanelVisible function, it also needs to call this emit
186 function whenever the property changes.
187 */
188void QPlatformInputContext::emitInputPanelVisibleChanged()
189{
190 emit QGuiApplication::inputMethod()->visibleChanged();
191}
192
193QLocale QPlatformInputContext::locale() const
194{
195 return qt_keymapper_private()->keyboardInputLocale;
196}
197
198void QPlatformInputContext::emitLocaleChanged()
199{
200 emit QGuiApplication::inputMethod()->localeChanged();
201}
202
203Qt::LayoutDirection QPlatformInputContext::inputDirection() const
204{
205 return qt_keymapper_private()->keyboardInputDirection;
206}
207
208void QPlatformInputContext::emitInputDirectionChanged(Qt::LayoutDirection newDirection)
209{
210 emit QGuiApplication::inputMethod()->inputDirectionChanged(newDirection);
211}
212
213/*!
214 This virtual method gets called to notify updated focus to \a object.
215 \warning Input methods must not call this function directly.
216 */
217void QPlatformInputContext::setFocusObject(QObject *object)
218{
219 Q_UNUSED(object);
220}
221
222/*!
223 Returns \c true if current focus object supports input method events.
224 */
225bool QPlatformInputContext::inputMethodAccepted() const
226{
227 return QPlatformInputContextPrivate::s_inputMethodAccepted;
228}
229
230bool QPlatformInputContextPrivate::s_inputMethodAccepted = false;
231
232void QPlatformInputContextPrivate::setInputMethodAccepted(bool accepted)
233{
234 QPlatformInputContextPrivate::s_inputMethodAccepted = accepted;
235}
236
237/*!
238 \brief QPlatformInputContext::setSelectionOnFocusObject
239 \param anchorPos Beginning of selection in currently active window native coordinates
240 \param cursorPos End of selection in currently active window native coordinates
241*/
242void QPlatformInputContext::setSelectionOnFocusObject(const QPointF &nativeAnchorPos, const QPointF &nativeCursorPos)
243{
244 QObject *focus = qApp->focusObject();
245 if (!focus)
246 return;
247
248 QWindow *window = qApp->focusWindow();
249 const QPointF &anchorPos = QHighDpi::fromNativePixels(value: nativeAnchorPos, context: window);
250 const QPointF &cursorPos = QHighDpi::fromNativePixels(value: nativeCursorPos, context: window);
251
252 QInputMethod *im = QGuiApplication::inputMethod();
253 const QTransform mapToLocal = im->inputItemTransform().inverted();
254 bool success;
255 int anchor = QInputMethod::queryFocusObject(query: Qt::ImCursorPosition, argument: anchorPos * mapToLocal).toInt(ok: &success);
256 if (success) {
257 int cursor = QInputMethod::queryFocusObject(query: Qt::ImCursorPosition, argument: cursorPos * mapToLocal).toInt(ok: &success);
258 if (success) {
259 if (anchor == cursor && anchorPos != cursorPos)
260 return;
261 QList<QInputMethodEvent::Attribute> imAttributes;
262 imAttributes.append(t: QInputMethodEvent::Attribute(QInputMethodEvent::Selection, anchor, cursor - anchor, QVariant()));
263 QInputMethodEvent event(QString(), imAttributes);
264 QGuiApplication::sendEvent(receiver: focus, event: &event);
265 }
266 }
267}
268
269/*!
270 \brief QPlatformInputContext::queryFocusObject
271
272 Queries the current foucus object with a window position in native pixels.
273*/
274QVariant QPlatformInputContext::queryFocusObject(Qt::InputMethodQuery query, QPointF nativePosition)
275{
276 const QPointF position = QHighDpi::fromNativePixels(value: nativePosition, context: QGuiApplication::focusWindow());
277 const QInputMethod *im = QGuiApplication::inputMethod();
278 const QTransform mapToLocal = im->inputItemTransform().inverted();
279 return im->queryFocusObject(query, argument: mapToLocal.map(p: position));
280}
281
282/*!
283 \brief QPlatformInputContext::inputItemRectangle
284
285 Returns the input item rectangle for the currently active window
286 and input methiod in native window coordinates.
287*/
288QRectF QPlatformInputContext::inputItemRectangle()
289{
290 QInputMethod *im = QGuiApplication::inputMethod();
291 const QRectF deviceIndependentRectangle = im->inputItemTransform().mapRect(im->inputItemRectangle());
292 return QHighDpi::toNativePixels(value: deviceIndependentRectangle, context: QGuiApplication::focusWindow());
293}
294
295/*!
296 \brief QPlatformInputContext::inputItemClipRectangle
297
298 Returns the input item clip rectangle for the currently active window
299 and input methiod in native window coordinates.
300*/
301QRectF QPlatformInputContext::inputItemClipRectangle()
302{
303 return QHighDpi::toNativePixels(
304 value: QGuiApplication::inputMethod()->inputItemClipRectangle(), context: QGuiApplication::focusWindow());
305}
306
307/*!
308 \brief QPlatformInputContext::cursorRectangle
309
310 Returns the cursor rectangle for the currently active window
311 and input methiod in native window coordinates.
312*/
313QRectF QPlatformInputContext::cursorRectangle()
314{
315 return QHighDpi::toNativePixels(
316 value: QGuiApplication::inputMethod()->cursorRectangle(), context: QGuiApplication::focusWindow());
317}
318
319/*!
320 \brief QPlatformInputContext::anchorRectangle
321
322 Returns the anchor rectangle for the currently active window
323 and input methiod in native window coordinates.
324*/
325QRectF QPlatformInputContext::anchorRectangle()
326{
327 return QHighDpi::toNativePixels(
328 value: QGuiApplication::inputMethod()->anchorRectangle(), context: QGuiApplication::focusWindow());
329}
330
331/*!
332 \brief QPlatformInputContext::keyboardRectangle
333
334 Returns the keyboard rectangle for the currently active window
335 and input methiod in native window coordinates.
336*/
337QRectF QPlatformInputContext::keyboardRectangle()
338{
339 return QHighDpi::toNativePixels(
340 value: QGuiApplication::inputMethod()->keyboardRectangle(), context: QGuiApplication::focusWindow());
341}
342
343QT_END_NAMESPACE
344
345#include "moc_qplatforminputcontext.cpp"
346

source code of qtbase/src/gui/kernel/qplatforminputcontext.cpp