28 #include <hbinputmethod.h> |
28 #include <hbinputmethod.h> |
29 #include <hbinputkeymapfactory.h> |
29 #include <hbinputkeymapfactory.h> |
30 #include <hbinputpredictionengine.h> |
30 #include <hbinputpredictionengine.h> |
31 #include <hbinputsettingproxy.h> |
31 #include <hbinputsettingproxy.h> |
32 #include <hbinputpredictionfactory.h> |
32 #include <hbinputpredictionfactory.h> |
|
33 #include <hbinputbutton.h> |
33 #include "hbinputabstractbase.h" |
34 #include "hbinputabstractbase.h" |
34 #include "hbinputbasic12keyhandler.h" |
35 #include "hbinputbasic12keyhandler.h" |
35 #include "hbinputbasic12keyhandler_p.h" |
36 #include "hbinputbasic12keyhandler_p.h" |
36 |
37 |
37 HbInputBasic12KeyHandlerPrivate::HbInputBasic12KeyHandlerPrivate() |
38 HbInputBasic12KeyHandlerPrivate::HbInputBasic12KeyHandlerPrivate() |
38 : mLastKey(0), |
39 : mLastKey(0), |
39 mCurrentChar(0), |
40 mCurrentChar(0), |
40 mNumChr(0), |
41 mNumChr(0), |
41 mDownKey(0), |
42 mDownKey(0), |
42 mCurrentlyFocused(0), |
43 mCurrentlyFocused(0), |
43 mLongPressHappened(false), |
44 mLongPressHappened(false), |
44 mShiftKeyDoubleTapped(false) |
45 mShiftKeyDoubleTapped(false) |
45 { |
46 { |
46 } |
47 } |
47 |
48 |
48 HbInputBasic12KeyHandlerPrivate::~HbInputBasic12KeyHandlerPrivate() |
49 HbInputBasic12KeyHandlerPrivate::~HbInputBasic12KeyHandlerPrivate() |
49 { |
50 { |
50 } |
51 } |
51 |
52 |
52 // handles the key press events. |
53 // handles the key press events. |
53 void HbInputBasic12KeyHandlerPrivate::handleAlphaEvent(int buttonId) |
54 bool HbInputBasic12KeyHandlerPrivate::handleAlphaEvent(int buttonId, HbKeyboardType type) |
54 { |
55 { |
55 Q_Q(HbInputBasic12KeyHandler); |
56 Q_Q(HbInputBasic12KeyHandler); |
56 HbInputFocusObject *focusObject = 0; |
57 HbInputFocusObject *focusObject = mInputMethod->focusObject(); |
57 focusObject = mInputMethod->focusObject(); |
|
58 if (!focusObject) { |
|
59 return; |
|
60 } |
|
61 //This condition is to avoid get the characters mapped to Asterisk |
|
62 //Especially for Thai language we have mapped character to Asterisk |
|
63 if(buttonId != Qt::Key_Asterisk) { |
|
64 mCurrentChar = q->getNthCharacterInKey(mNumChr, buttonId); |
|
65 } |
|
66 |
|
67 if (mCurrentChar != 0) { |
|
68 QString str; |
|
69 str += mCurrentChar; |
|
70 |
|
71 QList<QInputMethodEvent::Attribute> list; |
|
72 QInputMethodEvent event(str, list); |
|
73 focusObject->sendEvent(event); |
|
74 } |
|
75 } |
|
76 |
|
77 bool HbInputBasic12KeyHandlerPrivate::buttonPressed(const QKeyEvent *keyEvent) |
|
78 { |
|
79 Q_UNUSED(keyEvent); |
|
80 mLongPressHappened = false; |
|
81 HbInputFocusObject *focusObject = 0; |
|
82 focusObject = mInputMethod->focusObject(); |
|
83 if (!focusObject) { |
58 if (!focusObject) { |
84 return false; |
59 return false; |
85 } |
60 } |
86 int buttonId = keyEvent->key(); |
61 |
87 // mark a shift key double tap. This would be handled when the release event is received. |
62 int index = mNumChr; |
88 if ( (buttonId == Qt::Key_Shift) && (mLastKey == buttonId) && mTimer->isActive() ) { |
63 do { |
89 mShiftKeyDoubleTapped = true; |
64 //This condition is to avoid get the characters mapped to Asterisk |
90 } |
65 //Especially for Thai language we have mapped character to Asterisk |
|
66 if (buttonId != HbInputButton::ButtonKeyCodeAsterisk || |
|
67 mInputMethod->currentKeyboardType() == HbKeyboardSctPortrait) { |
|
68 mCurrentChar = q->getNthCharacterInKey(mNumChr, buttonId, type); |
|
69 } |
|
70 |
|
71 if (mCurrentChar != 0) { |
|
72 if (focusObject->characterAllowedInEditor(mCurrentChar)) { |
|
73 QString str; |
|
74 str += mCurrentChar; |
|
75 |
|
76 //If the keypad is SCT, we can commit the character immidiately |
|
77 if (mInputMethod->currentKeyboardType() == HbKeyboardSctPortrait) { |
|
78 focusObject->filterAndCommitCharacter(mCurrentChar); |
|
79 mCurrentChar = 0; |
|
80 } else { |
|
81 QList<QInputMethodEvent::Attribute> list; |
|
82 QInputMethodEvent event(str, list); |
|
83 focusObject->sendEvent(event); |
|
84 } |
|
85 return true; |
|
86 } |
|
87 } else { |
|
88 break; |
|
89 } |
|
90 } while (index != mNumChr); |
|
91 return false; |
|
92 } |
|
93 |
|
94 bool HbInputBasic12KeyHandlerPrivate::buttonPressed(const QKeyEvent *keyEvent) |
|
95 { |
|
96 Q_Q(HbInputBasic12KeyHandler); |
|
97 mLongPressHappened = false; |
|
98 HbInputFocusObject *focusObject = mInputMethod->focusObject(); |
|
99 if (!focusObject) { |
|
100 return false; |
|
101 } |
|
102 int buttonId = keyEvent->key(); |
|
103 |
|
104 if (keyEvent->isAutoRepeat() && mDownKey == buttonId) { |
|
105 mTimer->stop(); |
|
106 if (mDownKey == HbInputButton::ButtonKeyCodeShift) { |
|
107 mLongPressHappened = true; |
|
108 mInputMethod->switchMode(HbInputButton::ButtonKeyCodeShift); |
|
109 } else if (mDownKey == HbInputButton::ButtonKeyCodeSymbol || |
|
110 (mDownKey == HbInputButton::ButtonKeyCodeAsterisk && |
|
111 mInputMethod->currentKeyboardType() != HbKeyboardSctPortrait)) { |
|
112 mLongPressHappened = true; |
|
113 mInputMethod->selectSpecialCharacterTableMode(); |
|
114 } else if (mDownKey != HbInputButton::ButtonKeyCodeDelete && |
|
115 mInputMethod->currentKeyboardType() != HbKeyboardSctPortrait) { |
|
116 mLongPressHappened = true; |
|
117 q->commitFirstMappedNumber(mDownKey, mInputMethod->currentKeyboardType()); |
|
118 } |
|
119 if (mLongPressHappened) { |
|
120 mDownKey = 0; |
|
121 return true; |
|
122 } |
|
123 } |
|
124 |
|
125 // mark a shift key double tap. This would be handled when the release event is received. |
|
126 if ((buttonId == HbInputButton::ButtonKeyCodeShift) && (mLastKey == buttonId) && mTimer->isActive()) { |
|
127 mShiftKeyDoubleTapped = true; |
|
128 } |
|
129 |
91 if (mInputMethod) { |
130 if (mInputMethod) { |
92 if (mLastKey != buttonId) |
131 if (mLastKey != buttonId || mInputMethod->currentKeyboardType() == HbKeyboardSctPortrait) |
93 { |
132 { |
94 if(mCurrentChar != 0) { |
133 if (mCurrentChar != 0) { |
95 if (!focusObject->characterAllowedInEditor(mCurrentChar)) { |
134 if (!focusObject->characterAllowedInEditor(mCurrentChar)) { |
96 focusObject->sendCommitString(QString()); |
135 focusObject->sendCommitString(QString()); |
97 } else { |
136 } else { |
98 if (isEnterCharacter(mCurrentChar)) { |
137 if (isEnterCharacter(mCurrentChar)) { |
99 focusObject->sendPreEditString(QString("")); // Make sure the enter character is cleared. |
138 focusObject->sendPreEditString(QString("")); // Make sure the enter character is cleared. |
100 mCurrentChar = QChar('\n'); // Convert enter character to line feed. |
139 mCurrentChar = QChar('\n'); // Convert enter character to line feed. |
101 } |
140 } |
102 QChar commitChar(mCurrentChar); |
141 QChar commitChar(mCurrentChar); |
103 mCurrentChar = 0; |
142 mCurrentChar = 0; |
|
143 mNumChr = 0; |
104 focusObject->filterAndCommitCharacter(commitChar); |
144 focusObject->filterAndCommitCharacter(commitChar); |
105 } |
145 } |
106 } |
146 } |
107 } |
147 } |
108 |
148 |
109 mDownKey = buttonId; |
149 mDownKey = buttonId; |
110 mTimer->stop(); |
150 mTimer->stop(); |
111 mTimer->start(HbMultiTapTimerTimeout); |
151 if (mInputMethod->currentKeyboardType() == HbKeyboardVirtual12Key) { |
112 } |
152 mTimer->start(HbMultiTapTimerTimeout); |
|
153 } |
|
154 } |
113 return false; |
155 return false; |
114 } |
156 } |
115 |
157 |
116 /*! |
158 /*! |
117 Handles the key release events from the VKB. Launches the SCT with key release event of |
159 Handles the key release events from the VKB. Launches the SCT with key release event of |
118 asterisk. |
160 asterisk. |
119 */ |
161 */ |
120 bool HbInputBasic12KeyHandlerPrivate::buttonReleased(const QKeyEvent *keyEvent) |
162 bool HbInputBasic12KeyHandlerPrivate::buttonReleased(const QKeyEvent *keyEvent) |
121 { |
163 { |
122 HbInputVkbWidget::HbFlickDirection flickDir = static_cast<HbVirtual12Key*>(mInputMethod)->flickDirection(); |
164 HbInputVkbWidget::HbFlickDirection flickDir = static_cast<HbVirtual12Key*>(mInputMethod)->flickDirection(); |
123 if (mInputMethod && flickDir!=HbInputVkbWidget::HbFlickDirectionDown) { |
165 if (mInputMethod && flickDir!=HbInputVkbWidget::HbFlickDirectionDown) { |
124 Q_Q(HbInputBasic12KeyHandler); |
166 Q_Q(HbInputBasic12KeyHandler); |
125 int buttonId = keyEvent->key(); |
167 int buttonId = keyEvent->key(); |
126 HbInputFocusObject *focusObject = 0; |
168 HbInputFocusObject *focusObject = mInputMethod->focusObject(); |
127 focusObject = mInputMethod->focusObject(); |
169 if (!focusObject || !mDownKey) { |
128 if (!focusObject || !mDownKey) { |
170 return false; |
129 return false; |
171 } |
130 } |
172 mDownKey = 0; |
131 mDownKey = 0; |
173 if (mLongPressHappened){ |
132 if ( mLongPressHappened ){ |
174 mLongPressHappened = false; |
133 return false; |
175 return false; |
134 } |
176 } |
135 if(mTimer->isActive() && mLastKey != buttonId) { |
177 |
136 mNumChr = 0; |
178 if (mTimer->isActive() && mLastKey != buttonId) { |
137 |
179 mNumChr = 0; |
138 |
180 |
139 // For QLineEdit it works fine. For HbLineEdit, need to set the state |
181 // For QLineEdit it works fine. For HbLineEdit, need to set the state |
140 // to lower by calling activateState(). |
182 // to lower by calling activateState(). |
141 // This is needed for the scenario - When automatic text case is true |
183 // This is needed for the scenario - When automatic text case is true |
142 // click a button and before the multitap timer expires click on |
184 // click a button and before the multitap timer expires click on |
143 // another button. |
185 // another button. |
144 // Need to check for shift key : In empty editor, click on editor |
186 // Need to check for shift key : In empty editor, click on editor |
145 // press shift, multitap on a button. The char is entered in upper case. |
187 // press shift, multitap on a button. The char is entered in upper case. |
146 // It should be entered in lower case. |
188 // It should be entered in lower case. |
147 if (mLastKey && (Qt::Key_Shift != mLastKey)) { |
189 if (mLastKey && (HbInputButton::ButtonKeyCodeShift != mLastKey)) { |
148 mInputMethod->updateState(); |
190 mInputMethod->updateState(); |
149 } |
191 } |
150 refreshAutoCompleter(); |
192 refreshAutoCompleter(); |
151 } |
193 } |
152 |
194 |
153 if (buttonId == Qt::Key_Return) { |
195 if (buttonId == HbInputButton::ButtonKeyCodeEnter) { |
154 mInputMethod->closeKeypad(); |
196 mInputMethod->closeKeypad(); |
155 mLastKey = buttonId; |
197 mLastKey = buttonId; |
156 return true; |
198 return true; |
157 } else if (buttonId == Qt::Key_Shift) { |
199 } else if (buttonId == HbInputButton::ButtonKeyCodeShift) { |
158 // single tap of shift key toggles prediction status in case insensitive languages |
200 // single tap of shift key toggles prediction status in case insensitive languages |
159 // The Editor should not be Web or URL which allows only Latin Alphabet |
201 // The Editor should not be Web or URL which allows only Latin Alphabet |
160 if (!HbInputSettingProxy::instance()->globalInputLanguage().isCaseSensitiveLanguage() && |
202 if (!HbInputSettingProxy::instance()->globalInputLanguage().isCaseSensitiveLanguage() && |
161 ((HbEditorConstraintLatinAlphabetOnly | HbEditorConstraintAutoCompletingField)!=focusObject->editorInterface().constraints()) && |
203 ((HbEditorConstraintLatinAlphabetOnly | HbEditorConstraintAutoCompletingField)!=focusObject->editorInterface().inputConstraints()) && |
162 // when the language does not support prediction in that case we should not update the state and prediction |
204 // when the language does not support prediction in that case we should not update the state and prediction |
163 HbPredictionFactory::instance()->predictionEngineForLanguage(mInputMethod->inputState().language())) { |
205 HbPredictionFactory::instance()->predictionEngineForLanguage(mInputMethod->inputState().language())) { |
164 HbInputSettingProxy::instance()->togglePrediction(); |
206 HbInputSettingProxy::instance()->togglePrediction(); |
165 } else { |
207 } else { |
166 // For single key press, change the text input case. If the second shift key press is |
208 // For single key press, change the text input case. If the second shift key press is |
167 // received within long key press time out interval, then activate the next state |
209 // received within long key press time out interval, then activate the next state |
168 if (mShiftKeyDoubleTapped){ |
210 if (mShiftKeyDoubleTapped){ |
169 mShiftKeyDoubleTapped = false; |
211 mShiftKeyDoubleTapped = false; |
170 mTimer->stop(); |
212 mTimer->stop(); |
171 if( HbInputSettingProxy::instance()->globalInputLanguage() == mInputMethod->inputState().language() || |
213 if( HbInputSettingProxy::instance()->globalInputLanguage() == mInputMethod->inputState().language() || |
172 HbInputSettingProxy::instance()->globalSecondaryInputLanguage() == mInputMethod->inputState().language() || |
214 HbInputSettingProxy::instance()->globalSecondaryInputLanguage() == mInputMethod->inputState().language() || |
173 ((HbEditorConstraintLatinAlphabetOnly | HbEditorConstraintAutoCompletingField)==focusObject->editorInterface().constraints())){ |
215 ((HbEditorConstraintLatinAlphabetOnly | HbEditorConstraintAutoCompletingField)==focusObject->editorInterface().inputConstraints())){ |
174 // in latin variants , double tap of shift key toggles the prediction status |
216 // in latin variants , double tap of shift key toggles the prediction status |
175 // revert back to the old case as this is a double tap |
217 // revert back to the old case as this is a double tap |
176 // (the case was changed on the single tap) |
218 // (the case was changed on the single tap) |
177 updateTextCase(); |
219 updateTextCase(); |
178 // when the language does not support prediction in that case we should not update the state and prediction |
220 // when the language does not support prediction in that case we should not update the state and prediction |
179 if(HbPredictionFactory::instance()->predictionEngineForLanguage(mInputMethod->inputState().language())) { |
221 if(HbPredictionFactory::instance()->predictionEngineForLanguage(mInputMethod->inputState().language())) { |
180 q->togglePrediction(); |
222 q->togglePrediction(); |
181 } |
223 } |
182 } else { |
224 } else { |
183 // if the global language is different from the input mode language, we should |
225 // if the global language is different from the input mode language, we should |
184 // go back to the root state |
226 // go back to the root state |
185 // e.g. double tap of hash/shift key is used to change |
227 // e.g. double tap of hash/shift key is used to change |
186 // to chinese input mode from latin input mode |
228 // to chinese input mode from latin input mode |
187 HbInputState rootState; |
229 HbInputState rootState; |
188 mInputMethod->editorRootState(rootState); |
230 mInputMethod->editorRootState(rootState); |
189 mInputMethod->activateState(rootState); |
231 mInputMethod->activateState(rootState); |
190 } |
232 } |
191 } else { |
233 } else { |
192 updateTextCase(); |
234 updateTextCase(); |
193 mTimer->start(HbLongPressTimerTimeout); |
235 mTimer->start(HbMultiTapTimerTimeout); |
194 } |
236 } |
195 } |
237 } |
196 mLastKey = buttonId; |
238 mLastKey = buttonId; |
197 mCurrentChar = 0; |
239 mCurrentChar = 0; |
198 return true; |
240 return true; |
199 } |
241 } |
200 |
242 |
201 // Let's see if we can get the handler for this button in the base class. |
243 // Let's see if we can get the handler for this button in the base class. |
202 if (q->HbInputBasicHandler::filterEvent(keyEvent)) { |
244 if (q->HbInputBasicHandler::filterEvent(keyEvent)) { |
203 mCurrentChar = 0; |
245 mCurrentChar = 0; |
204 return true; |
246 return true; |
205 } |
247 } |
206 mLastKey = buttonId; |
248 mLastKey = buttonId; |
207 handleAlphaEvent(buttonId); |
249 if (handleAlphaEvent(buttonId, mInputMethod->currentKeyboardType())) { |
208 |
250 return true; |
209 // it was a long press on sct swith button. so just return form here. |
251 } |
210 if (!mTimer->isActive() && buttonId == Qt::Key_Control) { |
252 |
211 return true; |
253 // it was a long press on sct swith button. so just return form here. |
212 } |
254 if (!mTimer->isActive() && buttonId == HbInputButton::ButtonKeyCodeSymbol) { |
213 if (buttonId == Qt::Key_Asterisk || buttonId == Qt::Key_Control) { |
255 return true; |
214 //Same asterisk key is used for launching candidate list (long key press) |
256 } |
215 //and also for SCT. So, do not launch SCT if candidate list is already launched. |
257 if (buttonId == HbInputButton::ButtonKeyCodeAsterisk || buttonId == HbInputButton::ButtonKeyCodeSymbol || |
216 mInputMethod->switchMode(buttonId); |
258 buttonId == HbInputButton::ButtonKeyCodeAlphabet) { |
217 return true; |
259 //Same asterisk key is used for launching candidate list (long key press) |
218 } |
260 //and also for SCT. So, do not launch SCT if candidate list is already launched. |
219 } |
261 mInputMethod->switchMode(buttonId); |
220 return false; |
262 return true; |
|
263 } |
|
264 } |
|
265 return false; |
221 } |
266 } |
222 |
267 |
223 void HbInputBasic12KeyHandlerPrivate::_q_timeout() |
268 void HbInputBasic12KeyHandlerPrivate::_q_timeout() |
224 { |
269 { |
225 Q_Q(HbInputBasic12KeyHandler); |
|
226 mTimer->stop(); |
270 mTimer->stop(); |
227 mNumChr = 0; |
271 mNumChr = 0; |
228 |
272 |
229 HbInputFocusObject *focusedObject = 0; |
273 HbInputFocusObject *focusedObject = mInputMethod->focusObject(); |
230 focusedObject = mInputMethod->focusObject(); |
|
231 if (!focusedObject) { |
274 if (!focusedObject) { |
232 qDebug("HbInputBasic12KeyHandler::timeout focusObject == 0"); |
275 qDebug("HbInputBasic12KeyHandler::timeout focusObject == 0"); |
233 return; |
276 return; |
234 } |
277 } |
235 |
278 |
236 if (isEnterCharacter(mCurrentChar)) { |
279 if (isEnterCharacter(mCurrentChar)) { |
237 focusedObject->sendPreEditString(QString("")); // Make sure the enter character is cleared. |
280 focusedObject->sendPreEditString(QString("")); // Make sure the enter character is cleared. |
238 mCurrentChar = QChar('\n'); // Convert enter character to line feed. |
281 mCurrentChar = QChar('\n'); // Convert enter character to line feed. |
239 } |
282 } |
240 |
283 |
241 //Long key press number key is applicable to all keys |
284 if (!mDownKey && mLastKey != HbInputButton::ButtonKeyCodeShift) { |
242 if (mDownKey ) { |
|
243 //switch to numeric mode for long key press of Hash key |
|
244 if (mDownKey == Qt::Key_Shift) { |
|
245 mInputMethod->switchMode(Qt::Key_Shift); |
|
246 } else if (mDownKey == Qt::Key_Control ) { |
|
247 mInputMethod->selectSpecialCharacterTableMode(); |
|
248 mLongPressHappened = true; |
|
249 } else if (mDownKey == Qt::Key_Asterisk) { |
|
250 //switch to sct mode for long tap of * key |
|
251 mInputMethod->switchMode(mDownKey); |
|
252 } else if (mDownKey != Qt::Key_Delete) { |
|
253 q->commitFirstMappedNumber(mDownKey); |
|
254 mLongPressHappened = true; |
|
255 } |
|
256 mDownKey = 0; |
|
257 } else if(mLastKey != Qt::Key_Shift){ |
|
258 if (!focusedObject->characterAllowedInEditor(mCurrentChar)) { |
285 if (!focusedObject->characterAllowedInEditor(mCurrentChar)) { |
259 focusedObject->sendCommitString(QString()); |
286 focusedObject->sendCommitString(QString()); |
260 } else { |
287 } else { |
261 if ( mCurrentChar != 0){ |
288 if ( mCurrentChar != 0){ |
262 focusedObject->filterAndCommitCharacter(mCurrentChar); |
289 focusedObject->filterAndCommitCharacter(mCurrentChar); |