1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "qplatforminputcontext.h"
41 #include <qguiapplication.h>
42 #include <QRect>
43 #include "private/qkeymapper_p.h"
44 #include <qpa/qplatforminputcontext_p.h>
45 
46 #include <QtGui/qtransform.h>
47 
48 QT_BEGIN_NAMESPACE
49 
50 /*!
51     \class QPlatformInputContext
52     \since 5.0
53     \internal
54     \preliminary
55     \ingroup qpa
56     \brief The QPlatformInputContext class abstracts the input method dependent data and composing state.
57 
58     An input method is responsible for inputting complex text that cannot
59     be inputted via simple keymap. It converts a sequence of input
60     events (typically key events) into a text string through the input
61     method specific converting process. The class of the processes are
62     widely ranging from simple finite state machine to complex text
63     translator that pools a whole paragraph of a text with text
64     editing capability to perform grammar and semantic analysis.
65 
66     To abstract such different input method specific intermediate
67     information, Qt offers the QPlatformInputContext as base class. The
68     concept is well known as 'input context' in the input method
69     domain. An input context is created for a text widget in response
70     to a demand. It is ensured that an input context is prepared for
71     an input method before input to a text widget.
72 
73     QPlatformInputContext provides an interface the actual input methods
74     can derive from by reimplementing methods.
75 
76     \sa QInputMethod
77 */
78 
79 /*!
80     \internal
81  */
QPlatformInputContext()82 QPlatformInputContext::QPlatformInputContext()
83     : QObject(*(new QPlatformInputContextPrivate))
84 {
85 }
86 
87 /*!
88     \internal
89  */
~QPlatformInputContext()90 QPlatformInputContext::~QPlatformInputContext()
91 {
92 }
93 
94 /*!
95     Returns input context validity. Deriving implementations should return true.
96  */
isValid() const97 bool QPlatformInputContext::isValid() const
98 {
99     return false;
100 }
101 
102 /*!
103     Returns whether the implementation supports \a capability.
104     \internal
105     \since 5.4
106  */
hasCapability(Capability capability) const107 bool QPlatformInputContext::hasCapability(Capability capability) const
108 {
109     Q_UNUSED(capability)
110     return true;
111 }
112 
113 /*!
114     Method to be called when input method needs to be reset. Called by QInputMethod::reset().
115     No further QInputMethodEvents should be sent as response.
116  */
reset()117 void QPlatformInputContext::reset()
118 {
119 }
120 
commit()121 void QPlatformInputContext::commit()
122 {
123 }
124 
125 /*!
126     Notification on editor updates. Called by QInputMethod::update().
127  */
update(Qt::InputMethodQueries)128 void QPlatformInputContext::update(Qt::InputMethodQueries)
129 {
130 }
131 
132 /*!
133     Called when when the word currently being composed in input item is tapped by
134     the user. Input methods often use this information to offer more word
135     suggestions to the user.
136  */
invokeAction(QInputMethod::Action action,int cursorPosition)137 void QPlatformInputContext::invokeAction(QInputMethod::Action action, int cursorPosition)
138 {
139     Q_UNUSED(cursorPosition)
140     // Default behavior for simple ephemeral input contexts. Some
141     // complex input contexts should not be reset here.
142     if (action == QInputMethod::Click)
143         reset();
144 }
145 
146 /*!
147     This function can be reimplemented to filter input events.
148     Return true if the event has been consumed. Otherwise, the unfiltered event will
149     be forwarded to widgets as ordinary way. Although the input events have accept()
150     and ignore() methods, leave it untouched.
151 */
filterEvent(const QEvent * event)152 bool QPlatformInputContext::filterEvent(const QEvent *event)
153 {
154     Q_UNUSED(event)
155     return false;
156 }
157 
158 /*!
159     This function can be reimplemented to return virtual keyboard rectangle in currently active
160     window coordinates. Default implementation returns invalid rectangle.
161  */
keyboardRect() const162 QRectF QPlatformInputContext::keyboardRect() const
163 {
164     return QRectF();
165 }
166 
167 /*!
168     Active QPlatformInputContext is responsible for providing keyboardRectangle property to QInputMethod.
169     In addition of providing the value in keyboardRect function, it also needs to call this emit
170     function whenever the property changes.
171  */
emitKeyboardRectChanged()172 void QPlatformInputContext::emitKeyboardRectChanged()
173 {
174     emit QGuiApplication::inputMethod()->keyboardRectangleChanged();
175 }
176 
177 /*!
178     This function can be reimplemented to return true whenever input method is animating
179     shown or hidden. Default implementation returns \c false.
180  */
isAnimating() const181 bool QPlatformInputContext::isAnimating() const
182 {
183     return false;
184 }
185 
186 /*!
187     Active QPlatformInputContext is responsible for providing animating property to QInputMethod.
188     In addition of providing the value in isAnimation function, it also needs to call this emit
189     function whenever the property changes.
190  */
emitAnimatingChanged()191 void QPlatformInputContext::emitAnimatingChanged()
192 {
193     emit QGuiApplication::inputMethod()->animatingChanged();
194 }
195 
196 /*!
197     Request to show input panel.
198  */
showInputPanel()199 void QPlatformInputContext::showInputPanel()
200 {
201 }
202 
203 /*!
204     Request to hide input panel.
205  */
hideInputPanel()206 void QPlatformInputContext::hideInputPanel()
207 {
208 }
209 
210 /*!
211     Returns input panel visibility status. Default implementation returns \c false.
212  */
isInputPanelVisible() const213 bool QPlatformInputContext::isInputPanelVisible() const
214 {
215     return false;
216 }
217 
218 /*!
219     Active QPlatformInputContext is responsible for providing visible property to QInputMethod.
220     In addition of providing the value in isInputPanelVisible function, it also needs to call this emit
221     function whenever the property changes.
222  */
emitInputPanelVisibleChanged()223 void QPlatformInputContext::emitInputPanelVisibleChanged()
224 {
225     emit QGuiApplication::inputMethod()->visibleChanged();
226 }
227 
locale() const228 QLocale QPlatformInputContext::locale() const
229 {
230     return qt_keymapper_private()->keyboardInputLocale;
231 }
232 
emitLocaleChanged()233 void QPlatformInputContext::emitLocaleChanged()
234 {
235     emit QGuiApplication::inputMethod()->localeChanged();
236 }
237 
inputDirection() const238 Qt::LayoutDirection QPlatformInputContext::inputDirection() const
239 {
240     return qt_keymapper_private()->keyboardInputDirection;
241 }
242 
emitInputDirectionChanged(Qt::LayoutDirection newDirection)243 void QPlatformInputContext::emitInputDirectionChanged(Qt::LayoutDirection newDirection)
244 {
245     emit QGuiApplication::inputMethod()->inputDirectionChanged(newDirection);
246 }
247 
248 /*!
249     This virtual method gets called to notify updated focus to \a object.
250     \warning Input methods must not call this function directly.
251  */
setFocusObject(QObject * object)252 void QPlatformInputContext::setFocusObject(QObject *object)
253 {
254     Q_UNUSED(object)
255 }
256 
257 /*!
258     Returns \c true if current focus object supports input method events.
259  */
inputMethodAccepted() const260 bool QPlatformInputContext::inputMethodAccepted() const
261 {
262     return QPlatformInputContextPrivate::s_inputMethodAccepted;
263 }
264 
265 bool QPlatformInputContextPrivate::s_inputMethodAccepted = false;
266 
setInputMethodAccepted(bool accepted)267 void QPlatformInputContextPrivate::setInputMethodAccepted(bool accepted)
268 {
269     QPlatformInputContextPrivate::s_inputMethodAccepted = accepted;
270 }
271 
272 /*!
273  * \brief QPlatformInputContext::setSelectionOnFocusObject
274  * \param anchorPos Beginning of selection in currently active window coordinates
275  * \param cursorPos End of selection in currently active window coordinates
276  */
setSelectionOnFocusObject(const QPointF & anchorPos,const QPointF & cursorPos)277 void QPlatformInputContext::setSelectionOnFocusObject(const QPointF &anchorPos, const QPointF &cursorPos)
278 {
279     QObject *focus = qApp->focusObject();
280     if (!focus)
281         return;
282 
283     QInputMethod *im = QGuiApplication::inputMethod();
284     const QTransform mapToLocal = im->inputItemTransform().inverted();
285     bool success;
286     int anchor = QInputMethod::queryFocusObject(Qt::ImCursorPosition, anchorPos * mapToLocal).toInt(&success);
287     if (success) {
288         int cursor = QInputMethod::queryFocusObject(Qt::ImCursorPosition, cursorPos * mapToLocal).toInt(&success);
289         if (success) {
290             if (anchor == cursor && anchorPos != cursorPos)
291                 return;
292             QList<QInputMethodEvent::Attribute> imAttributes;
293             imAttributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection, anchor, cursor - anchor, QVariant()));
294             QInputMethodEvent event(QString(), imAttributes);
295             QGuiApplication::sendEvent(focus, &event);
296         }
297     }
298 }
299 
300 QT_END_NAMESPACE
301