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