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 | |
13 | QT_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 | */ |
47 | QPlatformInputContext::QPlatformInputContext() |
48 | : QObject(*(new QPlatformInputContextPrivate)) |
49 | { |
50 | } |
51 | |
52 | /*! |
53 | \internal |
54 | */ |
55 | QPlatformInputContext::~QPlatformInputContext() |
56 | { |
57 | } |
58 | |
59 | /*! |
60 | Returns input context validity. Deriving implementations should return true. |
61 | */ |
62 | bool 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 | */ |
72 | bool 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 | */ |
82 | void QPlatformInputContext::reset() |
83 | { |
84 | } |
85 | |
86 | void QPlatformInputContext::commit() |
87 | { |
88 | } |
89 | |
90 | /*! |
91 | Notification on editor updates. Called by QInputMethod::update(). |
92 | */ |
93 | void 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 | */ |
102 | void 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 | */ |
117 | bool 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 | */ |
127 | QRectF 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 | */ |
137 | void 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 | */ |
146 | bool 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 | */ |
156 | void QPlatformInputContext::emitAnimatingChanged() |
157 | { |
158 | emit QGuiApplication::inputMethod()->animatingChanged(); |
159 | } |
160 | |
161 | /*! |
162 | Request to show input panel. |
163 | */ |
164 | void QPlatformInputContext::showInputPanel() |
165 | { |
166 | } |
167 | |
168 | /*! |
169 | Request to hide input panel. |
170 | */ |
171 | void QPlatformInputContext::hideInputPanel() |
172 | { |
173 | } |
174 | |
175 | /*! |
176 | Returns input panel visibility status. Default implementation returns \c false. |
177 | */ |
178 | bool 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 | */ |
188 | void QPlatformInputContext::emitInputPanelVisibleChanged() |
189 | { |
190 | emit QGuiApplication::inputMethod()->visibleChanged(); |
191 | } |
192 | |
193 | QLocale QPlatformInputContext::locale() const |
194 | { |
195 | return qt_keymapper_private()->keyboardInputLocale; |
196 | } |
197 | |
198 | void QPlatformInputContext::emitLocaleChanged() |
199 | { |
200 | emit QGuiApplication::inputMethod()->localeChanged(); |
201 | } |
202 | |
203 | Qt::LayoutDirection QPlatformInputContext::inputDirection() const |
204 | { |
205 | return qt_keymapper_private()->keyboardInputDirection; |
206 | } |
207 | |
208 | void 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 | */ |
217 | void 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 | */ |
225 | bool QPlatformInputContext::inputMethodAccepted() const |
226 | { |
227 | return QPlatformInputContextPrivate::s_inputMethodAccepted; |
228 | } |
229 | |
230 | bool QPlatformInputContextPrivate::s_inputMethodAccepted = false; |
231 | |
232 | void 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 | */ |
242 | void 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 | */ |
274 | QVariant 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 | */ |
288 | QRectF 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 | */ |
301 | QRectF 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 | */ |
313 | QRectF 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 | */ |
325 | QRectF 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 | */ |
337 | QRectF QPlatformInputContext::keyboardRectangle() |
338 | { |
339 | return QHighDpi::toNativePixels( |
340 | value: QGuiApplication::inputMethod()->keyboardRectangle(), context: QGuiApplication::focusWindow()); |
341 | } |
342 | |
343 | QT_END_NAMESPACE |
344 | |
345 | #include "moc_qplatforminputcontext.cpp" |
346 | |