20 ** |
20 ** |
21 ** If you have questions regarding the use of this file, please contact |
21 ** If you have questions regarding the use of this file, please contact |
22 ** Nokia at developer.feedback@nokia.com. |
22 ** Nokia at developer.feedback@nokia.com. |
23 ** |
23 ** |
24 ****************************************************************************/ |
24 ****************************************************************************/ |
|
25 #include "hbinputmethod.h" |
|
26 #include "hbinputmethod_p.h" |
|
27 |
25 #include <QInputMethodEvent> |
28 #include <QInputMethodEvent> |
26 #include <QGraphicsView> |
29 #include <QGraphicsView> |
27 #include <QGraphicsProxyWidget> |
30 #include <QGraphicsProxyWidget> |
28 #include <QLocale> |
31 #include <QLocale> |
29 |
32 |
30 #include "hbinputmethod.h" |
|
31 #include "hbinputmethod_p.h" |
|
32 #include "hbinputmodecache_p.h" |
33 #include "hbinputmodecache_p.h" |
33 #include "hbinputsettingproxy.h" |
34 #include "hbinputsettingproxy.h" |
34 #include "hbinputcontextproxy_p.h" |
35 #include "hbinputcontextproxy_p.h" |
35 #include "hbinputfilter.h" |
36 #include "hbinputfilter.h" |
36 #include "hbinputmethodnull_p.h" |
37 #include "hbinputmethodnull_p.h" |
37 #include "hbinputpredictionfactory.h" |
38 #include "hbinputpredictionfactory.h" |
38 #include "hbinputextradictionaryfactory.h" |
39 #include "hbinputextradictionaryfactory.h" |
39 #include "hbinputstandardfilters.h" |
40 #include "hbinputstandardfilters.h" |
40 #include "hbinpututils.h" |
41 #include "hbinpututils.h" |
41 #include "hbinputvkbhost.h" |
42 #include "hbinputvkbhost.h" |
|
43 #include "hbinputvkbhostbridge.h" |
42 |
44 |
43 /*! |
45 /*! |
44 @alpha |
46 @alpha |
45 @hbcore |
47 @hbcore |
46 \class HbInputMethod |
48 \class HbInputMethod |
177 } |
179 } |
178 |
180 |
179 /*! |
181 /*! |
180 Initializes the input framework. |
182 Initializes the input framework. |
181 */ |
183 */ |
182 bool HbInputMethod::initializeFramework(QApplication& app) |
184 bool HbInputMethod::initializeFramework(QApplication &app) |
183 { |
185 { |
184 // Activate singleton shutdown. |
186 // Activate singleton shutdown. |
185 connect(&app, SIGNAL(aboutToQuit()), HbInputModeCache::instance(), SLOT(shutdown())); |
187 connect(&app, SIGNAL(aboutToQuit()), HbInputModeCache::instance(), SLOT(shutdown())); |
186 connect(&app, SIGNAL(aboutToQuit()), HbInputSettingProxy::instance(), SLOT(shutdown())); |
188 connect(&app, SIGNAL(aboutToQuit()), HbInputSettingProxy::instance(), SLOT(shutdown())); |
187 connect(&app, SIGNAL(aboutToQuit()), HbPredictionFactory::instance(), SLOT(shutDown())); |
189 connect(&app, SIGNAL(aboutToQuit()), HbPredictionFactory::instance(), SLOT(shutDown())); |
194 } |
196 } |
195 |
197 |
196 master->d_ptr->mIsActive = true; |
198 master->d_ptr->mIsActive = true; |
197 |
199 |
198 // Finally set application input context. |
200 // Finally set application input context. |
199 QInputContext* proxy = master->d_ptr->proxy(); |
201 QInputContext *proxy = master->d_ptr->proxy(); |
200 // A check required so that Qt does not delete inputcontext |
202 // A check required so that Qt does not delete inputcontext |
201 // which we are passing. |
203 // which we are passing. |
202 if (proxy != app.inputContext()) |
204 if (proxy != app.inputContext()) { |
203 app.setInputContext(proxy); |
205 app.setInputContext(proxy); |
|
206 } |
204 |
207 |
205 return true; |
208 return true; |
206 } |
209 } |
207 |
210 |
208 /*! |
211 /*! |
209 Returns the active instance of HbInputMethod. There is always active HbInputMethod instance after |
212 Returns the active instance of HbInputMethod. There is always active HbInputMethod instance after |
210 InitializeFramework method has been called, even when there is no focused editor (in some cases it may |
213 InitializeFramework method has been called, even when there is no focused editor (in some cases it may |
211 be so called null input method). |
214 be so called null input method). |
212 */ |
215 */ |
213 HbInputMethod* HbInputMethod::activeInputMethod() |
216 HbInputMethod *HbInputMethod::activeInputMethod() |
214 { |
217 { |
215 // First try, try app input context directly. It is possible that it is an instance |
218 // First try, try app input context directly. It is possible that it is an instance |
216 // of HbInputMethod that is installed directly there without framework knowing about it |
219 // of HbInputMethod that is installed directly there without framework knowing about it |
217 // (that shouldn't be done, but it is possible). That's why we rely on app input context as |
220 // (that shouldn't be done, but it is possible). That's why we rely on app input context as |
218 // a primary source instead of mode cache. |
221 // a primary source instead of mode cache. |
219 QInputContext* context = qApp->inputContext(); |
222 QInputContext *context = qApp->inputContext(); |
220 if (context && context->inherits("HbInputMethod")) { |
223 if (context && context->inherits("HbInputMethod")) { |
221 HbInputMethod* active = static_cast<HbInputMethod*>(context); |
224 HbInputMethod *active = static_cast<HbInputMethod *>(context); |
222 return active; |
225 return active; |
223 } |
226 } |
224 |
227 |
225 // Then check if the 'null' is active. |
228 // Then check if the 'null' is active. |
226 HbInputMethod* nullInstance = HbInputMethodNull::Instance(); |
229 HbInputMethod *nullInstance = HbInputMethodNull::Instance(); |
227 if (nullInstance && nullInstance->isActiveMethod()) { |
230 if (nullInstance && nullInstance->isActiveMethod()) { |
228 return nullInstance; |
231 return nullInstance; |
229 } |
232 } |
230 |
233 |
231 // No it wasn't, then go through the methods in the cache and see which one is |
234 // No it wasn't, then go through the methods in the cache and see which one is |
312 This slot is connected to the setting proxy activeKeyboard attribute. It will |
315 This slot is connected to the setting proxy activeKeyboard attribute. It will |
313 activate proper state when the signal is received. |
316 activate proper state when the signal is received. |
314 */ |
317 */ |
315 void HbInputMethod::activeKeyboardChanged(HbKeyboardType newKeyboard) |
318 void HbInputMethod::activeKeyboardChanged(HbKeyboardType newKeyboard) |
316 { |
319 { |
317 if (!isActiveMethod()) { |
320 if (!isActiveMethod() || !HbInputSettingProxy::instance()->orientationChangeCompleted()) { |
318 return; |
321 return; |
319 } |
322 } |
320 |
323 |
321 Q_D(HbInputMethod); |
324 Q_D(HbInputMethod); |
322 |
325 |
323 d->mInputState.setKeyboard(newKeyboard); |
326 d->mInputState.setKeyboard(newKeyboard); |
324 HbInputMethod* stateHandler = d->findStateHandler(d->mInputState); |
327 HbInputMethod *stateHandler = d->findStateHandler(d->mInputState); |
325 if (stateHandler) { |
328 if (stateHandler) { |
326 d->inputStateToEditor(d->mInputState); |
329 d->inputStateToEditor(d->mInputState); |
327 if (stateHandler != this) { |
330 if (stateHandler != this) { |
328 // Context switch needed. |
331 // Context switch needed. |
329 d->contextSwitch(stateHandler); |
332 d->contextSwitch(stateHandler); |
372 default focus handling mechanism for QInputContext system. Input method |
375 default focus handling mechanism for QInputContext system. Input method |
373 implementation should never override this method unless it knows what it is doing. |
376 implementation should never override this method unless it knows what it is doing. |
374 |
377 |
375 \sa setFocusObject |
378 \sa setFocusObject |
376 */ |
379 */ |
377 void HbInputMethod::setFocusWidget(QWidget* widget) |
380 void HbInputMethod::setFocusWidget(QWidget *widget) |
378 { |
381 { |
379 Q_D(HbInputMethod); |
382 Q_D(HbInputMethod); |
380 |
383 |
381 if (d->mFocusLocked) { |
384 if (d->mFocusLocked) { |
382 return; |
385 return; |
383 } |
386 } |
384 |
387 |
385 // attach focuswidget to prxoy inputcontext as proxy is |
388 // attach focuswidget to prxoy inputcontext as proxy is |
386 // the only inputcotext known to qt framework. |
389 // the only inputcotext known to qt framework. |
387 d->proxy()->QInputContext::setFocusWidget(widget); |
390 d->proxy()->QInputContext::setFocusWidget(widget); |
388 |
391 |
389 if (!widget) { |
392 if (!widget) { |
390 // Losing focus. |
393 // Losing focus. |
391 if (d->mFocusObject) { |
394 if (d->mFocusObject) { |
392 focusLost(false); |
395 focusLost(false); |
393 d->hideMainWindow(); |
396 d->hideMainWindow(); |
443 delete d->mFocusObject; |
446 delete d->mFocusObject; |
444 d->mFocusObject = 0; |
447 d->mFocusObject = 0; |
445 |
448 |
446 // Attach focus. |
449 // Attach focus. |
447 d->mFocusObject = new HbInputFocusObject(widget); |
450 d->mFocusObject = new HbInputFocusObject(widget); |
448 connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(editorDeleted(QObject*))); |
451 connect(widget, SIGNAL(destroyed(QObject *)), this, SLOT(editorDeleted(QObject *))); |
449 |
452 |
450 d->setFocusCommon(); |
453 d->setFocusCommon(); |
451 |
454 |
452 // The focus jumped from one editor to another. Make sure that vkb host |
455 // The focus jumped from one editor to another. Make sure that vkb host |
453 // updates the situation correctly. |
456 // updates the situation correctly. |
461 |
464 |
462 /*! |
465 /*! |
463 Checks if the destroyed widget is currently focused and clears the focus |
466 Checks if the destroyed widget is currently focused and clears the focus |
464 if needed. This method should not be overridden. |
467 if needed. This method should not be overridden. |
465 */ |
468 */ |
466 void HbInputMethod::widgetDestroyed(QWidget* widget) |
469 void HbInputMethod::widgetDestroyed(QWidget *widget) |
467 { |
470 { |
468 Q_D(HbInputMethod); |
471 Q_D(HbInputMethod); |
469 |
472 |
470 if (d->mFocusObject && d->mFocusObject->object() == widget) { |
473 if (d->mFocusObject && d->mFocusObject->object() == widget) { |
471 delete d->mFocusObject; |
474 delete d->mFocusObject; |
484 requestSoftwareInputPanel event. |
487 requestSoftwareInputPanel event. |
485 |
488 |
486 \sa setFocusWidget |
489 \sa setFocusWidget |
487 \sa HbInputFocusObject |
490 \sa HbInputFocusObject |
488 */ |
491 */ |
489 void HbInputMethod::setFocusObject(HbInputFocusObject* focusObject) |
492 void HbInputMethod::setFocusObject(HbInputFocusObject *focusObject) |
490 { |
493 { |
491 Q_D(HbInputMethod); |
494 Q_D(HbInputMethod); |
492 |
495 |
493 if (d->mFocusLocked) { |
496 if (d->mFocusLocked) { |
494 return; |
497 return; |
495 } |
498 } |
496 |
499 |
497 if (focusObject == 0) { |
500 if (focusObject == 0) { |
498 // Losing focus. |
501 // Losing focus. |
499 if (d->mFocusObject != 0) { |
502 if (d->mFocusObject != 0) { |
500 disconnect(d->mFocusObject->object(), SIGNAL(destroyed(QObject*)), this, SLOT(editorDeleted(QObject*))); |
503 disconnect(d->mFocusObject->object(), SIGNAL(destroyed(QObject *)), this, SLOT(editorDeleted(QObject *))); |
501 focusLost(false); |
504 focusLost(false); |
502 d->hideMainWindow(); |
505 d->hideMainWindow(); |
503 delete d->mFocusObject; |
506 delete d->mFocusObject; |
504 d->mFocusObject = 0; |
507 d->mFocusObject = 0; |
505 } |
508 } |
506 return; |
509 return; |
507 } |
510 } |
508 |
511 |
509 if(d->compareWithCurrentFocusObject( focusObject )) { |
512 if (d->compareWithCurrentFocusObject(focusObject)) { |
510 // The incoming focus object is either same or points to same |
513 // The incoming focus object is either same or points to same |
511 // widget that the framework is already focused to and nothing needs to be done here. |
514 // widget that the framework is already focused to and nothing needs to be done here. |
512 // But because the ownership of the focus object is transferred to the |
515 // But because the ownership of the focus object is transferred to the |
513 // the framework, we need to delete the the incoming focus object in case it is |
516 // the framework, we need to delete the the incoming focus object in case it is |
514 // dirrefent than current one. |
517 // dirrefent than current one. |
515 if (d->mFocusObject != focusObject) { |
518 if (d->mFocusObject != focusObject) { |
522 |
525 |
523 // Delete previous focus object. |
526 // Delete previous focus object. |
524 if (d->mFocusObject) { |
527 if (d->mFocusObject) { |
525 refreshHost = true; |
528 refreshHost = true; |
526 focusLost(true); |
529 focusLost(true); |
527 disconnect(d->mFocusObject->object(), SIGNAL(destroyed(QObject*)), this, SLOT(editorDeleted(QObject*))); |
530 disconnect(d->mFocusObject->object(), SIGNAL(destroyed(QObject *)), this, SLOT(editorDeleted(QObject *))); |
528 delete d->mFocusObject; |
531 delete d->mFocusObject; |
529 d->mFocusObject = 0; |
532 d->mFocusObject = 0; |
530 } |
533 } |
531 |
534 |
532 // Attach focus. |
535 // Attach focus. |
533 d->mFocusObject = focusObject; |
536 d->mFocusObject = focusObject; |
534 connect(d->mFocusObject->object(), SIGNAL(destroyed(QObject*)), this, SLOT(editorDeleted(QObject*))); |
537 connect(d->mFocusObject->object(), SIGNAL(destroyed(QObject *)), this, SLOT(editorDeleted(QObject *))); |
535 |
538 |
536 d->setFocusCommon(); |
539 d->setFocusCommon(); |
537 |
540 |
538 // The focus jumped from one editor to another. Make sure that vkb host |
541 // The focus jumped from one editor to another. Make sure that vkb host |
539 // updates the situation correctly. |
542 // updates the situation correctly. |
591 |
594 |
592 /*! |
595 /*! |
593 The framework calls this method every time the input state changes. This is an empty default |
596 The framework calls this method every time the input state changes. This is an empty default |
594 implementation and the inheriting class should override it. |
597 implementation and the inheriting class should override it. |
595 */ |
598 */ |
596 void HbInputMethod::inputStateActivated(const HbInputState& newState) |
599 void HbInputMethod::inputStateActivated(const HbInputState &newState) |
597 { |
600 { |
598 Q_UNUSED(newState); |
601 Q_UNUSED(newState); |
599 // Empty default implementation. |
602 // Empty default implementation. |
600 if (this != HbInputMethodNull::Instance()) { |
603 if (this != HbInputMethodNull::Instance()) { |
601 qWarning("WARNING: inputStateActivated() default implementation called: Is that ok?"); |
604 qWarning("WARNING: inputStateActivated() default implementation called: Is that ok?"); |
641 instance may occur. |
644 instance may occur. |
642 |
645 |
643 \sa activateNextState |
646 \sa activateNextState |
644 \sa InputState |
647 \sa InputState |
645 */ |
648 */ |
646 bool HbInputMethod::activateState(const HbInputState& state) |
649 bool HbInputMethod::activateState(const HbInputState &state) |
647 { |
650 { |
648 Q_D(HbInputMethod); |
651 Q_D(HbInputMethod); |
649 |
652 |
650 if (!d->stateAllowedInEditor(state)) { |
653 if (!d->stateAllowedInEditor(state)) { |
651 return false; |
654 return false; |
652 } |
655 } |
653 |
656 |
654 d->mStateChangeInProgress = true; |
657 d->mStateChangeInProgress = true; |
655 |
658 |
656 HbInputMethod* stateHandler = HbInputModeCache::instance()->findStateHandler(state); |
659 HbInputMethod *stateHandler = HbInputModeCache::instance()->findStateHandler(state); |
657 |
660 |
658 if (!stateHandler) { |
661 if (!stateHandler) { |
659 stateHandler = HbInputMethodNull::Instance(); |
662 stateHandler = HbInputMethodNull::Instance(); |
660 } |
663 } |
661 |
664 |
697 if (currentTextCase == HbTextCaseAutomatic) { |
700 if (currentTextCase == HbTextCaseAutomatic) { |
698 if (!autoCaseNeeded) { |
701 if (!autoCaseNeeded) { |
699 currentTextCase = HbTextCaseLower; |
702 currentTextCase = HbTextCaseLower; |
700 refresh = true; |
703 refresh = true; |
701 } |
704 } |
702 } else if (autoCaseNeeded && currentTextCase != HbTextCaseUpper ) { |
705 } else if (autoCaseNeeded && currentTextCase != HbTextCaseUpper) { |
703 if (!d->isFixedCaseEditor()) { |
706 if (!d->isFixedCaseEditor()) { |
704 currentTextCase = HbTextCaseAutomatic; |
707 currentTextCase = HbTextCaseAutomatic; |
705 refresh = true; |
708 refresh = true; |
706 } else { |
709 } else { |
707 return; |
710 return; |
719 Receives the screen orientation signal. Will determine correct input state for new |
722 Receives the screen orientation signal. Will determine correct input state for new |
720 orientation and find state handler for it. |
723 orientation and find state handler for it. |
721 */ |
724 */ |
722 void HbInputMethod::orientationChanged(Qt::Orientation orientation) |
725 void HbInputMethod::orientationChanged(Qt::Orientation orientation) |
723 { |
726 { |
|
727 Q_D(HbInputMethod); |
724 Q_UNUSED(orientation); |
728 Q_UNUSED(orientation); |
725 |
729 |
726 if (isActiveMethod()) { |
730 if (d->mOldFocusObject) { |
727 // Make sure that if there was an editor focus before the orientation change, |
731 setFocusObject(d->mOldFocusObject); |
728 // it will re-focus. |
732 d->mOldFocusObject = 0; |
729 QInputContext *ic = qApp->inputContext(); |
733 } |
730 if (ic) { |
734 |
731 QEvent *event = new QEvent(QEvent::RequestSoftwareInputPanel); |
|
732 ic->filterEvent(event); |
|
733 delete event; |
|
734 } |
|
735 } |
|
736 } |
735 } |
737 |
736 |
738 /*! |
737 /*! |
739 This slot is connected to setting proxy's orientation change warning signal. The default |
738 This slot is connected to setting proxy's orientation change warning signal. The default |
740 base class implementation is empty. |
739 base class implementation is empty. |
741 |
740 |
742 \sa HbInputSettingProxy |
741 \sa HbInputSettingProxy |
743 */ |
742 */ |
744 void HbInputMethod::orientationAboutToChange() |
743 void HbInputMethod::orientationAboutToChange() |
745 { |
744 { |
|
745 Q_D(HbInputMethod); |
|
746 reset(); |
|
747 d->inputStateToEditor(d->mInputState); |
|
748 if (d->mFocusObject) { |
|
749 d->mOldFocusObject = d->mFocusObject; |
|
750 d->mFocusObject = 0; |
|
751 } |
|
752 HbVkbHostBridge::instance()->closeKeypad(true); |
746 } |
753 } |
747 |
754 |
748 /*! |
755 /*! |
749 Returns active input language. Unlike setting proxy's global input language, |
756 Returns active input language. Unlike setting proxy's global input language, |
750 this method takes into account input state language and possible editor local language, |
757 this method takes into account input state language and possible editor local language, |