2 * Copyright (c) 2012 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include "sclresourcecache.h"
19 #include "scleventhandler.h"
21 #include "sclkeydefines.h"
22 #include "scluiimpl.h"
26 CSCLEventHandler::CSCLEventHandler()
30 m_default_event_callback = NULL;
31 m_cur_input_mode_event_callback = NULL;
34 CSCLEventHandler::~CSCLEventHandler()
40 CSCLEventHandler::get_instance()
42 static CSCLEventHandler instance;
46 static void handle_shift_button_click_event(SclUIEventDesc ui_event_desc)
48 CSCLUIImpl *uiimpl = CSCLUIImpl::get_instance();
49 CSCLContext *context = CSCLContext::get_instance();
51 if (uiimpl && context) {
52 if (ui_event_desc.key_type == KEY_TYPE_CONTROL && ui_event_desc.key_event == MVK_Shift_L) {
53 switch (uiimpl->get_shift_state()) {
54 case SCL_SHIFT_STATE_OFF: {
55 uiimpl->set_shift_state(SCL_SHIFT_STATE_ON);
58 case SCL_SHIFT_STATE_ON: {
59 /* The default next state should be LOCK state */
60 SCLShiftState next_state = SCL_SHIFT_STATE_LOCK;
61 if (context->get_shift_multi_touch_enabled()) {
63 if (context->get_shift_multi_touch_state() == SCL_SHIFT_MULTITOUCH_ON_PRESSED) {
64 /* If the shift multi touch state is ON_PRESSED, don't leave ON state now */
65 next_state = SCL_SHIFT_STATE_ON;
66 } else if (context->get_shift_multi_touch_state() == SCL_SHIFT_MULTITOUCH_ON_KEY_ENTERED) {
67 /* If some keys were already entered while shift key was in pressed state, move to OFF */
68 next_state = SCL_SHIFT_STATE_OFF;
72 uiimpl->set_shift_state(next_state);
75 case SCL_SHIFT_STATE_LOCK: {
76 uiimpl->set_shift_state(SCL_SHIFT_STATE_OFF);
79 case SCL_SHIFT_STATE_MAX:
87 static void handle_shift_state_on_button_click_event(SclUIEventDesc ui_event_desc)
89 CSCLUIImpl *uiimpl = CSCLUIImpl::get_instance();
91 /* do not need the libscl-ui auto-captial the shift state */
92 if (FALSE == uiimpl->get_autocapital_shift_state()) {
96 CSCLContext *context = CSCLContext::get_instance();
98 sclboolean turn_shift_off = TRUE;
99 if (ui_event_desc.key_event == MVK_Shift_L || ui_event_desc.key_event == MVK_Caps_Lock) {
100 turn_shift_off = FALSE;
102 if (ui_event_desc.key_type == KEY_TYPE_MODECHANGE) {
103 turn_shift_off = FALSE;
105 if (ui_event_desc.key_modifier == KEY_MODIFIER_MULTITAP_START ||
106 ui_event_desc.key_modifier == KEY_MODIFIER_MULTITAP_REPEAT) {
107 turn_shift_off = FALSE;
109 /* If we are in ON_PRESSED or ON_KEY_ENTERED mode of shift multi touch state, do not turn it off now */
111 if (context->get_shift_multi_touch_enabled() && turn_shift_off) {
112 if (context->get_shift_multi_touch_state() == SCL_SHIFT_MULTITOUCH_ON_PRESSED) {
113 context->set_shift_multi_touch_state(SCL_SHIFT_MULTITOUCH_ON_KEY_ENTERED);
114 turn_shift_off = FALSE;
115 } else if (context->get_shift_multi_touch_state() == SCL_SHIFT_MULTITOUCH_ON_KEY_ENTERED) {
116 turn_shift_off = FALSE;
120 if (turn_shift_off) {
121 if (uiimpl->get_shift_state() == SCL_SHIFT_STATE_ON) {
122 uiimpl->set_shift_state(SCL_SHIFT_STATE_OFF);
127 static void handle_mode_change_button_click_event(SclUIEventDesc ui_event_desc)
129 CSCLUIImpl *uiimpl = CSCLUIImpl::get_instance();
132 if (ui_event_desc.key_type == KEY_TYPE_MODECHANGE) {
133 uiimpl->set_input_mode(ui_event_desc.key_value);
139 CSCLEventHandler::on_event_key_clicked(SclUIEventDesc ui_event_desc)
141 SCLEventReturnType ret = SCL_EVENT_PASS_ON;
143 pre_process_ui_event(ui_event_desc);
145 if (m_cur_input_mode_event_callback) {
146 ret = m_cur_input_mode_event_callback->on_event_key_clicked(ui_event_desc);
148 if (ret == SCL_EVENT_PASS_ON) {
149 if (m_default_event_callback) {
150 ret = m_default_event_callback->on_event_key_clicked(ui_event_desc);
154 if (ret == SCL_EVENT_PASS_ON) {
155 /* Here we can put the fallback processing of this UIEvent */
157 /* General requirement - 1 */
158 /* When the SHIFT button was clicked, we change the shift state to OFF -> ON -> LOCK -> OFF ... */
159 handle_shift_button_click_event(ui_event_desc);
161 /* General requirement - 2 */
162 /* If a key was clicked but it is neither a SHIFT nor a CAPSLOCK, we just turn the shift off, if it is on */
163 handle_shift_state_on_button_click_event(ui_event_desc);
165 /* General requirement - 3 */
166 /* If the key type is KEY_TYPE_MODECHANGE, change the current input mode to given key_value */
167 handle_mode_change_button_click_event(ui_event_desc);
174 CSCLEventHandler::on_event_drag_state_changed(SclUIEventDesc ui_event_desc)
176 SCLEventReturnType ret = SCL_EVENT_PASS_ON;
178 pre_process_ui_event(ui_event_desc);
180 if (m_cur_input_mode_event_callback) {
181 ret = m_cur_input_mode_event_callback->on_event_drag_state_changed(ui_event_desc);
183 if (ret == SCL_EVENT_PASS_ON) {
184 if (m_default_event_callback) {
185 ret = m_default_event_callback->on_event_drag_state_changed(ui_event_desc);
189 if (ret == SCL_EVENT_PASS_ON) {
190 /* Here we can put the fallback processing of this UIEvent */
191 CSCLUIImpl *uiimpl = CSCLUIImpl::get_instance();
192 CSCLContext *context = CSCLContext::get_instance();
194 /* General requirement - 1 */
195 /* When the SHIFT button was 'pressed' and shift button multitouch action is enabled,
196 we change the current shift multitouch state to 'ON_PRESSED' */
197 if (uiimpl && context) {
198 if (context->get_shift_multi_touch_enabled()) {
199 if (ui_event_desc.event_type == EVENT_TYPE_PRESS) {
201 if (ui_event_desc.key_event == MVK_Shift_L) {
202 if (context->get_shift_multi_touch_state() == SCL_SHIFT_MULTITOUCH_OFF) {
203 uiimpl->set_shift_state(SCL_SHIFT_STATE_ON);
204 context->set_shift_multi_touch_state(SCL_SHIFT_MULTITOUCH_ON_PRESSED);
217 CSCLEventHandler::on_event_notification(SCLUINotiType noti_type, SclNotiDesc *etc_info)
219 SCLEventReturnType ret = SCL_EVENT_PASS_ON;
221 if (m_cur_input_mode_event_callback) {
222 ret = m_cur_input_mode_event_callback->on_event_notification(noti_type, etc_info);
224 if (ret == SCL_EVENT_PASS_ON) {
225 if (m_default_event_callback) {
226 ret = m_default_event_callback->on_event_notification(noti_type, etc_info);
230 if (ret == SCL_EVENT_PASS_ON) {
231 /* Here we can put the fallback processing of this UIEvent */
238 CSCLEventHandler::set_input_mode(const sclchar *input_mode)
242 sclboolean ret = FALSE;
243 SclNotiInputModeChangeDesc desc;
244 desc.input_mode = input_mode;
245 if (SCL_EVENT_PASS_ON == on_event_notification(SCL_UINOTITYPE_INPUT_MODE_CHANGE, &desc)) {
246 m_cur_input_mode_event_callback = NULL;
249 std::string id = input_mode;
250 std::map<std::string, ISCLUIEventCallback*>::iterator iter = m_input_mode_event_callbacks.find(input_mode);
251 if (iter != m_input_mode_event_callbacks.end()) {
252 m_cur_input_mode_event_callback = (iter->second);
263 CSCLEventHandler::set_event_callback(ISCLUIEventCallback *callback, const sclchar *input_mode)
267 scl_assert_return(callback);
270 std::string id = input_mode;
271 m_input_mode_event_callbacks[id] = callback;
273 m_default_event_callback = callback;
278 CSCLEventHandler::pre_process_ui_event(SclUIEventDesc &ui_event_desc)
283 const sclchar *key_value;
285 } KEY_VALUE_EVENT_CONVERT_TABLE;
287 KEY_VALUE_EVENT_CONVERT_TABLE control_keys[] = {
288 {"Space", MVK_space },
289 {"BackSpace", MVK_BackSpace },
290 {"Shift", MVK_Shift_L },
291 {"CapsLock", MVK_Caps_Lock },
292 {"Enter", MVK_Return },
294 {"Right", MVK_Right },
297 {"Escape", MVK_Escape },
300 /* Translate key_values only when key_event is 0 and key_value is not NULL */
301 if (ui_event_desc.key_value && ui_event_desc.key_event == 0) {
302 if (ui_event_desc.key_type == KEY_TYPE_CHAR) {
303 /* If the key_value is a string with length 1, and the first character has value between
304 SCL_ISCHAR range, provide the corresponding ASCII code in key_event field */
305 if (ui_event_desc.key_value[0] != '\0' && ui_event_desc.key_value[1] == '\0') {
306 if (SCL_ISCHAR(ui_event_desc.key_value[0])) {
307 ui_event_desc.key_event = static_cast<sclulong>(ui_event_desc.key_value[0]);
310 } else if (ui_event_desc.key_type == KEY_TYPE_CONTROL) {
311 const scluint control_keys_size = sizeof(control_keys) / sizeof(KEY_VALUE_EVENT_CONVERT_TABLE);
313 for (scluint loop = 0;loop < control_keys_size;loop++) {
314 if (strncmp(control_keys[loop].key_value, ui_event_desc.key_value, strlen(control_keys[loop].key_value)) == 0) {
315 ui_event_desc.key_event = control_keys[loop].key_event;
318 } else if (ui_event_desc.key_type == KEY_TYPE_STRING) {
319 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
321 ui_event_desc.key_value = cache->find_substituted_string(ui_event_desc.key_value);