//============================================================================ // INCLUDES //============================================================================ #include "FreeVirtualKeyboardInputContext.h" #include #include #include #include #include #include #include #include #include #include #include #include "DeclarativeInputEngine.h" /** * Private data class for FreeVirtualKeyboardInputContext */ class FreeVirtualKeyboardInputContextPrivate { public: FreeVirtualKeyboardInputContextPrivate(); QQuickFlickable* Flickable; QQuickItem* FocusItem; bool Visible; DeclarativeInputEngine* InputEngine; QPropertyAnimation* FlickableContentScrollAnimation;//< for smooth scrolling of flickable content item }; //============================================================================== FreeVirtualKeyboardInputContextPrivate::FreeVirtualKeyboardInputContextPrivate() : Flickable(0), FocusItem(0), Visible(false), InputEngine(new DeclarativeInputEngine()) { qDebug() << "FreeVirtualKeyboardInputContextPrivate :: CONSTRUCTOR"; } //============================================================================== FreeVirtualKeyboardInputContext::FreeVirtualKeyboardInputContext() : QPlatformInputContext(), d(new FreeVirtualKeyboardInputContextPrivate) { d->FlickableContentScrollAnimation = new QPropertyAnimation(this); d->FlickableContentScrollAnimation->setPropertyName("contentY"); d->FlickableContentScrollAnimation->setDuration(400); d->FlickableContentScrollAnimation->setEasingCurve(QEasingCurve(QEasingCurve::OutBack)); qmlRegisterSingletonType("FreeVirtualKeyboard", 1, 0, "InputEngine", inputEngineProvider); connect(d->InputEngine, SIGNAL(animatingChanged()), this, SLOT(ensureFocusedObjectVisible())); } //============================================================================== FreeVirtualKeyboardInputContext::~FreeVirtualKeyboardInputContext() { qDebug( "FreeVirtualKeyboardInputContext DESTRUCTOR !!!"); } //============================================================================== FreeVirtualKeyboardInputContext* FreeVirtualKeyboardInputContext::instance() { static FreeVirtualKeyboardInputContext* InputContextInstance = new FreeVirtualKeyboardInputContext; return InputContextInstance; } //============================================================================== bool FreeVirtualKeyboardInputContext::isValid() const { qDebug("IS VALID called"); return true; } //============================================================================== QRectF FreeVirtualKeyboardInputContext::keyboardRect() const { qDebug("QRect called"); return QRectF(); } //============================================================================== void FreeVirtualKeyboardInputContext::showInputPanel() { qDebug( "showInputPanel"); d->Visible = true; QPlatformInputContext::showInputPanel(); emitInputPanelVisibleChanged(); } //============================================================================== void FreeVirtualKeyboardInputContext::hideInputPanel() { qDebug( "hideInputPanel"); d->Visible = false; QPlatformInputContext::hideInputPanel(); emitInputPanelVisibleChanged(); } //============================================================================== bool FreeVirtualKeyboardInputContext::isInputPanelVisible() const { return d->Visible; } //============================================================================== bool FreeVirtualKeyboardInputContext::isAnimating() const { return false; } //============================================================================== void FreeVirtualKeyboardInputContext::setFocusObject(QObject *object) { static const int NumericInputHints = Qt::ImhPreferNumbers | Qt::ImhDate | Qt::ImhTime | Qt::ImhDigitsOnly | Qt::ImhFormattedNumbersOnly; static const int DialableInputHints = Qt::ImhDialableCharactersOnly; d->Flickable = 0; qDebug() << "FreeVirtualKeyboardInputContext::setFocusObject"; if (!object) { return; } // we only support QML at the moment - so if this is not a QML item, then // we leave immediatelly d->FocusItem = dynamic_cast(object); if (!d->FocusItem) { return; } // Check if an input control has focus that accepts text input - if not, // then we can leave immediatelly bool AcceptsInput = d->FocusItem->inputMethodQuery(Qt::ImEnabled).toBool(); if (!AcceptsInput) { return; } // Set input mode depending on input method hints queried from focused // object / item Qt::InputMethodHints InputMethodHints(d->FocusItem->inputMethodQuery(Qt::ImHints).toInt()); qDebug() << QString("InputMethodHints: %1").arg(InputMethodHints, 0, 16); if (InputMethodHints & DialableInputHints) { d->InputEngine->setInputMode(DeclarativeInputEngine::Dialable); } else if (InputMethodHints & NumericInputHints) { d->InputEngine->setInputMode(DeclarativeInputEngine::Numeric); } else { d->InputEngine->setInputMode(DeclarativeInputEngine::Latin); } // Search for the top most flickable so that we can scroll the control // into the visible area, if the keyboard hides the control // QQuickItem* i = d->FocusItem; // while (i) // { // QQuickFlickable* Flickable = dynamic_cast(i); // if (Flickable) // { // d->Flickable = Flickable; // qDebug() << "is QQuickFlickable"; // } // i = i->parentItem(); // } ensureFocusedObjectVisible(); } //============================================================================== void FreeVirtualKeyboardInputContext::ensureFocusedObjectVisible() { if (d->Visible && !d->InputEngine->isAnimating() ) { QQuickItem* i = d->FocusItem; while (i) { QQuickFlickable* Flickable = dynamic_cast(i); if (Flickable) { d->Flickable = Flickable; qDebug() << "is QQuickFlickable"; } i = i->parentItem(); } } // If the keyboard is hidden, no scrollable element exists or the keyboard // is just animating, then we leave here if (!d->Visible || !d->Flickable || d->InputEngine->isAnimating() ) { return; } qDebug() << "FreeVirtualKeyboardInputContext::ensureFocusedObjectVisible"; QRectF FocusItemRect(0, 0, d->FocusItem->width(), d->FocusItem->height()); FocusItemRect = d->Flickable->mapRectFromItem(d->FocusItem, FocusItemRect); qDebug() << "FocusItemRect: " << FocusItemRect; qDebug() << "Content origin: " << QPointF(d->Flickable->contentX(), d->Flickable->contentY()); qDebug() << "Flickable size: " << QSize(d->Flickable->width(), d->Flickable->height()); d->FlickableContentScrollAnimation->setTargetObject(d->Flickable); qreal ContentY = d->Flickable->contentY(); if (FocusItemRect.bottom() >= d->Flickable->height()) { qDebug() << "Item outside!!! FocusItemRect.bottom() >= d->Flickable->height()"; qDebug() << "ContentY " << d->Flickable->contentY() << "FocusItem Bottom : " << FocusItemRect.bottom() << "Flickable Height " << d->Flickable->height(); ContentY = d->Flickable->contentY() + (FocusItemRect.bottom() - d->Flickable->height()); d->FlickableContentScrollAnimation->setEndValue(ContentY); d->FlickableContentScrollAnimation->start(); } else if (FocusItemRect.top() < 0) { qDebug() << "Item outside!!! d->FocusItem->position().x < 0"; ContentY = d->Flickable->contentY() + FocusItemRect.top(); d->FlickableContentScrollAnimation->setEndValue(ContentY); d->FlickableContentScrollAnimation->start(); } } //============================================================================== QObject* FreeVirtualKeyboardInputContext::inputEngineProvider(QQmlEngine *engine, QJSEngine *scriptEngine) { Q_UNUSED(engine) Q_UNUSED(scriptEngine) return FreeVirtualKeyboardInputContext::instance()->d->InputEngine; } //------------------------------------------------------------------------------ // EOF FreeVirtualKeyboardInpitContext.cpp