FreeVirtualKeyboardInputContext.cpp 8.5 KB

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