An error occurred while loading the file. Please try again.
-
Frederik Gladhorn authored
Change-Id: Ic3528e5de45871818e105cde5ab6b5465db09623 Reviewed-by:
Mitch Curtis <mitch.curtis@digia.com>
a565b4c8
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc
** All rights reserved.
** For any questions to Digia, please use contact form at http://qt.digia.com
**
** This file is part of the Qt Quick Enterprise Controls add-on.
**
** Licensees holding valid Qt Enterprise licenses may use this file in
** accordance with the Qt Enterprise License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.
**
** If you have questions regarding the use of this file, please use
** contact form at http://qt.digia.com
**
****************************************************************************/
#include "declarativeinputengine.h"
#include "declarativeinputcontext.h"
#include "defaultinputmethod.h"
#include "virtualkeyboarddebug.h"
#include <QTimerEvent>
class DeclarativeInputEnginePrivate
{
public:
virtual ~DeclarativeInputEnginePrivate() { }
DeclarativeInputContext *inputContext;
QPointer<AbstractInputMethod> inputMethod;
AbstractInputMethod *defaultInputMethod;
DeclarativeInputEngine::TextCase textCase;
DeclarativeInputEngine::InputMode inputMode;
QMap<DeclarativeSelectionListModel::Type, DeclarativeSelectionListModel *> selectionListModels;
Qt::Key activeKey;
QString activeKeyText;
Qt::KeyboardModifiers activeKeyModifiers;
Qt::Key previousKey;
int repeatTimer;
int repeatCount;
int recursiveMethodLock;
};
class RecursiveMethodGuard
{
public:
explicit RecursiveMethodGuard(int &ref) : m_ref(ref)
{
m_ref++;
}
~RecursiveMethodGuard()
{
m_ref--;
}
bool locked() const
{
return m_ref > 1;
}
private:
int &m_ref;
};
/*!
\qmltype InputEngine
\inqmlmodule QtQuick.Enterprise.VirtualKeyboard 1.0
\ingroup qtvirtualkeyboard-qml
\instantiates DeclarativeInputEngine
\brief Maps the user input to the input methods.
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
The input engine is responsible for routing input events to input
methods. The actual input logic is implemented by the input methods.
The input engine also includes the default input method, which takes
care of default processing if the active input method does not handle
the event.
*/
/*!
\class DeclarativeInputEngine
\inmodule InputFramework
\brief The DeclarativeInputEngine class provides an input engine
that supports C++ and QML integration.
The input engine is responsible for routing input events to input
methods. The actual input logic is implemented by the input methods.
The input engine also includes the default input method, which takes
care of default processing if the active input method does not handle
the event.
*/
/*!
\internal
Constructs an input engine with input context as \a parent.
*/
DeclarativeInputEngine::DeclarativeInputEngine(DeclarativeInputContext *parent) :
QObject(parent),
d_ptr(new DeclarativeInputEnginePrivate())
{
Q_D(DeclarativeInputEngine);
d->inputContext = parent;
if (d->inputContext) {
connect(d->inputContext, SIGNAL(shiftChanged()), SLOT(shiftChanged()));
connect(d->inputContext, SIGNAL(localeChanged()), SLOT(localeChanged()));
}
d->defaultInputMethod = new DefaultInputMethod(this);
if (d->defaultInputMethod)
d->defaultInputMethod->setInputEngine(this);
d->textCase = Lower;
d->inputMode = Latin;
d->selectionListModels[DeclarativeSelectionListModel::WordCandidateList] = new DeclarativeSelectionListModel(this);
d->activeKey = Qt::Key_unknown;
d->previousKey = Qt::Key_unknown;
}
/*!
\internal
Destroys the input engine and frees all allocated resources.
*/
DeclarativeInputEngine::~DeclarativeInputEngine()
{
}
/*!
\qmlmethod bool InputEngine::virtualKeyPress(int key, string text, int modifiers, bool repeat)
Called by the keyboard layer to indicate that \a key was pressed, with
the given \a text and \a modifiers.
The \a key is set as an active key (down key). The actual key event is
triggered when the key is released by the virtualKeyRelease() method. The
key press event can be discarded by calling virtualKeyCancel().
The key press also initiates the key repeat timer if \a repeat is \c true.
Returns \c true if the key was accepted by this input engine.
\sa virtualKeyCancel(), virtualKeyRelease()
*/
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
/*!
Called by the keyboard layer to indicate that \a key was pressed, with
the given \a text and \a modifiers.
The \a key is set as an active key (down key). The actual key event is
triggered when the key is released by the virtualKeyRelease() method. The
key press event can be discarded by calling virtualKeyCancel().
The key press also initiates the key repeat timer if \a repeat is \c true.
Returns \c true if the key was accepted by this input engine.
\sa virtualKeyCancel(), virtualKeyRelease()
*/
bool DeclarativeInputEngine::virtualKeyPress(Qt::Key key, const QString &text, Qt::KeyboardModifiers modifiers, bool repeat)
{
Q_D(DeclarativeInputEngine);
VIRTUALKEYBOARD_DEBUG() << "DeclarativeInputEngine::virtualKeyPress():" << key << text << modifiers << repeat;
bool accept = false;
if (d->activeKey == Qt::Key_unknown || d->activeKey == key) {
d->activeKey = key;
d->activeKeyText = text;
d->activeKeyModifiers = modifiers;
if (repeat) {
d->repeatTimer = startTimer(600);
}
accept = true;
emit activeKeyChanged(d->activeKey);
} else {
qWarning("key press ignored; key is already active");
}
return accept;
}
/*!
\qmlmethod void InputEngine::virtualKeyCancel()
Reverts the active key state without emitting the key event.
This method is useful when the user discards the current key and
the key state needs to be restored.
*/
/*!
Reverts the active key state without emitting the key event.
This method is useful when the user discards the current key and
the key state needs to be restored.
*/
void DeclarativeInputEngine::virtualKeyCancel()
{
Q_D(DeclarativeInputEngine);
VIRTUALKEYBOARD_DEBUG() << "DeclarativeInputEngine::virtualKeyCancel()";
if (d->activeKey != Qt::Key_unknown) {
d->activeKey = Qt::Key_unknown;
d->activeKeyText = QString();
d->activeKeyModifiers = Qt::KeyboardModifiers();
if (d->repeatTimer) {
killTimer(d->repeatTimer);
d->repeatTimer = 0;
d->repeatCount = 0;
}
emit activeKeyChanged(d->activeKey);
}
}
/*!
\qmlmethod bool InputEngine::virtualKeyRelease(int key, string text, int modifiers)
Releases the key at \a key. The method emits a key event for the input
method if the event has not been generated by a repeating timer.
The \a text and \a modifiers are passed to the input method.
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
Returns \c true if the key was accepted by the input engine.
*/
/*!
Releases the key at \a key. The method emits a key event for the input
method if the event has not been generated by a repeating timer.
The \a text and \a modifiers are passed to the input method.
Returns \c true if the key was accepted by the input engine.
*/
bool DeclarativeInputEngine::virtualKeyRelease(Qt::Key key, const QString &text, Qt::KeyboardModifiers modifiers)
{
Q_D(DeclarativeInputEngine);
VIRTUALKEYBOARD_DEBUG() << "DeclarativeInputEngine::virtualKeyRelease():" << key << text << modifiers;
bool accept = false;
if (d->activeKey == key) {
if (!d->repeatCount) {
accept = virtualKeyClick(key, text, modifiers);
} else {
accept = true;
}
} else {
qWarning("key release ignored; key is not pressed");
}
if (d->activeKey != Qt::Key_unknown) {
d->previousKey = d->activeKey;
emit previousKeyChanged(d->previousKey);
d->activeKey = Qt::Key_unknown;
d->activeKeyText = QString();
d->activeKeyModifiers = Qt::KeyboardModifiers();
if (d->repeatTimer) {
killTimer(d->repeatTimer);
d->repeatTimer = 0;
d->repeatCount = 0;
}
emit activeKeyChanged(d->activeKey);
}
return accept;
}
/*!
\qmlmethod bool InputEngine::virtualKeyClick(int key, string text, int modifiers)
Emits a key click event for the given \a key, \a text and \a modifiers.
Returns \c true if the key event was accepted by the input engine.
*/
/*!
Emits a key click event for the given \a key, \a text and \a modifiers.
Returns \c true if the key event was accepted by the input engine.
*/
bool DeclarativeInputEngine::virtualKeyClick(Qt::Key key, const QString &text, Qt::KeyboardModifiers modifiers)
{
Q_D(DeclarativeInputEngine);
bool accept = false;
if (d->inputMethod) {
RecursiveMethodGuard guard(d->recursiveMethodLock);
if (!guard.locked()) {
accept = d->inputMethod->keyEvent(key, text, modifiers);
if (!accept) {
accept = d->defaultInputMethod->keyEvent(key, text, modifiers);
}
emit virtualKeyClicked(key, text, modifiers);
}
} else {
qWarning() << "input method is not set";
}
return accept;
}
/*!
Returns the \c DeclarativeInputContext instance associated with the input
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
engine.
*/
DeclarativeInputContext *DeclarativeInputEngine::inputContext() const
{
Q_D(const DeclarativeInputEngine);
return d->inputContext;
}
/*!
Returns the currently active key, or Qt::Key_unknown if no key is active.
*/
Qt::Key DeclarativeInputEngine::activeKey() const
{
Q_D(const DeclarativeInputEngine);
return d->activeKey;
}
/*!
Returns the previously active key, or Qt::Key_unknown if no key has been
active.
*/
Qt::Key DeclarativeInputEngine::previousKey() const
{
Q_D(const DeclarativeInputEngine);
return d->previousKey;
}
/*!
Returns the active input method.
*/
AbstractInputMethod *DeclarativeInputEngine::inputMethod() const
{
Q_D(const DeclarativeInputEngine);
return d->inputMethod;
}
/*!
Sets \a inputMethod as the active input method.
*/
void DeclarativeInputEngine::setInputMethod(AbstractInputMethod *inputMethod)
{
Q_D(DeclarativeInputEngine);
VIRTUALKEYBOARD_DEBUG() << "DeclarativeInputEngine::setInputMethod():" << inputMethod;
if (!d->inputMethod || !inputMethod || d->inputMethod->className() != inputMethod->className()) {
update();
if (d->inputMethod) {
d->inputMethod->setInputEngine(0);
}
d->inputMethod = inputMethod;
if (d->inputMethod) {
d->inputMethod->setInputEngine(this);
// Allocate selection lists for the input method
QList<DeclarativeSelectionListModel::Type> activeSelectionLists = d->inputMethod->selectionLists();
QList<DeclarativeSelectionListModel::Type> inactiveSelectionLists = d->selectionListModels.keys();
foreach (const DeclarativeSelectionListModel::Type &selectionListType, activeSelectionLists) {
if (!d->selectionListModels.contains(selectionListType)) {
d->selectionListModels[selectionListType] = new DeclarativeSelectionListModel(this);
if (selectionListType == DeclarativeSelectionListModel::WordCandidateList) {
emit wordCandidateListModelChanged();
}
}
d->selectionListModels[selectionListType]->setDataSource(inputMethod, selectionListType);
if (selectionListType == DeclarativeSelectionListModel::WordCandidateList) {
emit wordCandidateListVisibleHintChanged();
}
inactiveSelectionLists.removeAll(selectionListType);
}
// Deallocate inactive selection lists
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
foreach (const DeclarativeSelectionListModel::Type &selectionListType, inactiveSelectionLists) {
if (d->selectionListModels.contains(selectionListType)) {
d->selectionListModels[selectionListType]->setDataSource(0, selectionListType);
if (selectionListType == DeclarativeSelectionListModel::WordCandidateList) {
emit wordCandidateListVisibleHintChanged();
}
}
}
}
emit inputMethodChanged();
emit inputModesChanged();
}
}
/*!
Returns the list of available input modes.
*/
QList<int> DeclarativeInputEngine::inputModes() const
{
Q_D(const DeclarativeInputEngine);
QList<InputMode> inputModeList;
if (d->inputMethod) {
inputModeList = d->inputMethod->inputModes(d->inputContext->locale());
}
if (inputModeList.isEmpty()) {
return QList<int>();
}
QList<int> resultList;
foreach (const InputMode &inputMode, inputModeList) {
resultList.append(inputMode);
}
return resultList;
}
DeclarativeInputEngine::InputMode DeclarativeInputEngine::inputMode() const
{
Q_D(const DeclarativeInputEngine);
return d->inputMode;
}
void DeclarativeInputEngine::setInputMode(DeclarativeInputEngine::InputMode inputMode)
{
Q_D(DeclarativeInputEngine);
VIRTUALKEYBOARD_DEBUG() << "DeclarativeInputEngine::setInputMode():" << inputMode;
if (d->inputMethod) {
const QString locale(d->inputContext->locale());
QList<DeclarativeInputEngine::InputMode> inputModeList(d->inputMethod->inputModes(locale));
if (inputModeList.contains(inputMode)) {
d->inputMethod->setInputMode(locale, d->inputMode);
d->inputMode = inputMode;
emit inputModeChanged();
} else {
qWarning() << "the input mode" << inputMode << "is not valid";
}
}
}
DeclarativeSelectionListModel *DeclarativeInputEngine::wordCandidateListModel() const
{
Q_D(const DeclarativeInputEngine);
return d->selectionListModels[DeclarativeSelectionListModel::WordCandidateList];
}
bool DeclarativeInputEngine::wordCandidateListVisibleHint() const
{
Q_D(const DeclarativeInputEngine);
if (!d->selectionListModels.contains(DeclarativeSelectionListModel::WordCandidateList))
return false;
return d->selectionListModels[DeclarativeSelectionListModel::WordCandidateList]->dataSource() != 0;
}
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
/*!
\internal
Resets the input method.
*/
void DeclarativeInputEngine::reset()
{
Q_D(DeclarativeInputEngine);
if (d->inputMethod) {
RecursiveMethodGuard guard(d->recursiveMethodLock);
if (!guard.locked()) {
emit inputMethodReset();
}
}
}
/*!
\internal
Updates the input method's state. This method is called whenever the input
context is changed.
*/
void DeclarativeInputEngine::update()
{
Q_D(DeclarativeInputEngine);
if (d->inputMethod) {
RecursiveMethodGuard guard(d->recursiveMethodLock);
if (!guard.locked()) {
emit inputMethodUpdate();
}
}
}
/*!
\internal
Updates the text case for the input method.
*/
void DeclarativeInputEngine::shiftChanged()
{
Q_D(DeclarativeInputEngine);
TextCase newCase = d->inputContext->shift() ? Upper : Lower;
if (d->textCase == newCase) {
d->textCase = newCase;
if (d->inputMethod) {
d->inputMethod->setTextCase(d->textCase);
}
}
}
/*!
\internal
Updates the input mode when the locale has changed.
*/
void DeclarativeInputEngine::localeChanged()
{
Q_D(DeclarativeInputEngine);
update();
setInputMode(d->inputMode);
}
/*!
\internal
*/
void DeclarativeInputEngine::timerEvent(QTimerEvent *timerEvent)
{
Q_D(DeclarativeInputEngine);
if (timerEvent->timerId() == d->repeatTimer) {
d->repeatTimer = 0;
virtualKeyClick(d->activeKey, d->activeKeyText, d->activeKeyModifiers);
d->repeatTimer = startTimer(50);
d->repeatCount++;
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
}
}
/*!
\qmlproperty int InputEngine::activeKey
Currently pressed key.
*/
/*!
\property DeclarativeInputEngine::activeKey
\brief the active key.
Currently pressed key.
*/
/*!
\qmlproperty int InputEngine::previousKey
Previously pressed key.
*/
/*!
\property DeclarativeInputEngine::previousKey
\brief the previous active key.
Previously pressed key.
*/
/*!
\qmlproperty InputMethod InputEngine::inputMethod
Use this property to set the active input method, or to monitor when the
active input method changes.
*/
/*!
\property DeclarativeInputEngine::inputMethod
\brief the active input method.
Use this property to set active the input method, or to monitor when the
active input method changes.
*/
/*!
\qmlproperty list<int> InputEngine::inputModes
The list of available input modes is dependent on the input method and
locale. This property is updated when either of the dependencies change.
*/
/*!
\property DeclarativeInputEngine::inputModes
\brief the available input modes for active input method.
The list of available input modes is dependent on the input method and
locale. This property is updated when either of the dependencies changes.
*/
/*!
\qmlproperty int InputEngine::inputMode
Use this property to get or set the current input mode. The
InputEngine::inputModes property provides the list of valid input modes
for the current input method and locale.
The predefined input modes are:
\list
\li \c InputEngine.Latin The default input mode for latin text.
\li \c InputEngine.Numeric Only numeric input is allowed.
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
\li \c InputEngine.Dialable Only dialable input is allowed.
\endlist
*/
/*!
\property DeclarativeInputEngine::inputMode
\brief the current input mode.
Use this property to get or set the current input mode. The
DeclarativeInputEngine::inputModes provides list of valid input modes
for current input method and locale.
*/
/*!
\qmlproperty SelectionListModel InputEngine::wordCandidateListModel
Use this property to access the list model for the word candidate
list.
*/
/*!
\property DeclarativeInputEngine::wordCandidateListModel
\brief list model for the word candidate list.
Use this property to access the list model for the word candidate
list.
*/
/*!
\qmlproperty bool InputEngine::wordCandidateListVisibleHint
Use this property to check if the word candidate list should be visible
in the UI.
*/
/*!
\property DeclarativeInputEngine::wordCandidateListVisibleHint
\brief visible hint for the word candidate list.
Use this property to check if the word candidate list should be visible
in the UI.
*/
/*!
\enum DeclarativeInputEngine::InputMode
This enum specifies the input mode for the input method.
\value Latin
The default input mode for latin text.
\value Numeric
Only numeric input is allowed.
\value Dialable
Only dialable input is allowed.
*/
/*!
\enum DeclarativeInputEngine::TextCase
This enum specifies the text case for the input method.
\value Lower
Lower case text.
\value Upper
Upper case text.
*/
/*!
\qmlsignal void InputEngine::virtualKeyClicked(int key, string text, int modifiers)
631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
Indicates that the virtual \a key was clicked with the given \a text and
\a modifiers.
This signal is emitted after the input method has processed the key event.
*/
/*!
\fn void DeclarativeInputEngine::virtualKeyClicked(Qt::Key key, const QString &text, Qt::KeyboardModifiers modifiers)
Indicates that the virtual \a key was clicked with the given \a text and
\a modifiers.
This signal is emitted after the input method has processed the key event.
*/
/*!
\qmlsignal void InputEngine::activeKeyChanged(int key)
Indicates that the active \a key has changed.
*/
/*!
\fn void DeclarativeInputEngine::activeKeyChanged(Qt::Key key)
Indicates that the active \a key has changed.
*/
/*!
\qmlsignal void InputEngine::previousKeyChanged(int key)
Indicates that the previous \a key has changed.
*/
/*!
\fn void DeclarativeInputEngine::previousKeyChanged(Qt::Key key)
Indicates that the previous \a key has changed.
*/
/*!
\qmlsignal void InputEngine::inputMethodChanged()
Indicates that the input method has changed.
*/
/*!
\fn void DeclarativeInputEngine::inputMethodChanged()
Indicates that the input method has changed.
*/
/*!
\qmlsignal void InputEngine::inputMethodReset()
Emitted when the input method needs to be reset.
\note This signal is automatically connected to AbstractInputMethod::reset()
and InputMethod::reset() when the input method is activated.
*/
/*!
\fn void DeclarativeInputEngine::inputMethodReset()
Emitted when the input method needs to be reset.
\note This signal is automatically connected to AbstractInputMethod::reset()
and InputMethod::reset() when the input method is activated.
*/
/*!
\qmlsignal void InputEngine::inputMethodUpdate()
701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
\note This signal is automatically connected to AbstractInputMethod::update()
and InputMethod::update() when the input method is activated.
*/
/*!
\fn void DeclarativeInputEngine::inputMethodUpdate()
\note This signal is automatically connected to AbstractInputMethod::update()
and InputMethod::update() when the input method is activated.
*/
/*!
\qmlsignal void InputEngine::inputModesChanged()
Indicates that the available input modes have changed.
*/
/*!
\fn void DeclarativeInputEngine::inputModesChanged()
Indicates that the available input modes have changed.
*/
/*!
\qmlsignal void InputEngine::inputModeChanged()
Indicates that the input mode has changed.
*/
/*!
\fn void DeclarativeInputEngine::inputModeChanged()
Indicates that the input mode has changed.
*/