|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (developer.feedback@nokia.com) |
|
6 ** |
|
7 ** This file is part of the HbCore module of the UI Extensions for Mobile. |
|
8 ** |
|
9 ** GNU Lesser General Public License Usage |
|
10 ** This file may be used under the terms of the GNU Lesser General Public |
|
11 ** License version 2.1 as published by the Free Software Foundation and |
|
12 ** appearing in the file LICENSE.LGPL included in the packaging of this file. |
|
13 ** Please review the following information to ensure the GNU Lesser General |
|
14 ** Public License version 2.1 requirements will be met: |
|
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
16 ** |
|
17 ** In addition, as a special exception, Nokia gives you certain additional |
|
18 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
20 ** |
|
21 ** If you have questions regarding the use of this file, please contact |
|
22 ** Nokia at developer.feedback@nokia.com. |
|
23 ** |
|
24 ****************************************************************************/ |
|
25 #include <QInputMethodEvent> |
|
26 #include <QGraphicsView> |
|
27 #include <QGraphicsProxyWidget> |
|
28 #include <QLocale> |
|
29 |
|
30 #include "hbinputmethod.h" |
|
31 #include "hbinputmethod_p.h" |
|
32 #include "hbinputmodecache_p.h" |
|
33 #include "hbinputsettingproxy.h" |
|
34 #include "hbinputcontextproxy_p.h" |
|
35 #include "hbinputfilter.h" |
|
36 #include "hbinputmethodnull_p.h" |
|
37 #include "hbinputpredictionfactory.h" |
|
38 #include "hbinputstandardfilters.h" |
|
39 #include "hbinpututils.h" |
|
40 #include "hbinputvkbhost.h" |
|
41 |
|
42 /*! |
|
43 @alpha |
|
44 @hbcore |
|
45 \class HbInputMethod |
|
46 \brief A base class for input method implementations. |
|
47 |
|
48 HbInputMethod is the base class for input method implementations. It inherits from QInputContext, |
|
49 connects to the input framework behind the scenes and provides focusing and other framework level |
|
50 services. |
|
51 |
|
52 An internal framework class called HbInputModeCache scans through the system and looks for available HbInputMethod instances. It then forms a list of available input methods based on language |
|
53 and keyboard type. Input method plugin reports (on plugin level, as meta-data) which languages, keyboards and input modes that input method instance supports. Input mode cache then activates suitable |
|
54 input method depending on the situation. It can also switch active input method on the fly |
|
55 when the focus switches between editors and the previously active input method is unable to |
|
56 support newly focused editor. |
|
57 |
|
58 Custom input methods are a special class of input methods. Once a custom input method is |
|
59 activated from UI, input mode cache stops resolving suitable input methods upon focus operations |
|
60 and the custom input is ative in all editors until it is deactivated. |
|
61 |
|
62 Following is the basic input framework program flow: |
|
63 |
|
64 1. An editor gains input focus. |
|
65 2 Input mode cache resolves correct mode handler and activates it. |
|
66 3. A virtual function HbInputMethod::focusReceived is called. At this point the input method |
|
67 initializes whatever it needs to initialize in order to start the input operation (for example, |
|
68 opens the virtual keyboard by using HbVkbHost API) and waits for user actions. |
|
69 4. Text is written. The input method delivers results to the editor buffer by using HbInputFocusObject API. |
|
70 It can access editor attributes via HbEditorInterface API. |
|
71 5. The active editor loses focus. At this point the input method receives a call to virtual function |
|
72 HbInputMethod::focusLost and is expected to conclude any ongoing input operations and shut down active |
|
73 UI elements (such as the virtual keyboard). |
|
74 6. The input method waits for next focusReceived() call. |
|
75 |
|
76 \sa QInputContext |
|
77 \sa HbInputFocusObject |
|
78 \sa HbEditorInterface |
|
79 \sa HbVkbHost |
|
80 */ |
|
81 |
|
82 /*! |
|
83 Constructs the object |
|
84 */ |
|
85 HbInputMethod::HbInputMethod() : d_ptr(new HbInputMethodPrivate(this)) |
|
86 { |
|
87 HbInputSettingProxy::instance()->connectObservingObject(this); |
|
88 } |
|
89 |
|
90 /*! |
|
91 Destructs the object |
|
92 */ |
|
93 HbInputMethod::~HbInputMethod() |
|
94 { |
|
95 HbInputSettingProxy::instance()->disconnectObservingObject(this); |
|
96 |
|
97 delete d_ptr; |
|
98 } |
|
99 |
|
100 /*! |
|
101 Initializes the HbInputs framework. Each Qt application needs to call this |
|
102 method once in order to connect to the HbInputs framework. |
|
103 */ |
|
104 bool HbInputMethod::initializeFramework(QApplication& app) |
|
105 { |
|
106 // Activate singleton shutdown. |
|
107 connect(&app, SIGNAL(aboutToQuit()), HbInputModeCache::instance(), SLOT(shutdown())); |
|
108 connect(&app, SIGNAL(aboutToQuit()), HbInputSettingProxy::instance(), SLOT(shutdown())); |
|
109 connect(&app, SIGNAL(aboutToQuit()), HbPredictionFactory::instance(), SLOT(shutDown())); |
|
110 |
|
111 HbInputMethod *master = HbInputMethodNull::Instance(); |
|
112 |
|
113 if (!master) { |
|
114 return false; |
|
115 } |
|
116 |
|
117 master->d_ptr->mIsActive = true; |
|
118 |
|
119 // Finally set application input context. |
|
120 QInputContext* proxy = master->d_ptr->newProxy(); |
|
121 app.setInputContext(proxy); |
|
122 |
|
123 return true; |
|
124 } |
|
125 |
|
126 /*! |
|
127 Returns active instance of HbInputMethod. There is always active HbInputMethod instance after |
|
128 InitializeFramework method has been called, even when there is no focused editor (in some cases it may |
|
129 be so called null input method). Normally this method is needed only for special cases, such as developing |
|
130 and debugging framework level code, but it is made public for convenience. |
|
131 */ |
|
132 HbInputMethod* HbInputMethod::activeInputMethod() |
|
133 { |
|
134 // First try, try app input context directly. It is possible that it is an instance |
|
135 // of HbInputMethod that is installed directly there without framework knowing about it |
|
136 // (that shouldn't be done, but it is possible). That's why we rely on app input context as |
|
137 // a primary source instead of mode cache. |
|
138 QInputContext* context = qApp->inputContext(); |
|
139 if (context && context->inherits("HbInputMethod")) { |
|
140 HbInputMethod* active = static_cast<HbInputMethod*>(context); |
|
141 return active; |
|
142 } |
|
143 |
|
144 // Then check if the 'null' is active. |
|
145 HbInputMethod* nullInstance = HbInputMethodNull::Instance(); |
|
146 if (nullInstance && nullInstance->isActiveMethod()) { |
|
147 return nullInstance; |
|
148 } |
|
149 |
|
150 // No it wasn't, then go through the methods in the cache and see which one is |
|
151 // active. |
|
152 return HbInputModeCache::instance()->activeMethod(); |
|
153 } |
|
154 |
|
155 /*! |
|
156 Lists custom input methods. |
|
157 */ |
|
158 QList<HbInputMethodDescriptor> HbInputMethod::listCustomInputMethods() |
|
159 { |
|
160 return HbInputModeCache::instance()->listCustomInputMethods(); |
|
161 } |
|
162 |
|
163 /*! |
|
164 Activates given input method. input context is |
|
165 switched to custom method. Returns false if input method was not found |
|
166 or the framework was not able to activate it. |
|
167 */ |
|
168 bool HbInputMethod::activateInputMethod(const HbInputMethodDescriptor &inputMethod) |
|
169 { |
|
170 Q_D(HbInputMethod); |
|
171 |
|
172 if (!inputMethod.isEmpty()) { |
|
173 HbInputSettingProxy::instance()->setActiveCustomInputMethod(inputMethod); |
|
174 |
|
175 if (inputMethod.isDefault()) { |
|
176 d->setFocusCommon(); |
|
177 return true; |
|
178 } else { |
|
179 HbInputMethod *customMethod = HbInputModeCache::instance()->loadInputMethod(inputMethod); |
|
180 if (customMethod) { |
|
181 d->contextSwitch(customMethod); |
|
182 return true; |
|
183 } |
|
184 } |
|
185 } |
|
186 |
|
187 return false; |
|
188 } |
|
189 |
|
190 |
|
191 /*! |
|
192 This slot is called when the input language changes. The framework connects it |
|
193 to the input setting proxy. When the signal is received, the input method implementation |
|
194 is notified by calling inputLanguageChanged. |
|
195 |
|
196 \sa inputLanguageChanged |
|
197 \sa HbInputSettingProxy |
|
198 */ |
|
199 void HbInputMethod::globalInputLanguageChanged(const HbInputLanguage &newLanguage) |
|
200 { |
|
201 Q_D(HbInputMethod); |
|
202 |
|
203 inputLanguageChanged(newLanguage); |
|
204 |
|
205 if (!isActiveMethod()) { |
|
206 // Notify non-active input methods of language change, but check |
|
207 // if the method has promised to handle the new language only |
|
208 // in the active method |
|
209 return; |
|
210 } |
|
211 |
|
212 // Just behave as if this was the first focus operation |
|
213 // to this editor. |
|
214 if (d->mFocusObject) { |
|
215 HbInputState state; |
|
216 editorRootState(state); |
|
217 activateState(state); |
|
218 } |
|
219 } |
|
220 |
|
221 /*! |
|
222 This slot is called when the secondary input language changes. The framework connects it |
|
223 to the input setting proxy. When the signal is received, the input method implementation |
|
224 is notified by calling secondaryInputLanguageChanged. |
|
225 |
|
226 \sa secondaryInputLanguageChanged |
|
227 \sa HbInputSettingProxy |
|
228 */ |
|
229 void HbInputMethod::globalSecondaryInputLanguageChanged(const HbInputLanguage &aNewLanguage) |
|
230 { |
|
231 secondaryInputLanguageChanged(aNewLanguage); |
|
232 } |
|
233 |
|
234 /*! |
|
235 This slot is connected to the setting proxy hw keyboard attribute. It will |
|
236 do refreshState() when the signal is received. |
|
237 */ |
|
238 void HbInputMethod::activeHwKeyboardChanged(HbKeyboardType newKeyboard) |
|
239 { |
|
240 Q_UNUSED(newKeyboard); |
|
241 Q_D(HbInputMethod); |
|
242 |
|
243 // Do here whatever needs to be done on HbInputMethod level, then |
|
244 // call virtual ActiveKeyboardChanged() in case plugin needs to do something. |
|
245 // ... |
|
246 d->refreshState(); |
|
247 } |
|
248 |
|
249 /*! |
|
250 This slot is connected to the setting proxy touch keyboard attribute. It will |
|
251 do refreshState() when the signal is received. |
|
252 */ |
|
253 void HbInputMethod::activeTouchKeyboardChanged(HbKeyboardType newKeyboard) |
|
254 { |
|
255 Q_UNUSED(newKeyboard); |
|
256 Q_D(HbInputMethod); |
|
257 |
|
258 d->refreshState(); |
|
259 } |
|
260 |
|
261 |
|
262 /*! |
|
263 This slot is connected to the setting proxy activeKeyboard attribute. It will |
|
264 activate proper state when the signal is received. |
|
265 */ |
|
266 void HbInputMethod::activeKeyboardChanged(HbKeyboardType newKeyboard) |
|
267 { |
|
268 if (!isActiveMethod()) { |
|
269 return; |
|
270 } |
|
271 Q_D(HbInputMethod); |
|
272 d->mInputState.setKeyboard(newKeyboard); |
|
273 HbInputMethod* stateHandler = d->findStateHandler(d->mInputState); |
|
274 if (stateHandler) { |
|
275 d->inputStateToEditor(d->mInputState); |
|
276 if (stateHandler != this) { |
|
277 // Context switch needed. |
|
278 d->contextSwitch(stateHandler); |
|
279 } else { |
|
280 // Same method handles new state, just report the state change. |
|
281 inputStateActivated(d->mInputState); |
|
282 } |
|
283 } |
|
284 } |
|
285 |
|
286 /*! |
|
287 This slot is called when the predictive input state changes. The framework connects it |
|
288 to the input setting proxy. When the signal is received, the input method implementation |
|
289 is notified by calling predictiveInputStatusChanged. |
|
290 |
|
291 \sa predictiveInputStatusChanged |
|
292 \sa HbInputSettingProxy |
|
293 */ |
|
294 void HbInputMethod::predictiveInputStateChanged(int newStatus) |
|
295 { |
|
296 // Do here whatever needs to be done on HbInputMethod level, then |
|
297 // call virtual predictiveInputStatusChanged() in case plugin needs to do something. |
|
298 // ... |
|
299 |
|
300 predictiveInputStatusChanged(newStatus); |
|
301 } |
|
302 |
|
303 /*! |
|
304 The framework calls this method when an input capable widget receives UI focus. This is empty |
|
305 default implementation and the inheriting class should override it. |
|
306 |
|
307 \sa focusLost |
|
308 */ |
|
309 void HbInputMethod::focusReceived() |
|
310 { |
|
311 // Empty default implementation, do nothing. |
|
312 } |
|
313 |
|
314 /*! |
|
315 The framework calls this method when an active editor loses focus. The parameter focusSwitch |
|
316 is true if the focus is moving from one editor to another and false if the input focus |
|
317 going to be lost completely. |
|
318 |
|
319 \sa focusReceived |
|
320 */ |
|
321 void HbInputMethod::focusLost(bool focusSwitch) |
|
322 { |
|
323 Q_UNUSED(focusSwitch); |
|
324 // Empty default implementation, do nothing. |
|
325 } |
|
326 |
|
327 /*! |
|
328 Returns pointer to active focus object. |
|
329 */ |
|
330 HbInputFocusObject* HbInputMethod::focusObject() const |
|
331 { |
|
332 Q_D(const HbInputMethod); |
|
333 return d->mFocusObject; |
|
334 } |
|
335 |
|
336 /*! |
|
337 QWidget based editors notify focus changes through this method. This is the |
|
338 default focus handling mechanism for QInputContext system. Input method |
|
339 implementation should never override this method unless it knows what it is doing. |
|
340 |
|
341 \sa setFocusObject |
|
342 */ |
|
343 void HbInputMethod::setFocusWidget(QWidget* widget) |
|
344 { |
|
345 Q_D(HbInputMethod); |
|
346 |
|
347 if (d->mFocusLocked) { |
|
348 return; |
|
349 } |
|
350 |
|
351 QInputContext::setFocusWidget(widget); |
|
352 |
|
353 if (!widget) { |
|
354 // Losing focus. |
|
355 if (d->mFocusObject) { |
|
356 focusLost(false); |
|
357 delete d->mFocusObject; |
|
358 d->mFocusObject = 0; |
|
359 } |
|
360 return; |
|
361 } |
|
362 |
|
363 QGraphicsView* gView = qobject_cast<QGraphicsView*>(widget); |
|
364 if (gView) { |
|
365 // We don't want to focus to graphics view but the items inside the scene, so just return |
|
366 return; |
|
367 } |
|
368 |
|
369 // Check whether the editor has read-only constraint and reject focus |
|
370 // if so. |
|
371 bool readOnly = false; |
|
372 if (HbEditorInterface::isConnected(widget)) { |
|
373 HbEditorInterface eInt(widget); |
|
374 if (eInt.constraints() & HbEditorConstraintIgnoreFocus) { |
|
375 readOnly = true; |
|
376 } |
|
377 } |
|
378 |
|
379 // Focusing widget doesn't have input capabilities |
|
380 // or it is read-only. |
|
381 if (readOnly && HbInputFocusObject::isReadOnlyWidget(widget)) { |
|
382 if (d->mFocusObject) { |
|
383 focusLost(); |
|
384 } |
|
385 return; |
|
386 } |
|
387 |
|
388 if (d->mFocusObject) { |
|
389 if (d->mFocusObject->object() == widget) { |
|
390 // Focus remains in same widget, do nothing. |
|
391 return; |
|
392 } else { |
|
393 // Lose editor focus unless we are focusing back to the editor from e.g. a vkb |
|
394 focusLost(); |
|
395 } |
|
396 } |
|
397 |
|
398 bool refreshHost = false; |
|
399 |
|
400 // Delete previous focus object. |
|
401 if (d->mFocusObject) { |
|
402 refreshHost = true; |
|
403 disconnect(d->mFocusObject, SIGNAL(editorDeleted()), this, SLOT(editorDeleted())); |
|
404 } |
|
405 delete d->mFocusObject; |
|
406 d->mFocusObject = 0; |
|
407 |
|
408 // Attach focus. |
|
409 d->mFocusObject = new HbInputFocusObject(widget); |
|
410 connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(editorDeleted(QObject*))); |
|
411 |
|
412 d->setFocusCommon(); |
|
413 |
|
414 // The focus jumped from one editor to another. Make sure that vkb host |
|
415 // updates the situation correctly. |
|
416 if (refreshHost && d->mFocusObject) { |
|
417 HbVkbHost *vkbHost = d->mFocusObject->editorInterface().vkbHost(); |
|
418 if (vkbHost) { |
|
419 vkbHost->refresh(); |
|
420 } |
|
421 } |
|
422 } |
|
423 |
|
424 /*! |
|
425 Checks if the destroyed widget is currently focused and clears the focus |
|
426 if needed. This method should not be overridden. |
|
427 |
|
428 \sa focusObjectDestroyed |
|
429 */ |
|
430 void HbInputMethod::widgetDestroyed(QWidget* widget) |
|
431 { |
|
432 Q_D(HbInputMethod); |
|
433 |
|
434 if (d->mFocusObject && d->mFocusObject->object() == widget) { |
|
435 releaseFocus(); |
|
436 } |
|
437 } |
|
438 |
|
439 /*! |
|
440 Checks if the destroyed object is currently focused and clears the focus |
|
441 if needed. |
|
442 |
|
443 \sa widgetDestroyed |
|
444 */ |
|
445 void HbInputMethod::focusObjectDestroyed(const HbInputFocusObject* focusObject) |
|
446 { |
|
447 Q_D(HbInputMethod); |
|
448 |
|
449 if (focusObject && focusObject == d->mFocusObject) { |
|
450 releaseFocus(); |
|
451 } |
|
452 } |
|
453 |
|
454 /*! |
|
455 Graphics item based editors (or any other object that implements |
|
456 HbInputFocusObject) send their focus events notifications through this method. |
|
457 Since Qt's QInputContext mechanism works only with QWidget based editors, |
|
458 this alternate focus channel is needed for objects belonging to a graphics scene |
|
459 (in case of a graphics scene, the topmost QWidget that has focus is |
|
460 graphics view, not the the object inside the view). The ownership of |
|
461 incoming focus object is transferred to the input framework. |
|
462 |
|
463 \sa setFocusWidget |
|
464 \sa HbInputFocusObject |
|
465 */ |
|
466 void HbInputMethod::setFocusObject(HbInputFocusObject* focusObject) |
|
467 { |
|
468 Q_D(HbInputMethod); |
|
469 |
|
470 if (d->mFocusLocked) { |
|
471 return; |
|
472 } |
|
473 |
|
474 if (focusObject == 0) { |
|
475 // Losing focus. |
|
476 if (d->mFocusObject != 0) { |
|
477 focusLost(false); |
|
478 delete d->mFocusObject; |
|
479 d->mFocusObject = 0; |
|
480 } |
|
481 return; |
|
482 } |
|
483 |
|
484 if(d->compareWithCurrentFocusObject( focusObject )) { |
|
485 // The incoming focus object is either same or points to same |
|
486 // widget that the framework is already focused to and nothing needs to be done here. |
|
487 // But because the ownership of the focus object is transferred to the |
|
488 // the framework, we need to delete the the incoming focus object in case it is |
|
489 // dirrefent than current one. |
|
490 if (d->mFocusObject != focusObject) { |
|
491 delete focusObject; |
|
492 } |
|
493 return; |
|
494 } |
|
495 |
|
496 bool refreshHost = false; |
|
497 |
|
498 // Delete previous focus object. |
|
499 if (d->mFocusObject) { |
|
500 refreshHost = true; |
|
501 focusLost(true); |
|
502 disconnect(d->mFocusObject->object(), SIGNAL(destroyed(QObject*)), this, SLOT(editorDeleted(QObject*))); |
|
503 delete d->mFocusObject; |
|
504 d->mFocusObject = 0; |
|
505 } |
|
506 QInputContext::setFocusWidget(0); |
|
507 |
|
508 // Attach focus. |
|
509 d->mFocusObject = focusObject; |
|
510 connect(d->mFocusObject->object(), SIGNAL(destroyed(QObject*)), this, SLOT(editorDeleted(QObject*))); |
|
511 |
|
512 // If this is embedded QWidget, then set base class focus too. |
|
513 QWidget *widget = qobject_cast<QWidget*>(focusObject->object()); |
|
514 if (widget) { |
|
515 QInputContext::setFocusWidget(widget); |
|
516 } |
|
517 |
|
518 d->setFocusCommon(); |
|
519 |
|
520 // The focus jumped from one editor to another. Make sure that vkb host |
|
521 // updates the situation correctly. |
|
522 if (refreshHost && d->mFocusObject) { |
|
523 HbVkbHost *vkbHost = d->mFocusObject->editorInterface().vkbHost(); |
|
524 if (vkbHost) { |
|
525 vkbHost->refresh(); |
|
526 } |
|
527 } |
|
528 } |
|
529 |
|
530 /*! |
|
531 The secondary channel uses this slot for inserting text active editor. |
|
532 */ |
|
533 void HbInputMethod::receiveText(const QString& string) |
|
534 { |
|
535 Q_D(HbInputMethod); |
|
536 |
|
537 if (isActiveMethod() && d->mFocusObject && |
|
538 (d->editorConstraints() & HbEditorConstraintsNoSecondaryChannel) == 0) { |
|
539 QList<QInputMethodEvent::Attribute> list; |
|
540 QInputMethodEvent event(QString(), list); |
|
541 event.setCommitString(string); |
|
542 d->mFocusObject->sendEvent(event); |
|
543 } |
|
544 } |
|
545 |
|
546 /*! |
|
547 This slot is called when the candidate list popup is closed. The base |
|
548 class implementation is empty so any input method interested in |
|
549 candidate list close event should implement it. |
|
550 */ |
|
551 void HbInputMethod::candidatePopupClosed(int closingKey) |
|
552 { |
|
553 Q_UNUSED(closingKey); |
|
554 // Empty default implementation |
|
555 } |
|
556 |
|
557 /*! |
|
558 The framework calls this method when device-wide input language changes. |
|
559 The base class implementation is empty so any input method interested in |
|
560 language switch events should implement it. Note that this method reports |
|
561 change in system wide input language. Local input language in active editor |
|
562 may still remain same. |
|
563 |
|
564 \sa activeLanguage |
|
565 */ |
|
566 void HbInputMethod::inputLanguageChanged(const HbInputLanguage &newLanguage) |
|
567 { |
|
568 Q_UNUSED(newLanguage); |
|
569 // Empty default implementation. |
|
570 } |
|
571 |
|
572 /*! |
|
573 The framework calls this method when device-wide secondary input language changes. |
|
574 The base class implementation is empty so any input method interested in language switch |
|
575 events should override it in the actual inputmethod. |
|
576 */ |
|
577 void HbInputMethod::secondaryInputLanguageChanged(const HbInputLanguage &aNewLanguage) |
|
578 { |
|
579 // Empty default implementation. |
|
580 Q_UNUSED(aNewLanguage); |
|
581 } |
|
582 |
|
583 /*! |
|
584 The framework calls this method when the predictive input status changes. |
|
585 The base class implementation is empty so any input method interested in |
|
586 prediction status events should implement it. |
|
587 */ |
|
588 void HbInputMethod::predictiveInputStatusChanged(int newStatus) |
|
589 { |
|
590 Q_UNUSED(newStatus); |
|
591 // Empty default implementation. |
|
592 } |
|
593 |
|
594 /*! |
|
595 Returns true if given input mode is allowed in active editor. |
|
596 */ |
|
597 bool HbInputMethod::modeAllowedInEditor(HbInputModeType mode) const |
|
598 { |
|
599 Q_D(const HbInputMethod); |
|
600 return d->modeAllowedInEditor(mode); |
|
601 } |
|
602 |
|
603 /*! |
|
604 Returns true if this instance is currently active QInputContext in QApplication. |
|
605 */ |
|
606 bool HbInputMethod::isActiveMethod() const |
|
607 { |
|
608 Q_D(const HbInputMethod); |
|
609 return d->mIsActive; |
|
610 } |
|
611 |
|
612 /*! |
|
613 The framework calls this method every time the input state changes. This is an empty default |
|
614 implementation and the inheriting class should override it. |
|
615 */ |
|
616 void HbInputMethod::inputStateActivated(const HbInputState& newState) |
|
617 { |
|
618 Q_UNUSED(newState); |
|
619 // Empty default implementation. |
|
620 if (this != HbInputMethodNull::Instance()) { |
|
621 qDebug("WARNING: inputStateActivated() default implementation called: Is that ok?"); |
|
622 } |
|
623 } |
|
624 |
|
625 /*! |
|
626 Returns active input state. |
|
627 |
|
628 \sa activateState |
|
629 \sa activateNextState |
|
630 */ |
|
631 HbInputState HbInputMethod::inputState() const |
|
632 { |
|
633 Q_D(const HbInputMethod); |
|
634 return d->mInputState; |
|
635 } |
|
636 |
|
637 /*! |
|
638 Returns the first input state that should be activated when an editor is |
|
639 focused for the first time. The state is constructed from edirtor attributes and |
|
640 input settings. |
|
641 */ |
|
642 void HbInputMethod::editorRootState(HbInputState &result) const |
|
643 { |
|
644 Q_D(const HbInputMethod); |
|
645 d->editorRootState(result); |
|
646 } |
|
647 |
|
648 /*! |
|
649 |
|
650 */ |
|
651 void HbInputMethod::constructLatinState(HbInputState &result) const |
|
652 { |
|
653 Q_D(const HbInputMethod); |
|
654 d->constructLatinState(result); |
|
655 } |
|
656 |
|
657 /*! |
|
658 Activates given input state. State handler must be among cached input methods, this |
|
659 method doesn't resolve it from non-cached plugins. Returns true if the framework was |
|
660 able to find handler for the new state. A context switch to another input method |
|
661 instance may occur. |
|
662 |
|
663 \sa activateNextState |
|
664 \sa InputState |
|
665 */ |
|
666 bool HbInputMethod::activateState(const HbInputState& state) |
|
667 { |
|
668 Q_D(HbInputMethod); |
|
669 |
|
670 if (!d->stateAllowedInEditor(state)) { |
|
671 return false; |
|
672 } |
|
673 |
|
674 d->mStateChangeInProgress = true; |
|
675 |
|
676 HbInputMethod* stateHandler = HbInputModeCache::instance()->findStateHandler(state); |
|
677 |
|
678 if (!stateHandler) { |
|
679 stateHandler = HbInputMethodNull::Instance(); |
|
680 } |
|
681 |
|
682 d->mInputState = state; |
|
683 |
|
684 if (stateHandler != this) { |
|
685 stateHandler->d_ptr->mStateChangeInProgress = true; |
|
686 // Context switch needed. |
|
687 d->inputStateToEditor(d->mInputState); |
|
688 d->contextSwitch(stateHandler); |
|
689 stateHandler->d_ptr->mStateChangeInProgress = false; |
|
690 } else { |
|
691 // Same method handles new state, just report the state change. |
|
692 d->inputStateToEditor(d->mInputState); |
|
693 inputStateActivated(d->mInputState); |
|
694 } |
|
695 |
|
696 d->mStateChangeInProgress = false; |
|
697 |
|
698 return true; |
|
699 } |
|
700 |
|
701 /*! |
|
702 Updates the input state to automatic or lower case, with a check on editor contraints. |
|
703 */ |
|
704 void HbInputMethod::updateState() |
|
705 { |
|
706 Q_D(HbInputMethod); |
|
707 |
|
708 if (!d->textCaseApplies()) { |
|
709 return; |
|
710 } |
|
711 |
|
712 bool autoCaseNeeded = d->automaticTextCaseNeeded(); |
|
713 HbTextCase currentTextCase = d->mInputState.textCase(); |
|
714 |
|
715 bool refresh = false; |
|
716 |
|
717 if (currentTextCase == HbTextCaseAutomatic) { |
|
718 if (!autoCaseNeeded) { |
|
719 currentTextCase = HbTextCaseLower; |
|
720 refresh = true; |
|
721 } |
|
722 } else if (autoCaseNeeded && currentTextCase != HbTextCaseUpper ) { |
|
723 if (!d->isFixedCaseEditor()) { |
|
724 currentTextCase = HbTextCaseAutomatic; |
|
725 refresh = true; |
|
726 } else { |
|
727 return; |
|
728 } |
|
729 } |
|
730 |
|
731 if (refresh) { |
|
732 d->mInputState.setTextCase(currentTextCase); |
|
733 d->inputStateToEditor(d->mInputState); |
|
734 inputStateActivated(d->mInputState); |
|
735 } |
|
736 } |
|
737 |
|
738 /*! |
|
739 Clears focus state from input method side. After calling this method, |
|
740 HbInputMethod instance thinks that it is not focused to any widget. |
|
741 The widget itself still remain focused to this input context. |
|
742 */ |
|
743 void HbInputMethod::releaseFocus() |
|
744 { |
|
745 Q_D(HbInputMethod); |
|
746 |
|
747 delete d->mFocusObject; |
|
748 d->mFocusObject = 0; |
|
749 } |
|
750 |
|
751 /*! |
|
752 Receives the screen orientation signal. Will determine correct input state for new |
|
753 orientation and find state handler for it. |
|
754 */ |
|
755 void HbInputMethod::orientationChanged(Qt::Orientation orientation) |
|
756 { |
|
757 Q_UNUSED(orientation); |
|
758 |
|
759 if (isActiveMethod()) { |
|
760 // Make sure that if there was an editor focus before the orientation change, |
|
761 // it will re-focus. |
|
762 QInputContext *ic = qApp->inputContext(); |
|
763 if (ic) { |
|
764 QEvent *event = new QEvent(QEvent::RequestSoftwareInputPanel); |
|
765 ic->filterEvent(event); |
|
766 delete event; |
|
767 } |
|
768 } |
|
769 } |
|
770 |
|
771 /*! |
|
772 This slot is connected to setting proxy's orientation change warning signal. The default |
|
773 base class implementation is empty. |
|
774 |
|
775 \sa HbInputSettingProxy |
|
776 */ |
|
777 void HbInputMethod::orientationAboutToChange() |
|
778 { |
|
779 } |
|
780 |
|
781 /*! |
|
782 Returns active input language. Unlike setting proxy's global input language, |
|
783 this method takes into account input state language and possible editor local language, |
|
784 so the return value reflects real situation in currently active editor instead of |
|
785 the global setting. If input state defines language, then that is used. Otherwise |
|
786 editor's local input language is checked first and if that is not specified, then |
|
787 global input language is returned. |
|
788 */ |
|
789 HbInputLanguage HbInputMethod::activeLanguage() const |
|
790 { |
|
791 Q_D(const HbInputMethod); |
|
792 return d->activeLanguage(); |
|
793 } |
|
794 |
|
795 /*! |
|
796 Once this method is called, the framework will ignore all the incoming focus events completely |
|
797 until focus is unlocked. Context switch operation will unlock it |
|
798 automatically. Usually this feature is not needed, but it may come handy in some cases |
|
799 where an input method implementation knows that is is going to do something on the UI-level |
|
800 that will steal the focus, but wants to ensure that the framework keeps its |
|
801 focus in the original editor during that time. |
|
802 |
|
803 \sa unlockFocus |
|
804 */ |
|
805 void HbInputMethod::lockFocus() |
|
806 { |
|
807 Q_D(HbInputMethod); |
|
808 d->mFocusLocked = true; |
|
809 } |
|
810 |
|
811 /*! |
|
812 Unlocks the focus. After calling this method the framework will start to receive |
|
813 focus events again, in case they where locked out before. |
|
814 |
|
815 \sa lockFocus |
|
816 */ |
|
817 void HbInputMethod::unlockFocus() |
|
818 { |
|
819 Q_D(HbInputMethod); |
|
820 d->mFocusLocked = false; |
|
821 } |
|
822 |
|
823 /*! |
|
824 Removes input method focus and asks active input plugin to close its active UI-components |
|
825 (such as touch keypads). This may be needed in some special cases where the underlying |
|
826 application wants to make sure that there are no input related elements on the screen. |
|
827 |
|
828 This is a if-all-else fails backup method. Same can be done (more efficiently) by doing |
|
829 following. |
|
830 |
|
831 \code |
|
832 QInputContext* inputContext = qApp->inputContext(); |
|
833 if (inputContext) { |
|
834 inputContext->setFocusWidget(0); |
|
835 } |
|
836 \endcode |
|
837 */ |
|
838 void HbInputMethod::forceUnfocus() |
|
839 { |
|
840 HbInputMethod* active = activeInputMethod(); |
|
841 |
|
842 if (active) { |
|
843 active->focusLost(false); |
|
844 active->releaseFocus(); |
|
845 delete active->d_ptr->mFocusObject; |
|
846 active->d_ptr->mFocusObject = 0; |
|
847 } |
|
848 } |
|
849 |
|
850 /*! |
|
851 Wrapper |
|
852 */ |
|
853 bool HbInputMethod::automaticTextCaseNeeded() const |
|
854 { |
|
855 Q_D(const HbInputMethod); |
|
856 return d->automaticTextCaseNeeded(); |
|
857 } |
|
858 |
|
859 /*! |
|
860 Wrapper |
|
861 */ |
|
862 void HbInputMethod::inputStateToEditor(const HbInputState& source) |
|
863 { |
|
864 Q_D(HbInputMethod); |
|
865 d->inputStateToEditor(source); |
|
866 } |
|
867 |
|
868 /*! |
|
869 Returns true if state change operation is in progress. This is useful in those |
|
870 cases where focus operations should behave differently during state change |
|
871 than in normal focus-in / focus-out operations. For example, we may not want |
|
872 to run virtual keyboard animations during state change but just switch to another |
|
873 vkb immediately. |
|
874 */ |
|
875 bool HbInputMethod::stateChangeInProgress() const |
|
876 { |
|
877 Q_D(const HbInputMethod); |
|
878 return d->mStateChangeInProgress; |
|
879 } |
|
880 |
|
881 /*! |
|
882 When an editor becomes focused, the framework connects its destroyed signal |
|
883 to this slot and it takes care of closing the input and resetting the input method. |
|
884 */ |
|
885 void HbInputMethod::editorDeleted(QObject *obj) |
|
886 { |
|
887 Q_UNUSED(obj); |
|
888 |
|
889 focusLost(); |
|
890 releaseFocus(); |
|
891 reset(); |
|
892 } |
|
893 |
|
894 /*! |
|
895 This function returns true if there is a context switch happening due to a orientation |
|
896 switch. |
|
897 */ |
|
898 bool HbInputMethod::orientationContextSwitchInProgress() |
|
899 { |
|
900 Q_D(HbInputMethod); |
|
901 return d->mIsOrientationContextSwitchInProgress; |
|
902 } |
|
903 |
|
904 // End of file |
|
905 |