FreeVirtualKeyboardInputContext.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. //============================================================================
  2. // INCLUDES
  3. //============================================================================
  4. #include "FreeVirtualKeyboardInputContext.h"
  5. #include <QDebug>
  6. #include <QEvent>
  7. #include <QGuiApplication>
  8. #include <QQmlEngine>
  9. #include <QQmlContext>
  10. #include <QVariant>
  11. #include <QQmlEngine>
  12. #include <QJSEngine>
  13. #include <QPropertyAnimation>
  14. #include <private/qquickflickable_p.h>
  15. #include "DeclarativeInputEngine.h"
  16. /**
  17. * Private data class for FreeVirtualKeyboardInputContext
  18. */
  19. class FreeVirtualKeyboardInputContextPrivate
  20. {
  21. public:
  22. FreeVirtualKeyboardInputContextPrivate();
  23. QQuickFlickable* Flickable;
  24. QQuickItem* FocusItem;
  25. bool Visible;
  26. DeclarativeInputEngine* InputEngine;
  27. QPropertyAnimation* FlickableContentScrollAnimation;//< for smooth scrolling of flickable content item
  28. };
  29. //==============================================================================
  30. FreeVirtualKeyboardInputContextPrivate::FreeVirtualKeyboardInputContextPrivate()
  31. : Flickable(0),
  32. FocusItem(0),
  33. Visible(false),
  34. InputEngine(new DeclarativeInputEngine())
  35. {
  36. }
  37. //==============================================================================
  38. FreeVirtualKeyboardInputContext::FreeVirtualKeyboardInputContext() :
  39. QPlatformInputContext(), d(new FreeVirtualKeyboardInputContextPrivate)
  40. {
  41. d->FlickableContentScrollAnimation = new QPropertyAnimation(this);
  42. d->FlickableContentScrollAnimation->setPropertyName("contentY");
  43. d->FlickableContentScrollAnimation->setDuration(400);
  44. d->FlickableContentScrollAnimation->setEasingCurve(QEasingCurve(QEasingCurve::OutBack));
  45. qmlRegisterSingletonType<DeclarativeInputEngine>("FreeVirtualKeyboard", 1, 0,
  46. "InputEngine", inputEngineProvider);
  47. connect(d->InputEngine, SIGNAL(animatingChanged()), this, SLOT(ensureFocusedObjectVisible()));
  48. }
  49. //==============================================================================
  50. FreeVirtualKeyboardInputContext::~FreeVirtualKeyboardInputContext()
  51. {
  52. }
  53. //==============================================================================
  54. FreeVirtualKeyboardInputContext* FreeVirtualKeyboardInputContext::instance()
  55. {
  56. static FreeVirtualKeyboardInputContext* InputContextInstance = new FreeVirtualKeyboardInputContext;
  57. return InputContextInstance;
  58. }
  59. //==============================================================================
  60. bool FreeVirtualKeyboardInputContext::isValid() const
  61. {
  62. return true;
  63. }
  64. //==============================================================================
  65. QRectF FreeVirtualKeyboardInputContext::keyboardRect() const
  66. {
  67. return QRectF();
  68. }
  69. //==============================================================================
  70. void FreeVirtualKeyboardInputContext::showInputPanel()
  71. {
  72. qDebug( "showInputPanel");
  73. d->Visible = true;
  74. QPlatformInputContext::showInputPanel();
  75. emitInputPanelVisibleChanged();
  76. }
  77. //==============================================================================
  78. void FreeVirtualKeyboardInputContext::hideInputPanel()
  79. {
  80. qDebug( "hideInputPanel");
  81. d->Visible = false;
  82. QPlatformInputContext::hideInputPanel();
  83. emitInputPanelVisibleChanged();
  84. }
  85. //==============================================================================
  86. bool FreeVirtualKeyboardInputContext::isInputPanelVisible() const
  87. {
  88. return d->Visible;
  89. }
  90. //==============================================================================
  91. bool FreeVirtualKeyboardInputContext::isAnimating() const
  92. {
  93. return false;
  94. }
  95. //==============================================================================
  96. void FreeVirtualKeyboardInputContext::setFocusObject(QObject *object)
  97. {
  98. static const int NumericInputHints = Qt::ImhPreferNumbers | Qt::ImhDate
  99. | Qt::ImhTime | Qt::ImhDigitsOnly | Qt::ImhFormattedNumbersOnly;
  100. static const int DialableInputHints = Qt::ImhDialableCharactersOnly;
  101. qDebug() << "FreeVirtualKeyboardInputContext::setFocusObject";
  102. if (!object)
  103. {
  104. return;
  105. }
  106. // we only support QML at the moment - so if this is not a QML item, then
  107. // we leave immediatelly
  108. d->FocusItem = dynamic_cast<QQuickItem*>(object);
  109. if (!d->FocusItem)
  110. {
  111. return;
  112. }
  113. // Check if an input control has focus that accepts text input - if not,
  114. // then we can leave immediatelly
  115. bool AcceptsInput = d->FocusItem->inputMethodQuery(Qt::ImEnabled).toBool();
  116. if (!AcceptsInput)
  117. {
  118. return;
  119. }
  120. // Set input mode depending on input method hints queried from focused
  121. // object / item
  122. Qt::InputMethodHints InputMethodHints(d->FocusItem->inputMethodQuery(Qt::ImHints).toInt());
  123. qDebug() << QString("InputMethodHints: %1").arg(InputMethodHints, 0, 16);
  124. if (InputMethodHints & DialableInputHints)
  125. {
  126. d->InputEngine->setInputMode(DeclarativeInputEngine::Dialable);
  127. }
  128. else if (InputMethodHints & NumericInputHints)
  129. {
  130. d->InputEngine->setInputMode(DeclarativeInputEngine::Numeric);
  131. }
  132. else
  133. {
  134. d->InputEngine->setInputMode(DeclarativeInputEngine::Latin);
  135. }
  136. // Search for the top most flickable so that we can scroll the control
  137. // into the visible area, if the keyboard hides the control
  138. QQuickItem* i = d->FocusItem;
  139. d->Flickable = 0;
  140. while (i)
  141. {
  142. QQuickFlickable* Flickable = dynamic_cast<QQuickFlickable*>(i);
  143. if (Flickable)
  144. {
  145. d->Flickable = Flickable;
  146. qDebug() << "is QQuickFlickable";
  147. }
  148. i = i->parentItem();
  149. }
  150. ensureFocusedObjectVisible();
  151. }
  152. //==============================================================================
  153. void FreeVirtualKeyboardInputContext::ensureFocusedObjectVisible()
  154. {
  155. // If the keyboard is hidden, no scrollable element exists or the keyboard
  156. // is just animating, then we leave here
  157. if (!d->Visible || !d->Flickable || d->InputEngine->isAnimating())
  158. {
  159. return;
  160. }
  161. qDebug() << "FreeVirtualKeyboardInputContext::ensureFocusedObjectVisible";
  162. QRectF FocusItemRect(0, 0, d->FocusItem->width(), d->FocusItem->height());
  163. FocusItemRect = d->Flickable->mapRectFromItem(d->FocusItem, FocusItemRect);
  164. qDebug() << "FocusItemRect: " << FocusItemRect;
  165. qDebug() << "Content origin: " << QPointF(d->Flickable->contentX(),
  166. d->Flickable->contentY());
  167. qDebug() << "Flickable size: " << QSize(d->Flickable->width(), d->Flickable->height());
  168. d->FlickableContentScrollAnimation->setTargetObject(d->Flickable);
  169. qreal ContentY = d->Flickable->contentY();
  170. if (FocusItemRect.bottom() >= d->Flickable->height())
  171. {
  172. qDebug() << "Item outside!!! FocusItemRect.bottom() >= d->Flickable->height()";
  173. ContentY = d->Flickable->contentY() + (FocusItemRect.bottom() - d->Flickable->height()) + 20;
  174. d->FlickableContentScrollAnimation->setEndValue(ContentY);
  175. d->FlickableContentScrollAnimation->start();
  176. }
  177. else if (FocusItemRect.top() < 0)
  178. {
  179. qDebug() << "Item outside!!! d->FocusItem->position().x < 0";
  180. ContentY = d->Flickable->contentY() + FocusItemRect.top() - 20;
  181. d->FlickableContentScrollAnimation->setEndValue(ContentY);
  182. d->FlickableContentScrollAnimation->start();
  183. }
  184. }
  185. //==============================================================================
  186. QObject* FreeVirtualKeyboardInputContext::inputEngineProvider(QQmlEngine *engine, QJSEngine *scriptEngine)
  187. {
  188. Q_UNUSED(engine)
  189. Q_UNUSED(scriptEngine)
  190. return FreeVirtualKeyboardInputContext::instance()->d->InputEngine;
  191. }
  192. //------------------------------------------------------------------------------
  193. // EOF FreeVirtualKeyboardInpitContext.cpp