2 * Copyright 2012-2013 Samsung Electronics Co., Ltd.
4 * Licensed under the Flora License, Version 1.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://floralicense.org/license/
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::m_instance = NULL; /* For singleton */
28 CSCLEventHandler::CSCLEventHandler()
32 m_default_event_callback = NULL;
33 m_cur_input_mode_event_callback = NULL;
36 CSCLEventHandler::~CSCLEventHandler()
42 CSCLEventHandler::get_instance()
45 m_instance = new CSCLEventHandler();
47 return (CSCLEventHandler*)m_instance;
50 static void handle_shift_button_click_event(SclUIEventDesc ui_event_desc)
52 CSCLUIImpl *uiimpl = CSCLUIImpl::get_instance();
53 CSCLContext *context = CSCLContext::get_instance();
55 if (uiimpl && context) {
56 if (ui_event_desc.key_type == KEY_TYPE_CONTROL && ui_event_desc.key_event == MVK_Shift_L) {
57 switch (uiimpl->get_shift_state()) {
58 case SCL_SHIFT_STATE_OFF: {
59 uiimpl->set_shift_state(SCL_SHIFT_STATE_ON);
62 case SCL_SHIFT_STATE_ON: {
63 /* The default next state should be LOCK state */
64 SCLShiftState next_state = SCL_SHIFT_STATE_LOCK;
65 if (context->get_shift_multi_touch_enabled()) {
66 CSCLContext *context = CSCLContext::get_instance();
68 if (context->get_shift_multi_touch_state() == SCL_SHIFT_MULTITOUCH_ON_PRESSED) {
69 /* If the shift multi touch state is ON_PRESSED, don't leave ON state now */
70 next_state = SCL_SHIFT_STATE_ON;
71 } else if (context->get_shift_multi_touch_state() == SCL_SHIFT_MULTITOUCH_ON_KEY_ENTERED) {
72 /* If some keys were already entered while shift key was in pressed state, move to OFF */
73 next_state = SCL_SHIFT_STATE_OFF;
77 uiimpl->set_shift_state(next_state);
80 case SCL_SHIFT_STATE_LOCK: {
81 uiimpl->set_shift_state(SCL_SHIFT_STATE_OFF);
89 static void handle_shift_state_on_button_click_event(SclUIEventDesc ui_event_desc)
91 CSCLUIImpl *uiimpl = CSCLUIImpl::get_instance();
92 CSCLContext *context = CSCLContext::get_instance();
94 if (uiimpl && context) {
95 sclboolean turn_shift_off = TRUE;
96 if (ui_event_desc.key_type == KEY_TYPE_CONTROL) {
97 if (ui_event_desc.key_event == MVK_Shift_L || ui_event_desc.key_event == MVK_Caps_Lock) {
98 turn_shift_off = FALSE;
100 if (ui_event_desc.key_type == KEY_TYPE_MODECHANGE) {
101 turn_shift_off = FALSE;
104 /* If we are in ON_PRESSED or ON_KEY_ENTERED mode of shift multi touch state, do not turn it off now */
105 if (context->get_shift_multi_touch_enabled() && turn_shift_off) {
106 CSCLContext *context = CSCLContext::get_instance();
108 if (context->get_shift_multi_touch_state() == SCL_SHIFT_MULTITOUCH_ON_PRESSED) {
109 context->set_shift_multi_touch_state(SCL_SHIFT_MULTITOUCH_ON_KEY_ENTERED);
110 turn_shift_off = FALSE;
111 } else if (context->get_shift_multi_touch_state() == SCL_SHIFT_MULTITOUCH_ON_KEY_ENTERED) {
112 turn_shift_off = FALSE;
116 if (turn_shift_off) {
117 if (uiimpl->get_shift_state() == SCL_SHIFT_STATE_ON) {
118 /* If the ISE doesn't care about changing the shift state to off */
119 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
121 if (SCL_EVENT_PASS_ON ==
122 handler->on_event_notification(SCL_UINOTITYPE_SHIFT_STATE_CHANGE, SCL_SHIFT_STATE_OFF)) {
123 uiimpl->set_shift_state(SCL_SHIFT_STATE_OFF);
131 static void handle_mode_change_button_click_event(SclUIEventDesc ui_event_desc)
133 CSCLUIImpl *uiimpl = CSCLUIImpl::get_instance();
136 if (ui_event_desc.key_type == KEY_TYPE_MODECHANGE) {
137 uiimpl->set_input_mode(ui_event_desc.key_value);
143 CSCLEventHandler::on_event_key_clicked(SclUIEventDesc ui_event_desc)
145 SCLEventReturnType ret = SCL_EVENT_PASS_ON;
147 pre_process_ui_event(ui_event_desc);
149 if (m_cur_input_mode_event_callback) {
150 ret = m_cur_input_mode_event_callback->on_event_key_clicked(ui_event_desc);
152 if (ret == SCL_EVENT_PASS_ON) {
153 if (m_default_event_callback) {
154 ret = m_default_event_callback->on_event_key_clicked(ui_event_desc);
158 if (ret == SCL_EVENT_PASS_ON) {
159 /* Here we can put the fallback processing of this UIEvent */
161 /* General requirement - 1 */
162 /* When the SHIFT button was clicked, we change the shift state to OFF -> ON -> LOCK -> OFF ... */
163 handle_shift_button_click_event(ui_event_desc);
165 /* General requirement - 2 */
166 /* If a key was clicked but it is neither a SHIFT nor a CAPSLOCK, we just turn the shift off, if it is on */
167 handle_shift_state_on_button_click_event(ui_event_desc);
169 /* General requirement - 3 */
170 /* If the key type is KEY_TYPE_MODECHANGE, change the current input mode to given key_value */
171 handle_mode_change_button_click_event(ui_event_desc);
178 CSCLEventHandler::on_event_drag_state_changed(SclUIEventDesc ui_event_desc)
180 SCLEventReturnType ret = SCL_EVENT_PASS_ON;
182 pre_process_ui_event(ui_event_desc);
184 if (m_cur_input_mode_event_callback) {
185 ret = m_cur_input_mode_event_callback->on_event_drag_state_changed(ui_event_desc);
187 if (ret == SCL_EVENT_PASS_ON) {
188 if (m_default_event_callback) {
189 ret = m_default_event_callback->on_event_drag_state_changed(ui_event_desc);
193 if (ret == SCL_EVENT_PASS_ON) {
194 /* Here we can put the fallback processing of this UIEvent */
195 CSCLUIImpl *uiimpl = CSCLUIImpl::get_instance();
196 CSCLContext *context = CSCLContext::get_instance();
198 /* General requirement - 1 */
199 /* When the SHIFT button was 'pressed' and shift button multitouch action is enabled,
200 we change the current shift multitouch state to 'ON_PRESSED' */
201 if (uiimpl && context) {
202 if (context->get_shift_multi_touch_enabled()) {
203 if (ui_event_desc.event_type == EVENT_TYPE_PRESS) {
205 if (ui_event_desc.key_event == MVK_Shift_L) {
206 if (context->get_shift_multi_touch_state() == SCL_SHIFT_MULTITOUCH_OFF) {
207 if (SCL_EVENT_PASS_ON ==
208 on_event_notification(SCL_UINOTITYPE_SHIFT_STATE_CHANGE, SCL_SHIFT_STATE_ON)) {
209 uiimpl->set_shift_state(SCL_SHIFT_STATE_ON);
211 context->set_shift_multi_touch_state(SCL_SHIFT_MULTITOUCH_ON_PRESSED);
224 CSCLEventHandler::on_event_notification(SCLUINotiType noti_type, sclint etc_info)
226 SCLEventReturnType ret = SCL_EVENT_PASS_ON;
228 if (m_cur_input_mode_event_callback) {
229 ret = m_cur_input_mode_event_callback->on_event_notification(noti_type, etc_info);
231 if (ret == SCL_EVENT_PASS_ON) {
232 if (m_default_event_callback) {
233 ret = m_default_event_callback->on_event_notification(noti_type, etc_info);
237 if (ret == SCL_EVENT_PASS_ON) {
238 /* Here we can put the fallback processing of this UIEvent */
245 CSCLEventHandler::set_input_mode(const sclchar *input_mode)
249 sclboolean ret = FALSE;
250 m_cur_input_mode_event_callback = NULL;
253 std::string id = input_mode;
254 std::map<std::string, ISCLUIEventCallback*>::iterator iter = m_input_mode_event_callbacks.find(input_mode);
255 if (iter != m_input_mode_event_callbacks.end()) {
256 m_cur_input_mode_event_callback = (iter->second);
260 if (m_cur_input_mode_event_callback) {
268 CSCLEventHandler::set_event_callback(ISCLUIEventCallback *callback, const sclchar *input_mode)
272 scl_assert_return(callback);
275 std::string id = input_mode;
276 m_input_mode_event_callbacks[id] = callback;
278 m_default_event_callback = callback;
283 CSCLEventHandler::pre_process_ui_event(SclUIEventDesc &ui_event_desc)
288 const sclchar *key_value;
290 } KEY_VALUE_EVENT_CONVERT_TABLE;
292 KEY_VALUE_EVENT_CONVERT_TABLE control_keys[] = {
293 {"Space", MVK_space },
294 {"BackSpace", MVK_BackSpace },
295 {"Shift", MVK_Shift_L },
296 {"CapsLock", MVK_Caps_Lock },
297 {"Enter", MVK_Return },
299 {"Right", MVK_Right },
304 /* Translate key_values only when key_event is 0 and key_value is not NULL */
305 if (ui_event_desc.key_value && ui_event_desc.key_event == 0) {
306 if (ui_event_desc.key_type == KEY_TYPE_CHAR) {
307 /* If the key_value is a string with length 1, and the first character has value between
308 SCL_ISCHAR range, provide the corresponding ASCII code in key_event field */
309 if (ui_event_desc.key_value[0] != '\0' && ui_event_desc.key_value[1] == '\0') {
310 if (SCL_ISCHAR(ui_event_desc.key_value[0])) {
311 ui_event_desc.key_event = ui_event_desc.key_value[0];
314 } else if (ui_event_desc.key_type == KEY_TYPE_CONTROL) {
315 const scluint control_keys_size = sizeof(control_keys) / sizeof(KEY_VALUE_EVENT_CONVERT_TABLE);
317 for (scluint loop = 0;loop < control_keys_size;loop++) {
318 if (strncmp(control_keys[loop].key_value, ui_event_desc.key_value, strlen(control_keys[loop].key_value)) == 0) {
319 ui_event_desc.key_event = control_keys[loop].key_event;
322 } else if (ui_event_desc.key_type == KEY_TYPE_STRING) {
323 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
325 ui_event_desc.key_value = cache->find_substituted_string(ui_event_desc.key_value);